diff --git a/Makefile b/Makefile index 93e16e43c64c11cfcf2e9dde08ff23765995f121..63b307ab51ba67b69076c46c4754b44d4751b6b4 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,8 @@ BUILD_CFLAGS += --coverage endif # Dependencies -$(eval $(call find_lib,libknot)) +$(eval $(call find_lib,libknot,2.1)) +$(eval $(call find_lib,libzscanner,2.1)) $(eval $(call find_lib,libuv,1.0)) $(eval $(call find_alt,lua,luajit)) $(eval $(call find_lib,cmocka)) @@ -49,6 +50,9 @@ BUILD_CFLAGS += $(addprefix -I,$(wildcard contrib/ccan/*) contrib/murmurhash3) info: $(info Target: Knot DNS Resolver $(MAJOR).$(MINOR).$(PATCH)-$(PLATFORM)) $(info Compiler: $(CC) $(BUILD_CFLAGS)) + $(info ) + $(info Variables) + $(info ---------) $(info HARDENING: $(HARDENING)) $(info BUILDMODE: $(BUILDMODE)) $(info PREFIX: $(PREFIX)) @@ -63,14 +67,14 @@ info: $(info Dependencies) $(info ------------) $(info [$(HAS_libknot)] libknot (lib)) - $(info [$(HAS_lua)] LuaJIT (daemon)) + $(info [$(HAS_lua)] luajit (daemon)) $(info [$(HAS_libuv)] libuv (daemon)) $(info ) $(info Optional) $(info --------) $(info [$(HAS_doxygen)] doxygen (doc)) - $(info [$(HAS_go)] Go 1.5+ on amd64 (modules/go)) - $(info [$(HAS_geoip)] github.com/abh/geoip (modules/tinyweb)) + $(info [$(HAS_go)] go (modules/go, Go 1.5+ on amd64)) + $(info [$(HAS_geoip)] geoip (modules/tinyweb, github.com/abh/geoip)) $(info [$(HAS_libmemcached)] libmemcached (modules/memcached)) $(info [$(HAS_hiredis)] hiredis (modules/redis)) $(info [$(HAS_cmocka)] cmocka (tests/unit)) diff --git a/contrib/base32hex.c b/contrib/base32hex.c new file mode 100644 index 0000000000000000000000000000000000000000..28701e56f597f7a274b789a4c5bc37d113c4b8e6 --- /dev/null +++ b/contrib/base32hex.c @@ -0,0 +1,207 @@ +/* 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 "contrib/base32hex.h" + +#include <stdlib.h> +#include <stdint.h> + +/*! \brief Maximal length of binary input to Base32hex encoding. */ +#define MAX_BIN_DATA_LEN ((INT32_MAX / 8) * 5) + +/*! \brief Base32hex padding character. */ +const uint8_t base32hex_pad = '='; +/*! \brief Base32hex alphabet. */ +const uint8_t base32hex_enc[] = "0123456789ABCDEFGHIJKLMNOPQRSTUV"; + +/*! \brief Indicates bad Base32hex character. */ +#define KO 255 +/*! \brief Indicates Base32hex padding character. */ +#define PD 32 + +/*! \brief Transformation and validation table for decoding Base32hex. */ +const uint8_t base32hex_dec[256] = { + [ 0] = KO, [ 43] = KO, ['V'] = 31, [129] = KO, [172] = KO, [215] = KO, + [ 1] = KO, [ 44] = KO, ['W'] = KO, [130] = KO, [173] = KO, [216] = KO, + [ 2] = KO, [ 45] = KO, ['X'] = KO, [131] = KO, [174] = KO, [217] = KO, + [ 3] = KO, [ 46] = KO, ['Y'] = KO, [132] = KO, [175] = KO, [218] = KO, + [ 4] = KO, [ 47] = KO, ['Z'] = KO, [133] = KO, [176] = KO, [219] = KO, + [ 5] = KO, ['0'] = 0, [ 91] = KO, [134] = KO, [177] = KO, [220] = KO, + [ 6] = KO, ['1'] = 1, [ 92] = KO, [135] = KO, [178] = KO, [221] = KO, + [ 7] = KO, ['2'] = 2, [ 93] = KO, [136] = KO, [179] = KO, [222] = KO, + [ 8] = KO, ['3'] = 3, [ 94] = KO, [137] = KO, [180] = KO, [223] = KO, + [ 9] = KO, ['4'] = 4, [ 95] = KO, [138] = KO, [181] = KO, [224] = KO, + [ 10] = KO, ['5'] = 5, [ 96] = KO, [139] = KO, [182] = KO, [225] = KO, + [ 11] = KO, ['6'] = 6, ['a'] = 10, [140] = KO, [183] = KO, [226] = KO, + [ 12] = KO, ['7'] = 7, ['b'] = 11, [141] = KO, [184] = KO, [227] = KO, + [ 13] = KO, ['8'] = 8, ['c'] = 12, [142] = KO, [185] = KO, [228] = KO, + [ 14] = KO, ['9'] = 9, ['d'] = 13, [143] = KO, [186] = KO, [229] = KO, + [ 15] = KO, [ 58] = KO, ['e'] = 14, [144] = KO, [187] = KO, [230] = KO, + [ 16] = KO, [ 59] = KO, ['f'] = 15, [145] = KO, [188] = KO, [231] = KO, + [ 17] = KO, [ 60] = KO, ['g'] = 16, [146] = KO, [189] = KO, [232] = KO, + [ 18] = KO, ['='] = PD, ['h'] = 17, [147] = KO, [190] = KO, [233] = KO, + [ 19] = KO, [ 62] = KO, ['i'] = 18, [148] = KO, [191] = KO, [234] = KO, + [ 20] = KO, [ 63] = KO, ['j'] = 19, [149] = KO, [192] = KO, [235] = KO, + [ 21] = KO, [ 64] = KO, ['k'] = 20, [150] = KO, [193] = KO, [236] = KO, + [ 22] = KO, ['A'] = 10, ['l'] = 21, [151] = KO, [194] = KO, [237] = KO, + [ 23] = KO, ['B'] = 11, ['m'] = 22, [152] = KO, [195] = KO, [238] = KO, + [ 24] = KO, ['C'] = 12, ['n'] = 23, [153] = KO, [196] = KO, [239] = KO, + [ 25] = KO, ['D'] = 13, ['o'] = 24, [154] = KO, [197] = KO, [240] = KO, + [ 26] = KO, ['E'] = 14, ['p'] = 25, [155] = KO, [198] = KO, [241] = KO, + [ 27] = KO, ['F'] = 15, ['q'] = 26, [156] = KO, [199] = KO, [242] = KO, + [ 28] = KO, ['G'] = 16, ['r'] = 27, [157] = KO, [200] = KO, [243] = KO, + [ 29] = KO, ['H'] = 17, ['s'] = 28, [158] = KO, [201] = KO, [244] = KO, + [ 30] = KO, ['I'] = 18, ['t'] = 29, [159] = KO, [202] = KO, [245] = KO, + [ 31] = KO, ['J'] = 19, ['u'] = 30, [160] = KO, [203] = KO, [246] = KO, + [ 32] = KO, ['K'] = 20, ['v'] = 31, [161] = KO, [204] = KO, [247] = KO, + [ 33] = KO, ['L'] = 21, ['w'] = KO, [162] = KO, [205] = KO, [248] = KO, + [ 34] = KO, ['M'] = 22, ['x'] = KO, [163] = KO, [206] = KO, [249] = KO, + [ 35] = KO, ['N'] = 23, ['y'] = KO, [164] = KO, [207] = KO, [250] = KO, + [ 36] = KO, ['O'] = 24, ['z'] = KO, [165] = KO, [208] = KO, [251] = KO, + [ 37] = KO, ['P'] = 25, [123] = KO, [166] = KO, [209] = KO, [252] = KO, + [ 38] = KO, ['Q'] = 26, [124] = KO, [167] = KO, [210] = KO, [253] = KO, + [ 39] = KO, ['R'] = 27, [125] = KO, [168] = KO, [211] = KO, [254] = KO, + [ 40] = KO, ['S'] = 28, [126] = KO, [169] = KO, [212] = KO, [255] = KO, + [ 41] = KO, ['T'] = 29, [127] = KO, [170] = KO, [213] = KO, + [ 42] = KO, ['U'] = 30, [128] = KO, [171] = KO, [214] = KO, +}; + +int32_t base32hex_decode(const uint8_t *in, + const uint32_t in_len, + uint8_t *out, + const uint32_t out_len) +{ + // Checking inputs. + if (in == NULL || out == NULL) { + return -1; + } + if (in_len > INT32_MAX || out_len < ((in_len + 7) / 8) * 5) { + return -1; + } + if ((in_len % 8) != 0) { + return -1; + } + + const uint8_t *stop = in + in_len; + uint8_t *bin = out; + uint8_t pad_len = 0; + uint8_t c1, c2, c3, c4, c5, c6, c7, c8; + + // Decoding loop takes 8 characters and creates 5 bytes. + while (in < stop) { + // Filling and transforming 8 Base32hex chars. + c1 = base32hex_dec[in[0]]; + c2 = base32hex_dec[in[1]]; + c3 = base32hex_dec[in[2]]; + c4 = base32hex_dec[in[3]]; + c5 = base32hex_dec[in[4]]; + c6 = base32hex_dec[in[5]]; + c7 = base32hex_dec[in[6]]; + c8 = base32hex_dec[in[7]]; + + // Check 8. char if is bad or padding. + if (c8 >= PD) { + if (c8 == PD && pad_len == 0) { + pad_len = 1; + } else { + return -1; + } + } + + // Check 7. char if is bad or padding (if so, 6. must be too). + if (c7 >= PD) { + if (c7 == PD && c6 == PD && pad_len == 1) { + pad_len = 3; + } else { + return -1; + } + } + + // Check 6. char if is bad or padding. + if (c6 >= PD) { + if (!(c6 == PD && pad_len == 3)) { + return -1; + } + } + + // Check 5. char if is bad or padding. + if (c5 >= PD) { + if (c5 == PD && pad_len == 3) { + pad_len = 4; + } else { + return -1; + } + } + + // Check 4. char if is bad or padding (if so, 3. must be too). + if (c4 >= PD) { + if (c4 == PD && c3 == PD && pad_len == 4) { + pad_len = 6; + } else { + return -1; + } + } + + // Check 3. char if is bad or padding. + if (c3 >= PD) { + if (!(c3 == PD && pad_len == 6)) { + return -1; + } + } + + // 1. and 2. chars must not be padding. + if (c2 >= PD || c1 >= PD) { + return -1; + } + + // Computing of output data based on padding length. + switch (pad_len) { + case 0: + bin[4] = (c7 << 5) + c8; + case 1: + bin[3] = (c5 << 7) + (c6 << 2) + (c7 >> 3); + case 3: + bin[2] = (c4 << 4) + (c5 >> 1); + case 4: + bin[1] = (c2 << 6) + (c3 << 1) + (c4 >> 4); + case 6: + bin[0] = (c1 << 3) + (c2 >> 2); + } + + // Update output end. + switch (pad_len) { + case 0: + bin += 5; + break; + case 1: + bin += 4; + break; + case 3: + bin += 3; + break; + case 4: + bin += 2; + break; + case 6: + bin += 1; + break; + } + + in += 8; + } + + return (bin - out); +} diff --git a/contrib/base32hex.h b/contrib/base32hex.h new file mode 100644 index 0000000000000000000000000000000000000000..404b981a81347d6117f2a4c7cf198db52ad0f223 --- /dev/null +++ b/contrib/base32hex.h @@ -0,0 +1,52 @@ +/* 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 Base32hex implementation (RFC 4648). + * + * \note Input Base32hex string can contain a-v characters. These characters + * are considered as A-V equivalent. + * + * \addtogroup contrib + * @{ + */ + +#pragma once + +#include <stdint.h> + +/*! + * \brief Decodes text data using Base32hex. + * + * \note Input data needn't be terminated with '\0'. + * + * \note Input data must be continuous Base32hex string! + * + * \param in Input text data. + * \param in_len Length of input string. + * \param out Output data buffer. + * \param out_len Size of output buffer. + * + * \retval >=0 length of output data. + * \retval KNOT_E* if error. + */ +int32_t base32hex_decode(const uint8_t *in, + const uint32_t in_len, + uint8_t *out, + const uint32_t out_len); + +/*! @} */ diff --git a/contrib/contrib.mk b/contrib/contrib.mk index 3daf43df53f5eeb163856ea91867c9330df1c1e6..5d924734a740b4ffdb16eb44d6563c5d25a7f545 100644 --- a/contrib/contrib.mk +++ b/contrib/contrib.mk @@ -4,7 +4,8 @@ contrib_SOURCES := \ contrib/ccan/isaac/isaac.c \ contrib/ccan/json/json.c \ contrib/ucw/mempool.c \ - contrib/murmurhash3/murmurhash3.c + contrib/murmurhash3/murmurhash3.c \ + contrib/base32hex.c contrib_CFLAGS := -fPIC contrib_TARGET := $(abspath contrib)/contrib$(AREXT) $(eval $(call make_static,contrib,contrib)) diff --git a/contrib/wire.h b/contrib/wire.h new file mode 100644 index 0000000000000000000000000000000000000000..7a367cd177a045119a5d7f902ac415c274517d83 --- /dev/null +++ b/contrib/wire.h @@ -0,0 +1,174 @@ +/* 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 Wire integer operations. + * + * \addtogroup contrib + * @{ + */ + +#pragma once + +#include <stdint.h> +#include <string.h> + +#if defined(__linux__) +# include <endian.h> +# ifndef be64toh +# include <arpa/inet.h> +# include <byteswap.h> +# if BYTE_ORDER == LITTLE_ENDIAN +# define be16toh(x) ntohs(x) +# define be32toh(x) ntohl(x) +# define be64toh(x) bswap_64 (x) +# define le16toh(x) (x) +# define le32toh(x) (x) +# define le64toh(x) (x) +# else +# define be16toh(x) (x) +# define be32toh(x) (x) +# define be64toh(x) (x) +# define le16toh(x) ntohs(x) +# define le32toh(x) ntohl(x) +# define le64toh(x) bswap_64 (x) +# endif +# endif +#elif defined(__FreeBSD__) || defined(__NetBSD__) +# include <sys/endian.h> +#elif defined(__OpenBSD__) +# include <endian.h> +#elif defined(__APPLE__) +# include <libkern/OSByteOrder.h> +# define be16toh(x) OSSwapBigToHostInt16(x) +# define be32toh(x) OSSwapBigToHostInt32(x) +# define be64toh(x) OSSwapBigToHostInt64(x) +# define htobe16(x) OSSwapHostToBigInt16(x) +# define htobe32(x) OSSwapHostToBigInt32(x) +# define htobe64(x) OSSwapHostToBigInt64(x) +# define le16toh(x) OSSwapLittleToHostInt16(x) +# define le32toh(x) OSSwapLittleToHostInt32(x) +# define le64toh(x) OSSwapLittleToHostInt64(x) +# define htole16(x) OSSwapHostToLittleInt16(x) +# define htole32(x) OSSwapHostToLittleInt32(x) +# define htole64(x) OSSwapHostToLittleInt64(x) +#endif + +/*! + * \brief Reads 2 bytes from the wireformat data. + * + * \param pos Data to read the 2 bytes from. + * + * \return The 2 bytes read, in host byte order. + */ +inline static uint16_t wire_read_u16(const uint8_t *pos) +{ + return be16toh(*(uint16_t *)pos); +} + +/*! + * \brief Reads 4 bytes from the wireformat data. + * + * \param pos Data to read the 4 bytes from. + * + * \return The 4 bytes read, in host byte order. + */ +inline static uint32_t wire_read_u32(const uint8_t *pos) +{ + return be32toh(*(uint32_t *)pos); +} + +/*! + * \brief Reads 6 bytes from the wireformat data. + * + * \param pos Data to read the 6 bytes from. + * + * \return The 6 bytes read, in host byte order. + */ +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. + * + * \param pos Data to read the 8 bytes from. + * + * \return The 8 bytes read, in host byte order. + */ +inline static uint64_t wire_read_u64(const uint8_t *pos) +{ + return be64toh(*(uint64_t *)pos); +} + +/*! + * \brief Writes 2 bytes in wireformat. + * + * The data are stored in network byte order (big endian). + * + * \param pos Position where to put the 2 bytes. + * \param data Data to put. + */ +inline static void wire_write_u16(uint8_t *pos, uint16_t data) +{ + *(uint16_t *)pos = htobe16(data); +} + +/*! + * \brief Writes 4 bytes in wireformat. + * + * The data are stored in network byte order (big endian). + * + * \param pos Position where to put the 4 bytes. + * \param data Data to put. + */ +inline static void wire_write_u32(uint8_t *pos, uint32_t data) +{ + *(uint32_t *)pos = htobe32(data); +} + +/*! + * \brief Writes 6 bytes in wireformat. + * + * The data are stored in network byte order (big endian). + * + * \param pos Position where to put the 4 bytes. + * \param data Data to put. + */ +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. + * + * The data are stored in network byte order (big endian). + * + * \param pos Position where to put the 8 bytes. + * \param data Data to put. + */ +inline static void wire_write_u64(uint8_t *pos, uint64_t data) +{ + *(uint64_t *)pos = htobe64(data); +} + +/*! @} */ diff --git a/daemon/bindings.c b/daemon/bindings.c index e97230c91af78593f598024f9f298fc97b28ca85..0c62422c372bbae4fcff31d4fbd9fa0fca5c5237 100644 --- a/daemon/bindings.c +++ b/daemon/bindings.c @@ -14,6 +14,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <assert.h> #include <uv.h> #include <contrib/cleanup.h> #include <libknot/descriptor.h> @@ -334,11 +335,11 @@ static int cache_backends(lua_State *L) static int cache_count(lua_State *L) { struct engine *engine = engine_luaget(L); - const namedb_api_t *storage = engine->resolver.cache.api; + const knot_db_api_t *storage = engine->resolver.cache.api; /* Fetch item count */ struct kr_cache_txn txn; - int ret = kr_cache_txn_begin(&engine->resolver.cache, &txn, NAMEDB_RDONLY); + int ret = kr_cache_txn_begin(&engine->resolver.cache, &txn, KNOT_DB_RDONLY); if (ret != 0) { format_error(L, kr_strerror(ret)); lua_error(L); diff --git a/daemon/daemon.mk b/daemon/daemon.mk index c96c1e46de7eecebdc3bf84da6087084e0be5a06..2693ab7ec0f7ed192c51936f547cca47dc2c8a94 100644 --- a/daemon/daemon.mk +++ b/daemon/daemon.mk @@ -24,7 +24,7 @@ bindings-install: $(kresd_DIST) $(DESTDIR)$(MODULEDIR) kresd_CFLAGS := -fPIE kresd_DEPEND := $(libkres) $(contrib) -kresd_LIBS := $(libkres_TARGET) $(contrib_TARGET) $(libknot_LIBS) $(libdnssec_LIBS) $(libuv_LIBS) $(lua_LIBS) +kresd_LIBS := $(libkres_TARGET) $(contrib_TARGET) $(libknot_LIBS) $(libzscanner_LIBS) $(libdnssec_LIBS) $(libuv_LIBS) $(lua_LIBS) # Make binary ifeq ($(HAS_lua)|$(HAS_libuv), yes|yes) diff --git a/daemon/engine.c b/daemon/engine.c index fcdca1aad89837f6154bde5f3efcaa59fca1dfe2..7e4fc8b25ec3685fdbd9911b4f7a5dd354beba0d 100644 --- a/daemon/engine.c +++ b/daemon/engine.c @@ -21,9 +21,9 @@ #include <unistd.h> #include <grp.h> #include <pwd.h> -#include <libknot/internal/mempattern.h> -/* #include <libknot/internal/namedb/namedb_trie.h> @todo Not supported (doesn't keep value copy) */ -#include <libknot/internal/namedb/namedb_lmdb.h> +/* #include <libknot/internal/namedb/knot_db_trie.h> @todo Not supported (doesn't keep value copy) */ +#include <libknot/db/db_lmdb.h> +#include <zscanner/scanner.h> #include "daemon/engine.h" #include "daemon/bindings.h" @@ -177,7 +177,7 @@ static int l_option(lua_State *L) unsigned opt_code = 0; if (lua_isstring(L, 1)) { const char *opt = lua_tostring(L, 1); - for (const lookup_table_t *it = kr_query_flag_names(); it->name; ++it) { + for (const knot_lookup_t *it = kr_query_flag_names(); it->name; ++it) { if (strcmp(it->name, opt) == 0) { opt_code = it->id; break; @@ -200,6 +200,52 @@ static int l_option(lua_State *L) return 1; } +/** Enable/disable trust anchor. */ +static int l_trustanchor(lua_State *L) +{ + struct engine *engine = engine_luaget(L); + const char *anchor = lua_tostring(L, 1); + bool enable = lua_isboolean(L, 2) ? lua_toboolean(L, 2) : true; + if (!anchor || strlen(anchor) == 0) { + return 0; + } + /* If disabling, parse the owner string only. */ + if (!enable) { + knot_dname_t *owner = knot_dname_from_str(NULL, anchor, KNOT_DNAME_MAXLEN); + if (!owner) { + lua_pushstring(L, "invalid trust anchor owner"); + lua_error(L); + } + lua_pushboolean(L, kr_ta_del(&engine->resolver.trust_anchors, owner) == 0); + free(owner); + return 1; + } + + /* Parse the record */ + zs_scanner_t *zs = malloc(sizeof(*zs)); + if (!zs || zs_init(zs, ".", 1, 0) != 0) { + free(zs); + lua_pushstring(L, "not enough memory"); + lua_error(L); + } + int ok = zs_set_input_string(zs, anchor, strlen(anchor)) == 0 && + zs_parse_all(zs) == 0; + /* Add it to TA set and cleanup */ + if (ok) { + ok = kr_ta_add(&engine->resolver.trust_anchors, + zs->r_owner, zs->r_type, zs->r_ttl, zs->r_data, zs->r_data_length) == 0; + } + zs_deinit(zs); + free(zs); + /* Report errors */ + if (!ok) { + lua_pushstring(L, "failed to process trust anchor RR"); + lua_error(L); + } + lua_pushboolean(L, true); + return 1; +} + /** Unpack JSON object to table */ static void l_unpack_json(lua_State *L, JsonNode *table) { @@ -320,9 +366,9 @@ static int l_trampoline(lua_State *L) */ /** @internal Make lmdb options. */ -void *namedb_lmdb_mkopts(const char *conf, size_t maxsize) +void *knot_db_lmdb_mkopts(const char *conf, size_t maxsize) { - struct namedb_lmdb_opts *opts = malloc(sizeof(*opts)); + struct knot_db_lmdb_opts *opts = malloc(sizeof(*opts)); if (opts) { memset(opts, 0, sizeof(*opts)); opts->path = (conf && strlen(conf)) ? conf : "."; @@ -366,7 +412,7 @@ static int init_resolver(struct engine *engine) /* Initialize storage backends */ struct storage_api lmdb = { - "lmdb://", namedb_lmdb_api, namedb_lmdb_mkopts + "lmdb://", knot_db_lmdb_api, knot_db_lmdb_mkopts }; return array_push(engine->storage_registry, lmdb); @@ -395,6 +441,8 @@ static int init_state(struct engine *engine) lua_setglobal(engine->L, "option"); lua_pushcfunction(engine->L, l_setuser); lua_setglobal(engine->L, "user"); + lua_pushcfunction(engine->L, l_trustanchor); + lua_setglobal(engine->L, "trustanchor"); lua_pushcfunction(engine->L, l_libpath); lua_setglobal(engine->L, "libpath"); lua_pushliteral(engine->L, MODULEDIR); @@ -406,7 +454,7 @@ static int init_state(struct engine *engine) return kr_ok(); } -int engine_init(struct engine *engine, mm_ctx_t *pool) +int engine_init(struct engine *engine, knot_mm_t *pool) { if (engine == NULL) { return kr_error(EINVAL); diff --git a/daemon/engine.h b/daemon/engine.h index 0b32dfd80ca6a2325080c131663f092452364e2e..d9755157bf6e619b541b58f942125ba478b4ab14 100644 --- a/daemon/engine.h +++ b/daemon/engine.h @@ -35,13 +35,14 @@ */ struct lua_State; +#include "lib/utils.h" #include "lib/resolve.h" #include "daemon/network.h" /** Cache storage backend. */ struct storage_api { const char *prefix; /**< Storage prefix, e.g. 'lmdb://' */ - const namedb_api_t *(*api)(void); /**< Storage API implementation */ + const knot_db_api_t *(*api)(void); /**< Storage API implementation */ void *(*opts_create)(const char *, size_t); /**< Storage options factory */ }; @@ -53,11 +54,11 @@ struct engine { struct network net; module_array_t modules; storage_registry_t storage_registry; - mm_ctx_t *pool; + knot_mm_t *pool; struct lua_State *L; }; -int engine_init(struct engine *engine, mm_ctx_t *pool); +int engine_init(struct engine *engine, knot_mm_t *pool); void engine_deinit(struct engine *engine); /** @warning This function leaves 1 string result on stack. */ int engine_cmd(struct engine *engine, const char *str); diff --git a/daemon/lua/kres.lua b/daemon/lua/kres.lua index 0834b65d7f010a2ae7ce767ae3a5343c95799a33..a041c3b7008d6aa11be3743aea1193db7297b2be 100644 --- a/daemon/lua/kres.lua +++ b/daemon/lua/kres.lua @@ -11,7 +11,7 @@ local bit = require('bit') local bor = bit.bor local band = bit.band local C = ffi.C -local knot = ffi.load(libpath('libknot', '1')) +local knot = ffi.load(libpath('libknot', '2')) ffi.cdef[[ /* @@ -118,9 +118,6 @@ struct sockaddr { /* libknot */ typedef int knot_section_t; /* Do not touch */ typedef void knot_rrinfo_t; /* Do not touch */ -typedef struct node { - struct node *next, *prev; -} node_t; typedef uint8_t knot_dname_t; typedef uint8_t knot_rdata_t; typedef struct knot_rdataset { @@ -174,7 +171,6 @@ typedef struct { size_t cap; } rr_array_t; struct kr_query { - node_t _node; struct kr_query *parent; knot_dname_t *sname; uint16_t type; @@ -258,6 +254,7 @@ int kr_pkt_put(knot_pkt_t *pkt, const knot_dname_t *name, uint32_t ttl, uint16_t rclass, uint16_t rtype, const uint8_t *rdata, uint16_t rdlen); int kr_pkt_recycle(knot_pkt_t *pkt); const char *kr_inaddr(const struct sockaddr *addr); +int kr_inaddr_family(const struct sockaddr *addr); int kr_inaddr_len(const struct sockaddr *addr); int kr_straddr_family(const char *addr); int kr_straddr_subnet(void *dst, const char *addr); @@ -285,6 +282,7 @@ ffi.metatype( sockaddr_t, { __index = { len = function(sa) return C.kr_inaddr_len(sa) end, ip = function (sa) return C.kr_inaddr(sa) end, + family = function (sa) return C.kr_inaddr_family(sa) end, } }) @@ -353,10 +351,6 @@ local kr_query_t = ffi.typeof('struct kr_query') ffi.metatype( kr_query_t, { __index = { name = function(qry, new_name) return ffi.string(qry.sname, knot.knot_dname_size(qry.sname)) end, - next = function(qry) - assert(qry) - return C.kr_rplan_next(qry) - end, resolved = function(qry) return band(qry.flags, kres.query.RESOLVED) ~= 0 end, @@ -443,4 +437,4 @@ local kres = { context = function () return ffi.cast('struct kr_context *', __engine) end, } -return kres \ No newline at end of file +return kres diff --git a/daemon/lua/trust_anchors.lua b/daemon/lua/trust_anchors.lua index 3ffb123e8e1b4ac4922f42aa4bcd6e19afe962d0..bc756648bfb62b3ac993e10e8d4adc1abb5ff367 100644 --- a/daemon/lua/trust_anchors.lua +++ b/daemon/lua/trust_anchors.lua @@ -1,6 +1,66 @@ +-- Fetch over HTTPS with peert cert checked +local function https_fetch(url, ca) + local ssl_ok, https = pcall(require, 'ssl.https') + local ltn_ok, ltn12 = pcall(require, 'ltn12') + if not ssl_ok or not ltn_ok then + return nil, 'luasec and luasocket needed for root TA bootstrap' + end + local resp = {} + local r, c, h, s = https.request{ + url = url, + cafile = ca, + verify = {'peer', 'fail_if_no_peer_cert' }, + protocol = 'tlsv1_2', + sink = ltn12.sink.table(resp), + } + if r == nil then return r, c end + return resp[1] +end + +-- Fetch root anchors in XML over HTTPS +local function bootstrap(url, ca) + -- @todo ICANN certificate is verified against current CA + -- this is not ideal, as it should rather verify .xml signature which + -- is signed by ICANN long-lived cert, but luasec has no PKCS7 + ca = ca or etcdir..'/icann-ca.pem' + url = url or 'https://data.iana.org/root-anchors/root-anchors.xml' + local xml, err = https_fetch(url, ca) + if not xml then + return false, string.format('[ ta ] fetch of "%s" failed: %s', url, err) + end + -- Parse root trust anchor + local fields = {} + string.gsub(xml, "<([%w]+).->([^<]+)</[%w]+>", function (k, v) fields[k] = v end) + local rrdata = string.format('%s %s %s %s', fields.KeyDigest, fields.Algorithm, fields.DigestType, fields.Digest) + local rr = string.format('%s 0 IN DS %s', fields.TrustAnchor, rrdata) + -- Add to key set, create an empty keyset file to be filled + print('[ ta ] warning: root anchor bootstrapped, you SHOULD check the key manually, see: '.. + 'https://data.iana.org/root-anchors/draft-icann-dnssec-trust-anchor.html#sigs') + return rr +end + +-- Load the module (check for FFI) local ffi_ok, ffi = pcall(require, 'ffi') if not ffi_ok then - return { error = 'FFI not available, trust_anchors disabled.' } + -- Simplified TA management, no RFC5011 automatics + return { + -- Reuse Lua/C global function + add = trustanchor, + -- Simplified trust anchor management + config = function (path) + if not path then return end + if not io.open(path, 'r') then + local rr, err = bootstrap() + if not rr then print(err) return false end + io.open(path, 'w'):write(rr..'\n') + end + for line in io.lines(path) do + trustanchor(line) + end + end, + -- Disabled + set_insecure = function () error('[ ta ] FFI not available, this function is disabled') end, + } end local kres = require('kres') local C = ffi.C @@ -147,25 +207,6 @@ local function keyset_write(keyset, path) os.rename(path..'.lock', path) end --- Fetch over HTTPS with peert cert checked -local function https_fetch(url, ca) - local ssl_ok, https = pcall(require, 'ssl.https') - local ltn_ok, ltn12 = pcall(require, 'ltn12') - if not ssl_ok or not ltn_ok then - return nil, 'luasec and luasocket needed for root TA bootstrap' - end - local resp = {} - local r, c, h, s = https.request{ - url = url, - cafile = ca, - verify = {'peer', 'fail_if_no_peer_cert' }, - protocol = 'tlsv1_2', - sink = ltn12.sink.table(resp), - } - if r == nil then return r, c end - return resp[1] -end - -- TA store management local trust_anchors = { keyset = {}, @@ -210,19 +251,21 @@ local trust_anchors = { return true end, -- Load keys from a file (managed) - config = function (path, unmanaged, bootstrap) - bootstrap = true + config = function (path, unmanaged) -- Bootstrap if requested and keyfile doesn't exist - if bootstrap and not io.open(path, 'r') then - if not trust_anchors.bootstrap() then + if not io.open(path, 'r') then + local rr, msg = bootstrap() + print(msg) + if not rr then error('you MUST obtain the root TA manually, see: '.. 'http://knot-resolver.readthedocs.org/en/latest/daemon.html#enabling-dnssec') end + trustanchor(rr) elseif path == trust_anchors.file_current then return end -- Parse new keys - local new_keys = require('zonefile').parse_file(path) + local new_keys = require('zonefile').file(path) trust_anchors.file_current = path if unmanaged then trust_anchors.file_current = nil end trust_anchors.keyset = {} @@ -233,11 +276,7 @@ local trust_anchors = { end, -- Add DS/DNSKEY record(s) (unmanaged) add = function (keystr) - local store = kres.context().trust_anchors - return require('zonefile').parser(function (p) - local rr = p:current_rr() - C.kr_ta_add(store, rr.owner, rr.type, rr.ttl, rr.rdata, #rr.rdata) - end):read(keystr..'\n') + return trustanchor(keystr) end, -- Negative TA management set_insecure = function (list) @@ -249,33 +288,6 @@ local trust_anchors = { end trust_anchors.insecure = list end, - bootstrap = function (url, ca) - -- Fetch root anchors in XML over HTTPS - -- @todo ICANN certificate is verified against current CA - -- this is not ideal, as it should rather verify .xml signature which - -- is signed by ICANN long-lived cert, but luasec has no PKCS7 - ca = ca or etcdir..'/icann-ca.pem' - url = url or 'https://data.iana.org/root-anchors/root-anchors.xml' - local xml, err = https_fetch(url, ca) - if not xml then - print(string.format('[ ta ] fetch of "%s" failed: %s', url, err)) - return false - end - -- Parse root trust anchor - local fields = {} - string.gsub(xml, "<([%w]+).->([^<]+)</[%w]+>", function (k, v) fields[k] = v end) - local rrdata = string.format('%s %s %s %s', fields.KeyDigest, fields.Algorithm, fields.DigestType, fields.Digest) - local rr = string.format('%s 0 IN DS %s', fields.TrustAnchor, rrdata) - -- Add to key set, create an empty keyset file to be filled - if trust_anchors.add(rr) ~= 0 then - print(string.format('[ ta ] invalid format of the RR "%s"', rr)) - return false - end - print(string.format('[ ta ] bootstrapped root anchor "%s"', rrdata)) - print('[ ta ] warning: you SHOULD check the key manually, see: '.. - 'https://data.iana.org/root-anchors/draft-icann-dnssec-trust-anchor.html#sigs') - return true - end, } return trust_anchors \ No newline at end of file diff --git a/daemon/main.c b/daemon/main.c index 62375a40e30bdd8d1a7bd090e729703fb62e731d..4eda21ac848fdef101115d249b2f0487bf4237bf 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -18,9 +18,11 @@ #include <string.h> #include <getopt.h> #include <uv.h> +#include <assert.h> #include <contrib/cleanup.h> #include <contrib/ucw/mempool.h> #include <contrib/ccan/asprintf/asprintf.h> +#include <libknot/error.h> #include "lib/defines.h" #include "lib/resolve.h" @@ -141,7 +143,7 @@ static void help(int argc, char *argv[]) " [rundir] Path to the working directory (default: .)\n"); } -static struct worker_ctx *init_worker(uv_loop_t *loop, struct engine *engine, mm_ctx_t *pool, int worker_id, int worker_count) +static struct worker_ctx *init_worker(uv_loop_t *loop, struct engine *engine, knot_mm_t *pool, int worker_id, int worker_count) { /* Load bindings */ engine_lualib(engine, "modules", lib_modules); @@ -333,9 +335,9 @@ int main(int argc, char **argv) uv_signal_start(&sigint, signal_handler, SIGINT); uv_signal_start(&sigterm, signal_handler, SIGTERM); /* Create a server engine. */ - mm_ctx_t pool = { + knot_mm_t pool = { .ctx = mp_new (4096), - .alloc = (mm_alloc_t) mp_alloc + .alloc = (knot_mm_alloc_t) mp_alloc }; struct engine engine; ret = engine_init(&engine, &pool); diff --git a/daemon/network.c b/daemon/network.c index 103823dc682369aac5f20cd84601a700124a3cfa..ace172595b5930819be06dc82f0d0516edeb118c 100644 --- a/daemon/network.c +++ b/daemon/network.c @@ -14,6 +14,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <unistd.h> #include "daemon/network.h" #include "daemon/worker.h" #include "daemon/io.h" diff --git a/daemon/worker.c b/daemon/worker.c index b05643a2726f2a99ad4137d704eed1fa25631e83..b541b1eee70a811166a56f1879336b5e0a9b89a1 100644 --- a/daemon/worker.c +++ b/daemon/worker.c @@ -20,10 +20,12 @@ #include <libknot/descriptor.h> #include <contrib/ucw/lib.h> #include <contrib/ucw/mempool.h> +#include <contrib/wire.h> #if defined(__GLIBC__) && defined(_GNU_SOURCE) #include <malloc.h> #endif - +#include <assert.h> +#include "lib/utils.h" #include "daemon/worker.h" #include "daemon/engine.h" #include "daemon/io.h" @@ -227,9 +229,9 @@ static struct qr_task *qr_task_create(struct worker_ctx *worker, uv_handle_t *ha } /* Recycle available mempool if possible */ - mm_ctx_t pool = { + knot_mm_t pool = { .ctx = pool_take(worker), - .alloc = (mm_alloc_t) mp_alloc + .alloc = (knot_mm_alloc_t) mp_alloc }; /* Create resolution task */ @@ -263,9 +265,14 @@ static struct qr_task *qr_task_create(struct worker_ctx *worker, uv_handle_t *ha task->retry.data = task; task->timeout.data = task; task->on_complete = NULL; + task->req.qsource.key = NULL; + task->req.qsource.addr = NULL; /* Remember query source addr */ if (addr) { - memcpy(&task->source.addr, addr, sockaddr_len(addr)); + size_t addr_len = sizeof(struct sockaddr_in); + if (addr->sa_family == AF_INET6) + addr_len = sizeof(struct sockaddr_in6); + memcpy(&task->source.addr, addr, addr_len); task->req.qsource.addr = (const struct sockaddr *)&task->source.addr; } else { task->source.addr.ip4.sin_family = AF_UNSPEC; @@ -505,10 +512,10 @@ static void subreq_finalize(struct qr_task *task, const struct sockaddr *packet_ map_del(&task->worker->outstanding, key); } /* Notify waiting tasks. */ - struct kr_query *leader_qry = TAIL(task->req.rplan.pending); + struct kr_query *leader_qry = array_tail(task->req.rplan.pending); for (size_t i = task->waiting.len; i --> 0;) { struct qr_task *follower = task->waiting.at[i]; - struct kr_query *qry = TAIL(follower->req.rplan.pending); + struct kr_query *qry = array_tail(follower->req.rplan.pending); /* Reuse MSGID and 0x20 secret */ if (qry) { qry->id = leader_qry->id; @@ -773,7 +780,7 @@ int worker_reserve(struct worker_ctx *worker, size_t ring_maxlen) return kr_error(ENOMEM); memset(&worker->pkt_pool, 0, sizeof(worker->pkt_pool)); worker->pkt_pool.ctx = mp_new (4 * sizeof(knot_pkt_t)); - worker->pkt_pool.alloc = (mm_alloc_t) mp_alloc; + worker->pkt_pool.alloc = (knot_mm_alloc_t) mp_alloc; worker->outstanding = map_make(); return kr_ok(); } diff --git a/daemon/worker.h b/daemon/worker.h index 00a67a56bed24fd2ee27163a3c2cbe4e142e82f2..eed855d82d72a72e1b86915ac4736ec498c9298e 100644 --- a/daemon/worker.h +++ b/daemon/worker.h @@ -16,8 +16,6 @@ #pragma once -#include <libknot/internal/mempattern.h> - #include "daemon/engine.h" #include "lib/generic/array.h" #include "lib/generic/map.h" @@ -52,7 +50,7 @@ struct worker_ctx { map_t outstanding; mp_freelist_t pools; mp_freelist_t ioreqs; - mm_ctx_t pkt_pool; + knot_mm_t pkt_pool; }; /* Worker callback */ diff --git a/doc/build.rst b/doc/build.rst index 9d0dccb882254649f0762e37b27fc6c19c689049..0374be556f45cf8e0df87de48dbf4c87ef915cd5 100644 --- a/doc/build.rst +++ b/doc/build.rst @@ -30,7 +30,7 @@ The following is a list of software required to build Knot DNS Resolver from sou "`GNU Make`_ 3.80+", "*all*", "*(build only)*" "`pkg-config`_", "*all*", "*(build only)* [#]_" "C compiler", "*all*", "*(build only)* [#]_" - "libknot_ 2.0+", "*all*", "Knot DNS library (requires autotools, GnuTLS and Jansson)." + "libknot_ 2.1+", "*all*", "Knot DNS library (requires autotools, GnuTLS and Jansson)." "LuaJIT_ 2.0+", "``daemon``", "Embedded scripting language." "libuv_ 1.7+", "``daemon``", "Multiplatform I/O and services (libuv_ 1.0 with limitations [#]_)." @@ -45,7 +45,6 @@ There are also *optional* packages that enable specific functionality in Knot DN "hiredis_", "``modules/redis``", "To build redis backend module." "Go_ 1.5+", "``modules``", "Build modules written in Go." "cmocka_", "``unit tests``", "Unit testing framework." - "Python_", "``integration tests``", "For test scripts." "Doxygen_", "``documentation``", "Generating API documentation." "Sphinx_", "``documentation``", "Building this HTML/PDF documentation." "breathe_", "``documentation``", "Exposing Doxygen API doc to Sphinx." @@ -169,31 +168,37 @@ By default the resolver library is built as a dynamic library with versioned ABI When the library is linked statically, it usually produces a smaller binary. However linking it to various C modules might violate ODR and increase the size. -Building dependencies -~~~~~~~~~~~~~~~~~~~~~ +Resolving dependencies +~~~~~~~~~~~~~~~~~~~~~~ -Several dependencies may not be in the packages yet, the script pulls and installs all dependencies in a chroot. -You can avoid rebuilding dependencies by specifying `BUILD_IGNORE` variable, see the Dockerfile_ for example. -Usually you only really need to rebuild libknot_. +The build system relies on `pkg-config`_ to find dependencies. +You can override it to force custom versions of the software by environment variables. .. code-block:: bash - $ export FAKEROOT="${HOME}/.local" - $ export PKG_CONFIG_PATH="${FAKEROOT}/lib/pkgconfig" - $ export BUILD_IGNORE="..." # Ignore installed dependencies - $ ./scripts/bootstrap-depends.sh ${FAKEROOT} + $ make libknot_CFLAGS="-I/opt/include" libknot_LIBS="-L/opt/lib -lknot -ldnssec" -.. note:: The build system relies on `pkg-config`_ to find dependencies. - You can override it to force custom versions of the software by environment variables. +Optional dependencies may be disabled as well using ``HAS_x=yes|no`` variable. - .. code-block:: bash +.. code-block:: bash - $ make libknot_CFLAGS="-I/opt/include" libknot_LIBS="-L/opt/lib -lknot -lknot-int -ldnssec" + $ make HAS_go=no HAS_cmocka=no .. warning:: If the dependencies lie outside of library search path, you need to add them somehow. Try ``LD_LIBRARY_PATH`` on Linux/BSD, and ``DYLD_FALLBACK_LIBRARY_PATH`` on OS X. Otherwise you need to add the locations to linker search path. +Several dependencies may not be in the packages yet, the script pulls and installs all dependencies in a chroot. +You can avoid rebuilding dependencies by specifying `BUILD_IGNORE` variable, see the Dockerfile_ for example. +Usually you only really need to rebuild libknot_. + +.. code-block:: bash + + $ export FAKEROOT="${HOME}/.local" + $ export PKG_CONFIG_PATH="${FAKEROOT}/lib/pkgconfig" + $ export BUILD_IGNORE="..." # Ignore installed dependencies + $ ./scripts/bootstrap-depends.sh ${FAKEROOT} + Building extras ~~~~~~~~~~~~~~~ diff --git a/lib/README.rst b/lib/README.rst index 56b94dc27439b6dc68de9dfb70938e54e4658a73..ac0d5e94a2efd4db7a0d945e6ff192eecc9cb289 100644 --- a/lib/README.rst +++ b/lib/README.rst @@ -259,10 +259,6 @@ In layers that either begin or finalize, you can walk the list of resolved queri local last = req:resolved() print(last.type) - last = last:next() - if last ~= nil then - print(last.type) - end As described in the layers, you can not only retrieve information about current query, but also push new ones or pop old ones. diff --git a/lib/cache.c b/lib/cache.c index 50347f7220d796f20bb6e2a01bd1813aca96bf4e..f9c9b62d35a0ff7331b2f8e7f6031ccd4db5f066 100644 --- a/lib/cache.c +++ b/lib/cache.c @@ -20,8 +20,7 @@ #include <unistd.h> #include <errno.h> -#include <libknot/internal/mempattern.h> -#include <libknot/internal/namedb/namedb_lmdb.h> +#include <libknot/db/db_lmdb.h> #include <libknot/errcode.h> #include <libknot/descriptor.h> #include <libknot/dname.h> @@ -48,8 +47,8 @@ static void assert_right_version(struct kr_cache *cache) if (ret != 0) { return; /* N/A, doesn't work. */ } - namedb_val_t key = { KEY_VERSION, 2 }; - namedb_val_t val = { NULL, 0 }; + knot_db_val_t key = { KEY_VERSION, 2 }; + knot_db_val_t val = { NULL, 0 }; ret = txn_api(&txn)->find(&txn.t, &key, &val, 0); if (ret == 0) { /* Version is OK */ kr_cache_txn_abort(&txn); @@ -70,13 +69,13 @@ static void assert_right_version(struct kr_cache *cache) } } -int kr_cache_open(struct kr_cache *cache, const namedb_api_t *api, void *opts, mm_ctx_t *mm) +int kr_cache_open(struct kr_cache *cache, const knot_db_api_t *api, void *opts, knot_mm_t *mm) { if (!cache) { return kr_error(EINVAL); } /* Open cache */ - cache->api = (api == NULL) ? namedb_lmdb_api() : api; + cache->api = (api == NULL) ? knot_db_lmdb_api() : api; int ret = cache->api->init(&cache->db, mm, opts); if (ret != 0) { return ret; @@ -109,7 +108,7 @@ int kr_cache_txn_begin(struct kr_cache *cache, struct kr_cache_txn *txn, unsigne } else { /* Count statistics */ txn->owner = cache; - if (flags & NAMEDB_RDONLY) { + if (flags & KNOT_DB_RDONLY) { cache->stats.txn_read += 1; } else { cache->stats.txn_write += 1; @@ -166,8 +165,8 @@ static struct kr_cache_entry *lookup(struct kr_cache_txn *txn, uint8_t tag, cons } /* Look up and return value */ - namedb_val_t key = { keybuf, key_len }; - namedb_val_t val = { NULL, 0 }; + knot_db_val_t key = { keybuf, key_len }; + knot_db_val_t val = { NULL, 0 }; int ret = txn_api(txn)->find(&txn->t, &key, &val, 0); if (ret != KNOT_EOK) { return NULL; @@ -220,7 +219,7 @@ int kr_cache_peek(struct kr_cache_txn *txn, uint8_t tag, const knot_dname_t *nam return ret; } -static void entry_write(struct kr_cache_entry *dst, struct kr_cache_entry *header, namedb_val_t data) +static void entry_write(struct kr_cache_entry *dst, struct kr_cache_entry *header, knot_db_val_t data) { assert(dst && header); memcpy(dst, header, sizeof(*header)); @@ -229,7 +228,7 @@ static void entry_write(struct kr_cache_entry *dst, struct kr_cache_entry *heade } int kr_cache_insert(struct kr_cache_txn *txn, uint8_t tag, const knot_dname_t *name, uint16_t type, - struct kr_cache_entry *header, namedb_val_t data) + struct kr_cache_entry *header, knot_db_val_t data) { if (!txn_is_valid(txn) || !name || !header) { return kr_error(EINVAL); @@ -241,13 +240,13 @@ int kr_cache_insert(struct kr_cache_txn *txn, uint8_t tag, const knot_dname_t *n if (key_len == 0) { return kr_error(EILSEQ); } - namedb_val_t key = { keybuf, key_len }; - namedb_val_t entry = { NULL, sizeof(*header) + data.len }; - const namedb_api_t *db_api = txn_api(txn); + knot_db_val_t key = { keybuf, key_len }; + knot_db_val_t entry = { NULL, sizeof(*header) + data.len }; + const knot_db_api_t *db_api = txn_api(txn); /* LMDB can do late write and avoid copy */ txn->owner->stats.insert += 1; - if (db_api == namedb_lmdb_api()) { + if (db_api == knot_db_lmdb_api()) { int ret = db_api->insert(&txn->t, &key, &entry, 0); if (ret != 0) { return ret; @@ -281,7 +280,7 @@ int kr_cache_remove(struct kr_cache_txn *txn, uint8_t tag, const knot_dname_t *n if (key_len == 0) { return kr_error(EILSEQ); } - namedb_val_t key = { keybuf, key_len }; + knot_db_val_t key = { keybuf, key_len }; txn->owner->stats.delete += 1; return txn_api(txn)->del(&txn->t, &key); } @@ -331,7 +330,7 @@ int kr_cache_peek_rank(struct kr_cache_txn *txn, uint8_t tag, const knot_dname_t return found->rank; } -int kr_cache_materialize(knot_rrset_t *dst, const knot_rrset_t *src, uint32_t drift, mm_ctx_t *mm) +int kr_cache_materialize(knot_rrset_t *dst, const knot_rrset_t *src, uint32_t drift, knot_mm_t *mm) { if (!dst || !src) { return kr_error(EINVAL); @@ -391,7 +390,7 @@ int kr_cache_insert_rr(struct kr_cache_txn *txn, const knot_rrset_t *rr, uint16_ rd = kr_rdataset_next(rd); } - namedb_val_t data = { rr->rrs.data, knot_rdataset_size(&rr->rrs) }; + knot_db_val_t data = { rr->rrs.data, knot_rdataset_size(&rr->rrs) }; return kr_cache_insert(txn, KR_CACHE_RR, rr->owner, rr->type, &header, data); } @@ -443,6 +442,6 @@ int kr_cache_insert_rrsig(struct kr_cache_txn *txn, const knot_rrset_t *rr, uint } uint16_t covered = knot_rrsig_type_covered(&rr->rrs, 0); - namedb_val_t data = { rr->rrs.data, knot_rdataset_size(&rr->rrs) }; + knot_db_val_t data = { rr->rrs.data, knot_rdataset_size(&rr->rrs) }; return kr_cache_insert(txn, KR_CACHE_SIG, rr->owner, covered, &header, data); } diff --git a/lib/cache.h b/lib/cache.h index 3fabea7ced0d18e8764e2af1434a56d308d10607..89ce695f90345479fc126130dcb6eb23d3ab725b 100644 --- a/lib/cache.h +++ b/lib/cache.h @@ -17,7 +17,7 @@ #pragma once #include <libknot/rrset.h> -#include <libknot/internal/namedb/namedb.h> +#include <libknot/db/db.h> #include "lib/defines.h" /** Cache entry tag */ @@ -61,8 +61,8 @@ struct kr_cache_entry */ struct kr_cache { - namedb_t *db; /**< Storage instance */ - const namedb_api_t *api; /**< Storage engine */ + knot_db_t *db; /**< Storage instance */ + const knot_db_api_t *api; /**< Storage engine */ struct { uint32_t hit; /**< Number of cache hits */ uint32_t miss; /**< Number of cache misses */ @@ -75,7 +75,7 @@ struct kr_cache /** Cache transaction */ struct kr_cache_txn { - namedb_txn_t t; /**< Storage transaction */ + knot_db_txn_t t; /**< Storage transaction */ struct kr_cache *owner; /**< Transaction owner */ }; @@ -88,7 +88,7 @@ struct kr_cache_txn { * @return 0 or an error code */ KR_EXPORT -int kr_cache_open(struct kr_cache *cache, const namedb_api_t *api, void *opts, mm_ctx_t *mm); +int kr_cache_open(struct kr_cache *cache, const knot_db_api_t *api, void *opts, knot_mm_t *mm); /** * Close persistent cache. @@ -153,7 +153,7 @@ int kr_cache_peek(struct kr_cache_txn *txn, uint8_t tag, const knot_dname_t *nam */ KR_EXPORT int kr_cache_insert(struct kr_cache_txn *txn, uint8_t tag, const knot_dname_t *name, uint16_t type, - struct kr_cache_entry *header, namedb_val_t data); + struct kr_cache_entry *header, knot_db_val_t data); /** * Remove asset from cache. @@ -207,7 +207,7 @@ int kr_cache_peek_rr(struct kr_cache_txn *txn, knot_rrset_t *rr, uint16_t *rank, * @return 0 or an errcode */ KR_EXPORT -int kr_cache_materialize(knot_rrset_t *dst, const knot_rrset_t *src, uint32_t drift, mm_ctx_t *mm); +int kr_cache_materialize(knot_rrset_t *dst, const knot_rrset_t *src, uint32_t drift, knot_mm_t *mm); /** * Insert RRSet into cache, replacing any existing data. diff --git a/lib/dnssec.c b/lib/dnssec.c index 1577aaab234bea7ca834f0bc40584b1fadb099ac..91680adbf82880801de0ea39a64503c457821cee 100644 --- a/lib/dnssec.c +++ b/lib/dnssec.c @@ -27,7 +27,7 @@ #include <libknot/rrtype/dnskey.h> #include <libknot/rrtype/nsec.h> #include <libknot/rrtype/rrsig.h> - +#include <contrib/wire.h> #include "lib/defines.h" #include "lib/dnssec/nsec.h" diff --git a/lib/dnssec.h b/lib/dnssec.h index 82ea7bccfa290a0e2970ed3091ea8b05c8d0072d..b6d41df969d326428155e4c0064ed20d03aea731 100644 --- a/lib/dnssec.h +++ b/lib/dnssec.h @@ -17,7 +17,6 @@ #pragma once #include "lib/defines.h" -#include <libknot/internal/consts.h> #include <libknot/packet/pkt.h> /** diff --git a/lib/dnssec/nsec.c b/lib/dnssec/nsec.c index 7106a968e54733242fb27427de1ff301120d2825..a9a0532366c90af6c92f7c8194e3fc85e0167735 100644 --- a/lib/dnssec/nsec.c +++ b/lib/dnssec/nsec.c @@ -138,7 +138,7 @@ static int name_error_response_check_rr(int *flags, const knot_rrset_t *nsec, } int kr_nsec_name_error_response_check(const knot_pkt_t *pkt, knot_section_t section_id, - const knot_dname_t *sname, mm_ctx_t *pool) + const knot_dname_t *sname) { const knot_pktsection_t *sec = knot_pkt_section(pkt, section_id); if (!sec || !sname) { diff --git a/lib/dnssec/nsec.h b/lib/dnssec/nsec.h index 41bdc1a746824124ba673bc29ac0176ee3cc7609..21ac6e4d307073490a89d12a134351f4e905aa50 100644 --- a/lib/dnssec/nsec.h +++ b/lib/dnssec/nsec.h @@ -16,8 +16,6 @@ #pragma once -#include <libknot/internal/consts.h> -#include <libknot/internal/mempattern.h> #include <libknot/packet/pkt.h> /** @@ -35,11 +33,10 @@ bool kr_nsec_bitmap_contains_type(const uint8_t *bm, uint16_t bm_size, uint16_t * @param pkt Packet structure to be processed. * @param section_id Packet section to be processed. * @param sname Name to be checked. - * @param pool * @return 0 or error code. */ int kr_nsec_name_error_response_check(const knot_pkt_t *pkt, knot_section_t section_id, - const knot_dname_t *sname, mm_ctx_t *pool); + const knot_dname_t *sname); /** * No data response check (RFC4035 3.1.3.1; RFC4035 5.4, bullet 1). diff --git a/lib/dnssec/nsec3.c b/lib/dnssec/nsec3.c index dcfa4053e72353d1d76f1d8930e4d21de426973e..a0b22d46d3b219ad7772ac8619b022a6fab3c37d 100644 --- a/lib/dnssec/nsec3.c +++ b/lib/dnssec/nsec3.c @@ -21,7 +21,7 @@ #include <dnssec/error.h> #include <dnssec/nsec.h> #include <libknot/descriptor.h> -#include <libknot/internal/base32hex.h> +#include <contrib/base32hex.h> #include <libknot/rrset.h> #include <libknot/rrtype/nsec3.h> @@ -107,7 +107,7 @@ static int read_owner_hash(dnssec_binary_t *hash, size_t max_hash_size, const kn int32_t ret = base32hex_decode(nsec3->owner + 1, nsec3->owner[0], hash->data, max_hash_size); if (ret < 0) { - return ret; + return kr_error(EILSEQ); } hash->size = ret; diff --git a/lib/dnssec/nsec3.h b/lib/dnssec/nsec3.h index b4a50405c5121881a69f2052eb158e95b4150747..50e27e43172ae2db5ac7a362adbf57ec2df87bb4 100644 --- a/lib/dnssec/nsec3.h +++ b/lib/dnssec/nsec3.h @@ -16,8 +16,6 @@ #pragma once -#include <libknot/internal/consts.h> -#include <libknot/internal/mempattern.h> #include <libknot/packet/pkt.h> /** diff --git a/lib/dnssec/packet/pkt.c b/lib/dnssec/packet/pkt.c deleted file mode 100644 index 91088aba197958da11ac5de5cf5072a351f048de..0000000000000000000000000000000000000000 --- a/lib/dnssec/packet/pkt.c +++ /dev/null @@ -1,56 +0,0 @@ -/* Copyright (C) 2015 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/internal/consts.h> - -#include "lib/dnssec/packet/pkt.h" - -/** - * Search in section for given type. - * @param sec Packet section. - * @param type Type to search for. - * @return True if found. - */ -static bool section_has_type(const knot_pktsection_t *sec, uint16_t type) -{ - if (!sec) { - return false; - } - - for (unsigned i = 0; i < sec->count; ++i) { - const knot_rrset_t *rr = knot_pkt_rr(sec, i); - if (rr->type == type) { - return true; - } - } - - return false; -} - -bool _knot_pkt_has_type(const knot_pkt_t *pkt, uint16_t type) -{ - if (!pkt) { - return false; - } - - if (section_has_type(knot_pkt_section(pkt, KNOT_ANSWER), type)) { - return true; - } - if (section_has_type(knot_pkt_section(pkt, KNOT_AUTHORITY), type)) { - return true; - } - return section_has_type(knot_pkt_section(pkt, KNOT_ADDITIONAL), type); -} diff --git a/lib/dnssec/packet/pkt.h b/lib/dnssec/packet/pkt.h deleted file mode 100644 index 429ad0fb882716aa216186208198c838e6f5aac7..0000000000000000000000000000000000000000 --- a/lib/dnssec/packet/pkt.h +++ /dev/null @@ -1,27 +0,0 @@ -/* Copyright (C) 2015 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 <libknot/packet/pkt.h> - -/** - * Check whether packet contains given type. - * @param pkt Packet to seek through. - * @param type RR type to search for. - * @return True if found. - */ -bool _knot_pkt_has_type(const knot_pkt_t *pkt, uint16_t type); diff --git a/lib/dnssec/rrtype/ds.h b/lib/dnssec/rrtype/ds.h deleted file mode 100644 index 32e131c310679259e25e44a3066e8b40b80becd7..0000000000000000000000000000000000000000 --- a/lib/dnssec/rrtype/ds.h +++ /dev/null @@ -1,50 +0,0 @@ -/* Copyright (C) 2015 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 <libknot/rdataset.h> - -static inline -uint16_t _knot_ds_ktag(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)); -} - -static inline -uint8_t _knot_ds_alg(const knot_rdataset_t *rrs, size_t pos) -{ - KNOT_RDATASET_CHECK(rrs, pos, return 0); - return *knot_rdata_offset(rrs, pos, 2); -} - -static inline -uint8_t _knot_ds_dtype(const knot_rdataset_t *rrs, size_t pos) -{ - KNOT_RDATASET_CHECK(rrs, pos, return 0); - return *knot_rdata_offset(rrs, pos, 3); -} - -static inline -void _knot_ds_digest(const knot_rdataset_t *rrs, size_t pos, - uint8_t **digest, uint16_t *digest_size) -{ - KNOT_RDATASET_CHECK(rrs, pos, return); - *digest = knot_rdata_offset(rrs, pos, 4); - const knot_rdata_t *rr = knot_rdataset_at(rrs, pos); - *digest_size = knot_rdata_rdlen(rr) - 4; -} diff --git a/lib/dnssec/signature.c b/lib/dnssec/signature.c index 1570ab855b217d9da65c2ba9b78eb0a49cc34821..78af44c03e461b89bf9ae6be37b9bceeed9d16e7 100644 --- a/lib/dnssec/signature.c +++ b/lib/dnssec/signature.c @@ -26,10 +26,10 @@ #include <libknot/packet/wire.h> #include <libknot/rrset.h> #include <libknot/rrtype/rrsig.h> +#include <libknot/rrtype/ds.h> #include "lib/defines.h" #include "lib/utils.h" -#include "lib/dnssec/rrtype/ds.h" #include "lib/dnssec/signature.h" static int authenticate_ds(const dnssec_key_t *key, dnssec_binary_t *ds_rdata, uint8_t digest_type) @@ -69,7 +69,7 @@ int kr_authenticate_referral(const knot_rrset_t *ref, const dnssec_key_t *key) .size = knot_rdata_rdlen(rd), .data = knot_rdata_data(rd) }; - ret = authenticate_ds(key, &ds_rdata, _knot_ds_dtype(&ref->rrs, i)); + ret = authenticate_ds(key, &ds_rdata, knot_ds_digest_type(&ref->rrs, i)); if (ret == 0) { /* Found a good DS */ break; } diff --git a/lib/layer/iterate.c b/lib/layer/iterate.c index 69ec3714c678c924d48eb7e1ed846ae844cae838..32485306fec133b19b9d68543b7578087f7f4dbf 100644 --- a/lib/layer/iterate.c +++ b/lib/layer/iterate.c @@ -15,6 +15,7 @@ */ #include <sys/time.h> +#include <assert.h> #include <libknot/descriptor.h> #include <libknot/rrtype/rdname.h> @@ -520,7 +521,7 @@ static int resolve(knot_layer_t *ctx, knot_pkt_t *pkt) } #ifndef NDEBUG - lookup_table_t *rcode = lookup_by_id(knot_rcode_names, knot_wire_get_rcode(pkt->wire)); + const knot_lookup_t *rcode = knot_lookup_by_id(knot_rcode_names, knot_wire_get_rcode(pkt->wire)); #endif /* Check response code. */ diff --git a/lib/layer/pktcache.c b/lib/layer/pktcache.c index 3330e20f688945765bcb0fd94c25c92efd7702d8..b9b6db957fa3d64f6a72322dd633be8ed9fab543 100644 --- a/lib/layer/pktcache.c +++ b/lib/layer/pktcache.c @@ -110,7 +110,7 @@ static int pktcache_peek(knot_layer_t *ctx, knot_pkt_t *pkt) /* Prepare read transaction */ struct kr_cache_txn txn; struct kr_cache *cache = &req->ctx->cache; - if (kr_cache_txn_begin(cache, &txn, NAMEDB_RDONLY) != 0) { + if (kr_cache_txn_begin(cache, &txn, KNOT_DB_RDONLY) != 0) { return ctx->state; } @@ -191,7 +191,7 @@ static int pktcache_stash(knot_layer_t *ctx, knot_pkt_t *pkt) if (kr_cache_txn_begin(&req->ctx->cache, &txn, 0) != 0) { return ctx->state; /* Couldn't acquire cache, ignore. */ } - namedb_val_t data = { pkt->wire, pkt->size }; + knot_db_val_t data = { pkt->wire, pkt->size }; struct kr_cache_entry header = { .timestamp = qry->timestamp.tv_sec, .ttl = ttl, diff --git a/lib/layer/rrcache.c b/lib/layer/rrcache.c index eff217023c549ca4704311486a7971639bb37439..ca5bdedf19fb55a39318dc8b693b9bda43079039 100644 --- a/lib/layer/rrcache.c +++ b/lib/layer/rrcache.c @@ -80,7 +80,7 @@ static int loot_rr(struct kr_cache_txn *txn, knot_pkt_t *pkt, const knot_dname_t static int loot_rrcache(struct kr_cache *cache, knot_pkt_t *pkt, struct kr_query *qry, uint16_t rrtype, bool dobit) { struct kr_cache_txn txn; - int ret = kr_cache_txn_begin(cache, &txn, NAMEDB_RDONLY); + int ret = kr_cache_txn_begin(cache, &txn, KNOT_DB_RDONLY); if (ret != 0) { return ret; } @@ -209,7 +209,7 @@ static int stash_commit(map_t *stash, struct kr_query *qry, struct kr_cache_txn return map_walk(stash, &commit_rr, &baton); } -static void stash_glue(map_t *stash, knot_pkt_t *pkt, const knot_dname_t *ns_name, mm_ctx_t *pool) +static void stash_glue(map_t *stash, knot_pkt_t *pkt, const knot_dname_t *ns_name, knot_mm_t *pool) { const knot_pktsection_t *additional = knot_pkt_section(pkt, KNOT_ADDITIONAL); for (unsigned i = 0; i < additional->count; ++i) { @@ -223,7 +223,7 @@ static void stash_glue(map_t *stash, knot_pkt_t *pkt, const knot_dname_t *ns_nam } /* @internal DS is special and is present only parent-side */ -static void stash_ds(struct kr_query *qry, knot_pkt_t *pkt, map_t *stash, mm_ctx_t *pool) +static void stash_ds(struct kr_query *qry, knot_pkt_t *pkt, map_t *stash, knot_mm_t *pool) { const knot_pktsection_t *authority = knot_pkt_section(pkt, KNOT_AUTHORITY); for (unsigned i = 0; i < authority->count; ++i) { @@ -234,7 +234,7 @@ static void stash_ds(struct kr_query *qry, knot_pkt_t *pkt, map_t *stash, mm_ctx } } -static int stash_authority(struct kr_query *qry, knot_pkt_t *pkt, map_t *stash, mm_ctx_t *pool) +static int stash_authority(struct kr_query *qry, knot_pkt_t *pkt, map_t *stash, knot_mm_t *pool) { const knot_pktsection_t *authority = knot_pkt_section(pkt, KNOT_AUTHORITY); for (unsigned i = 0; i < authority->count; ++i) { @@ -253,7 +253,7 @@ static int stash_authority(struct kr_query *qry, knot_pkt_t *pkt, map_t *stash, return kr_ok(); } -static int stash_answer(struct kr_query *qry, knot_pkt_t *pkt, map_t *stash, mm_ctx_t *pool) +static int stash_answer(struct kr_query *qry, knot_pkt_t *pkt, map_t *stash, knot_mm_t *pool) { /* Work with QNAME, as minimised name data is cacheable. */ const knot_dname_t *cname_begin = knot_pkt_qname(pkt); @@ -312,7 +312,7 @@ static int rrcache_stash(knot_layer_t *ctx, knot_pkt_t *pkt) ret = stash_answer(qry, pkt, &stash, &req->pool); } /* Cache authority only if chasing referral/cname chain */ - if (!is_auth || qry != TAIL(req->rplan.pending)) { + if (!is_auth || qry != array_tail(req->rplan.pending)) { ret = stash_authority(qry, pkt, &stash, &req->pool); } /* Cache DS records in referrals */ diff --git a/lib/layer/validate.c b/lib/layer/validate.c index 6f97bb620efc84b8885fd4ad7a4a8f2fa70273e9..88c50e11b3aa728afaf7cf2fd8c7d2b2d448ad09 100644 --- a/lib/layer/validate.c +++ b/lib/layer/validate.c @@ -26,7 +26,6 @@ #include "lib/dnssec/nsec.h" #include "lib/dnssec/nsec3.h" -#include "lib/dnssec/packet/pkt.h" #include "lib/dnssec.h" #include "lib/layer.h" #include "lib/resolve.h" @@ -37,6 +36,44 @@ #define DEBUG_MSG(qry, fmt...) QRDEBUG(qry, "vldr", fmt) +/** + * Search in section for given type. + * @param sec Packet section. + * @param type Type to search for. + * @return True if found. + */ +static bool section_has_type(const knot_pktsection_t *sec, uint16_t type) +{ + if (!sec) { + return false; + } + + for (unsigned i = 0; i < sec->count; ++i) { + const knot_rrset_t *rr = knot_pkt_rr(sec, i); + if (rr->type == type) { + return true; + } + } + + return false; +} + +static bool pkt_has_type(const knot_pkt_t *pkt, uint16_t type) +{ + if (!pkt) { + return false; + } + + if (section_has_type(knot_pkt_section(pkt, KNOT_ANSWER), type)) { + return true; + } + if (section_has_type(knot_pkt_section(pkt, KNOT_AUTHORITY), type)) { + return true; + } + return section_has_type(knot_pkt_section(pkt, KNOT_ADDITIONAL), type); +} + + /** @internal Baton for validate_section */ struct validate_baton { const knot_pkt_t *pkt; @@ -63,7 +100,7 @@ static int validate_rrset(const char *key, void *val, void *data) } static int validate_section(struct kr_query *qry, knot_pkt_t *answer, - knot_section_t section_id, mm_ctx_t *pool, + knot_section_t section_id, knot_mm_t *pool, bool has_nsec3) { const knot_pktsection_t *sec = knot_pkt_section(answer, section_id); @@ -120,7 +157,7 @@ fail: return ret; } -static int validate_records(struct kr_query *qry, knot_pkt_t *answer, mm_ctx_t *pool, bool has_nsec3) +static int validate_records(struct kr_query *qry, knot_pkt_t *answer, knot_mm_t *pool, bool has_nsec3) { if (!qry->zone_cut.key) { DEBUG_MSG(qry, "<= no DNSKEY, can't validate\n"); @@ -346,7 +383,7 @@ static int validate(knot_layer_t *ctx, knot_pkt_t *pkt) /* Check if this is a DNSKEY answer, check trust chain and store. */ uint8_t pkt_rcode = knot_wire_get_rcode(pkt->wire); uint16_t qtype = knot_pkt_qtype(pkt); - bool has_nsec3 = _knot_pkt_has_type(pkt, KNOT_RRTYPE_NSEC3); + bool has_nsec3 = pkt_has_type(pkt, KNOT_RRTYPE_NSEC3); if (knot_wire_get_aa(pkt->wire) && qtype == KNOT_RRTYPE_DNSKEY) { ret = validate_keyset(qry, pkt, has_nsec3); if (ret != 0) { @@ -360,7 +397,7 @@ static int validate(knot_layer_t *ctx, knot_pkt_t *pkt) if (!(qry->flags & QUERY_CACHED) && pkt_rcode == KNOT_RCODE_NXDOMAIN) { /* @todo If knot_pkt_qname(pkt) is used instead of qry->sname then the tests crash. */ if (!has_nsec3) { - ret = kr_nsec_name_error_response_check(pkt, KNOT_AUTHORITY, qry->sname, &req->pool); + ret = kr_nsec_name_error_response_check(pkt, KNOT_AUTHORITY, qry->sname); } else { ret = kr_nsec3_name_error_response_check(pkt, KNOT_AUTHORITY, qry->sname); } diff --git a/lib/lib.mk b/lib/lib.mk index 7d89590fb25632431492691d41915340a74cb341..5ed3345113d10f18684dcfa3d6f64098e7e98c4c 100644 --- a/lib/lib.mk +++ b/lib/lib.mk @@ -6,7 +6,6 @@ libkres_SOURCES := \ lib/layer/pktcache.c \ lib/dnssec/nsec.c \ lib/dnssec/nsec3.c \ - lib/dnssec/packet/pkt.c \ lib/dnssec/signature.c \ lib/dnssec/ta.c \ lib/dnssec.c \ @@ -25,8 +24,6 @@ libkres_HEADERS := \ lib/layer.h \ lib/dnssec/nsec.h \ lib/dnssec/nsec3.h \ - lib/dnssec/packet/pkt.h \ - lib/dnssec/rrtype/ds.h \ lib/dnssec/signature.h \ lib/dnssec/ta.h \ lib/dnssec.h \ diff --git a/lib/nsrep.c b/lib/nsrep.c index b872c33e8bece03be4477f999e0cb69532db7efb..3fd91d7d0b4543d66f0d0bc14bfec15a94060160 100644 --- a/lib/nsrep.c +++ b/lib/nsrep.c @@ -18,7 +18,6 @@ #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> -#include <libknot/internal/sockaddr.h> #include "lib/nsrep.h" #include "lib/rplan.h" diff --git a/lib/resolve.c b/lib/resolve.c index df7c91ff9d427e4cdd8f6fb59e0ae78df1850d56..e104faf957cb1dbc15ef5823b569284de6493b00 100644 --- a/lib/resolve.c +++ b/lib/resolve.c @@ -17,6 +17,8 @@ #include <ctype.h> #include <stdio.h> #include <fcntl.h> +#include <assert.h> +#include <arpa/inet.h> #include <libknot/rrtype/rdname.h> #include <libknot/descriptor.h> #include <ucw/mempool.h> @@ -161,7 +163,7 @@ static int ns_fetch_cut(struct kr_query *qry, struct kr_request *req, knot_pkt_t /* Find closest zone cut from cache */ struct kr_cache_txn txn; - if (kr_cache_txn_begin(&req->ctx->cache, &txn, NAMEDB_RDONLY) == 0) { + if (kr_cache_txn_begin(&req->ctx->cache, &txn, KNOT_DB_RDONLY) == 0) { /* If at/subdomain of parent zone cut, start from its encloser. * This is for case when we get to a dead end (and need glue from parent), or DS refetch. */ struct kr_query *parent = qry->parent; @@ -311,10 +313,17 @@ static int answer_finalize(struct kr_request *request, int state) return ret; } } - /* Set AD=1 if succeeded and requested secured answer. */ struct kr_rplan *rplan = &request->rplan; - if (state == KNOT_STATE_DONE && !EMPTY_LIST(rplan->resolved)) { - struct kr_query *last = TAIL(rplan->resolved); + /* Always set SERVFAIL for bogus answers. */ + if (state == KNOT_STATE_FAIL && rplan->pending.len > 0) { + struct kr_query *last = array_tail(rplan->pending); + if ((last->flags & QUERY_DNSSEC_WANT) && (last->flags & QUERY_DNSSEC_BOGUS)) { + knot_wire_set_rcode(answer->wire,KNOT_RCODE_SERVFAIL); + } + } + /* Set AD=1 if succeeded and requested secured answer. */ + if (state == KNOT_STATE_DONE && rplan->resolved.len > 0) { + struct kr_query *last = array_tail(rplan->resolved); /* Do not set AD for RRSIG query, as we can't validate it. */ if ((last->flags & QUERY_DNSSEC_WANT) && knot_pkt_has_dnssec(answer) && knot_pkt_qtype(answer) != KNOT_RRTYPE_RRSIG) { @@ -360,8 +369,6 @@ int kr_resolve_begin(struct kr_request *request, struct kr_context *ctx, knot_pk request->options = ctx->options; request->state = KNOT_STATE_CONSUME; request->current_query = NULL; - request->qsource.key = NULL; - request->qsource.addr = NULL; array_init(request->authority); array_init(request->additional); @@ -420,7 +427,7 @@ int kr_resolve_consume(struct kr_request *request, const struct sockaddr *src, k } /* Different processing for network error */ - struct kr_query *qry = TAIL(rplan->pending); + struct kr_query *qry = array_tail(rplan->pending); bool tried_tcp = (qry->flags & QUERY_TCP); if (!packet || packet->size == 0) { if (tried_tcp) @@ -447,7 +454,7 @@ int kr_resolve_consume(struct kr_request *request, const struct sockaddr *src, k gettimeofday(&now, NULL); kr_nsrep_update_rtt(&qry->ns, src, time_diff(&qry->timestamp, &now), ctx->cache_rtt); WITH_DEBUG { - char addr_str[SOCKADDR_STRLEN]; + char addr_str[INET6_ADDRSTRLEN]; inet_ntop(src->sa_family, kr_inaddr(src), addr_str, sizeof(addr_str)); DEBUG_MSG(qry, "<= server: '%s' rtt: %ld ms\n", addr_str, time_diff(&qry->timestamp, &now)); } @@ -457,7 +464,7 @@ int kr_resolve_consume(struct kr_request *request, const struct sockaddr *src, k } else if (!(qry->flags & QUERY_DNSSEC_BOGUS)) { kr_nsrep_update_rtt(&qry->ns, src, KR_NS_TIMEOUT, ctx->cache_rtt); WITH_DEBUG { - char addr_str[SOCKADDR_STRLEN]; + char addr_str[INET6_ADDRSTRLEN]; inet_ntop(src->sa_family, kr_inaddr(src), addr_str, sizeof(addr_str)); DEBUG_MSG(qry, "=> server: '%s' flagged as 'bad'\n", addr_str); } @@ -624,7 +631,7 @@ int kr_resolve_produce(struct kr_request *request, struct sockaddr **dst, int *t return KNOT_STATE_FAIL; } /* If we have deferred answers, resume them. */ - struct kr_query *qry = TAIL(rplan->pending); + struct kr_query *qry = array_tail(rplan->pending); if (qry->deferred != NULL) { /* @todo: Refactoring validator, check trust chain before resuming. */ switch(trust_chain_check(request, qry)) { @@ -718,7 +725,7 @@ ns_election: } WITH_DEBUG { - char qname_str[KNOT_DNAME_MAXLEN], zonecut_str[KNOT_DNAME_MAXLEN], ns_str[SOCKADDR_STRLEN], type_str[16]; + char qname_str[KNOT_DNAME_MAXLEN], zonecut_str[KNOT_DNAME_MAXLEN], ns_str[INET6_ADDRSTRLEN], type_str[16]; knot_dname_to_str(qname_str, knot_pkt_qname(packet), sizeof(qname_str)); knot_dname_to_str(zonecut_str, qry->zone_cut.name, sizeof(zonecut_str)); knot_rrtype_to_string(knot_pkt_qtype(packet), type_str, sizeof(type_str)); @@ -760,7 +767,7 @@ int kr_resolve_finish(struct kr_request *request, int state) request->state = state; ITERATE_LAYERS(request, NULL, finish); DEBUG_MSG(NULL, "finished: %d, queries: %zu, mempool: %zu B\n", - request->state, list_size(&rplan->resolved), (size_t) mp_total_size(request->pool.ctx)); + request->state, rplan->resolved.len, (size_t) mp_total_size(request->pool.ctx)); return KNOT_STATE_DONE; } @@ -772,7 +779,7 @@ struct kr_rplan *kr_resolve_plan(struct kr_request *request) return NULL; } -mm_ctx_t *kr_resolve_pool(struct kr_request *request) +knot_mm_t *kr_resolve_pool(struct kr_request *request) { if (request) { return &request->pool; diff --git a/lib/resolve.h b/lib/resolve.h index 905e134e003c123b5cd613871f6e695e8304219a..d79b58a6c9ef19ff989c0bb5c480f9d6572b029c 100644 --- a/lib/resolve.h +++ b/lib/resolve.h @@ -92,7 +92,7 @@ struct kr_context kr_nsrep_lru_t *cache_rtt; kr_nsrep_lru_t *cache_rep; module_array_t *modules; - mm_ctx_t *pool; + knot_mm_t *pool; }; /** @@ -118,7 +118,7 @@ struct kr_request { rr_array_t authority; rr_array_t additional; struct kr_rplan rplan; - mm_ctx_t pool; + knot_mm_t pool; }; /** @@ -191,5 +191,5 @@ struct kr_rplan *kr_resolve_plan(struct kr_request *request); * @return mempool */ KR_EXPORT KR_PURE -mm_ctx_t *kr_resolve_pool(struct kr_request *request); +knot_mm_t *kr_resolve_pool(struct kr_request *request); diff --git a/lib/rplan.c b/lib/rplan.c index 8bae41cd1dab5e67bfab02c9b43c5a30db12ffbd..6eb52a0dca747debf0740200cf1dca6f3a0f9301 100644 --- a/lib/rplan.c +++ b/lib/rplan.c @@ -29,19 +29,19 @@ ((q)->sclass == (cls) && (q)->stype == type && knot_dname_is_equal((q)->sname, name)) /** @internal LUT of query flag names. */ -const lookup_table_t query_flag_names[] = { +const knot_lookup_t query_flag_names[] = { #define X(flag, _) { QUERY_ ## flag, #flag }, QUERY_FLAGS(X) #undef X { 0, NULL } }; -const lookup_table_t *kr_query_flag_names(void) +const knot_lookup_t *kr_query_flag_names(void) { return query_flag_names; } -static struct kr_query *query_create(mm_ctx_t *pool, const knot_dname_t *name) +static struct kr_query *query_create(knot_mm_t *pool, const knot_dname_t *name) { if (name == NULL) { return NULL; @@ -63,14 +63,14 @@ static struct kr_query *query_create(mm_ctx_t *pool, const knot_dname_t *name) return qry; } -static void query_free(mm_ctx_t *pool, struct kr_query *qry) +static void query_free(knot_mm_t *pool, struct kr_query *qry) { kr_zonecut_deinit(&qry->zone_cut); mm_free(pool, qry->sname); mm_free(pool, qry); } -int kr_rplan_init(struct kr_rplan *rplan, struct kr_request *request, mm_ctx_t *pool) +int kr_rplan_init(struct kr_rplan *rplan, struct kr_request *request, knot_mm_t *pool) { if (rplan == NULL) { return KNOT_EINVAL; @@ -80,8 +80,8 @@ int kr_rplan_init(struct kr_rplan *rplan, struct kr_request *request, mm_ctx_t * rplan->pool = pool; rplan->request = request; - init_list(&rplan->pending); - init_list(&rplan->resolved); + array_init(rplan->pending); + array_init(rplan->resolved); return KNOT_EOK; } @@ -91,13 +91,14 @@ void kr_rplan_deinit(struct kr_rplan *rplan) return; } - struct kr_query *qry = NULL, *next = NULL; - WALK_LIST_DELSAFE(qry, next, rplan->pending) { - query_free(rplan->pool, qry); + for (size_t i = 0; i < rplan->pending.len; ++i) { + query_free(rplan->pool, rplan->pending.at[i]); } - WALK_LIST_DELSAFE(qry, next, rplan->resolved) { - query_free(rplan->pool, qry); + for (size_t i = 0; i < rplan->resolved.len; ++i) { + query_free(rplan->pool, rplan->resolved.at[i]); } + array_clear_mm(rplan->pending, mm_free, rplan->pool); + array_clear_mm(rplan->resolved, mm_free, rplan->pool); } bool kr_rplan_empty(struct kr_rplan *rplan) @@ -106,7 +107,7 @@ bool kr_rplan_empty(struct kr_rplan *rplan) return true; } - return EMPTY_LIST(rplan->pending); + return rplan->pending.len == 0; } struct kr_query *kr_rplan_push(struct kr_rplan *rplan, struct kr_query *parent, @@ -116,6 +117,12 @@ struct kr_query *kr_rplan_push(struct kr_rplan *rplan, struct kr_query *parent, return NULL; } + /* Make sure there's enough space */ + int ret = array_reserve_mm(rplan->pending, rplan->pending.len + 1, kr_memreserve, rplan->pool); + if (ret != 0) { + return NULL; + } + struct kr_query *qry = query_create(rplan->pool, name); if (qry == NULL) { return NULL; @@ -126,8 +133,8 @@ struct kr_query *kr_rplan_push(struct kr_rplan *rplan, struct kr_query *parent, qry->parent = parent; qry->ns.addr[0].ip.sa_family = AF_UNSPEC; gettimeofday(&qry->timestamp, NULL); - add_tail(&rplan->pending, &qry->node); kr_zonecut_init(&qry->zone_cut, (const uint8_t *)"", rplan->pool); + array_push(rplan->pending, qry); WITH_DEBUG { char name_str[KNOT_DNAME_MAXLEN], type_str[16]; @@ -144,16 +151,26 @@ int kr_rplan_pop(struct kr_rplan *rplan, struct kr_query *qry) return KNOT_EINVAL; } - rem_node(&qry->node); - add_tail(&rplan->resolved, &qry->node); + /* Make sure there's enough space */ + int ret = array_reserve_mm(rplan->resolved, rplan->resolved.len + 1, kr_memreserve, rplan->pool); + if (ret != 0) { + return ret; + } + + /* Find the query, it will likely be on top */ + for (size_t i = rplan->pending.len; i --> 0;) { + if (rplan->pending.at[i] == qry) { + array_del(rplan->pending, i); + array_push(rplan->resolved, qry); + break; + } + } return KNOT_EOK; } bool kr_rplan_satisfies(struct kr_query *closure, const knot_dname_t *name, uint16_t cls, uint16_t type) { - if (!name) - return false; - while (closure != NULL) { + while (name && closure) { if (QUERY_PROVIDES(closure, name, cls, type)) { return true; } @@ -164,18 +181,10 @@ bool kr_rplan_satisfies(struct kr_query *closure, const knot_dname_t *name, uint struct kr_query *kr_rplan_resolved(struct kr_rplan *rplan) { - if (EMPTY_LIST(rplan->resolved)) { - return NULL; - } - return TAIL(rplan->resolved); -} - -struct kr_query *kr_rplan_next(struct kr_query *qry) -{ - if (!qry) { + if (rplan->resolved.len == 0) { return NULL; } - return (struct kr_query *)qry->node.prev; /* The lists are used as stack, TOP is the TAIL. */ + return array_tail(rplan->resolved); } #undef DEBUG_MSG diff --git a/lib/rplan.h b/lib/rplan.h index 0d05269c755d4c7e1140675489af4a1a7ddd866a..f2e2cbaf33b0e3d5e942fb9424e826d0a2c6470b 100644 --- a/lib/rplan.h +++ b/lib/rplan.h @@ -18,9 +18,7 @@ #include <sys/time.h> #include <libknot/dname.h> -#include <libknot/internal/lists.h> -#include <libknot/internal/namedb/namedb.h> -#include <libknot/internal/sockaddr.h> +#include <libknot/codes.h> #include "lib/cache.h" #include "lib/zonecut.h" @@ -55,13 +53,12 @@ enum kr_query_flag { /** Query flag names table */ KR_EXPORT KR_CONST -const lookup_table_t *kr_query_flag_names(void); +const knot_lookup_t *kr_query_flag_names(void); /** * Single query representation. */ struct kr_query { - node_t node; struct kr_query *parent; knot_dname_t *sname; uint16_t stype; @@ -75,6 +72,9 @@ struct kr_query { struct kr_layer_pickle *deferred; }; +/** @internal Array of queries. */ +typedef array_t(struct kr_query *) kr_qarray_t; + /** * Query resolution plan structure. * @@ -83,10 +83,10 @@ struct kr_query { * It also keeps a notion of current zone cut. */ struct kr_rplan { - list_t pending; /**< List of pending queries. */ - list_t resolved; /**< List of resolved queries. */ - struct kr_request *request; /**< Parent resolution request. */ - mm_ctx_t *pool; /**< Temporary memory pool. */ + kr_qarray_t pending; /**< List of pending queries. */ + kr_qarray_t resolved; /**< List of resolved queries. */ + struct kr_request *request; /**< Parent resolution request. */ + knot_mm_t *pool; /**< Temporary memory pool. */ }; /** @@ -96,7 +96,7 @@ struct kr_rplan { * @param pool ephemeral memory pool for whole resolution */ KR_EXPORT -int kr_rplan_init(struct kr_rplan *rplan, struct kr_request *request, mm_ctx_t *pool); +int kr_rplan_init(struct kr_rplan *rplan, struct kr_request *request, knot_mm_t *pool); /** * Deinitialize resolution plan, aborting any uncommited transactions. diff --git a/lib/utils.c b/lib/utils.c index 4cad3f4ad7876f109feac5d8d04436adf0c08ec8..00e5d65fe86296529f60844fe64b04b3d86896cb 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -180,7 +180,7 @@ int kr_memreserve(void *baton, char **mem, size_t elm_size, size_t want, size_t if (*have >= want) { return 0; } else { - mm_ctx_t *pool = baton; + knot_mm_t *pool = baton; size_t next_size = array_next_count(want); void *mem_new = mm_alloc(pool, next_size * elm_size); if (mem_new != NULL) { @@ -239,6 +239,13 @@ const char *kr_inaddr(const struct sockaddr *addr) } } +int kr_inaddr_family(const struct sockaddr *addr) +{ + if (!addr) + return AF_UNSPEC; + return addr->sa_family; +} + int kr_inaddr_len(const struct sockaddr *addr) { if (!addr) { @@ -337,7 +344,7 @@ int kr_rrkey(char *key, const knot_dname_t *owner, uint16_t type, uint8_t rank) return (char *)&key_buf[ret] - key; } -int kr_rrmap_add(map_t *stash, const knot_rrset_t *rr, uint8_t rank, mm_ctx_t *pool) +int kr_rrmap_add(map_t *stash, const knot_rrset_t *rr, uint8_t rank, knot_mm_t *pool) { if (!stash || !rr) { return kr_error(EINVAL); @@ -372,7 +379,7 @@ int kr_rrmap_add(map_t *stash, const knot_rrset_t *rr, uint8_t rank, mm_ctx_t *p return knot_rdataset_merge(&stashed->rrs, &rr->rrs, pool); } -int kr_rrarray_add(rr_array_t *array, const knot_rrset_t *rr, mm_ctx_t *pool) +int kr_rrarray_add(rr_array_t *array, const knot_rrset_t *rr, knot_mm_t *pool) { int ret = array_reserve_mm(*array, array->len + 1, kr_memreserve, pool); if (ret != 0) { diff --git a/lib/utils.h b/lib/utils.h index d47dce3b6cec0814b9baf1610ce44abf7cd0ffa0..698bd6e0772c1bb17b2376da9238690fe1879637 100644 --- a/lib/utils.h +++ b/lib/utils.h @@ -17,11 +17,13 @@ #pragma once #include <stdio.h> +#include <stdbool.h> #include <sys/time.h> #include <netinet/in.h> #include <libknot/packet/pkt.h> #include "lib/generic/map.h" #include "lib/generic/array.h" +#include "lib/defines.h" /* * Logging and debugging. @@ -42,6 +44,22 @@ KR_EXPORT void kr_log_debug(const char *fmt, ...); #define WITH_DEBUG if(0) #endif +/** @cond Memory alloc routines */ +static inline void *mm_alloc(knot_mm_t *mm, size_t size) +{ + if (mm) return mm->alloc(mm->ctx, size); + else return malloc(size); +} +static inline void mm_free(knot_mm_t *mm, void *what) +{ + if (mm) { + if (mm->free) + mm->free(what); + } + else free(what); +} +/* @endcond */ + /** Return time difference in miliseconds. * @note based on the _BSD_SOURCE timersub() macro */ static inline long time_diff(struct timeval *begin, struct timeval *end) { @@ -77,7 +95,7 @@ int kr_rand_reseed(void); KR_EXPORT unsigned kr_rand_uint(unsigned max); -/** Memory reservation routine for mm_ctx_t */ +/** Memory reservation routine for knot_mm_t */ KR_EXPORT int kr_memreserve(void *baton, char **mem, size_t elm_size, size_t want, size_t *have); @@ -93,6 +111,9 @@ int kr_pkt_put(knot_pkt_t *pkt, const knot_dname_t *name, uint32_t ttl, /** Address bytes for given family. */ KR_EXPORT KR_PURE const char *kr_inaddr(const struct sockaddr *addr); +/** Address family. */ +KR_EXPORT KR_PURE +int kr_inaddr_family(const struct sockaddr *addr); /** Address length for given family. */ KR_EXPORT KR_PURE int kr_inaddr_len(const struct sockaddr *addr); @@ -131,10 +152,10 @@ int kr_rrkey(char *key, const knot_dname_t *owner, uint16_t type, uint8_t rank); * @note RRSIG RRSets are merged according the type covered fields. * @return 0 or an error */ -int kr_rrmap_add(map_t *stash, const knot_rrset_t *rr, uint8_t rank, mm_ctx_t *pool); +int kr_rrmap_add(map_t *stash, const knot_rrset_t *rr, uint8_t rank, knot_mm_t *pool); /** @internal Add RRSet copy to RR array. */ -int kr_rrarray_add(rr_array_t *array, const knot_rrset_t *rr, mm_ctx_t *pool); +int kr_rrarray_add(rr_array_t *array, const knot_rrset_t *rr, knot_mm_t *pool); /** * Call module property. diff --git a/lib/zonecut.c b/lib/zonecut.c index 05e18a9cf8eab42977541409152c211bb3fd3990..cab154ea3e873d5c05cd12cdb8bf6a486c306407 100644 --- a/lib/zonecut.c +++ b/lib/zonecut.c @@ -78,7 +78,7 @@ static void update_cut_name(struct kr_zonecut *cut, const knot_dname_t *name) cut->name = next_name; } -int kr_zonecut_init(struct kr_zonecut *cut, const knot_dname_t *name, mm_ctx_t *pool) +int kr_zonecut_init(struct kr_zonecut *cut, const knot_dname_t *name, knot_mm_t *pool) { if (!cut || !name) { return kr_error(EINVAL); @@ -349,7 +349,7 @@ static int fetch_ns(struct kr_context *ctx, struct kr_zonecut *cut, const knot_d * Fetch RRSet of given type. */ static int fetch_rrset(knot_rrset_t **rr, const knot_dname_t *owner, uint16_t type, - struct kr_cache_txn *txn, mm_ctx_t *pool, uint32_t timestamp) + struct kr_cache_txn *txn, knot_mm_t *pool, uint32_t timestamp) { if (!rr) { return kr_error(ENOENT); diff --git a/lib/zonecut.h b/lib/zonecut.h index 64ebd7b5b998b325171ef1faa2f416138ed0e570..b87f80cda691012375bb3d8f0415ff6d429c1cce 100644 --- a/lib/zonecut.h +++ b/lib/zonecut.h @@ -33,7 +33,7 @@ struct kr_zonecut { knot_rrset_t* key; /**< Zone cut DNSKEY. */ knot_rrset_t* trust_anchor; /**< Current trust anchor. */ struct kr_zonecut *parent; /**< Parent zone cut. */ - mm_ctx_t *pool; /**< Memory pool. */ + knot_mm_t *pool; /**< Memory pool. */ }; /** @@ -44,7 +44,7 @@ struct kr_zonecut { * @return 0 or error code */ KR_EXPORT -int kr_zonecut_init(struct kr_zonecut *cut, const knot_dname_t *name, mm_ctx_t *pool); +int kr_zonecut_init(struct kr_zonecut *cut, const knot_dname_t *name, knot_mm_t *pool); /** * Clear the structure and free the address set. diff --git a/modules/cachectl/cachectl.c b/modules/cachectl/cachectl.c index ce7c407d4696ec01f8da89d679e08ec04f0f87b6..f47bc42520b7faa9a3fb9c1fecf5800cbd2336d7 100644 --- a/modules/cachectl/cachectl.c +++ b/modules/cachectl/cachectl.c @@ -27,6 +27,7 @@ #include <time.h> #include <libknot/descriptor.h> +#include <libknot/error.h> #include <ccan/json/json.h> #include "daemon/engine.h" @@ -40,7 +41,7 @@ * Properties. */ -typedef int (*cache_cb_t)(struct kr_cache_txn *txn, namedb_iter_t *it, namedb_val_t *key, void *baton); +typedef int (*cache_cb_t)(struct kr_cache_txn *txn, knot_db_iter_t *it, knot_db_val_t *key, void *baton); /** @internal Prefix walk. */ static int cache_prefixed(struct engine *engine, const char *args, unsigned txn_flags, cache_cb_t cb, void *baton) @@ -76,7 +77,7 @@ static int cache_prefixed(struct engine *engine, const char *args, unsigned txn_ /* Start search transaction */ struct kr_cache *cache = &engine->resolver.cache; - const namedb_api_t *api = cache->api; + const knot_db_api_t *api = cache->api; struct kr_cache_txn txn; ret = kr_cache_txn_begin(cache, &txn, txn_flags); if (ret != 0) { @@ -86,10 +87,10 @@ static int cache_prefixed(struct engine *engine, const char *args, unsigned txn_ /* Walk through cache records matching given prefix. * Note that since the backend of the cache is opaque, there's no exactly efficient * way to do prefix search (i.e. Redis uses hashtable but offers SCAN, LMDB can do lexical closest match, ...). */ - namedb_val_t key = { prefix, prefix_len }; - namedb_iter_t *it = api->iter_begin(&txn.t, 0); + knot_db_val_t key = { prefix, prefix_len }; + knot_db_iter_t *it = api->iter_begin(&txn.t, 0); if (it) { /* Seek first key matching the prefix. */ - it = api->iter_seek(it, &key, NAMEDB_GEQ); + it = api->iter_seek(it, &key, KNOT_DB_GEQ); } while (it != NULL) { if (api->iter_key(it, &key) != 0) { @@ -123,7 +124,7 @@ static bool is_expired(struct kr_cache_entry *entry, uint32_t drift) } /** @internal Delete iterated key. */ -static int cache_delete_cb(struct kr_cache_txn *txn, namedb_iter_t *it, namedb_val_t *key, void *baton) +static int cache_delete_cb(struct kr_cache_txn *txn, knot_db_iter_t *it, knot_db_val_t *key, void *baton) { struct kr_cache *cache = txn->owner; return cache->api->del(&txn->t, key); @@ -140,7 +141,7 @@ static char* prune(void *env, struct kr_module *module, const char *args) { struct engine *engine = env; struct kr_cache *cache = &engine->resolver.cache; - const namedb_api_t *storage = cache->api; + const knot_db_api_t *storage = cache->api; struct kr_cache_txn txn; int ret = kr_cache_txn_begin(cache, &txn, 0); @@ -161,10 +162,10 @@ static char* prune(void *env, struct kr_module *module, const char *args) /* Fetch current time and start iterating */ struct timeval now; gettimeofday(&now, NULL); - namedb_iter_t *it = storage->iter_begin(&txn.t, 0); + knot_db_iter_t *it = storage->iter_begin(&txn.t, 0); while (it && pruned < prune_max) { /* Fetch RR from cache */ - namedb_val_t key, val; + knot_db_val_t key, val; if (storage->iter_key(it, &key) != 0 || storage->iter_val(it, &val) != 0) { break; @@ -242,7 +243,7 @@ static char* clear(void *env, struct kr_module *module, const char *args) } /** @internal Serialize cached record name into JSON. */ -static int cache_dump_cb(struct kr_cache_txn *txn, namedb_iter_t *it, namedb_val_t *key, void *baton) +static int cache_dump_cb(struct kr_cache_txn *txn, knot_db_iter_t *it, knot_db_val_t *key, void *baton) { JsonNode* json_records = baton; char buf[KNOT_DNAME_MAXLEN]; @@ -291,7 +292,7 @@ static char* get(void *env, struct kr_module *module, const char *args) char *result = NULL; JsonNode *json_records = json_mkobject(); if (json_records) { - int ret = cache_prefixed(env, args, NAMEDB_RDONLY, &cache_dump_cb, json_records); + int ret = cache_prefixed(env, args, KNOT_DB_RDONLY, &cache_dump_cb, json_records); if (ret == 0) { result = json_encode(json_records); } diff --git a/modules/hints/hints.c b/modules/hints/hints.c index 03c13ce0699e6bea705f9731d815ad9bab4866bb..ff7eb922a190d634905c26973c66917d50ce3612 100644 --- a/modules/hints/hints.c +++ b/modules/hints/hints.c @@ -214,7 +214,13 @@ static int query(knot_layer_t *ctx, knot_pkt_t *pkt) static int parse_addr_str(struct sockaddr_storage *sa, const char *addr) { int family = strchr(addr, ':') ? AF_INET6 : AF_INET; - return sockaddr_set(sa, family, addr, 0); + memset(sa, 0, sizeof(struct sockaddr_storage)); + sa->ss_family = family; + char *addr_bytes = (char *)kr_inaddr((struct sockaddr *)sa); + if (inet_pton(family, addr, addr_bytes) < 1) { + return kr_error(EILSEQ); + } + return 0; } static int add_pair(struct kr_zonecut *hints, const char *name, const char *addr) @@ -276,11 +282,11 @@ static int load(struct kr_module *module, const char *path) } /* Create pool and copy itself */ - mm_ctx_t _pool = { + knot_mm_t _pool = { .ctx = mp_new(4096), - .alloc = (mm_alloc_t) mp_alloc + .alloc = (knot_mm_alloc_t) mp_alloc }; - mm_ctx_t *pool = mm_alloc(&_pool, sizeof(*pool)); + knot_mm_t *pool = mm_alloc(&_pool, sizeof(*pool)); if (!pool) { return kr_error(ENOMEM); } @@ -330,7 +336,7 @@ static char* hint_set(void *env, struct kr_module *module, const char *args) /** @internal Pack address list into JSON array. */ static JsonNode *pack_addrs(pack_t *pack) { - char buf[SOCKADDR_STRLEN]; + char buf[INET6_ADDRSTRLEN]; JsonNode *root = json_mkarray(); uint8_t *addr = pack_head(*pack); while (addr != pack_tail(*pack)) { diff --git a/modules/kmemcached/kmemcached.c b/modules/kmemcached/kmemcached.c index 367c31c8585b9046d8d34744365eafc8ce813747..d1979818ac9766e126205c78ef0d933e5eb05347 100644 --- a/modules/kmemcached/kmemcached.c +++ b/modules/kmemcached/kmemcached.c @@ -14,7 +14,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <libknot/internal/namedb/namedb.h> +#include <libknot/db/db.h> #include <contrib/cleanup.h> #include "daemon/engine.h" @@ -22,7 +22,7 @@ #include "lib/cache.h" /** @internal Memcached API */ -extern const namedb_api_t *namedb_memcached_api(void); +extern const knot_db_api_t *namedb_memcached_api(void); /** @internal Make memcached options. */ void *namedb_memcached_mkopts(const char *conf, size_t maxsize) diff --git a/modules/kmemcached/namedb_memcached.c b/modules/kmemcached/namedb_memcached.c index 3aefe1b72618d07efec9c8d45695b278eb60f26e..5d764565eaad84adfbe23ddc82509ca7d023eab9 100644 --- a/modules/kmemcached/namedb_memcached.c +++ b/modules/kmemcached/namedb_memcached.c @@ -26,7 +26,7 @@ #include <assert.h> #include <string.h> #include <libmemcached/memcached.h> -#include <libknot/internal/namedb/namedb.h> +#include <libknot/db/db.h> #include <libknot/errcode.h> #include <contrib/cleanup.h> @@ -37,7 +37,7 @@ /* Oh, the irony... */ typedef array_t(char *) freelist_t; -static int init(namedb_t **db, mm_ctx_t *mm, void *arg) +static int init(knot_db_t **db, knot_mm_t *mm, void *arg) { if (!db || !arg) { return KNOT_EINVAL; @@ -55,12 +55,12 @@ static int init(namedb_t **db, mm_ctx_t *mm, void *arg) return KNOT_EOK; } -static void deinit(namedb_t *db) +static void deinit(knot_db_t *db) { memcached_free((memcached_st *)db); } -static int txn_begin(namedb_t *db, namedb_txn_t *txn, unsigned flags) +static int txn_begin(knot_db_t *db, knot_db_txn_t *txn, unsigned flags) { freelist_t *freelist = malloc(sizeof(*freelist)); if (!freelist) { @@ -72,7 +72,7 @@ static int txn_begin(namedb_t *db, namedb_txn_t *txn, unsigned flags) return KNOT_EOK; } -static int txn_commit(namedb_txn_t *txn) +static int txn_commit(knot_db_txn_t *txn) { freelist_t *freelist = txn->txn; if (freelist) { @@ -86,7 +86,7 @@ static int txn_commit(namedb_txn_t *txn) return KNOT_EOK; } -static void txn_abort(namedb_txn_t *txn) +static void txn_abort(knot_db_txn_t *txn) { /** @warning No real transactions here, * all the reads/writes are done synchronously. @@ -96,7 +96,7 @@ static void txn_abort(namedb_txn_t *txn) txn_commit(txn); } -static int count(namedb_txn_t *txn) +static int count(knot_db_txn_t *txn) { memcached_return_t error = 0; memcached_stat_st *stats = memcached_stat(txn->db, NULL, &error); @@ -108,7 +108,7 @@ static int count(namedb_txn_t *txn) return ret; } -static int clear(namedb_txn_t *txn) +static int clear(knot_db_txn_t *txn) { memcached_return_t ret = memcached_flush(txn->db, 0); if (ret != 0) { @@ -117,7 +117,7 @@ static int clear(namedb_txn_t *txn) return KNOT_EOK; } -static int find(namedb_txn_t *txn, namedb_val_t *key, namedb_val_t *val, unsigned flags) +static int find(knot_db_txn_t *txn, knot_db_val_t *key, knot_db_val_t *val, unsigned flags) { uint32_t mc_flags = 0; memcached_return_t error = 0; @@ -134,7 +134,7 @@ static int find(namedb_txn_t *txn, namedb_val_t *key, namedb_val_t *val, unsigne return KNOT_EOK; } -static int insert(namedb_txn_t *txn, namedb_val_t *key, namedb_val_t *val, unsigned flags) +static int insert(knot_db_txn_t *txn, knot_db_val_t *key, knot_db_val_t *val, unsigned flags) { if (!txn || !key || !val) { return KNOT_EINVAL; @@ -150,7 +150,7 @@ static int insert(namedb_txn_t *txn, namedb_val_t *key, namedb_val_t *val, unsig return KNOT_EOK; } -static int del(namedb_txn_t *txn, namedb_val_t *key) +static int del(knot_db_txn_t *txn, knot_db_val_t *key) { memcached_return_t ret = memcached_delete(txn->db, key->data, key->len, 0); if (ret != 0) { @@ -159,43 +159,43 @@ static int del(namedb_txn_t *txn, namedb_val_t *key) return KNOT_EOK; } -static namedb_iter_t *iter_begin(namedb_txn_t *txn, unsigned flags) +static knot_db_iter_t *iter_begin(knot_db_txn_t *txn, unsigned flags) { /* Iteration is not supported, pruning should be * left on the memcached server */ return NULL; } -static namedb_iter_t *iter_seek(namedb_iter_t *iter, namedb_val_t *key, unsigned flags) +static knot_db_iter_t *iter_seek(knot_db_iter_t *iter, knot_db_val_t *key, unsigned flags) { assert(0); return NULL; /* ENOTSUP */ } -static namedb_iter_t *iter_next(namedb_iter_t *iter) +static knot_db_iter_t *iter_next(knot_db_iter_t *iter) { assert(0); return NULL; } -static int iter_key(namedb_iter_t *iter, namedb_val_t *val) +static int iter_key(knot_db_iter_t *iter, knot_db_val_t *val) { return KNOT_ENOTSUP; } -static int iter_val(namedb_iter_t *iter, namedb_val_t *val) +static int iter_val(knot_db_iter_t *iter, knot_db_val_t *val) { return KNOT_ENOTSUP; } -static void iter_finish(namedb_iter_t *iter) +static void iter_finish(knot_db_iter_t *iter) { assert(0); } -const namedb_api_t *namedb_memcached_api(void) +const knot_db_api_t *namedb_memcached_api(void) { - static const namedb_api_t api = { + static const knot_db_api_t api = { "memcached", init, deinit, txn_begin, txn_commit, txn_abort, diff --git a/modules/policy/policy.lua b/modules/policy/policy.lua index 8fcc089fbfd855c0813aa1516c7627e73caabc1e..57ae53ee6a2737d0d72e59532598b0982ad9666f 100644 --- a/modules/policy/policy.lua +++ b/modules/policy/policy.lua @@ -81,15 +81,13 @@ local function rpz_parse(action, path) ['\012rpz-tcp-only\0'] = policy.TC, -- Policy triggers @NYI@ } - local parser = require('zonefile').parser(function (p) - local name = ffi.string(p.r_owner, p.r_owner_length) - local action = ffi.string(p.r_data, p.r_data_length) + local parser = require('zonefile').new() + if not parser:open(path) then error(string.format('failed to parse "%s"', path)) end + while parser:parse() do + local name = ffi.string(parser.r_owner, parser.r_owner_length) + local action = ffi.string(parser.r_data, parser.r_data_length) rules[name] = action_map[action] - end, function (p) - print(string.format('[policy.rpz] %s: line %d: %s', path, - tonumber(p.line_counter), p:last_error())) - end) - parser:parse_file(path) + end return rules end diff --git a/modules/policy/zonefile.lua b/modules/policy/zonefile.lua index 0c090d5f383dab9ef0a04ec9e73aa3678d2e23ef..c2f6fcac385e2889ec5d6173b9487940bbb1818c 100644 --- a/modules/policy/zonefile.lua +++ b/modules/policy/zonefile.lua @@ -3,8 +3,11 @@ -- local ffi = require('ffi') -local libzscanner = ffi.load(libpath('libzscanner', '0')) +local utils = require('kdns.utils') +local libzscanner = ffi.load(libpath('libzscanner', '1')) ffi.cdef[[ +void free(void *ptr); +void *realloc(void *ptr, size_t size); /* * Data structures @@ -38,9 +41,16 @@ typedef struct { uint64_t siz, hp, vp; int8_t lat_sign, long_sign, alt_sign; } loc_t; +typedef struct zs_state { + static const int NONE = 0; + static const int DATA = 1; + static const int ERROR = 2; + static const int INCLUDE = 3; + static const int EOF = 4; + static const int STOP = 5; +} zs_state_t; -typedef struct scanner zs_scanner_t; -struct scanner { +typedef struct scanner { int cs; int top; int stack[RAGEL_STACK_SIZE]; @@ -54,7 +64,8 @@ struct scanner { uint8_t *item_length_location; uint32_t buffer_length; uint8_t buffer[MAX_RDATA_LENGTH]; - char include_filename[MAX_RDATA_LENGTH + 1]; + char include_filename[MAX_RDATA_LENGTH]; + char *path; window_t windows[BITMAP_WINDOWS]; int16_t last_window; apl_t apl; @@ -68,18 +79,29 @@ struct scanner { uint8_t zone_origin[MAX_DNAME_LENGTH + MAX_LABEL_LENGTH]; uint16_t default_class; uint32_t default_ttl; - void (*process_record)(zs_scanner_t *); - void (*process_error)(zs_scanner_t *); - void *data; - char *path; - uint64_t line_counter; - int error_code; - uint64_t error_counter; - bool stop; + int state; + struct { + bool automatic; + void (*record)(struct zs_scanner *); + void (*error)(struct zs_scanner *); + void *data; + } process; + struct { + const char *start; + const char *current; + const char *end; + bool eof; + } input; struct { char *name; int descriptor; } file; + struct { + int code; + uint64_t counter; + bool fatal; + } error; + uint64_t line_counter; uint32_t r_owner_length; uint8_t r_owner[MAX_DNAME_LENGTH + MAX_LABEL_LENGTH]; uint16_t r_class; @@ -87,72 +109,115 @@ struct scanner { uint16_t r_type; uint32_t r_data_length; uint8_t r_data[MAX_RDATA_LENGTH]; -}; +} zs_scanner_t; /* * Function signatures */ - -zs_scanner_t* zs_scanner_create(const char *origin, - const uint16_t rclass, - const uint32_t ttl, - void (*process_record)(zs_scanner_t *), - void (*process_error)(zs_scanner_t *), - void *data); -void zs_scanner_free(zs_scanner_t *scanner); -int zs_scanner_parse(zs_scanner_t *scanner, - const char *start, - const char *end, - const bool final_block); -int zs_scanner_parse_file(zs_scanner_t *scanner, - const char *file_name); +int zs_init(zs_scanner_t *scanner, const char *origin, const uint16_t rclass, const uint32_t ttl); +void zs_deinit(zs_scanner_t *scanner); +int zs_set_input_string(zs_scanner_t *scanner, const char *input, size_t size); +int zs_set_input_file(zs_scanner_t *scanner, const char *file_name); +int zs_parse_record(zs_scanner_t *scanner); const char* zs_strerror(const int code); ]] +-- Constant table +local zs_state = ffi.new('struct zs_state') + +-- Sorted set of records +local bsearch = utils.bsearch +sortedset_t = ffi.typeof('struct { knot_rrset_t *at; int32_t len; int32_t cap; }') +ffi.metatype(sortedset_t, { + __gc = function (set) + for i = 0, tonumber(set.len) - 1 do set.at[i]:init(nil, 0) end + ffi.C.free(set.at) + end, + __len = function (set) return tonumber(set.len) end, + __index = { + newrr = function (set, noinit) + -- Reserve enough memory in buffer + if set.cap == set.len then assert(utils.buffer_grow(set)) end + local nid = set.len + set.len = nid + 1 + -- Don't initialize if caller is going to do it immediately + if not noinit then + ffi.fill(set.at + nid, ffi.sizeof(set.at[0])) + end + return set.at[nid] + end, + sort = function (set) + -- Prefetch RR set comparison function + return utils.sort(set.at, tonumber(set.len)) + end, + search = function (set, owner) + return bsearch(set.at, tonumber(set.len), owner) + end, + searcher = function (set) + return utils.bsearcher(set.at, tonumber(set.len)) + end, + } +}) + -- Wrap scanner context -local zs_scanner_t = ffi.typeof('zs_scanner_t') +local const_char_t = ffi.typeof('const char *') +local zs_scanner_t = ffi.typeof('struct scanner') ffi.metatype( zs_scanner_t, { - __new = function(zs, on_record, on_error) - return ffi.gc(libzscanner.zs_scanner_create('.', 1, 3600, on_record, on_error, nil), - libzscanner.zs_scanner_free) + __gc = function(zs) return libzscanner.zs_deinit(zs) end, + __new = function(ct, origin, class, ttl) + if not class then class = 1 end + if not ttl then ttl = 3600 end + local parser = ffi.new(ct) + libzscanner.zs_init(parser, origin, class, ttl) + return parser end, __index = { - parse_file = function(zs, file) - return libzscanner.zs_scanner_parse_file(zs, file) + open = function (zs, file) + assert(ffi.istype(zs, zs_scanner_t)) + local ret = libzscanner.zs_set_input_file(zs, file) + if ret ~= 0 then return false, zs:strerr() end + return true end, - read = function(zs, str) - local buf = ffi.cast(ffi.typeof('const char *'), str) - return libzscanner.zs_scanner_parse(zs, buf, buf + #str, false) + parse = function(zs, input) + assert(ffi.istype(zs, zs_scanner_t)) + if input ~= nil then libzscanner.zs_set_input_string(zs, input, #input) end + local ret = libzscanner.zs_parse_record(zs) + -- Return current state only when parsed correctly, otherwise return error + if ret == 0 and zs.state ~= zs_state.ERROR then + return zs.state == zs_state.DATA + else + return false, zs:strerr() + end end, current_rr = function(zs) + assert(ffi.istype(zs, zs_scanner_t)) return {owner = ffi.string(zs.r_owner, zs.r_owner_length), ttl = tonumber(zs.r_ttl), class = tonumber(zs.r_class), type = tonumber(zs.r_type), rdata = ffi.string(zs.r_data, zs.r_data_length)} end, - last_error = function(zs) - return ffi.string(libzscanner.zs_strerror(zs.error_code)) + strerr = function(zs) + assert(ffi.istype(zs, zs_scanner_t)) + return ffi.string(libzscanner.zs_strerror(zs.error.code)) end, }, }) -- Module API -local zonefile = {} - -function zonefile.parser(on_record, on_error) - return zs_scanner_t(on_record, on_error) -end - -function zonefile.parse_file(file) - local records = {} - local context = zonefile.parser(function (parser) - table.insert(records, parser:current_rr()) - end) - if context:parse_file(file) ~= 0 then - return nil - end - return records -end - -return zonefile +local rrparser = { + new = zs_scanner_t, + file = function (path) + local zs = zs_scanner_t() + local ok, err = zs:open(path) + if not ok then error(err) end + local results = {} + while zs:parse() do + table.insert(results, zs:current_rr()) + end + return results + end, + state = zs_state, + set = sortedset_t, +} +return rrparser diff --git a/modules/redis/namedb_redis.c b/modules/redis/namedb_redis.c index 6f95fdc7e3c2720cd4a4686408f7d689a94d620e..db10c5d517c2a79ebd77173c8180eb2c9d23f69d 100644 --- a/modules/redis/namedb_redis.c +++ b/modules/redis/namedb_redis.c @@ -22,7 +22,7 @@ #include <assert.h> #include <string.h> -#include <libknot/internal/namedb/namedb.h> +#include <libknot/db/db.h> #include "modules/redis/redis.h" @@ -79,7 +79,7 @@ static void cli_free(struct redis_cli *cli) free(cli); } -static int init(namedb_t **db, mm_ctx_t *mm, void *arg) +static int init(knot_db_t **db, knot_mm_t *mm, void *arg) { if (!db || !arg) { return kr_error(EINVAL); @@ -99,13 +99,13 @@ static int init(namedb_t **db, mm_ctx_t *mm, void *arg) return ret; } -static void deinit(namedb_t *db) +static void deinit(knot_db_t *db) { struct redis_cli *cli = db; cli_free(cli); } -static int txn_begin(namedb_t *db, namedb_txn_t *txn, unsigned flags) +static int txn_begin(knot_db_t *db, knot_db_txn_t *txn, unsigned flags) { if (!db || !txn) { return kr_error(EINVAL); @@ -114,7 +114,7 @@ static int txn_begin(namedb_t *db, namedb_txn_t *txn, unsigned flags) return kr_ok(); } -static int txn_commit(namedb_txn_t *txn) +static int txn_commit(knot_db_txn_t *txn) { if (!txn || !txn->db) { return kr_error(EINVAL); @@ -124,7 +124,7 @@ static int txn_commit(namedb_txn_t *txn) return kr_ok(); } -static void txn_abort(namedb_txn_t *txn) +static void txn_abort(knot_db_txn_t *txn) { /** @warning No real transactions here. */ txn_commit(txn); @@ -145,7 +145,7 @@ static void txn_abort(namedb_txn_t *txn) } \ } -static int count(namedb_txn_t *txn) +static int count(knot_db_txn_t *txn) { if (!txn || !txn->db) { return kr_error(EINVAL); @@ -165,7 +165,7 @@ static int count(namedb_txn_t *txn) return ret; } -static int clear(namedb_txn_t *txn) +static int clear(knot_db_txn_t *txn) { if (!txn || !txn->db) { return kr_error(EINVAL); @@ -181,7 +181,7 @@ static int clear(namedb_txn_t *txn) return kr_ok(); } -static int find(namedb_txn_t *txn, namedb_val_t *key, namedb_val_t *val, unsigned flags) +static int find(knot_db_txn_t *txn, knot_db_val_t *key, knot_db_val_t *val, unsigned flags) { if (!txn || !key || !val) { return kr_error(EINVAL); @@ -207,7 +207,7 @@ static int find(namedb_txn_t *txn, namedb_val_t *key, namedb_val_t *val, unsigne return kr_ok(); } -static int insert(namedb_txn_t *txn, namedb_val_t *key, namedb_val_t *val, unsigned flags) +static int insert(knot_db_txn_t *txn, knot_db_val_t *key, knot_db_val_t *val, unsigned flags) { if (!txn || !key || !val) { return kr_error(EINVAL); @@ -228,48 +228,48 @@ static int insert(namedb_txn_t *txn, namedb_val_t *key, namedb_val_t *val, unsig return kr_ok(); } -static int del(namedb_txn_t *txn, namedb_val_t *key) +static int del(knot_db_txn_t *txn, knot_db_val_t *key) { return kr_error(ENOSYS); } -static namedb_iter_t *iter_begin(namedb_txn_t *txn, unsigned flags) +static knot_db_iter_t *iter_begin(knot_db_txn_t *txn, unsigned flags) { /* Iteration is not supported, pruning should be * left on the Redis server setting */ return NULL; } -static namedb_iter_t *iter_seek(namedb_iter_t *iter, namedb_val_t *key, unsigned flags) +static knot_db_iter_t *iter_seek(knot_db_iter_t *iter, knot_db_val_t *key, unsigned flags) { assert(0); return NULL; /* ENOSYS */ } -static namedb_iter_t *iter_next(namedb_iter_t *iter) +static knot_db_iter_t *iter_next(knot_db_iter_t *iter) { assert(0); return NULL; } -static int iter_key(namedb_iter_t *iter, namedb_val_t *val) +static int iter_key(knot_db_iter_t *iter, knot_db_val_t *val) { return kr_error(ENOSYS); } -static int iter_val(namedb_iter_t *iter, namedb_val_t *val) +static int iter_val(knot_db_iter_t *iter, knot_db_val_t *val) { return kr_error(ENOSYS); } -static void iter_finish(namedb_iter_t *iter) +static void iter_finish(knot_db_iter_t *iter) { assert(0); } -const namedb_api_t *namedb_redis_api(void) +const knot_db_api_t *namedb_redis_api(void) { - static const namedb_api_t api = { + static const knot_db_api_t api = { "redis", init, deinit, txn_begin, txn_commit, txn_abort, diff --git a/modules/redis/redis.c b/modules/redis/redis.c index c38cbc5ccf633fba34a91aa44f72af3736962778..79f7c66cbe36e8fb855d3bedaf582890a648f771 100644 --- a/modules/redis/redis.c +++ b/modules/redis/redis.c @@ -14,7 +14,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <libknot/internal/namedb/namedb.h> +#include <libknot/db/db.h> #include <contrib/cleanup.h> #include <uv.h> @@ -24,7 +24,7 @@ #include "lib/cache.h" /** @internal Redis API */ -extern const namedb_api_t *namedb_redis_api(void); +extern const knot_db_api_t *namedb_redis_api(void); /** @internal Make redis options. */ void *namedb_redis_mkopts(const char *conf_, size_t maxsize) diff --git a/modules/stats/stats.c b/modules/stats/stats.c index 2b3e6219e7a4f25747a18cddbd3c0793a6528184..884098da2b9da98c4bf9a57df32698feb8551313 100644 --- a/modules/stats/stats.c +++ b/modules/stats/stats.c @@ -115,9 +115,9 @@ static void collect_sample(struct stat_data *data, struct kr_rplan *rplan, knot_ { /* Sample key = {[2] type, [1-255] owner} */ char key[sizeof(uint16_t) + KNOT_DNAME_MAXLEN]; - struct kr_query *qry = NULL; - WALK_LIST(qry, rplan->resolved) { + for (size_t i = 0; i < rplan->resolved.len; ++i) { /* Sample queries leading to iteration or expiring */ + struct kr_query *qry = rplan->resolved.at[i]; if ((qry->flags & QUERY_CACHED) && !(qry->flags & QUERY_EXPIRING)) { continue; } @@ -146,10 +146,10 @@ static int collect(knot_layer_t *ctx) collect_answer(data, param->answer); collect_sample(data, rplan, param->answer); /* Count cached and unresolved */ - if (!EMPTY_LIST(rplan->resolved)) { + if (rplan->resolved.len > 0) { /* Histogram of answer latency. */ - struct kr_query *first = HEAD(rplan->resolved); - struct kr_query *last = TAIL(rplan->resolved); + struct kr_query *first = rplan->resolved.at[0]; + struct kr_query *last = array_tail(rplan->resolved); struct timeval now; gettimeofday(&now, NULL); long elapsed = time_diff(&first->timestamp, &now); diff --git a/modules/view/view.lua b/modules/view/view.lua index 1efd5fbcd0569e39208c8c6c447c1b2f34f4fda9..2550112d0db77f0df5018fe15622450afc9f7879 100644 --- a/modules/view/view.lua +++ b/modules/view/view.lua @@ -2,11 +2,6 @@ local kres = require('kres') local policy = require('policy') local ffi = require('ffi') local C = ffi.C -ffi.cdef[[ -int kr_straddr_family(const char *addr); -int kr_straddr_subnet(void *dst, const char *addr); -int kr_bitcmp(const char *a, const char *b, int bits); -]] -- Module declaration local view = { @@ -29,7 +24,7 @@ end -- @function Match IP against given subnet local function match_subnet(family, subnet, bitlen, addr) - return (family == addr.sa_family) and (C.kr_bitcmp(subnet, addr:ip(), bitlen) == 0) + return (family == addr:family()) and (C.kr_bitcmp(subnet, addr:ip(), bitlen) == 0) end -- @function Find view for given request @@ -64,4 +59,4 @@ view.layer = { end } -return view \ No newline at end of file +return view diff --git a/scripts/bootstrap-depends.sh b/scripts/bootstrap-depends.sh index 3631130a27e07fffdcab2104b4ffb557d09742f3..6d7a90fc5eff23962f47ad00d03501425cca3877 100755 --- a/scripts/bootstrap-depends.sh +++ b/scripts/bootstrap-depends.sh @@ -1,11 +1,11 @@ #!/bin/bash -set -e +#set -e CMOCKA_TAG="cmocka-0.4.1" CMOCKA_URL="git://git.cryptomilk.org/projects/cmocka.git" LIBUV_TAG="v1.x" LIBUV_URL="https://github.com/libuv/libuv.git" -KNOT_TAG="c1353efc" +KNOT_TAG="v2.1.0-rc1" KNOT_URL="https://github.com/CZ-NIC/knot.git" GMP_TAG="6.0.0" GMP_URL="https://gmplib.org/download/gmp/gmp-${GMP_TAG}.tar.xz" @@ -15,8 +15,8 @@ NETTLE_TAG="2.7.1" NETTLE_URL="https://ftp.gnu.org/gnu/nettle/nettle-${NETTLE_TAG}.tar.gz" GNUTLS_TAG="3.3.12" GNUTLS_URL="ftp://ftp.gnutls.org/gcrypt/gnutls/v3.3/gnutls-${GNUTLS_TAG}.tar.xz" -LUA_TAG="v2.1" -LUA_URL="http://luajit.org/git/luajit-2.0.git" +LUA_TAG="2.1.0-beta1" +LUA_URL="http://luajit.org/download/LuaJIT-${LUA_TAG}.tar.gz" HIREDIS_TAG="v0.13.3" HIREDIS_URL="https://github.com/redis/hiredis.git" LIBMEMCACHED_TAG="1.0.18" @@ -109,7 +109,8 @@ pkg libknot ${KNOT_URL} ${KNOT_TAG} include/libknot \ --disable-static --with-lmdb=no --disable-fastparser --disable-daemon --disable-utilities --disable-documentation pkg cmocka ${CMOCKA_URL} ${CMOCKA_TAG} include/cmocka.h pkg libuv ${LIBUV_URL} ${LIBUV_TAG} include/uv.h --disable-static -pkg lua ${LUA_URL} ${LUA_TAG} lib/pkgconfig/luajit.pc amalg install BUILDMODE=dynamic LDFLAGS=-lm PREFIX=${PREFIX} +pkg lua ${LUA_URL} ${LUA_TAG} lib/pkgconfig/luajit.pc install BUILDMODE=dynamic LDFLAGS=-lm PREFIX=${PREFIX} +cat build.log # remove on successful build rm -rf ${BUILD_DIR} diff --git a/tests/deckard b/tests/deckard index 9d65d378b0b5e81b692ffe088a0a282f086a9efc..2e2feeb910f2092f4e24413405bb8f7e90fbb5d2 160000 --- a/tests/deckard +++ b/tests/deckard @@ -1 +1 @@ -Subproject commit 9d65d378b0b5e81b692ffe088a0a282f086a9efc +Subproject commit 2e2feeb910f2092f4e24413405bb8f7e90fbb5d2 diff --git a/tests/test.h b/tests/test.h index ceb43e0f95784eb06415b7c7113c171605f7cb59..b0e9c2ce49316a1b257f406a33180c329cea61b6 100644 --- a/tests/test.h +++ b/tests/test.h @@ -31,7 +31,7 @@ #pragma GCC diagnostic ignored "-Wdeprecated-declarations" #include "lib/defines.h" -#include <libknot/internal/mempattern.h> +#include "lib/utils.h" #include <libknot/descriptor.h> #include <libknot/rrset.h> @@ -42,7 +42,7 @@ static inline void mm_test_free(void *p) { if (p) test_free(p); } /** Memory context using CMocka allocator. */ -static inline void test_mm_ctx_init(mm_ctx_t *mm) +static inline void test_mm_ctx_init(knot_mm_t *mm) { mm->alloc = &mm_test_malloc; mm->free = &mm_test_free; diff --git a/tests/test_array.c b/tests/test_array.c index decac5b2c088205236e4a9d594bea3977dec65c7..d8ed5e3fc8219e74dd0ecf99ec8639a766a8e11d 100644 --- a/tests/test_array.c +++ b/tests/test_array.c @@ -17,7 +17,7 @@ #include "tests/test.h" #include "lib/generic/array.h" -mm_ctx_t global_mm; +knot_mm_t global_mm; static void test_array(void **state) { diff --git a/tests/test_cache.c b/tests/test_cache.c index 3bf0c41a56cd230a9071b720e0e998224928c086..19c621bf733d15b784a0019c73c1eee2aa301232 100644 --- a/tests/test_cache.c +++ b/tests/test_cache.c @@ -14,7 +14,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <libknot/internal/namedb/namedb_lmdb.h> +#include <libknot/db/db_lmdb.h> #include <ucw/mempool.h> #include "tests/test.h" @@ -24,7 +24,7 @@ #include <time.h> #include <dlfcn.h> -mm_ctx_t global_mm; +knot_mm_t global_mm; struct kr_cache_txn global_txn; knot_rrset_t global_rr; const char *global_env; @@ -33,32 +33,15 @@ struct kr_cache_entry global_fake_ce; #define NAMEDB_INTS 256 #define NAMEDB_DATA_SIZE (NAMEDB_INTS * sizeof(int)) uint8_t namedb_data[NAMEDB_DATA_SIZE]; -namedb_val_t global_namedb_data = {namedb_data, NAMEDB_DATA_SIZE}; -bool is_malloc_mocked = false; +knot_db_val_t global_namedb_data = {namedb_data, NAMEDB_DATA_SIZE}; #define CACHE_SIZE 10 * 4096 #define CACHE_TTL 10 #define CACHE_TIME 0 -void * (*original_malloc) (size_t __size); -int (*original_knot_rdataset_add)(knot_rdataset_t *rrs, const knot_rdata_t *rr, mm_ctx_t *mm) = NULL; +int (*original_knot_rdataset_add)(knot_rdataset_t *rrs, const knot_rdata_t *rr, knot_mm_t *mm) = NULL; -void *malloc(size_t __size) -{ - int err_mock = KNOT_EOK; - if (original_malloc == NULL) - { - original_malloc = dlsym(RTLD_NEXT,"malloc"); - assert_non_null (malloc); - } - if (is_malloc_mocked) - { - err_mock = mock(); - } - return (err_mock != KNOT_EOK) ? NULL : original_malloc (__size); -} - -int knot_rdataset_add(knot_rdataset_t *rrs, const knot_rdata_t *rr, mm_ctx_t *mm) +int knot_rdataset_add(knot_rdataset_t *rrs, const knot_rdata_t *rr, knot_mm_t *mm) { int err, err_mock; err_mock = (int)mock(); @@ -74,39 +57,39 @@ int knot_rdataset_add(knot_rdataset_t *rrs, const knot_rdata_t *rr, mm_ctx_t *mm } /* Simulate init failure */ -static int fake_test_init(namedb_t **db_ptr, mm_ctx_t *mm, void *arg) +static int fake_test_init(knot_db_t **db_ptr, knot_mm_t *mm, void *arg) { static char db[1024]; *db_ptr = db; return mock(); } -static void fake_test_deinit(namedb_t *db) +static void fake_test_deinit(knot_db_t *db) { return; } /* Simulate commit failure */ -static int fake_test_commit(namedb_txn_t *txn) +static int fake_test_commit(knot_db_txn_t *txn) { return KNOT_ESPACE; } /* Dummy abort */ -static void fake_test_abort(namedb_txn_t *txn) +static void fake_test_abort(knot_db_txn_t *txn) { return; } /* Stub for find */ -static int fake_test_find(namedb_txn_t *txn, namedb_val_t *key, namedb_val_t *val, unsigned flags) +static int fake_test_find(knot_db_txn_t *txn, knot_db_val_t *key, knot_db_val_t *val, unsigned flags) { val->data = &global_fake_ce; return KNOT_EOK; } /* Stub for insert */ -static int fake_test_ins(namedb_txn_t *txn, namedb_val_t *key, namedb_val_t *val, unsigned flags) +static int fake_test_ins(knot_db_txn_t *txn, knot_db_val_t *key, knot_db_val_t *val, unsigned flags) { struct kr_cache_entry *header = val->data; int res_cmp, err = (int)mock(); @@ -125,15 +108,15 @@ static int fake_test_ins(namedb_txn_t *txn, namedb_val_t *key, namedb_val_t *val return err; } -static int fake_test_txn_begin(namedb_t *db, namedb_txn_t *txn, unsigned flags) +static int fake_test_txn_begin(knot_db_t *db, knot_db_txn_t *txn, unsigned flags) { return KNOT_EOK; } /* Fake api */ -static namedb_api_t *fake_namedb_lmdb_api(void) +static knot_db_api_t *fake_knot_db_lmdb_api(void) { - static namedb_api_t fake_api = { + static knot_db_api_t fake_api = { "lmdb_fake_api", fake_test_init, fake_test_deinit, fake_test_txn_begin, fake_test_commit, fake_test_abort, @@ -145,10 +128,10 @@ static namedb_api_t *fake_namedb_lmdb_api(void) } /* Test cache open */ -static int test_open(void **state, namedb_api_t *api) +static int test_open(void **state, knot_db_api_t *api) { static struct kr_cache cache; - struct namedb_lmdb_opts opts; + struct knot_db_lmdb_opts opts; memset(&cache, 0, sizeof(cache)); memset(&opts, 0, sizeof(opts)); opts.path = global_env; @@ -162,10 +145,10 @@ static void test_open_fake_api(void **state) { bool res; will_return(fake_test_init,KNOT_EINVAL); - assert_int_equal(test_open(state, fake_namedb_lmdb_api()),KNOT_EINVAL); + assert_int_equal(test_open(state, fake_knot_db_lmdb_api()),KNOT_EINVAL); will_return(fake_test_init,KNOT_EOK); - assert_int_equal(test_open(state, fake_namedb_lmdb_api()),KNOT_EOK); - res = (((struct kr_cache *)(*state))->api == fake_namedb_lmdb_api()); + assert_int_equal(test_open(state, fake_knot_db_lmdb_api()),KNOT_EOK); + res = (((struct kr_cache *)(*state))->api == fake_knot_db_lmdb_api()); assert_true(res); } @@ -173,7 +156,7 @@ static void test_open_conventional_api(void **state) { bool res; assert_int_equal(test_open(state, NULL),KNOT_EOK); - res = (((struct kr_cache *)(*state))->api == namedb_lmdb_api()); + res = (((struct kr_cache *)(*state))->api == knot_db_lmdb_api()); assert_true(res); } @@ -197,7 +180,7 @@ static struct kr_cache_txn *test_txn_write(void **state) static struct kr_cache_txn *test_txn_rdonly(void **state) { assert_non_null(*state); - assert_int_equal(kr_cache_txn_begin(*state, &global_txn, NAMEDB_RDONLY), 0); + assert_int_equal(kr_cache_txn_begin(*state, &global_txn, KNOT_DB_RDONLY), 0); return &global_txn; } @@ -205,7 +188,7 @@ static struct kr_cache_txn *test_txn_rdonly(void **state) static void test_fake_invalid (void **state) { struct kr_cache_txn *txn = NULL; - const namedb_api_t *api_saved = NULL; + const knot_db_api_t *api_saved = NULL; knot_dname_t dname[] = ""; struct kr_cache_entry *entry = NULL; int ret = 0; @@ -224,24 +207,18 @@ static void test_fake_invalid (void **state) static void test_fake_insert(void **state) { - int ret_cache_ins_ok, ret_cache_lowmem, ret_cache_ins_inval; + int ret_cache_ins_ok, ret_cache_ins_inval; knot_dname_t dname[] = ""; struct kr_cache_txn *txn = test_txn_write(state); test_randstr((char *)&global_fake_ce,sizeof(global_fake_ce)); test_randstr((char *)namedb_data,NAMEDB_DATA_SIZE); - will_return(malloc,KNOT_EINVAL); - is_malloc_mocked = true; - ret_cache_lowmem = kr_cache_insert(txn, KR_CACHE_USER, dname, - KNOT_RRTYPE_TSIG, &global_fake_ce, global_namedb_data); - is_malloc_mocked = false; will_return(fake_test_ins,KNOT_EOK); ret_cache_ins_ok = kr_cache_insert(txn, KR_CACHE_USER, dname, KNOT_RRTYPE_TSIG, &global_fake_ce, global_namedb_data); will_return(fake_test_ins,KNOT_EINVAL); ret_cache_ins_inval = kr_cache_insert(txn, KR_CACHE_USER, dname, KNOT_RRTYPE_TSIG, &global_fake_ce, global_namedb_data); - assert_int_equal(ret_cache_lowmem, KNOT_ENOMEM); assert_int_equal(ret_cache_ins_ok, KNOT_EOK); assert_int_equal(ret_cache_ins_inval, KNOT_EINVAL); } @@ -251,7 +228,7 @@ static void test_invalid(void **state) { knot_dname_t dname[] = ""; uint32_t timestamp = CACHE_TIME; - struct namedb_lmdb_opts opts; + struct knot_db_lmdb_opts opts; struct kr_cache_entry *entry = NULL; memset(&opts, 0, sizeof(opts)); diff --git a/tests/test_pack.c b/tests/test_pack.c index c2a470b4a46719adeb04fcdaada5c9dd5c2f957b..b55c15cc2ea12ed2095273abbb8000eea4f0ab32 100644 --- a/tests/test_pack.c +++ b/tests/test_pack.c @@ -18,7 +18,7 @@ #include "lib/generic/pack.h" #define U8(x) (const uint8_t *)(x) -mm_ctx_t global_mm; +knot_mm_t global_mm; static void test_pack_std(void **state) { diff --git a/tests/test_rplan.c b/tests/test_rplan.c index 53d22f92bd43e536fe1e10b24e4a488f9bb6b586..f05cdde21a263bcdac84b4ae8ccc410fbb7e31e6 100644 --- a/tests/test_rplan.c +++ b/tests/test_rplan.c @@ -40,7 +40,7 @@ static void test_rplan_params(void **state) static void test_rplan_push(void **state) { - mm_ctx_t mm; + knot_mm_t mm; test_mm_ctx_init(&mm); struct kr_request request = { .pool = mm,