diff --git a/Knot.files b/Knot.files
index fa11379d33100ed6682ed4549802f52b3048f676..84426087e334100d27397d31b9e7ffc067acf7cc 100644
--- a/Knot.files
+++ b/Knot.files
@@ -49,6 +49,7 @@ src/contrib/dnstap/writer.h
 src/contrib/endian.h
 src/contrib/getline.c
 src/contrib/getline.h
+src/contrib/lookup.h
 src/contrib/net.c
 src/contrib/net.h
 src/contrib/openbsd/strlcat.c
@@ -68,6 +69,7 @@ src/contrib/ucw/heap.c
 src/contrib/ucw/heap.h
 src/contrib/ucw/mempool.c
 src/contrib/ucw/mempool.h
+src/contrib/wire.h
 src/contrib/wire_ctx.h
 src/dnssec/Makefile.am
 src/dnssec/contrib/gnutls_error.c
@@ -384,8 +386,6 @@ src/libknot/internal/trie/hat-trie.c
 src/libknot/internal/trie/hat-trie.h
 src/libknot/internal/trie/murmurhash3.c
 src/libknot/internal/trie/murmurhash3.h
-src/libknot/internal/utils.c
-src/libknot/internal/utils.h
 src/libknot/libknot.h
 src/libknot/packet/compr.c
 src/libknot/packet/compr.h
@@ -393,6 +393,7 @@ src/libknot/packet/pkt.c
 src/libknot/packet/pkt.h
 src/libknot/packet/rrset-wire.c
 src/libknot/packet/rrset-wire.h
+src/libknot/packet/wire.c
 src/libknot/packet/wire.h
 src/libknot/processing/layer.c
 src/libknot/processing/layer.h
@@ -409,6 +410,7 @@ src/libknot/rrset-dump.h
 src/libknot/rrset.c
 src/libknot/rrset.h
 src/libknot/rrtype/aaaa.h
+src/libknot/rrtype/dnskey.c
 src/libknot/rrtype/dnskey.h
 src/libknot/rrtype/naptr.c
 src/libknot/rrtype/naptr.h
@@ -420,7 +422,9 @@ src/libknot/rrtype/nsec3param.h
 src/libknot/rrtype/opt.c
 src/libknot/rrtype/opt.h
 src/libknot/rrtype/rdname.h
+src/libknot/rrtype/rrsig.c
 src/libknot/rrtype/rrsig.h
+src/libknot/rrtype/soa.c
 src/libknot/rrtype/soa.h
 src/libknot/rrtype/tsig.c
 src/libknot/rrtype/tsig.h
@@ -519,6 +523,7 @@ tests/hattrie.c
 tests/hhash.c
 tests/internal_mem.c
 tests/journal.c
+tests/lookup.c
 tests/modules/online_sign.c
 tests/namedb.c
 tests/net.c
@@ -538,7 +543,6 @@ tests/rrset_wire.c
 tests/server.c
 tests/test_conf.h
 tests/tsig_key.c
-tests/utils.c
 tests/wire.c
 tests/wire_ctx.c
 tests/worker_pool.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 5b57f016bf49d7a75a32e1f1d68595f4397415ff..11618953ef28431598d7f22e489c798b5cc36342 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -28,11 +28,13 @@ nobase_libcontrib_la_HEADERS =			\
 	contrib/base64.h			\
 	contrib/endian.h			\
 	contrib/getline.h			\
+	contrib/lookup.h			\
 	contrib/net.h				\
 	contrib/print.h				\
 	contrib/sockaddr.h			\
 	contrib/string.h			\
 	contrib/tolower.h			\
+	contrib/wire.h				\
 	contrib/wire_ctx.h			\
 	contrib/openbsd/strlcat.h		\
 	contrib/openbsd/strlcpy.h		\
@@ -89,8 +91,7 @@ nobase_libknot_internal_la_HEADERS = 		\
 	libknot/internal/namedb/namedb_lmdb.h	\
 	libknot/internal/namedb/namedb_trie.h	\
 	libknot/internal/trie/hat-trie.h	\
-	libknot/internal/trie/murmurhash3.h	\
-	libknot/internal/utils.h
+	libknot/internal/trie/murmurhash3.h
 
 libknot_yparser_ladir = $(includedir)
 nobase_libknot_yparser_la_HEADERS = 		\
@@ -124,6 +125,7 @@ libknot_la_SOURCES =				\
 	libknot/packet/compr.c			\
 	libknot/packet/pkt.c			\
 	libknot/packet/rrset-wire.c		\
+	libknot/packet/wire.c			\
 	libknot/processing/layer.c		\
 	libknot/processing/overlay.c		\
 	libknot/processing/requestor.c		\
@@ -131,10 +133,13 @@ libknot_la_SOURCES =				\
 	libknot/rdataset.c			\
 	libknot/rrset-dump.c			\
 	libknot/rrset.c				\
+	libknot/rrtype/dnskey.c			\
 	libknot/rrtype/naptr.c			\
 	libknot/rrtype/nsec3.c			\
 	libknot/rrtype/nsec3param.c		\
 	libknot/rrtype/opt.c			\
+	libknot/rrtype/rrsig.c			\
+	libknot/rrtype/soa.c			\
 	libknot/rrtype/tsig.c			\
 	libknot/tsig-op.c			\
 	libknot/tsig.c				\
@@ -156,7 +161,6 @@ libknot_internal_la_SOURCES = 			\
 	libknot/internal/namedb/namedb_trie.c	\
 	libknot/internal/trie/hat-trie.c	\
 	libknot/internal/trie/murmurhash3.c	\
-	libknot/internal/utils.c		\
 	$(nobase_libknot_internal_la_HEADERS)
 
 libcontrib_la_CPPFLAGS = $(AM_CPPFLAGS)
diff --git a/src/contrib/lookup.h b/src/contrib/lookup.h
new file mode 100644
index 0000000000000000000000000000000000000000..9bdf47a596059baefbda6908db6e9ab3ae16ff64
--- /dev/null
+++ b/src/contrib/lookup.h
@@ -0,0 +1,85 @@
+/*  Copyright (C) 2011 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+/*!
+ * \file
+ *
+ * \brief A general purpose lookup table.
+ *
+ * \addtogroup contrib
+ * @{
+ */
+
+#pragma once
+
+#include <string.h>
+
+/*!
+ * \brief A general purpose lookup table.
+ */
+typedef struct lookup_table {
+	int id;
+	const char *name;
+} lookup_table_t;
+
+/*!
+ * \brief Looks up the given name in the lookup table.
+ *
+ * \param table Lookup table.
+ * \param name Name to look up.
+ *
+ * \return Item in the lookup table with the given name or NULL if no such is
+ *         present.
+ */
+inline static const lookup_table_t *lookup_by_name(const lookup_table_t *table, const char *name)
+{
+	if (table == NULL || name == NULL) {
+		return NULL;
+	}
+
+	while (table->name != NULL) {
+		if (strcasecmp(name, table->name) == 0) {
+			return table;
+		}
+		table++;
+	}
+
+	return NULL;
+}
+
+/*!
+ * \brief Looks up the given id in the lookup table.
+ *
+ * \param table Lookup table.
+ * \param id ID to look up.
+ *
+ * \return Item in the lookup table with the given id or NULL if no such is
+ *         present.
+ */
+inline static const lookup_table_t *lookup_by_id(const lookup_table_t *table, int id)
+{
+	if (table == NULL) {
+		return NULL;
+	}
+
+	while (table->name != NULL) {
+		if (table->id == id) {
+			return table;
+		}
+		table++;
+	}
+
+	return NULL;
+}
diff --git a/src/libknot/internal/utils.h b/src/contrib/wire.h
similarity index 62%
rename from src/libknot/internal/utils.h
rename to src/contrib/wire.h
index 6c37bcc41342c25aaca9f4064ae0ec51832758fa..333e117ff8cf6c9177852e7b664f849dd6af5223 100644
--- a/src/libknot/internal/utils.h
+++ b/src/contrib/wire.h
@@ -1,13 +1,3 @@
-/*!
- * \file utils.h
- *
- * \author Lubos Slovak <lubos.slovak@nic.cz>
- *
- * \brief Various utilities.
- *
- * \addtogroup libknot
- * @{
- */
 /*  Copyright (C) 2011 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
 
     This program is free software: you can redistribute it and/or modify
@@ -23,48 +13,21 @@
     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 <string.h>
-#include <stdint.h>
-#include <stdio.h>
-
-/*!
- * \brief A general purpose lookup table.
- */
-struct lookup_table {
-	int id;
-	const char *name;
-};
-
-typedef struct lookup_table lookup_table_t;
-
 /*!
- * \brief Looks up the given name in the lookup table.
+ * \file
  *
- * \param table Lookup table.
- * \param name Name to look up.
+ * \brief Wire integer operations.
  *
- * \return Item in the lookup table with the given name or NULL if no such is
- *         present.
+ * \addtogroup contrib
+ * @{
  */
-lookup_table_t *lookup_by_name(lookup_table_t *table, const char *name);
 
-/*!
- * \brief Looks up the given id in the lookup table.
- *
- * \param table Lookup table.
- * \param id ID to look up.
- *
- * \return Item in the lookup table with the given id or NULL if no such is
- *         present.
- */
-lookup_table_t *lookup_by_id(lookup_table_t *table, int id);
+#pragma once
 
-/*
- * Writing / reading arbitrary data to / from wireformat.
- */
+#include <stdint.h>
+#include <string.h>
+
+#include "contrib/endian.h"
 
 /*!
  * \brief Reads 2 bytes from the wireformat data.
@@ -73,7 +36,10 @@ lookup_table_t *lookup_by_id(lookup_table_t *table, int id);
  *
  * \return The 2 bytes read, in host byte order.
  */
-uint16_t wire_read_u16(const uint8_t *pos);
+inline static uint16_t wire_read_u16(const uint8_t *pos)
+{
+	return be16toh(*(uint16_t *)pos);
+}
 
 /*!
  * \brief Reads 4 bytes from the wireformat data.
@@ -82,7 +48,10 @@ uint16_t wire_read_u16(const uint8_t *pos);
  *
  * \return The 4 bytes read, in host byte order.
  */
-uint32_t wire_read_u32(const uint8_t *pos);
+inline static uint32_t wire_read_u32(const uint8_t *pos)
+{
+	return be32toh(*(uint32_t *)pos);
+}
 
 /*!
  * \brief Reads 6 bytes from the wireformat data.
@@ -91,7 +60,12 @@ uint32_t wire_read_u32(const uint8_t *pos);
  *
  * \return The 6 bytes read, in host byte order.
  */
-uint64_t wire_read_u48(const uint8_t *pos);
+inline static uint64_t wire_read_u48(const uint8_t *pos)
+{
+	uint64_t input = 0;
+	memcpy((uint8_t *)&input + 1, pos, 6);
+	return be64toh(input) >> 8;
+}
 
 /*!
  * \brief Read 8 bytes from the wireformat data.
@@ -100,7 +74,10 @@ uint64_t wire_read_u48(const uint8_t *pos);
  *
  * \return The 8 bytes read, in host byte order.
  */
-uint64_t wire_read_u64(const uint8_t *pos);
+inline static uint64_t wire_read_u64(const uint8_t *pos)
+{
+	return be64toh(*(uint64_t *)pos);
+}
 
 /*!
  * \brief Writes 2 bytes in wireformat.
@@ -110,7 +87,10 @@ uint64_t wire_read_u64(const uint8_t *pos);
  * \param pos Position where to put the 2 bytes.
  * \param data Data to put.
  */
-void wire_write_u16(uint8_t *pos, uint16_t data);
+inline static void wire_write_u16(uint8_t *pos, uint16_t data)
+{
+	*(uint16_t *)pos = htobe16(data);
+}
 
 /*!
  * \brief Writes 4 bytes in wireformat.
@@ -120,7 +100,10 @@ void wire_write_u16(uint8_t *pos, uint16_t data);
  * \param pos Position where to put the 4 bytes.
  * \param data Data to put.
  */
-void wire_write_u32(uint8_t *pos, uint32_t data);
+inline static void wire_write_u32(uint8_t *pos, uint32_t data)
+{
+	*(uint32_t *)pos = htobe32(data);
+}
 
 /*!
  * \brief Writes 6 bytes in wireformat.
@@ -130,7 +113,11 @@ void wire_write_u32(uint8_t *pos, uint32_t data);
  * \param pos Position where to put the 4 bytes.
  * \param data Data to put.
  */
-void wire_write_u48(uint8_t *pos, uint64_t data);
+inline static void wire_write_u48(uint8_t *pos, uint64_t data)
+{
+	uint64_t swapped = htobe64(data << 8);
+	memcpy(pos, (uint8_t *)&swapped + 1, 6);
+}
 
 /*!
  * \brief Writes 8 bytes in wireformat.
@@ -140,6 +127,9 @@ void wire_write_u48(uint8_t *pos, uint64_t data);
  * \param pos Position where to put the 8 bytes.
  * \param data Data to put.
  */
-void wire_write_u64(uint8_t *pos, uint64_t data);
+inline static void wire_write_u64(uint8_t *pos, uint64_t data)
+{
+	*(uint64_t *)pos = htobe64(data);
+}
 
 /*! @} */
diff --git a/src/knot/conf/scheme.h b/src/knot/conf/scheme.h
index 8c0706e3c105b5f4fbf3ca6a7702721e86b48251..5549443315d46984ddf50bb3056e46cf20019dc9 100644
--- a/src/knot/conf/scheme.h
+++ b/src/knot/conf/scheme.h
@@ -26,6 +26,7 @@
 #pragma once
 
 #include "libknot/yparser/ypscheme.h"
+#include "contrib/lookup.h"
 
 #define C_ACL			"\x03""acl"
 #define C_ACTION		"\x06""action"
diff --git a/src/knot/conf/tools.c b/src/knot/conf/tools.c
index a4327b054c4ee6da24264b1c1410a8d86de39200..f44efdbffdc2baad2ea5480fc95ae117f92878c0 100644
--- a/src/knot/conf/tools.c
+++ b/src/knot/conf/tools.c
@@ -35,7 +35,6 @@
 #include "knot/conf/scheme.h"
 #include "knot/common/log.h"
 #include "libknot/errcode.h"
-#include "libknot/internal/utils.h"
 #include "libknot/yparser/yptrafo.h"
 #include "contrib/wire_ctx.h"
 
diff --git a/src/knot/ctl/remote.c b/src/knot/ctl/remote.c
index 0b70d54e68eefcb22a01d5630c7f4c30d7684830..18271eac3aa9c97aa88932fdb37f25ebf2801861 100644
--- a/src/knot/ctl/remote.c
+++ b/src/knot/ctl/remote.c
@@ -35,6 +35,7 @@
 #include "contrib/sockaddr.h"
 #include "contrib/string.h"
 #include "contrib/openbsd/strlcpy.h"
+#include "contrib/wire.h"
 
 #define KNOT_CTL_REALM "knot."
 #define KNOT_CTL_REALM_EXT ("." KNOT_CTL_REALM)
diff --git a/src/knot/modules/rosedb.c b/src/knot/modules/rosedb.c
index cadb72e8c7faa2294b222fb726448755d9c658c4..3c900a3612d5b1f8829d4755caa6c869ca23882b 100644
--- a/src/knot/modules/rosedb.c
+++ b/src/knot/modules/rosedb.c
@@ -21,8 +21,8 @@
 #include "knot/modules/rosedb.h"
 #include "knot/nameserver/process_query.h"
 #include "libknot/libknot.h"
-#include "libknot/internal/utils.h"
 #include "contrib/net.h"
+#include "contrib/wire.h"
 
 /* Module configuration scheme. */
 #define MOD_DBDIR		"\x05""dbdir"
diff --git a/src/knot/nameserver/axfr.c b/src/knot/nameserver/axfr.c
index 999ac3fef0f674b094d5dee5b1bb7a90cb74abdf..78756bc9999aec39e0c31b4162995fc0759a27ff 100644
--- a/src/knot/nameserver/axfr.c
+++ b/src/knot/nameserver/axfr.c
@@ -386,7 +386,7 @@ int axfr_answer_process(knot_pkt_t *pkt, struct answer_data *adata)
 	/* Check RCODE. */
 	uint8_t rcode = knot_wire_get_rcode(pkt->wire);
 	if (rcode != KNOT_RCODE_NOERROR) {
-		lookup_table_t *lut = lookup_by_id(knot_rcode_names, rcode);
+		const lookup_table_t *lut = lookup_by_id(knot_rcode_names, rcode);
 		if (lut != NULL) {
 			AXFRIN_LOG(LOG_WARNING, "server responded with %s", lut->name);
 		}
diff --git a/src/knot/nameserver/capture.c b/src/knot/nameserver/capture.c
index 15a1dba9cadff13eb9e46de57ba6818ead9838d0..e3092035f0a00d1196c3e5622ee54120fb996278 100644
--- a/src/knot/nameserver/capture.c
+++ b/src/knot/nameserver/capture.c
@@ -14,6 +14,8 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <assert.h>
+
 #include "knot/nameserver/capture.h"
 #include "knot/server/tcp-handler.h"
 #include "knot/server/udp-handler.h"
diff --git a/src/knot/nameserver/ixfr.c b/src/knot/nameserver/ixfr.c
index e61ce9cdff65a7aa66db74f85fd315b1edbfbd84..626c6cbb6363e21cc342c9915941c3ccf28cab4d 100644
--- a/src/knot/nameserver/ixfr.c
+++ b/src/knot/nameserver/ixfr.c
@@ -26,7 +26,6 @@
 #include "knot/zone/serial.h"
 #include "libknot/libknot.h"
 #include "libknot/descriptor.h"
-#include "libknot/internal/utils.h"
 #include "libknot/rrtype/soa.h"
 #include "contrib/print.h"
 #include "contrib/sockaddr.h"
@@ -696,7 +695,7 @@ int ixfr_process_answer(knot_pkt_t *pkt, struct answer_data *adata)
 	/* Check RCODE. */
 	uint8_t rcode = knot_wire_get_rcode(pkt->wire);
 	if (rcode != KNOT_RCODE_NOERROR) {
-		lookup_table_t *lut = lookup_by_id(knot_rcode_names, rcode);
+		const lookup_table_t *lut = lookup_by_id(knot_rcode_names, rcode);
 		if (lut != NULL) {
 			IXFRIN_LOG(LOG_WARNING, "server responded with %s", lut->name);
 		}
diff --git a/src/knot/nameserver/notify.c b/src/knot/nameserver/notify.c
index 5ff3775dccce606fe9e5e04a79e55f5c5396cec9..ea55347dcdff0d985ee7e3b2ade96ec8d66df132 100644
--- a/src/knot/nameserver/notify.c
+++ b/src/knot/nameserver/notify.c
@@ -119,7 +119,7 @@ int notify_process_answer(knot_pkt_t *pkt, struct answer_data *adata)
 	/* Check RCODE. */
 	uint8_t rcode = knot_wire_get_rcode(pkt->wire);
 	if (rcode != KNOT_RCODE_NOERROR) {
-		lookup_table_t *lut = lookup_by_id(knot_rcode_names, rcode);
+		const lookup_table_t *lut = lookup_by_id(knot_rcode_names, rcode);
 		if (lut != NULL) {
 			NOTIFY_RLOG(LOG_WARNING, "server responded with %s", lut->name);
 		}
diff --git a/src/knot/nameserver/nsec_proofs.c b/src/knot/nameserver/nsec_proofs.c
index ded586b5f873e78ae8e7654739a51ff9007fce86..39e8b441ceabd5162e4cd05799ecbe31ddcc70a6 100644
--- a/src/knot/nameserver/nsec_proofs.c
+++ b/src/knot/nameserver/nsec_proofs.c
@@ -14,6 +14,8 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <assert.h>
+
 #include "libknot/libknot.h"
 #include "knot/nameserver/nsec_proofs.h"
 #include "knot/nameserver/process_query.h"
diff --git a/src/knot/nameserver/process_query.c b/src/knot/nameserver/process_query.c
index 1df4dae13b13f9a9f97ee5a3bb021b7f33c77902..d24aee88eb7f519877b3af4fe05f0cdd2efd81e4 100644
--- a/src/knot/nameserver/process_query.c
+++ b/src/knot/nameserver/process_query.c
@@ -567,8 +567,8 @@ bool process_query_acl_check(const knot_dname_t *zone_name, acl_action_t action,
 	if (!acl_allowed(&acl, action, query_source, &tsig)) {
 		char addr_str[SOCKADDR_STRLEN] = { 0 };
 		sockaddr_tostr(addr_str, sizeof(addr_str), query_source);
-		lookup_table_t *act = lookup_by_id((lookup_table_t *)acl_actions,
-		                                   action);
+		const lookup_table_t *act = lookup_by_id((lookup_table_t *)acl_actions,
+		                                         action);
 		char *key_name = knot_dname_to_str_alloc(tsig.name);
 
 		log_zone_debug(zone_name,
diff --git a/src/knot/nameserver/tsig_ctx.c b/src/knot/nameserver/tsig_ctx.c
index 1429a5a4b54b64cf1970441a084234924fe3f120..60115e6b49bcbf536270471924b40ee44613fb97 100644
--- a/src/knot/nameserver/tsig_ctx.c
+++ b/src/knot/nameserver/tsig_ctx.c
@@ -14,6 +14,7 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <assert.h>
 #include <string.h>
 #include <stdint.h>
 #include <stdlib.h>
diff --git a/src/knot/zone/events/handlers.c b/src/knot/zone/events/handlers.c
index 6066027b43d3827ad8bcc5861ebc435dfb0a8a13..ba3ca9675097b3183593d9d5b5e9b19126794cc1 100644
--- a/src/knot/zone/events/handlers.c
+++ b/src/knot/zone/events/handlers.c
@@ -22,6 +22,7 @@
 #include "libknot/processing/requestor.h"
 #include "libknot/yparser/yptrafo.h"
 #include "contrib/ucw/mempool.h"
+#include "contrib/wire.h"
 
 #include "knot/common/log.h"
 #include "knot/common/trim.h"
diff --git a/src/knot/zone/events/replan.c b/src/knot/zone/events/replan.c
index bc32d8258ac33a5781d53dd21b5d28a8c9227a88..58991401954effcde480a85f7f78048529377475 100644
--- a/src/knot/zone/events/replan.c
+++ b/src/knot/zone/events/replan.c
@@ -14,11 +14,12 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-#include "libknot/rrtype/soa.h"
+#include <assert.h>
 
 #include "knot/zone/events/replan.h"
 #include "knot/zone/events/handlers.h"
 #include "knot/zone/zone.h"
+#include "libknot/rrtype/soa.h"
 #include "libknot/internal/macros.h"
 
 /* -- Zone event replanning functions --------------------------------------- */
diff --git a/src/knot/zone/semantic-check.c b/src/knot/zone/semantic-check.c
index 9aca0434e3e1870acb5b9a0c8e37c81962befe52..68f8f8682c36b111313ee49093680325252e354d 100644
--- a/src/knot/zone/semantic-check.c
+++ b/src/knot/zone/semantic-check.c
@@ -29,6 +29,7 @@
 #include "libknot/dnssec/rrset-sign.h"
 #include "libknot/internal/mempattern.h"
 #include "contrib/base32hex.h"
+#include "contrib/wire.h"
 
 static char *error_messages[(-ZC_ERR_UNKNOWN) + 1] = {
 	[-ZC_ERR_MISSING_SOA] =
diff --git a/src/knot/zone/timers.c b/src/knot/zone/timers.c
index 69b16f94737524499977399f245f4f7afbadbd2f..352da12ccb1b312f1718fb83063cd0f3fe0e9d5b 100644
--- a/src/knot/zone/timers.c
+++ b/src/knot/zone/timers.c
@@ -20,6 +20,7 @@
 #include "knot/zone/timers.h"
 #include "knot/zone/zonedb.h"
 #include "contrib/string.h"
+#include "contrib/wire.h"
 #include "contrib/wire_ctx.h"
 
 /* ---- Knot-internal event code to db key lookup tables ------------------ - */
diff --git a/src/knot/zone/zone-diff.c b/src/knot/zone/zone-diff.c
index 9ae624795c3f7f776e3c2e08eab24e1fd3d1df69..b51adbc13bbc6d7e265bd1e4fc1215f7fa56fdd7 100644
--- a/src/knot/zone/zone-diff.c
+++ b/src/knot/zone/zone-diff.c
@@ -22,7 +22,6 @@
 #include "knot/zone/zone-diff.h"
 #include "knot/zone/serial.h"
 #include "libknot/descriptor.h"
-#include "libknot/internal/utils.h"
 #include "libknot/rrtype/soa.h"
 
 struct zone_diff_param {
diff --git a/src/knot/zone/zone.c b/src/knot/zone/zone.c
index e99814fea6e8d0a457ed8623532cd12a73375648..1a3ee045b5d23af4605b3b0c8ef0985b42eeceb3 100644
--- a/src/knot/zone/zone.c
+++ b/src/knot/zone/zone.c
@@ -37,7 +37,6 @@
 #include "knot/nameserver/process_query.h"
 #include "libknot/libknot.h"
 #include "libknot/dname.h"
-#include "libknot/internal/utils.h"
 #include "contrib/string.h"
 #include "libknot/rrtype/soa.h"
 
diff --git a/src/libknot/codes.c b/src/libknot/codes.c
index ce3dc00f2037ab6ad080175b287a948a7d583650..570617d810143b027cc117c3635c12f6984b6a10 100644
--- a/src/libknot/codes.c
+++ b/src/libknot/codes.c
@@ -15,10 +15,11 @@
 */
 
 #include "libknot/codes.h"
+#include "libknot/consts.h"
+#include "contrib/lookup.h"
 #include "libknot/internal/macros.h"
 
-_public_
-lookup_table_t knot_opcode_names[] = {
+const lookup_table_t opcode_names[] = {
 	{ KNOT_OPCODE_QUERY,  "QUERY" },
 	{ KNOT_OPCODE_IQUERY, "IQUERY" },
 	{ KNOT_OPCODE_STATUS, "STATUS" },
@@ -26,9 +27,10 @@ lookup_table_t knot_opcode_names[] = {
 	{ KNOT_OPCODE_UPDATE, "UPDATE" },
 	{ 0, NULL }
 };
-
 _public_
-lookup_table_t knot_rcode_names[] = {
+const lookup_table_t *knot_opcode_names = opcode_names;
+
+const lookup_table_t rcode_names[] = {
 	{ KNOT_RCODE_NOERROR,  "NOERROR" },
 	{ KNOT_RCODE_FORMERR,  "FORMERR" },
 	{ KNOT_RCODE_SERVFAIL, "SERVFAIL" },
@@ -43,26 +45,29 @@ lookup_table_t knot_rcode_names[] = {
 	{ KNOT_RCODE_BADVERS,  "BADVERS" },
 	{ 0, NULL }
 };
-
 _public_
-lookup_table_t knot_tsig_err_names[] = {
+const lookup_table_t *knot_rcode_names = rcode_names;
+
+const lookup_table_t tsig_err_names[] = {
 	{ KNOT_TSIG_ERR_BADSIG,   "BADSIG" },
 	{ KNOT_TSIG_ERR_BADKEY,   "BADKEY" },
 	{ KNOT_TSIG_ERR_BADTIME,  "BADTIME" },
 	{ KNOT_TSIG_ERR_BADTRUNC, "BADTRUNC" },
 	{ 0, NULL }
 };
-
 _public_
-lookup_table_t knot_tkey_err_names[] = {
+const lookup_table_t *knot_tsig_err_names = tsig_err_names;
+
+const lookup_table_t tkey_err_names[] = {
 	{ KNOT_TKEY_ERR_BADMODE,  "BADMODE" },
 	{ KNOT_TKEY_ERR_BADNAME,  "BADNAME" },
 	{ KNOT_TKEY_ERR_BADALG,   "BADALG" },
 	{ 0, NULL }
 };
-
 _public_
-lookup_table_t knot_dnssec_alg_names[] = {
+const lookup_table_t *knot_tkey_err_names = tkey_err_names;
+
+const lookup_table_t dnssec_alg_names[] = {
 	{ KNOT_DNSSEC_ALG_RSAMD5,             "RSAMD5" },
 	{ KNOT_DNSSEC_ALG_DH,                 "DH" },
 	{ KNOT_DNSSEC_ALG_DSA,                "DSA" },
@@ -76,3 +81,5 @@ lookup_table_t knot_dnssec_alg_names[] = {
 	{ KNOT_DNSSEC_ALG_ECDSAP384SHA384,    "ECDSAP384SHA384" },
 	{ 0, NULL }
 };
+_public_
+const lookup_table_t *knot_dnssec_alg_names = dnssec_alg_names;
diff --git a/src/libknot/codes.h b/src/libknot/codes.h
index e79317759af3596affee345753d4dc9665d42687..7b219090c7b26ea135a9638a2bee93bebffb2654 100644
--- a/src/libknot/codes.h
+++ b/src/libknot/codes.h
@@ -24,35 +24,31 @@
 
 #pragma once
 
-#include <stdbool.h>
-#include <stdint.h>
-
-#include "libknot/consts.h"
-#include "libknot/internal/utils.h"
+struct lookup_table;
 
 /*!
  * \brief DNS operation code names.
  */
-extern lookup_table_t knot_opcode_names[];
+extern const struct lookup_table *knot_opcode_names;
 
 /*!
  * \brief DNS reply code names.
  */
-extern lookup_table_t knot_rcode_names[];
+extern const struct lookup_table *knot_rcode_names;
 
 /*!
  * \brief TSIG error names.
  */
-extern lookup_table_t knot_tsig_err_names[];
+extern const struct lookup_table *knot_tsig_err_names;
 
 /*!
  * \brief TKEY error names.
  */
-extern lookup_table_t knot_tkey_err_names[];
+extern const struct lookup_table *knot_tkey_err_names;
 
 /*!
  * \brief DNSSEC algorithm names.
  */
-extern lookup_table_t knot_dnssec_alg_names[];
+extern const struct lookup_table *knot_dnssec_alg_names;
 
 /*! @} */
diff --git a/src/libknot/dname.c b/src/libknot/dname.c
index 5f890f70c4913bb8ce585a88fd253cfe4c3aa8fe..32d6470d451268b126e8da0bfc343b1d61225c36 100644
--- a/src/libknot/dname.c
+++ b/src/libknot/dname.c
@@ -27,7 +27,6 @@
 #include "libknot/packet/wire.h"
 #include "libknot/internal/macros.h"
 #include "libknot/internal/mempattern.h"
-#include "libknot/internal/utils.h"
 #include "contrib/tolower.h"
 
 /*----------------------------------------------------------------------------*/
diff --git a/src/libknot/internal/utils.c b/src/libknot/internal/utils.c
deleted file mode 100644
index 5716517619945b0969104cddf4faee67c52bbd6a..0000000000000000000000000000000000000000
--- a/src/libknot/internal/utils.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*  Copyright (C) 2011 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
-
-    This program is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <string.h>
-#include <pthread.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#include "contrib/endian.h"
-#include "libknot/internal/utils.h"
-#include "libknot/internal/macros.h"
-
-/*----------------------------------------------------------------------------*/
-lookup_table_t *lookup_by_name(lookup_table_t *table, const char *name)
-{
-	if (table == NULL || name == NULL) {
-		return NULL;
-	}
-
-	while (table->name != NULL) {
-		if (strcasecmp(name, table->name) == 0) {
-			return table;
-		}
-		table++;
-	}
-
-	return NULL;
-}
-
-/*----------------------------------------------------------------------------*/
-lookup_table_t *lookup_by_id(lookup_table_t *table, int id)
-{
-	if (table == NULL) {
-		return NULL;
-	}
-
-	while (table->name != NULL) {
-		if (table->id == id) {
-			return table;
-		}
-		table++;
-	}
-
-	return NULL;
-}
-
-/*----------------------------------------------------------------------------*/
-
-uint16_t wire_read_u16(const uint8_t *pos)
-{
-	return be16toh(*(uint16_t *)pos);
-}
-
-uint32_t wire_read_u32(const uint8_t *pos)
-{
-	return be32toh(*(uint32_t *)pos);
-}
-
-uint64_t wire_read_u48(const uint8_t *pos)
-{
-	uint64_t input = 0;
-	memcpy((uint8_t *)&input + 1, pos, 6);
-	return be64toh(input) >> 8;
-}
-
-uint64_t wire_read_u64(const uint8_t *pos)
-{
-	return be64toh(*(uint64_t *)pos);
-}
-
-void wire_write_u16(uint8_t *pos, uint16_t data)
-{
-	*(uint16_t *)pos = htobe16(data);
-}
-
-void wire_write_u32(uint8_t *pos, uint32_t data)
-{
-	*(uint32_t *)pos = htobe32(data);
-}
-
-void wire_write_u48(uint8_t *pos, uint64_t data)
-{
-	uint64_t swapped = htobe64(data << 8);
-	memcpy(pos, (uint8_t *)&swapped + 1, 6);
-}
-
-void wire_write_u64(uint8_t *pos, uint64_t data)
-{
-	*(uint64_t *)pos = htobe64(data);
-}
diff --git a/src/libknot/packet/pkt.c b/src/libknot/packet/pkt.c
index b21bf8a8f1dba7fd5cce9f98e4250a89a454d262..7399e583dee22f9138342932d66e56a94dab256b 100644
--- a/src/libknot/packet/pkt.c
+++ b/src/libknot/packet/pkt.c
@@ -26,6 +26,7 @@
 #include "libknot/packet/wire.h"
 #include "libknot/packet/rrset-wire.h"
 #include "libknot/internal/macros.h"
+#include "contrib/wire.h"
 #include "contrib/wire_ctx.h"
 
 /*! \brief Packet RR array growth step. */
diff --git a/src/libknot/packet/rrset-wire.c b/src/libknot/packet/rrset-wire.c
index 4d2b93eced5e06850816a2367202d4103d758442..b1e62de01b3f6bf37a13154c789189590d6378c7 100644
--- a/src/libknot/packet/rrset-wire.c
+++ b/src/libknot/packet/rrset-wire.c
@@ -30,6 +30,7 @@
 #include "libknot/rrset.h"
 #include "libknot/rrtype/naptr.h"
 #include "libknot/internal/macros.h"
+#include "contrib/wire.h"
 #include "contrib/wire_ctx.h"
 
 #define RR_HEADER_SIZE 10
diff --git a/src/libknot/packet/wire.c b/src/libknot/packet/wire.c
new file mode 100644
index 0000000000000000000000000000000000000000..b949671ebbaddd2bfa4ed074ca6be46f63609145
--- /dev/null
+++ b/src/libknot/packet/wire.c
@@ -0,0 +1,126 @@
+/*  Copyright (C) 2011 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+
+#include "libknot/internal/macros.h"
+#include "libknot/packet/wire.h"
+#include "contrib/wire.h"
+
+_public_
+uint16_t knot_wire_get_id(const uint8_t *packet)
+{
+	return wire_read_u16(packet + KNOT_WIRE_OFFSET_ID);
+}
+
+_public_
+void knot_wire_set_id(uint8_t *packet, uint16_t id)
+{
+	wire_write_u16(packet + KNOT_WIRE_OFFSET_ID, id);
+}
+
+_public_
+uint16_t knot_wire_get_qdcount(const uint8_t *packet)
+{
+	return wire_read_u16(packet + KNOT_WIRE_OFFSET_QDCOUNT);
+}
+
+_public_
+void knot_wire_set_qdcount(uint8_t *packet, uint16_t qdcount)
+{
+	wire_write_u16(packet + KNOT_WIRE_OFFSET_QDCOUNT, qdcount);
+}
+
+_public_
+void knot_wire_add_qdcount(uint8_t *packet, int16_t n)
+{
+	wire_write_u16(packet + KNOT_WIRE_OFFSET_QDCOUNT,
+	                    knot_wire_get_qdcount(packet) + n);
+}
+
+_public_
+uint16_t knot_wire_get_ancount(const uint8_t *packet)
+{
+	return wire_read_u16(packet + KNOT_WIRE_OFFSET_ANCOUNT);
+}
+
+_public_
+void knot_wire_set_ancount(uint8_t *packet, uint16_t ancount)
+{
+	wire_write_u16(packet + KNOT_WIRE_OFFSET_ANCOUNT, ancount);
+}
+
+_public_
+void knot_wire_add_ancount(uint8_t *packet, int16_t n)
+{
+	wire_write_u16(packet + KNOT_WIRE_OFFSET_ANCOUNT,
+	                    knot_wire_get_ancount(packet) + n);
+}
+
+_public_
+uint16_t knot_wire_get_nscount(const uint8_t *packet)
+{
+	return wire_read_u16(packet + KNOT_WIRE_OFFSET_NSCOUNT);
+}
+
+_public_
+void knot_wire_set_nscount(uint8_t *packet, uint16_t nscount)
+{
+	wire_write_u16(packet + KNOT_WIRE_OFFSET_NSCOUNT, nscount);
+}
+
+_public_
+void knot_wire_add_nscount(uint8_t *packet, int16_t n)
+{
+	wire_write_u16(packet + KNOT_WIRE_OFFSET_NSCOUNT,
+	                    knot_wire_get_nscount(packet) + n);
+}
+
+_public_
+uint16_t knot_wire_get_arcount(const uint8_t *packet)
+{
+	return wire_read_u16(packet + KNOT_WIRE_OFFSET_ARCOUNT);
+}
+
+_public_
+void knot_wire_set_arcount(uint8_t *packet, uint16_t arcount)
+{
+	wire_write_u16(packet + KNOT_WIRE_OFFSET_ARCOUNT, arcount);
+}
+
+_public_
+void knot_wire_add_arcount(uint8_t *packet, int16_t n)
+{
+	wire_write_u16(packet + KNOT_WIRE_OFFSET_ARCOUNT,
+	                    knot_wire_get_arcount(packet) + n);
+}
+
+_public_
+void knot_wire_put_pointer(uint8_t *pos, uint16_t ptr)
+{
+	wire_write_u16(pos, ptr);		// Write pointer offset.
+	assert((pos[0] & KNOT_WIRE_PTR) == 0);	// Check for maximal offset.
+	pos[0] |= KNOT_WIRE_PTR;		// Add pointer mark.
+}
+
+_public_
+uint16_t knot_wire_get_pointer(const uint8_t *pos)
+{
+	assert((pos[0] & KNOT_WIRE_PTR) == KNOT_WIRE_PTR);	// Check pointer.
+	return (wire_read_u16(pos) - KNOT_WIRE_PTR_BASE);	// Return offset.
+}
+
+/*! @} */
diff --git a/src/libknot/packet/wire.h b/src/libknot/packet/wire.h
index 37f814c26943cb1ddb0e46c377295bb012b0faa1..dac6599989015de7467da03b7a5d1dcde30c6091 100644
--- a/src/libknot/packet/wire.h
+++ b/src/libknot/packet/wire.h
@@ -1,13 +1,3 @@
-/*!
- * \file wire.h
- *
- * \author Lubos Slovak <lubos.slovak@nic.cz>
- *
- * \brief Functions for manipulating and parsing raw data in DNS packets.
- *
- * \addtogroup libknot
- * @{
- */
 /*  Copyright (C) 2011 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
 
     This program is free software: you can redistribute it and/or modify
@@ -23,13 +13,19 @@
     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
+ *
+ * \brief Functions for manipulating and parsing raw data in DNS packets.
+ *
+ * \addtogroup libknot
+ * @{
+ */
 
 #pragma once
 
 #include <stdint.h>
-#include <assert.h>
-
-#include "libknot/internal/utils.h"
+#include <stdlib.h>
 
 /*! \brief Offset of DNS header fields in wireformat. */
 enum knot_wire_offsets {
@@ -65,10 +61,7 @@ enum knot_wire_sizes {
  *
  * \return DNS packet ID.
  */
-static inline uint16_t knot_wire_get_id(const uint8_t *packet)
-{
-	return wire_read_u16(packet + KNOT_WIRE_OFFSET_ID);
-}
+uint16_t knot_wire_get_id(const uint8_t *packet);
 
 /*!
  * \brief Sets the ID to the wire format of the packet.
@@ -76,10 +69,7 @@ static inline uint16_t knot_wire_get_id(const uint8_t *packet)
  * \param packet Wire format of the packet.
  * \param id DNS packet ID.
  */
-static inline void knot_wire_set_id(uint8_t *packet, uint16_t id)
-{
-	wire_write_u16(packet + KNOT_WIRE_OFFSET_ID, id);
-}
+void knot_wire_set_id(uint8_t *packet, uint16_t id);
 
 /*!
  * \brief Returns the first byte of flags from wire format of the packet.
@@ -135,10 +125,7 @@ static inline uint8_t knot_wire_set_flags2(uint8_t *packet, uint8_t flags2)
  *
  * \return QDCOUNT (count of Question entries in the packet).
  */
-static inline uint16_t knot_wire_get_qdcount(const uint8_t *packet)
-{
-	return wire_read_u16(packet + KNOT_WIRE_OFFSET_QDCOUNT);
-}
+uint16_t knot_wire_get_qdcount(const uint8_t *packet);
 
 /*!
  * \brief Sets the QDCOUNT (count of Question entries) to wire format of the
@@ -147,19 +134,12 @@ static inline uint16_t knot_wire_get_qdcount(const uint8_t *packet)
  * \param packet Wire format of the packet.
  * \param qdcount QDCOUNT (count of Question entries in the packet).
  */
-static inline void knot_wire_set_qdcount(uint8_t *packet, uint16_t qdcount)
-{
-	wire_write_u16(packet + KNOT_WIRE_OFFSET_QDCOUNT, qdcount);
-}
+void knot_wire_set_qdcount(uint8_t *packet, uint16_t qdcount);
 
 /*!
  * \brief Adds to QDCOUNT.
  */
-static inline void knot_wire_add_qdcount(uint8_t *packet, int16_t n)
-{
-	wire_write_u16(packet + KNOT_WIRE_OFFSET_QDCOUNT,
-	                    knot_wire_get_qdcount(packet) + n);
-}
+void knot_wire_add_qdcount(uint8_t *packet, int16_t n);
 
 /*!
  * \brief Returns the ANCOUNT (count of Answer entries) from wire format of
@@ -169,10 +149,7 @@ static inline void knot_wire_add_qdcount(uint8_t *packet, int16_t n)
  *
  * \return ANCOUNT (count of Answer entries in the packet).
  */
-static inline uint16_t knot_wire_get_ancount(const uint8_t *packet)
-{
-	return wire_read_u16(packet + KNOT_WIRE_OFFSET_ANCOUNT);
-}
+uint16_t knot_wire_get_ancount(const uint8_t *packet);
 
 /*!
  * \brief Sets the ANCOUNT (count of Answer entries) to wire format of the
@@ -181,19 +158,12 @@ static inline uint16_t knot_wire_get_ancount(const uint8_t *packet)
  * \param packet Wire format of the packet.
  * \param ancount ANCOUNT (count of Answer entries in the packet).
  */
-static inline void knot_wire_set_ancount(uint8_t *packet, uint16_t ancount)
-{
-	wire_write_u16(packet + KNOT_WIRE_OFFSET_ANCOUNT, ancount);
-}
+void knot_wire_set_ancount(uint8_t *packet, uint16_t ancount);
 
 /*!
  * \brief Adds to ANCOUNT.
  */
-static inline void knot_wire_add_ancount(uint8_t *packet, int16_t n)
-{
-	wire_write_u16(packet + KNOT_WIRE_OFFSET_ANCOUNT,
-	                    knot_wire_get_ancount(packet) + n);
-}
+void knot_wire_add_ancount(uint8_t *packet, int16_t n);
 
 /*!
  * \brief Returns the NSCOUNT (count of Authority entries) from wire format of
@@ -203,10 +173,7 @@ static inline void knot_wire_add_ancount(uint8_t *packet, int16_t n)
  *
  * \return NSCOUNT (count of Authority entries in the packet).
  */
-static inline uint16_t knot_wire_get_nscount(const uint8_t *packet)
-{
-	return wire_read_u16(packet + KNOT_WIRE_OFFSET_NSCOUNT);
-}
+uint16_t knot_wire_get_nscount(const uint8_t *packet);
 
 /*!
  * \brief Sets the NSCOUNT (count of Authority entries) to wire format of the
@@ -215,19 +182,12 @@ static inline uint16_t knot_wire_get_nscount(const uint8_t *packet)
  * \param packet Wire format of the packet.
  * \param nscount NSCOUNT (count of Authority entries in the packet).
  */
-static inline void knot_wire_set_nscount(uint8_t *packet, uint16_t nscount)
-{
-	wire_write_u16(packet + KNOT_WIRE_OFFSET_NSCOUNT, nscount);
-}
+void knot_wire_set_nscount(uint8_t *packet, uint16_t nscount);
 
 /*!
  * \brief Adds to NSCOUNT.
  */
-static inline void knot_wire_add_nscount(uint8_t *packet, int16_t n)
-{
-	wire_write_u16(packet + KNOT_WIRE_OFFSET_NSCOUNT,
-	                    knot_wire_get_nscount(packet) + n);
-}
+void knot_wire_add_nscount(uint8_t *packet, int16_t n);
 
 /*!
  * \brief Returns the ARCOUNT (count of Additional entries) from wire format of
@@ -237,10 +197,7 @@ static inline void knot_wire_add_nscount(uint8_t *packet, int16_t n)
  *
  * \return ARCOUNT (count of Additional entries in the packet).
  */
-static inline uint16_t knot_wire_get_arcount(const uint8_t *packet)
-{
-	return wire_read_u16(packet + KNOT_WIRE_OFFSET_ARCOUNT);
-}
+uint16_t knot_wire_get_arcount(const uint8_t *packet);
 
 /*!
  * \brief Sets the ARCOUNT (count of Additional entries) to wire format of the
@@ -249,19 +206,12 @@ static inline uint16_t knot_wire_get_arcount(const uint8_t *packet)
  * \param packet Wire format of the packet.
  * \param arcount ARCOUNT (count of Additional entries in the packet).
  */
-static inline void knot_wire_set_arcount(uint8_t *packet, uint16_t arcount)
-{
-	wire_write_u16(packet + KNOT_WIRE_OFFSET_ARCOUNT, arcount);
-}
+void knot_wire_set_arcount(uint8_t *packet, uint16_t arcount);
 
 /*!
  * \brief Adds to ARCOUNT.
  */
-static inline void knot_wire_add_arcount(uint8_t *packet, int16_t n)
-{
-	wire_write_u16(packet + KNOT_WIRE_OFFSET_ARCOUNT,
-	                    knot_wire_get_arcount(packet) + n);
-}
+void knot_wire_add_arcount(uint8_t *packet, int16_t n);
 
 /*
  * Packet header flags manipulation functions.
@@ -941,24 +891,15 @@ enum knot_wire_pointer_consts {
  * \param ptr Relative position of the item to which the pointer should point in
  *            the wire format of the packet.
  */
-static inline void knot_wire_put_pointer(uint8_t *pos, uint16_t ptr)
-{
-	wire_write_u16(pos, ptr);		// Write pointer offset.
-	assert((pos[0] & KNOT_WIRE_PTR) == 0);	// Check for maximal offset.
-	pos[0] |= KNOT_WIRE_PTR;		// Add pointer mark.
-}
+void knot_wire_put_pointer(uint8_t *pos, uint16_t ptr);
+
+uint16_t knot_wire_get_pointer(const uint8_t *pos);
 
 static inline int knot_wire_is_pointer(const uint8_t *pos)
 {
 	return ((pos[0] & KNOT_WIRE_PTR) == KNOT_WIRE_PTR);
 }
 
-static inline uint16_t knot_wire_get_pointer(const uint8_t *pos)
-{
-	assert((pos[0] & KNOT_WIRE_PTR) == KNOT_WIRE_PTR);	// Check pointer.
-	return (wire_read_u16(pos) - KNOT_WIRE_PTR_BASE);	// Return offset.
-}
-
 static inline const uint8_t *knot_wire_seek_label(const uint8_t *lp, const uint8_t *wire)
 {
 	while (knot_wire_is_pointer(lp)) {
diff --git a/src/libknot/rrset-dump.c b/src/libknot/rrset-dump.c
index 3f14ddab1289df4fecfffef35e0fc5aad0cfb1a6..638dc96153e028bd39770d33d9258d895200e9fa 100644
--- a/src/libknot/rrset-dump.c
+++ b/src/libknot/rrset-dump.c
@@ -29,12 +29,14 @@
 #include "dnssec/keytag.h"
 #include "libknot/rrset-dump.h"
 #include "libknot/codes.h"
+#include "libknot/consts.h"
 #include "libknot/descriptor.h"
 #include "libknot/errcode.h"
 #include "libknot/internal/macros.h"
-#include "libknot/internal/utils.h"
 #include "contrib/base32hex.h"
 #include "contrib/base64.h"
+#include "contrib/lookup.h"
+#include "contrib/wire.h"
 #include "contrib/wire_ctx.h"
 
 #define TAB_WIDTH		8
@@ -1188,9 +1190,10 @@ static void wire_tsig_rcode_to_str(rrset_dump_params_t *p)
 	data = wire_read_u16(p->in);
 
 	// Find RCODE name.
-	lookup_table_t *rcode = lookup_by_id((data >= knot_tsig_err_names->id) ?
-	                                     knot_tsig_err_names : knot_rcode_names,
-	                                     data);
+	const lookup_table_t *rcode = NULL;
+	rcode = lookup_by_id((data >= knot_tsig_err_names->id) ?
+	                     knot_tsig_err_names : knot_rcode_names,
+	                     data);
 	if (rcode != NULL) {
 		rcode_str = rcode->name;
 	}
@@ -1310,7 +1313,7 @@ static void dnskey_info(const uint8_t *rdata,
 	                                    .size = rdata_len };
 	dnssec_keytag(&rdata_bin, &key_tag);
 
-	lookup_table_t *alg = NULL;
+	const lookup_table_t *alg = NULL;
 	alg = lookup_by_id(knot_dnssec_alg_names, alg_id);
 
 	int ret = snprintf(out, out_len, "%s, %s (%zub), id = %u",
diff --git a/src/libknot/rrtype/dnskey.c b/src/libknot/rrtype/dnskey.c
new file mode 100644
index 0000000000000000000000000000000000000000..01311b11e557f8f5579de6078aeb9128e6bcbf4f
--- /dev/null
+++ b/src/libknot/rrtype/dnskey.c
@@ -0,0 +1,26 @@
+/*  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/rrtype/dnskey.h"
+#include "libknot/internal/macros.h"
+#include "contrib/wire.h"
+
+_public_
+uint16_t knot_dnskey_flags(const knot_rdataset_t *rrs, size_t pos)
+{
+	KNOT_RDATASET_CHECK(rrs, pos, return 0);
+	return wire_read_u16(knot_rdata_offset(rrs, pos, 0));
+}
diff --git a/src/libknot/rrtype/dnskey.h b/src/libknot/rrtype/dnskey.h
index 5abee54479ff21ec5c54b9e2f4865df42130f28e..7a919e28c53abc8d03cdc298df9a734dcc859141 100644
--- a/src/libknot/rrtype/dnskey.h
+++ b/src/libknot/rrtype/dnskey.h
@@ -20,12 +20,7 @@
 
 #define KNOT_RDATA_DNSKEY_FLAG_KSK 1
 
-static inline
-uint16_t knot_dnskey_flags(const knot_rdataset_t *rrs, size_t pos)
-{
-	KNOT_RDATASET_CHECK(rrs, pos, return 0);
-	return wire_read_u16(knot_rdata_offset(rrs, pos, 0));
-}
+uint16_t knot_dnskey_flags(const knot_rdataset_t *rrs, size_t pos);
 
 static inline
 uint8_t knot_dnskey_proto(const knot_rdataset_t *rrs, size_t pos)
diff --git a/src/libknot/rrtype/nsec3.c b/src/libknot/rrtype/nsec3.c
index 6eb01731edfad8864b0d25f845b42878efe43245..71d2410cfa218f745d9aa14303fa4bbcd8b77649 100644
--- a/src/libknot/rrtype/nsec3.c
+++ b/src/libknot/rrtype/nsec3.c
@@ -17,9 +17,15 @@
 #include <assert.h>
 
 #include "libknot/rrtype/nsec3.h"
-#include "libknot/errcode.h"
 #include "libknot/internal/macros.h"
-#include "contrib/tolower.h"
+#include "contrib/wire.h"
+
+_public_
+uint16_t knot_nsec3_iterations(const knot_rdataset_t *rrs, size_t pos)
+{
+	KNOT_RDATASET_CHECK(rrs, pos, return 0);
+	return wire_read_u16(knot_rdata_offset(rrs, pos, 2));
+}
 
 _public_
 void knot_nsec3_bitmap(const knot_rdataset_t *rrs, size_t pos,
diff --git a/src/libknot/rrtype/nsec3.h b/src/libknot/rrtype/nsec3.h
index 52c95638ee012488b1ad7e59aef5029c15f44b0e..6e175ec66f814cd39c585730f22dca31016a9923 100644
--- a/src/libknot/rrtype/nsec3.h
+++ b/src/libknot/rrtype/nsec3.h
@@ -49,12 +49,7 @@ uint8_t knot_nsec3_flags(const knot_rdataset_t *rrs, size_t pos)
 	return *knot_rdata_offset(rrs, pos, 1);
 }
 
-static inline
-uint16_t knot_nsec3_iterations(const knot_rdataset_t *rrs, size_t pos)
-{
-	KNOT_RDATASET_CHECK(rrs, pos, return 0);
-	return wire_read_u16(knot_rdata_offset(rrs, pos, 2));
-}
+uint16_t knot_nsec3_iterations(const knot_rdataset_t *rrs, size_t pos);
 
 static inline
 uint8_t knot_nsec3_salt_length(const knot_rdataset_t *rrs, size_t pos)
diff --git a/src/libknot/rrtype/nsec3param.c b/src/libknot/rrtype/nsec3param.c
index 69f9fb67e1cbe63e21a4fb6eb8a3b0d3923034e8..2062f0a9d4eab2213e26cf417f94a66c0f6696d4 100644
--- a/src/libknot/rrtype/nsec3param.c
+++ b/src/libknot/rrtype/nsec3param.c
@@ -18,6 +18,14 @@
 #include "libknot/errcode.h"
 #include "libknot/internal/macros.h"
 #include "contrib/string.h"
+#include "contrib/wire.h"
+
+_public_
+uint16_t knot_nsec3param_iterations(const knot_rdataset_t *rrs, size_t pos)
+{
+	KNOT_RDATASET_CHECK(rrs, pos, return 0);
+	return wire_read_u16(knot_rdata_offset(rrs, pos, 2));
+}
 
 _public_
 int knot_nsec3param_from_wire(knot_nsec3_params_t *params,
diff --git a/src/libknot/rrtype/nsec3param.h b/src/libknot/rrtype/nsec3param.h
index 133013a101e81856f5954ff8738f1028308c2d76..f933fb2db6603d076850f445566db2b5fb102370 100644
--- a/src/libknot/rrtype/nsec3param.h
+++ b/src/libknot/rrtype/nsec3param.h
@@ -16,13 +16,9 @@
 
 #pragma once
 
-#include <stdbool.h>
 #include <stdint.h>
-#include <string.h>
 
-#include "libknot/consts.h"
 #include "libknot/rdataset.h"
-#include "libknot/internal/utils.h"
 
 /*!
  * \brief Structure representing the NSEC3PARAM resource record.
@@ -51,12 +47,7 @@ uint8_t knot_nsec3param_flags(const knot_rdataset_t *rrs, size_t pos)
 	return *knot_rdata_offset(rrs, pos, 1);
 }
 
-static inline
-uint16_t knot_nsec3param_iterations(const knot_rdataset_t *rrs, size_t pos)
-{
-	KNOT_RDATASET_CHECK(rrs, pos, return 0);
-	return wire_read_u16(knot_rdata_offset(rrs, pos, 2));
-}
+uint16_t knot_nsec3param_iterations(const knot_rdataset_t *rrs, size_t pos);
 
 static inline
 uint8_t knot_nsec3param_salt_length(const knot_rdataset_t *rrs, size_t pos)
diff --git a/src/libknot/rrtype/rrsig.c b/src/libknot/rrtype/rrsig.c
new file mode 100644
index 0000000000000000000000000000000000000000..52bf695d061816d0b91d64083a68d5e49d417b3e
--- /dev/null
+++ b/src/libknot/rrtype/rrsig.c
@@ -0,0 +1,54 @@
+/*  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/rrtype/rrsig.h"
+#include "libknot/internal/macros.h"
+#include "contrib/wire.h"
+
+_public_
+uint16_t knot_rrsig_type_covered(const knot_rdataset_t *rrs, size_t pos)
+{
+	KNOT_RDATASET_CHECK(rrs, pos, return 0);
+	return wire_read_u16(knot_rdata_offset(rrs, pos, 0));
+}
+
+_public_
+uint32_t knot_rrsig_original_ttl(const knot_rdataset_t *rrs, size_t pos)
+{
+	KNOT_RDATASET_CHECK(rrs, pos, return 0);
+	return wire_read_u32(knot_rdata_offset(rrs, pos, 4));
+}
+
+_public_
+uint32_t knot_rrsig_sig_expiration(const knot_rdataset_t *rrs, size_t pos)
+{
+	KNOT_RDATASET_CHECK(rrs, pos, return 0);
+	return wire_read_u32(knot_rdata_offset(rrs, pos, 8));
+}
+
+_public_
+uint32_t knot_rrsig_sig_inception(const knot_rdataset_t *rrs, size_t pos)
+{
+	KNOT_RDATASET_CHECK(rrs, pos, return 0);
+	return wire_read_u32(knot_rdata_offset(rrs, pos, 12));
+}
+
+_public_
+uint16_t knot_rrsig_key_tag(const knot_rdataset_t *rrs, size_t pos)
+{
+	KNOT_RDATASET_CHECK(rrs, pos, return 0);
+	return wire_read_u16(knot_rdata_offset(rrs, pos, 16));
+}
diff --git a/src/libknot/rrtype/rrsig.h b/src/libknot/rrtype/rrsig.h
index ec1b7c6e8341f4633cd9d85e704bda122541ff43..cd2cb154391b2181807873ce49e2672980072a1d 100644
--- a/src/libknot/rrtype/rrsig.h
+++ b/src/libknot/rrtype/rrsig.h
@@ -16,14 +16,10 @@
 
 #pragma once
 
+#include "libknot/dname.h"
 #include "libknot/rdataset.h"
 
-static inline
-uint16_t knot_rrsig_type_covered(const knot_rdataset_t *rrs, size_t pos)
-{
-	KNOT_RDATASET_CHECK(rrs, pos, return 0);
-	return wire_read_u16(knot_rdata_offset(rrs, pos, 0));
-}
+uint16_t knot_rrsig_type_covered(const knot_rdataset_t *rrs, size_t pos);
 
 static inline
 uint8_t knot_rrsig_algorithm(const knot_rdataset_t *rrs, size_t pos)
@@ -39,33 +35,13 @@ uint8_t knot_rrsig_labels(const knot_rdataset_t *rrs, size_t pos)
 	return *knot_rdata_offset(rrs, pos, 3);
 }
 
-static inline
-uint32_t knot_rrsig_original_ttl(const knot_rdataset_t *rrs, size_t pos)
-{
-	KNOT_RDATASET_CHECK(rrs, pos, return 0);
-	return wire_read_u32(knot_rdata_offset(rrs, pos, 4));
-}
+uint32_t knot_rrsig_original_ttl(const knot_rdataset_t *rrs, size_t pos);
 
-static inline
-uint32_t knot_rrsig_sig_expiration(const knot_rdataset_t *rrs, size_t pos)
-{
-	KNOT_RDATASET_CHECK(rrs, pos, return 0);
-	return wire_read_u32(knot_rdata_offset(rrs, pos, 8));
-}
+uint32_t knot_rrsig_sig_expiration(const knot_rdataset_t *rrs, size_t pos);
 
-static inline
-uint32_t knot_rrsig_sig_inception(const knot_rdataset_t *rrs, size_t pos)
-{
-	KNOT_RDATASET_CHECK(rrs, pos, return 0);
-	return wire_read_u32(knot_rdata_offset(rrs, pos, 12));
-}
+uint32_t knot_rrsig_sig_inception(const knot_rdataset_t *rrs, size_t pos);
 
-static inline
-uint16_t knot_rrsig_key_tag(const knot_rdataset_t *rrs, size_t pos)
-{
-	KNOT_RDATASET_CHECK(rrs, pos, return 0);
-	return wire_read_u16(knot_rdata_offset(rrs, pos, 16));
-}
+uint16_t knot_rrsig_key_tag(const knot_rdataset_t *rrs, size_t pos);
 
 static inline
 const knot_dname_t *knot_rrsig_signer_name(const knot_rdataset_t *rrs,
diff --git a/src/libknot/rrtype/soa.c b/src/libknot/rrtype/soa.c
new file mode 100644
index 0000000000000000000000000000000000000000..1e3ef5246ba600cf163c9a89062efb1d23e48e0c
--- /dev/null
+++ b/src/libknot/rrtype/soa.c
@@ -0,0 +1,68 @@
+/*  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/rrtype/soa.h"
+#include "libknot/internal/macros.h"
+#include "contrib/wire.h"
+
+_public_
+uint32_t knot_soa_serial(const knot_rdataset_t *rrs)
+{
+	KNOT_RDATASET_CHECK(rrs, 0, return 0);
+	return wire_read_u32(knot_rdata_offset(rrs, 0,
+	                                       knot_soa_names_len(rrs)));
+}
+
+_public_
+void knot_soa_serial_set(knot_rdataset_t *rrs, uint32_t serial)
+{
+	KNOT_RDATASET_CHECK(rrs, 0, return);
+	// the number is in network byte order, transform it
+	wire_write_u32(knot_rdata_offset(rrs, 0, knot_soa_names_len(rrs)),
+	               serial);
+}
+
+_public_
+uint32_t knot_soa_refresh(const knot_rdataset_t *rrs)
+{
+	KNOT_RDATASET_CHECK(rrs, 0, return 0);
+	return wire_read_u32(knot_rdata_offset(rrs, 0,
+	                                       knot_soa_names_len(rrs) + 4));
+}
+
+_public_
+uint32_t knot_soa_retry(const knot_rdataset_t *rrs)
+{
+	KNOT_RDATASET_CHECK(rrs, 0, return 0);
+	return wire_read_u32(knot_rdata_offset(rrs, 0,
+	                                       knot_soa_names_len(rrs) + 8));
+}
+
+_public_
+uint32_t knot_soa_expire(const knot_rdataset_t *rrs)
+{
+	KNOT_RDATASET_CHECK(rrs, 0, return 0);
+	return wire_read_u32(knot_rdata_offset(rrs, 0,
+	                                       knot_soa_names_len(rrs) + 12));
+}
+
+_public_
+uint32_t knot_soa_minimum(const knot_rdataset_t *rrs)
+{
+	KNOT_RDATASET_CHECK(rrs, 0, return 0);
+	return wire_read_u32(knot_rdata_offset(rrs, 0,
+	                                       knot_soa_names_len(rrs) + 16));
+}
diff --git a/src/libknot/rrtype/soa.h b/src/libknot/rrtype/soa.h
index 6f99aa9f6dc06f5c42cd503d403c47f653e36c3b..caf4870b93cc242cab283b0d74b1d8eef36f4217 100644
--- a/src/libknot/rrtype/soa.h
+++ b/src/libknot/rrtype/soa.h
@@ -18,7 +18,6 @@
 
 #include "libknot/rdataset.h"
 #include "libknot/dname.h"
-#include "libknot/internal/utils.h"
 
 static inline
 const knot_dname_t *knot_soa_primary_ns(const knot_rdataset_t *rrs)
@@ -42,51 +41,14 @@ size_t knot_soa_names_len(const knot_rdataset_t *rrs)
 	       + knot_dname_size(knot_soa_mailbox(rrs));
 }
 
-static inline
-uint32_t knot_soa_serial(const knot_rdataset_t *rrs)
-{
-	KNOT_RDATASET_CHECK(rrs, 0, return 0);
-	return wire_read_u32(knot_rdata_offset(rrs, 0,
-	                                       knot_soa_names_len(rrs)));
-}
+uint32_t knot_soa_serial(const knot_rdataset_t *rrs);
 
-static inline
-void knot_soa_serial_set(knot_rdataset_t *rrs, uint32_t serial)
-{
-	KNOT_RDATASET_CHECK(rrs, 0, return);
-	// the number is in network byte order, transform it
-	wire_write_u32(knot_rdata_offset(rrs, 0, knot_soa_names_len(rrs)),
-	               serial);
-}
+void knot_soa_serial_set(knot_rdataset_t *rrs, uint32_t serial);
 
-static inline
-uint32_t knot_soa_refresh(const knot_rdataset_t *rrs)
-{
-	KNOT_RDATASET_CHECK(rrs, 0, return 0);
-	return wire_read_u32(knot_rdata_offset(rrs, 0,
-	                                       knot_soa_names_len(rrs) + 4));
-}
+uint32_t knot_soa_refresh(const knot_rdataset_t *rrs);
 
-static inline
-uint32_t knot_soa_retry(const knot_rdataset_t *rrs)
-{
-	KNOT_RDATASET_CHECK(rrs, 0, return 0);
-	return wire_read_u32(knot_rdata_offset(rrs, 0,
-	                                       knot_soa_names_len(rrs) + 8));
-}
+uint32_t knot_soa_retry(const knot_rdataset_t *rrs);
 
-static inline
-uint32_t knot_soa_expire(const knot_rdataset_t *rrs)
-{
-	KNOT_RDATASET_CHECK(rrs, 0, return 0);
-	return wire_read_u32(knot_rdata_offset(rrs, 0,
-	                                       knot_soa_names_len(rrs) + 12));
-}
+uint32_t knot_soa_expire(const knot_rdataset_t *rrs);
 
-static inline
-uint32_t knot_soa_minimum(const knot_rdataset_t *rrs)
-{
-	KNOT_RDATASET_CHECK(rrs, 0, return 0);
-	return wire_read_u32(knot_rdata_offset(rrs, 0,
-	                                       knot_soa_names_len(rrs) + 16));
-}
+uint32_t knot_soa_minimum(const knot_rdataset_t *rrs);
diff --git a/src/libknot/rrtype/tsig.c b/src/libknot/rrtype/tsig.c
index f926105f96616c0702e3a5a1872edd4fc82f4d82..cdcd66114e9d6a3e9b69ec532b84d98ef0cce46b 100644
--- a/src/libknot/rrtype/tsig.c
+++ b/src/libknot/rrtype/tsig.c
@@ -28,7 +28,7 @@
 #include "libknot/errcode.h"
 #include "libknot/rrset.h"
 #include "libknot/internal/macros.h"
-#include "libknot/internal/utils.h"
+#include "contrib/wire.h"
 #include "contrib/wire_ctx.h"
 
 /*! \brief TSIG field offsets. */
diff --git a/src/libknot/tsig-op.c b/src/libknot/tsig-op.c
index b56239558498ff6885ba72955a93bc878bd1e33f..9db4252d1c06bef5bb3f497f540a70cb09784049 100644
--- a/src/libknot/tsig-op.c
+++ b/src/libknot/tsig-op.c
@@ -33,6 +33,7 @@
 #include "libknot/tsig-op.h"
 #include "libknot/packet/rrset-wire.h"
 #include "libknot/internal/macros.h"
+#include "contrib/wire.h"
 
 const int KNOT_TSIG_MAX_DIGEST_SIZE = 64;    // size of HMAC-SHA512 digest
 const uint16_t KNOT_TSIG_FUDGE_DEFAULT = 300;  // default Fudge value
diff --git a/src/libknot/yparser/yparser.c b/src/libknot/yparser/yparser.c
index 3ad24a3dd6d4e3c84247c7995d3b3a08e8f4112a..f5abb8d5326d1034bd4b005f466ec5b828d3dfa9 100644
--- a/src/libknot/yparser/yparser.c
+++ b/src/libknot/yparser/yparser.c
@@ -21,7 +21,6 @@
 #include <sys/mman.h>
 #include <unistd.h>
 
-#include "libknot/internal/macros.h"
 #include "libknot/yparser/yparser.h"
 #include "libknot/errcode.h"
 
diff --git a/src/libknot/yparser/yparser.h b/src/libknot/yparser/yparser.h
index fa0571787d87d0dba5e7107a441ee9a0818fe2e8..0903be42e60c5aabd27d45f5a388ac587f549c3d 100644
--- a/src/libknot/yparser/yparser.h
+++ b/src/libknot/yparser/yparser.h
@@ -16,10 +16,9 @@
 /*!
  * \file
  *
- * Simple parser (Yparser) of a YAML-inspired data format.
+ * \brief Simple parser (Yparser) of a YAML-inspired data format.
  *
  * \addtogroup yparser
- *
  * @{
  */
 
diff --git a/src/libknot/yparser/ypformat.c b/src/libknot/yparser/ypformat.c
index a66553f836c37272aecb49692f6038833f158a17..9ed979bd93b37c48d4e3f0a9674982e71074d575 100644
--- a/src/libknot/yparser/ypformat.c
+++ b/src/libknot/yparser/ypformat.c
@@ -14,7 +14,8 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-#include "libknot/internal/macros.h"
+#include <stdio.h>
+
 #include "libknot/yparser/yptrafo.h"
 #include "libknot/errcode.h"
 
diff --git a/src/libknot/yparser/ypformat.h b/src/libknot/yparser/ypformat.h
index 7c99ba7b6cdd1a3c4bee6451517d490d038af9c9..0deab914782ba4baec1c5a0b33bfe38108d224a5 100644
--- a/src/libknot/yparser/ypformat.h
+++ b/src/libknot/yparser/ypformat.h
@@ -16,10 +16,9 @@
 /*!
  * \file
  *
- * Tools for Yparser format creation.
+ * \brief Tools for Yparser format creation.
  *
  * \addtogroup yparser
- *
  * @{
  */
 
diff --git a/src/libknot/yparser/ypscheme.c b/src/libknot/yparser/ypscheme.c
index f79dfb181278f76818603bf44f8831b5d9b9fc34..840624d2e2db02e9b79fdadb65ac5693394772f4 100644
--- a/src/libknot/yparser/ypscheme.c
+++ b/src/libknot/yparser/ypscheme.c
@@ -17,10 +17,10 @@
 #include <assert.h>
 #include <stdlib.h>
 
-#include "libknot/internal/macros.h"
 #include "libknot/yparser/ypscheme.h"
 #include "libknot/yparser/yptrafo.h"
 #include "libknot/errcode.h"
+#include "contrib/lookup.h"
 
 /*! Initializes the referenced item. */
 static int set_ref_item(
diff --git a/src/libknot/yparser/ypscheme.h b/src/libknot/yparser/ypscheme.h
index b2b0da4c21de5419d161f30b6e35099bc38a68c4..0d937101f978b3138fb07c3c8cd675e6261b2943 100644
--- a/src/libknot/yparser/ypscheme.h
+++ b/src/libknot/yparser/ypscheme.h
@@ -16,20 +16,22 @@
 /*!
  * \file
  *
- * Scheme layer for Yparser.
+ * \brief Scheme layer for Yparser.
  *
  * \addtogroup yparser
- *
  * @{
  */
 
 #pragma once
 
 #include <stdint.h>
+#include <stddef.h>
 
-#include "libknot/internal/utils.h"
 #include "libknot/yparser/yparser.h"
 
+struct wire_ctx;
+struct lookup_table;
+
 /*! Maximal length of item name. */
 #define YP_MAX_ITEM_NAME_LEN	64
 /*! Maximal length of binary identifier name (maximal dname length). */
@@ -43,8 +45,6 @@
 /*! Maximal node stack depth. */
 #define YP_MAX_NODE_DEPTH	2
 
-struct wire_ctx;
-
 #define YP_TXT_BIN_PARAMS 	struct wire_ctx *in, struct wire_ctx *out, const uint8_t *stop
 #define YP_BIN_TXT_PARAMS	struct wire_ctx *in, struct wire_ctx *out
 
@@ -119,7 +119,7 @@ typedef union {
 	/*! Option variables. */
 	struct {
 		/*! List of options (maximal value is 255). */
-		lookup_table_t const *opts;
+		struct lookup_table const *opts;
 		/*! Default value. */
 		unsigned dflt;
 	} o;
diff --git a/src/libknot/yparser/yptrafo.c b/src/libknot/yparser/yptrafo.c
index bf5746c85e02d33a42f700a0fbc2926487234739..4d913d1c31d0b58445238e7149d1eecb7992c2a8 100644
--- a/src/libknot/yparser/yptrafo.c
+++ b/src/libknot/yparser/yptrafo.c
@@ -21,11 +21,12 @@
 #include <stdlib.h>
 
 #include "libknot/yparser/yptrafo.h"
-#include "libknot/internal/macros.h"
 #include "libknot/consts.h"
 #include "libknot/dname.h"
 #include "contrib/base64.h"
+#include "contrib/lookup.h"
 #include "contrib/sockaddr.h"
+#include "contrib/wire.h"
 #include "contrib/wire_ctx.h"
 
 enum {
@@ -913,6 +914,12 @@ struct sockaddr_storage yp_addr_noport(
 	return ss;
 }
 
+int64_t yp_int(
+	const uint8_t *data)
+{
+	return (int64_t)wire_read_u64(data);
+}
+
 struct sockaddr_storage yp_addr(
 	const uint8_t *data,
 	bool *no_port)
@@ -946,3 +953,9 @@ struct sockaddr_storage yp_addr(
 
 	return ss;
 }
+
+const size_t yp_bin_len(
+	const uint8_t *data)
+{
+	return wire_read_u16(data);
+}
diff --git a/src/libknot/yparser/yptrafo.h b/src/libknot/yparser/yptrafo.h
index 8741c4379735e82661ac1a464d61b77b7d78356b..b51af85c2b1f34c58535fbfdd3210a4bc5a777ca 100644
--- a/src/libknot/yparser/yptrafo.h
+++ b/src/libknot/yparser/yptrafo.h
@@ -16,18 +16,17 @@
 /*!
  * \file
  *
- * Value transformations for Yparser.
+ * \brief Value transformations for Yparser.
  *
  * \addtogroup yparser
- *
  * @{
  */
 
 #pragma once
 
 #include "libknot/yparser/ypscheme.h"
-#include "libknot/internal/utils.h"
-#include "libknot/dname.h"
+
+struct lookup_table;
 
 /*!
  * Transforms textual item value to binary form.
@@ -102,11 +101,9 @@ inline static bool yp_bool(
  *
  * \return Integer value.
  */
-inline static int64_t yp_int(
-	const uint8_t *data)
-{
-	return (int64_t)wire_read_u64(data);
-}
+int64_t yp_int(
+	const uint8_t *data
+);
 
 /*!
  * Converts binary value to address value.
@@ -152,10 +149,10 @@ inline static unsigned yp_opt(
  *
  * \return Dname pointer.
  */
-inline static const knot_dname_t* yp_dname(
+inline static const uint8_t* yp_dname(
 	const uint8_t *data)
 {
-	return (const knot_dname_t *)data;
+	return data;
 }
 
 /*!
@@ -182,11 +179,9 @@ inline static const uint8_t* yp_bin(
  *
  * \return Data length.
  */
-inline static const size_t yp_bin_len(
-	const uint8_t *data)
-{
-	return wire_read_u16(data);
-}
+const size_t yp_bin_len(
+	const uint8_t *data
+);
 
 /*!
  * \brief Helper macros for conversion functions.
@@ -268,12 +263,12 @@ int yp_addr_to_txt(
 
 int yp_option_to_bin(
 	YP_TXT_BIN_PARAMS,
-	const lookup_table_t *opts
+	const struct lookup_table *opts
 );
 
 int yp_option_to_txt(
 	YP_BIN_TXT_PARAMS,
-	const lookup_table_t *opts
+	const struct lookup_table *opts
 );
 
 int yp_dname_to_bin(
diff --git a/src/utils/common/exec.c b/src/utils/common/exec.c
index d649795f7b2764fd5858559b3e276b85a67d3e4d..74e710a8a1f9dc83b23a8631e4370ba48c486f45 100644
--- a/src/utils/common/exec.c
+++ b/src/utils/common/exec.c
@@ -25,6 +25,7 @@
 #include "utils/common/params.h"
 #include "libknot/libknot.h"
 #include "libknot/internal/lists.h"
+#include "contrib/lookup.h"
 #include "contrib/print.h"
 #include "contrib/sockaddr.h"
 #include "contrib/openbsd/strlcat.h"
@@ -51,11 +52,11 @@ static lookup_table_t rtypes[] = {
 static void print_header(const knot_pkt_t *packet, const style_t *style,
                          const uint16_t ext_rcode)
 {
-	char    flags[64] = "";
+	char flags[64] = "";
 	uint8_t opcode_id;
 	const char *rcode_str = "Unknown";
 	const char *opcode_str = "Unknown";
-	lookup_table_t *rcode, *opcode;
+	const lookup_table_t *rcode, *opcode;
 
 	// Get RCODE from Header and check for Extended RCODE from OPT RR.
 	rcode = lookup_by_id(knot_rcode_names, ext_rcode);
@@ -136,7 +137,7 @@ static void print_footer(const size_t total_len,
                          const bool   incoming)
 {
 	struct tm tm;
-	char      date[64];
+	char date[64];
 
 	// Get current timestamp.
 	if (exec_time == 0) {
@@ -184,10 +185,10 @@ static void print_edns_client_subnet(const uint8_t *data, const uint16_t len)
 	struct in_addr addr4;
 	struct in6_addr addr6;
 	knot_addr_family_t family;
-	uint8_t  src_mask, dst_mask;
-	uint8_t  addr[IPV6_PREFIXLEN / 8] = { 0 };
+	uint8_t src_mask, dst_mask;
+	uint8_t addr[IPV6_PREFIXLEN / 8] = { 0 };
 	uint16_t addr_len = sizeof(addr);
-	char     addr_str[SOCKADDR_STRLEN] = { '\0' };
+	char addr_str[SOCKADDR_STRLEN] = { '\0' };
 
 	int ret = knot_edns_client_subnet_parse(data, len, &family, addr,
 	                                        &addr_len, &src_mask, &dst_mask);
@@ -215,10 +216,10 @@ static void print_edns_client_subnet(const uint8_t *data, const uint16_t len)
 
 static void print_section_opt(const knot_rrset_t *rr, const uint8_t rcode)
 {
-	uint8_t        ercode = knot_edns_get_ext_rcode(rr);
-	uint16_t       ext_rcode_id = knot_edns_whole_rcode(ercode, rcode);
-	const char     *ext_rcode_str = "Unused";
-	lookup_table_t *ext_rcode;
+	uint8_t ercode = knot_edns_get_ext_rcode(rr);
+	uint16_t ext_rcode_id = knot_edns_whole_rcode(ercode, rcode);
+	const char *ext_rcode_str = "Unused";
+	const lookup_table_t *ext_rcode;
 
 	if (ercode > 0) {
 		ext_rcode = lookup_by_id(knot_rcode_names, ext_rcode_id);
@@ -281,7 +282,7 @@ static void print_section_question(const knot_dname_t *owner,
                                    const style_t      *style)
 {
 	size_t buflen = 8192;
-	char   *buf = calloc(buflen, 1);
+	char *buf = calloc(buflen, 1);
 
 	// Don't print zero TTL.
 	knot_dump_style_t qstyle = style->style;
@@ -305,7 +306,7 @@ static void print_section_full(const knot_rrset_t *rrsets,
                                const bool         no_tsig)
 {
 	size_t buflen = 8192;
-	char   *buf = calloc(buflen, 1);
+	char *buf = calloc(buflen, 1);
 
 	for (size_t i = 0; i < count; i++) {
 		// Ignore OPT records.
@@ -345,7 +346,7 @@ static void print_section_dig(const knot_rrset_t *rrsets,
                               const style_t      *style)
 {
 	size_t buflen = 8192;
-	char   *buf = calloc(buflen, 1);
+	char *buf = calloc(buflen, 1);
 
 	for (size_t i = 0; i < count; i++) {
 		const knot_rrset_t *rrset = &rrsets[i];
@@ -379,13 +380,13 @@ static void print_section_host(const knot_rrset_t *rrsets,
                                const style_t      *style)
 {
 	size_t buflen = 8192;
-	char   *buf = calloc(buflen, 1);
+	char *buf = calloc(buflen, 1);
 
 	for (size_t i = 0; i < count; i++) {
 		const knot_rrset_t *rrset = &rrsets[i];
-		lookup_table_t     *descr;
-		char               type[32] = "NULL";
-		char               *owner;
+		const lookup_table_t *descr;
+		char type[32] = "NULL";
+		char *owner;
 
 		owner = knot_dname_to_str_alloc(rrset->owner);
 		if (style->style.ascii_to_idn != NULL) {
@@ -440,8 +441,7 @@ static void print_error_host(const uint16_t   code,
 	const char *rcode_str = "Unknown";
 	char type[32] = "Unknown";
 	char *owner;
-
-	lookup_table_t *rcode;
+	const lookup_table_t *rcode;
 
 	owner = knot_dname_to_str_alloc(knot_pkt_qname(packet));
 	if (style->style.ascii_to_idn != NULL) {
diff --git a/src/utils/knsupdate/knsupdate_exec.c b/src/utils/knsupdate/knsupdate_exec.c
index 2dc6ac9f022b6184ff928c103b07e19c8641ab55..99a42798f40b8537a1f26d06452d49a964ae5b06 100644
--- a/src/utils/knsupdate/knsupdate_exec.c
+++ b/src/utils/knsupdate/knsupdate_exec.c
@@ -33,6 +33,7 @@
 #include "utils/common/token.h"
 #include "libknot/libknot.h"
 #include "libknot/internal/macros.h"
+#include "contrib/lookup.h"
 #include "contrib/string.h"
 #include "contrib/openbsd/strlcpy.h"
 
@@ -881,7 +882,7 @@ int cmd_send(const char* lp, knsupdate_params_t *params)
 	uint8_t rc = knot_wire_get_rcode(params->answer->wire);
 	if (rc != KNOT_RCODE_NOERROR) {
 		const char *rcode_str = "Unknown";
-		lookup_table_t *rcode = lookup_by_id(knot_rcode_names, rc);
+		const lookup_table_t *rcode = lookup_by_id(knot_rcode_names, rc);
 		if (rcode != NULL) {
 			rcode_str = rcode->name;
 		}
diff --git a/src/utils/knsupdate/knsupdate_params.c b/src/utils/knsupdate/knsupdate_params.c
index a873f6644b7be5271eb28616ce129f0464ff1913..7ae15afc793ac35eae5d126d148052a1bbbef367 100644
--- a/src/utils/knsupdate/knsupdate_params.c
+++ b/src/utils/knsupdate/knsupdate_params.c
@@ -14,6 +14,7 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
+#include <assert.h>
 #include <getopt.h>
 #include <stdarg.h>
 #include <stdio.h>
diff --git a/tests/.gitignore b/tests/.gitignore
index 0006fc0ae54417f21fe41672e10cc61951676d6e..09dc34c7231d5cd8342dfde662fe6cbc040bc719 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -25,6 +25,7 @@ hattrie
 hhash
 internal_mem
 journal
+lookup
 modules/online_sign
 namedb
 net
@@ -43,7 +44,6 @@ rrset
 rrset_wire
 server
 tsig_key
-utils
 wire
 wire_ctx
 worker_pool
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 3df3a8dc3a71cf3df55ba03fb979e490d116f926..1ad9f47eed5fd5095d7a7e1b7da1d881442a0dd0 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -29,6 +29,7 @@ check_PROGRAMS = \
 	hhash				\
 	internal_mem			\
 	journal				\
+	lookup				\
 	namedb				\
 	net				\
 	net_shortwrite			\
@@ -46,7 +47,6 @@ check_PROGRAMS = \
 	rrset_wire			\
 	server				\
 	tsig_key			\
-	utils				\
 	wire				\
 	wire_ctx			\
 	worker_pool			\
diff --git a/tests/conf_tools.c b/tests/conf_tools.c
index f63b40b6441a7dc9d30788dee7a7755ac75e49a9..e3e450835948802cbe0841ca3bc387e08b9825da 100644
--- a/tests/conf_tools.c
+++ b/tests/conf_tools.c
@@ -22,6 +22,7 @@
 #include "libknot/yparser/yptrafo.h"
 #include "knot/conf/tools.h"
 #include "libknot/libknot.h"
+#include "contrib/wire.h"
 
 static void mod_id_test(const char *txt, const char *val)
 {
diff --git a/tests/edns.c b/tests/edns.c
index 1e55f4b248b5ba00e21d56e66b992c96737cdbbb..92896dedd2079892310839abac245148d3ee2f13 100644
--- a/tests/edns.c
+++ b/tests/edns.c
@@ -21,6 +21,7 @@
 #include "libknot/rrtype/opt.h"
 #include "libknot/descriptor.h"
 #include "contrib/sockaddr.h"
+#include "contrib/wire.h"
 
 static const uint16_t E_MAX_PLD = 10000;
 static const uint16_t E_MAX_PLD2 = 20000;
diff --git a/tests/journal.c b/tests/journal.c
index 1e7d8ab96a0c47b2854cd048f4e8b5c8a9eca04d..72031c0deabcd9eb4fb0af73a1796fdb91847fde 100644
--- a/tests/journal.c
+++ b/tests/journal.c
@@ -14,6 +14,7 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <assert.h>
 #include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
diff --git a/tests/utils.c b/tests/lookup.c
similarity index 89%
rename from tests/utils.c
rename to tests/lookup.c
index 35f674ec0fe537d44b8c405bb102239a064f88fd..39cc8f3397008075379c278f023ad9f8f2cbcd27 100644
--- a/tests/utils.c
+++ b/tests/lookup.c
@@ -16,14 +16,14 @@
 
 #include <tap/basic.h>
 
-#include "libknot/internal/utils.h"
-
-lookup_table_t test_table[] = {
-	{0, "test item 0"},
-	{10, ""},
-	{2, "test item 2"},
-	{-1, "test item -1"},
-	{ 0, NULL }
+#include "contrib/lookup.h"
+
+const lookup_table_t test_table[] = {
+	{  0, "test item 0" },
+	{ 10, "" },
+	{  2, "test item 2" },
+	{ -1, "test item -1" },
+	{  0, NULL }
 };
 
 int main(int argc, char *argv[])
@@ -31,7 +31,7 @@ int main(int argc, char *argv[])
 	plan(9);
 
 	/* Lookup by ID. */
-	lookup_table_t *found = lookup_by_id(test_table, 3);
+	const lookup_table_t *found = lookup_by_id(test_table, 3);
 	ok(found == NULL, "lookup table: find by id - non-existent ID");
 
 	found = lookup_by_id(test_table, 2);
diff --git a/tests/node.c b/tests/node.c
index bc4de4fff36efa6326fd475409f9d87cf2d993b1..28c5a3066b714a1c7e09d3522fc8d80e5b2ac0ec 100644
--- a/tests/node.c
+++ b/tests/node.c
@@ -19,6 +19,7 @@
 
 #include "knot/zone/node.h"
 #include "libknot/libknot.h"
+#include "contrib/wire.h"
 
 static knot_rrset_t *create_dummy_rrset(const knot_dname_t *owner,
                                         uint16_t type)
diff --git a/tests/process_answer.c b/tests/process_answer.c
index 063b72abbfc091bba7d67cb26d666522b97f27d8..256049ae0ba693acef606f791bfadc49fd0de963 100644
--- a/tests/process_answer.c
+++ b/tests/process_answer.c
@@ -14,6 +14,7 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <assert.h>
 #include <tap/basic.h>
 #include <string.h>
 #include <stdlib.h>
diff --git a/tests/process_query.c b/tests/process_query.c
index 7dba613a531caffaec5dc7fd5a0175bbaeb6365f..3c65947891ba6ea6c255bf05385491a1a578e7b3 100644
--- a/tests/process_query.c
+++ b/tests/process_query.c
@@ -14,6 +14,7 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <assert.h>
 #include <tap/basic.h>
 #include <string.h>
 #include <stdlib.h>
diff --git a/tests/requestor.c b/tests/requestor.c
index d59fe575b88433151381957158eb5f6570ac6aad..43926e55e0a8ea16f2dc66a259bbd555d59468e8 100644
--- a/tests/requestor.c
+++ b/tests/requestor.c
@@ -14,6 +14,7 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <assert.h>
 #include <tap/basic.h>
 #include <pthread.h>
 #include <stdlib.h>
diff --git a/tests/wire.c b/tests/wire.c
index 95bdd3266ccea104537e626a280640d2d9787b93..095a0a7f3d64403be537de48a754a54cafc2afba 100644
--- a/tests/wire.c
+++ b/tests/wire.c
@@ -16,7 +16,7 @@
 
 #include <tap/basic.h>
 
-#include "libknot/internal/utils.h"
+#include "contrib/wire.h"
 
 #define write_test(size, value, ...) { \
 	const uint8_t expect[] = { __VA_ARGS__ }; \
diff --git a/tests/ypscheme.c b/tests/ypscheme.c
index d4a5330e74275017eed97cb5f843823f8ce6269c..4dd0bce9a3c9f5bb9125ce71cb19bbf515626a52 100644
--- a/tests/ypscheme.c
+++ b/tests/ypscheme.c
@@ -22,6 +22,7 @@
 #include "libknot/yparser/ypscheme.h"
 #include "libknot/yparser/yptrafo.h"
 #include "libknot/libknot.h"
+#include "contrib/lookup.h"
 
 #define C_ID		"\x02""id"
 #define C_INT		"\x07""integer"
diff --git a/tests/yptrafo.c b/tests/yptrafo.c
index 3aecc164fcdad49653f9cc9ab5f905d8f643c3df..8dc3cc4cd9dd2e240f24d6f3f6947df5841ba5b8 100644
--- a/tests/yptrafo.c
+++ b/tests/yptrafo.c
@@ -22,6 +22,7 @@
 
 #include "libknot/yparser/yptrafo.h"
 #include "libknot/libknot.h"
+#include "contrib/lookup.h"
 
 static void int_test(const char *txt, int64_t num, yp_style_t s,
                      int64_t min, int64_t max)
diff --git a/tests/zone_timers.c b/tests/zone_timers.c
index 67b83926bc25b7d00bd0bacb463b0c9e9a04cc78..11135ca5afe3d0678880368a588810bbb4c064e7 100644
--- a/tests/zone_timers.c
+++ b/tests/zone_timers.c
@@ -14,6 +14,7 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <assert.h>
 #include <dirent.h>
 #include <stdlib.h>
 #include <time.h>