MAJOR := 1
MINOR := 0
PATCH := 0-beta2
+ABIVER := 1
+BUILDMODE := dynamic
HARDENING := yes
# Paths
--- /dev/null
+contrib_SOURCES := \
+ contrib/ccan/asprintf/asprintf.c \
+ contrib/ccan/ilog/ilog.c \
+ contrib/ccan/isaac/isaac.c \
+ contrib/ccan/json/json.c \
+ contrib/ucw/mempool.c \
+ contrib/murmurhash3/murmurhash3.c
+contrib_CFLAGS := -fPIC
+contrib_TARGET := $(abspath contrib)/contrib$(AREXT)
+$(eval $(call make_static,contrib,contrib))
kresd_CFLAGS := -fPIE
kresd_DEPEND := $(libkres) $(contrib)
-kresd_LIBS := $(contrib_TARGET) $(libkres_TARGET) $(libknot_LIBS) $(libdnssec_LIBS) $(libuv_LIBS) $(lua_LIBS)
+kresd_LIBS := $(libkres_TARGET) $(contrib_TARGET) $(libknot_LIBS) $(libdnssec_LIBS) $(libuv_LIBS) $(lua_LIBS)
# Make binary
ifeq ($(HAS_lua)|$(HAS_libuv), yes|yes)
static int l_verbose(lua_State *L)
{
if (lua_isboolean(L, 1) || lua_isnumber(L, 1)) {
- log_debug_enable(lua_toboolean(L, 1));
+ kr_debug_set(lua_toboolean(L, 1));
}
- lua_pushboolean(L, log_debug_status());
+ lua_pushboolean(L, kr_debug_status());
return 1;
}
unsigned opt_code = 0;
if (lua_isstring(L, 1)) {
const char *opt = lua_tostring(L, 1);
- for (const lookup_table_t *it = query_flag_names; it->name; ++it) {
+ for (const lookup_table_t *it = kr_query_flag_names(); it->name; ++it) {
if (strcmp(it->name, opt) == 0) {
opt_code = it->id;
break;
g_interactive = 0;
forks = atoi(optarg);
if (forks == 0) {
- log_error("[system] error '-f' requires number, not '%s'\n", optarg);
+ kr_log_error("[system] error '-f' requires number, not '%s'\n", optarg);
return EXIT_FAILURE;
}
#if (!defined(UV_VERSION_HEX)) || (!defined(SO_REUSEPORT))
if (forks > 1) {
- log_error("[system] libuv 1.7+ is required for SO_REUSEPORT support, multiple forks not supported\n");
+ kr_log_error("[system] libuv 1.7+ is required for SO_REUSEPORT support, multiple forks not supported\n");
return EXIT_FAILURE;
}
#endif
}
free(keyfile_buf);
if (!keyfile) {
- log_error("[system] keyfile '%s': not writeable\n", optarg);
+ kr_log_error("[system] keyfile '%s': not writeable\n", optarg);
return EXIT_FAILURE;
}
break;
case 'v':
- log_debug_enable(true);
+ kr_debug_set(true);
break;
case 'V':
- log_info("%s, version %s\n", "Knot DNS Resolver", PACKAGE_VERSION);
+ kr_log_info("%s, version %s\n", "Knot DNS Resolver", PACKAGE_VERSION);
return EXIT_SUCCESS;
case 'h':
case '?':
if (optind < argc) {
const char *rundir = argv[optind];
if (access(rundir, W_OK) != 0) {
- log_error("[system] rundir '%s': %s\n", rundir, strerror(errno));
+ kr_log_error("[system] rundir '%s': %s\n", rundir, strerror(errno));
return EXIT_FAILURE;
}
ret = chdir(rundir);
if (ret != 0) {
- log_error("[system] rundir '%s': %s\n", rundir, strerror(errno));
+ kr_log_error("[system] rundir '%s': %s\n", rundir, strerror(errno));
return EXIT_FAILURE;
}
if(config && access(config, R_OK) != 0) {
- log_error("[system] rundir '%s'\n", rundir);
- log_error("[system] config '%s': %s\n", config, strerror(errno));
+ kr_log_error("[system] rundir '%s'\n", rundir);
+ kr_log_error("[system] config '%s': %s\n", config, strerror(errno));
return EXIT_FAILURE;
}
}
struct engine engine;
ret = engine_init(&engine, &pool);
if (ret != 0) {
- log_error("[system] failed to initialize engine: %s\n", kr_strerror(ret));
+ kr_log_error("[system] failed to initialize engine: %s\n", kr_strerror(ret));
return EXIT_FAILURE;
}
/* Create worker */
struct worker_ctx *worker = init_worker(loop, &engine, &pool, forks, fork_count);
if (!worker) {
- log_error("[system] not enough memory\n");
+ kr_log_error("[system] not enough memory\n");
return EXIT_FAILURE;
}
/* Bind to sockets and run */
const char *addr = set_addr(addr_set.at[i], &port);
ret = network_listen(&engine.net, addr, (uint16_t)port, NET_UDP|NET_TCP);
if (ret != 0) {
- log_error("[system] bind to '%s#%d' %s\n", addr, port, knot_strerror(ret));
+ kr_log_error("[system] bind to '%s#%d' %s\n", addr, port, knot_strerror(ret));
ret = EXIT_FAILURE;
}
}
if (keyfile) {
auto_free char *cmd = afmt("trust_anchors.file = '%s'", keyfile);
if (!cmd) {
- log_error("[system] not enough memory\n");
+ kr_log_error("[system] not enough memory\n");
return EXIT_FAILURE;
}
engine_cmd(&engine, cmd);
assert(task);
knot_pkt_t *pkt = task->pktbuf;
assert(knot_wire_get_qr(pkt->wire) == false);
- return kr_rrmap_key(dst, knot_pkt_qname(pkt), knot_pkt_qtype(pkt), knot_pkt_qclass(pkt));
+ return kr_rrkey(dst, knot_pkt_qname(pkt), knot_pkt_qtype(pkt), knot_pkt_qclass(pkt));
}
static void subreq_finalize(struct qr_task *task, const struct sockaddr *packet_source, knot_pkt_t *pkt)
/* Clear from outstanding table. */
if (!task->leading)
return;
- char key[RRMAP_KEYSIZE];
+ char key[KR_RRKEY_LEN];
int ret = subreq_key(key, task);
if (ret > 0) {
assert(map_get(&task->worker->outstanding, key) == task);
static void subreq_lead(struct qr_task *task)
{
assert(task);
- char key[RRMAP_KEYSIZE];
+ char key[KR_RRKEY_LEN];
if (subreq_key(key, task) > 0) {
assert(map_contains(&task->worker->outstanding, key) == false);
map_set(&task->worker->outstanding, key, task);
static bool subreq_enqueue(struct qr_task *task)
{
assert(task);
- char key[RRMAP_KEYSIZE];
+ char key[KR_RRKEY_LEN];
if (subreq_key(key, task) > 0) {
struct qr_task *leader = map_get(&task->worker->outstanding, key);
if (leader) {
/* Enqueue itself to leader for this subrequest. */
- int ret = array_reserve_mm(leader->waiting, leader->waiting.len + 1, mm_reserve, &leader->req.pool);
+ int ret = array_reserve_mm(leader->waiting, leader->waiting.len + 1, kr_memreserve, &leader->req.pool);
if (ret == 0) {
array_push(leader->waiting, task);
qr_task_ref(task);
"-pie", "**enabled**", "enables ASLR for kresd (disable with ``make HARDENING=no``)"
"RELRO", "**enabled**", "full [#]_"
-You can also disable ELF hardening when it's unsupported with ``make HARDENING=no``.
+You can also disable linker hardening when it's unsupported with ``make HARDENING=no``.
.. [#] See `checksec.sh <http://www.trapkit.de/tools/checksec.html>`_
.. csv-table::
:header: "Component", "Variable", "Default", "Notes"
- "library", "``LIBDIR``", "``$(PREFIX)/lib``", "Built statically."
+ "library", "``LIBDIR``", "``$(PREFIX)/lib``", "pkg-config is auto-generated [#]_"
"daemon", "``BINDIR``", "``$(PREFIX)/bin``", ""
"configuration", "``ETCDIR``", "``$(PREFIX)/etc/kresd``", "Configuration file, templates."
"modules", "``MODULEDIR``", "``$(LIBDIR)/kdns_modules``", "[#]_"
"work directory", "", "``$(PREFIX)/var/run/kresd``", "Run directory for daemon."
+.. [#] The ``libkres.pc`` is installed in ``$(LIBDIR)/pkgconfig``.
.. [#] Users may install additional modules in ``~/.local/lib/kdns_modules`` or in the rundir of a specific instance.
.. note:: Each module is self-contained and may install additional bundled files within ``$(MODULEDIR)/$(modulename)``. These files should be read-only, non-executable.
+Static or dynamic?
+~~~~~~~~~~~~~~~~~~
+
+By default the resolver library is built as a dynamic library with versioned ABI. You can revert to static build with ``BUILDMODE`` variable.
+
+.. code-block:: bash
+
+ $ make BUILDMODE=dynamic # Default, create dynamic library
+ $ make BUILDMODE=static # Create static library
+
+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
~~~~~~~~~~~~~~~~~~~~~
/* Recreate cache and write version key */
ret = txn_api(&txn)->count(&txn.t);
if (ret > 0) { /* Non-empty cache, purge it. */
- log_info("[cache] purging cache\n");
+ kr_log_info("[cache] purging cache\n");
kr_cache_clear(&txn);
kr_cache_txn_commit(&txn);
ret = kr_cache_txn_begin(cache, &txn, 0);
#include <libknot/rrset.h>
#include <libknot/internal/namedb/namedb.h>
+#include "lib/defines.h"
/** Cache entry tag */
enum kr_cache_tag {
* @param mm memory context.
* @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);
/**
* @note This doesn't clear the data, just closes the connection to the database.
* @param cache database instance
*/
+KR_EXPORT
void kr_cache_close(struct kr_cache *cache);
/**
* @param flags transaction flags (see namedb.h in libknot)
* @return 0 or an errcode
*/
+KR_EXPORT
int kr_cache_txn_begin(struct kr_cache *cache, struct kr_cache_txn *txn, unsigned flags);
/**
* @param txn transaction instance
* @return 0 or an errcode
*/
+KR_EXPORT
int kr_cache_txn_commit(struct kr_cache_txn *txn);
/**
* Abort existing transaction instance.
* @param txn transaction instance
*/
+KR_EXPORT
void kr_cache_txn_abort(struct kr_cache_txn *txn);
/**
* @param timestamp current time (will be replaced with drift if successful)
* @return 0 or an errcode
*/
+KR_EXPORT
int kr_cache_peek(struct kr_cache_txn *txn, uint8_t tag, const knot_dname_t *name, uint16_t type,
struct kr_cache_entry **entry, uint32_t *timestamp);
* @param data inserted data
* @return 0 or an errcode
*/
+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);
* @param type record type
* @return 0 or an errcode
*/
+KR_EXPORT
int kr_cache_remove(struct kr_cache_txn *txn, uint8_t tag, const knot_dname_t *name, uint16_t type);
/**
* @param txn transaction instance
* @return 0 or an errcode
*/
+KR_EXPORT
int kr_cache_clear(struct kr_cache_txn *txn);
/**
* @param timestamp current time
* @return rank (0 or positive), or an error (negative number)
*/
+KR_EXPORT
int kr_cache_peek_rank(struct kr_cache_txn *txn, uint8_t tag, const knot_dname_t *name, uint16_t type, uint32_t timestamp);
/**
* @param timestamp current time (will be replaced with drift if successful)
* @return 0 or an errcode
*/
+KR_EXPORT
int kr_cache_peek_rr(struct kr_cache_txn *txn, knot_rrset_t *rr, uint16_t *rank, uint32_t *timestamp);
/**
* @param mm memory context
* @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);
/**
* @param timestamp current time
* @return 0 or an errcode
*/
+KR_EXPORT
int kr_cache_insert_rr(struct kr_cache_txn *txn, const knot_rrset_t *rr, uint16_t rank, uint32_t timestamp);
/**
* @param timestamp current time (will be replaced with drift if successful)
* @return 0 or an errcode
*/
+KR_EXPORT
int kr_cache_peek_rrsig(struct kr_cache_txn *txn, knot_rrset_t *rr, uint16_t *rank, uint32_t *timestamp);
/**
* @param timestamp current time
* @return 0 or an errcode
*/
+KR_EXPORT
int kr_cache_insert_rrsig(struct kr_cache_txn *txn, const knot_rrset_t *rr, uint16_t rank, uint32_t timestamp);
#define KR_CONST __attribute__((__const__))
#define KR_PURE __attribute__((__pure__))
#define KR_NORETURN __attribute__((__noreturn__))
+#define KR_COLD __attribute__((__cold__))
#else
#define KR_EXPORT
#define KR_CONST
#define KR_PURE
#define KR_NORETURN
+#define KR_COLD
#endif
/*
#pragma once
+#include "lib/defines.h"
#include <libknot/internal/consts.h>
#include <libknot/packet/pkt.h>
/**
* Initialise cryptographic back-end.
*/
+KR_EXPORT
void kr_crypto_init(void);
/**
* De-initialise cryptographic back-end.
*/
+KR_EXPORT
void kr_crypto_cleanup(void);
/**
* Re-initialise cryptographic back-end.
* @note Must be called after fork() in the child.
*/
+KR_EXPORT
void kr_crypto_reinit(void);
/** Opaque DNSSEC key pointer. */
bool has_nsec3);
/** Return true if the DNSKEY can be used as a ZSK. */
+KR_EXPORT KR_PURE
bool kr_dnssec_key_zsk(const uint8_t *dnskey_rdata);
/** Return true if the DNSKEY indicates being KSK (=> has SEP). */
+KR_EXPORT KR_PURE
bool kr_dnssec_key_ksk(const uint8_t *dnskey_rdata);
/** Return true if the DNSKEY is revoked. */
+KR_EXPORT KR_PURE
bool kr_dnssec_key_revoked(const uint8_t *dnskey_rdata);
/** Return DNSKEY tag.
* @param rdlen RDATA length.
* @return Key tag (positive number), or an error code
*/
+KR_EXPORT KR_PURE
int kr_dnssec_key_tag(uint16_t rrtype, const uint8_t *rdata, size_t rdlen);
/** Return 0 if the two keys are identical.
* @param key_b_rdlen Second key RDATA length
* @return 0 if they match or an error code
*/
+KR_EXPORT KR_PURE
int kr_dnssec_key_match(const uint8_t *key_a_rdata, size_t key_a_rdlen,
const uint8_t *key_b_rdata, size_t key_b_rdlen);
* @param name name of the TA
* @return non-empty RRSet or NULL
*/
+KR_EXPORT
knot_rrset_t *kr_ta_get(map_t *trust_anchors, const knot_dname_t *name);
/**
* @param rdlen
* @return 0 or an error
*/
+KR_EXPORT
int kr_ta_add(map_t *trust_anchors, const knot_dname_t *name, uint16_t type,
uint32_t ttl, const uint8_t *rdata, uint16_t rdlen);
* @param name name of the TA
* @return boolean
*/
+KR_EXPORT KR_PURE
int kr_ta_covers(map_t *trust_anchors, const knot_dname_t *name);
/**
* @param name name of the TA
* @return 0 or an error
*/
+KR_EXPORT
int kr_ta_del(map_t *trust_anchors, const knot_dname_t *name);
/**
* Clear trust store.
* @param trust_anchors trust store
*/
+KR_EXPORT
void kr_ta_clear(map_t *trust_anchors);
#include "map.h"
+ /* Exports */
+#if defined _WIN32 || defined __CYGWIN__
+ #define EXPORT __attribute__ ((dllexport))
+#else
+ #define EXPORT __attribute__ ((visibility ("default")))
+#endif
+
#ifdef _MSC_VER /* MSVC */
typedef unsigned __int8 uint8_t;
typedef unsigned __int32 uint32_t;
}
/*! Creates a new, empty critbit map */
-map_t map_make(void)
+EXPORT map_t map_make(void)
{
map_t map;
map.root = NULL;
}
/*! Returns non-zero if map contains str */
-int map_contains(map_t *map, const char *str)
+EXPORT int map_contains(map_t *map, const char *str)
{
return map_get(map, str) != NULL;
}
-void *map_get(map_t *map, const char *str)
+EXPORT void *map_get(map_t *map, const char *str)
{
const uint8_t *ubytes = (void *)str;
const size_t ulen = strlen(str);
}
/*! Inserts str into map, returns 0 on success */
-int map_set(map_t *map, const char *str, void *value)
+EXPORT int map_set(map_t *map, const char *str, void *value)
{
const uint8_t *const ubytes = (void *)str;
const size_t ulen = strlen(str);
}
/*! Deletes str from the map, returns 0 on success */
-int map_del(map_t *map, const char *str)
+EXPORT int map_del(map_t *map, const char *str)
{
const uint8_t *ubytes = (void *)str;
const size_t ulen = strlen(str);
}
/*! Clears the given map */
-void map_clear(map_t *map)
+EXPORT void map_clear(map_t *map)
{
if (map->root) {
cbt_traverse_delete(map, map->root);
}
/*! Calls callback for all strings in map with the given prefix */
-int map_walk_prefixed(map_t *map, const char *prefix,
+EXPORT int map_walk_prefixed(map_t *map, const char *prefix,
int (*callback)(const char *, void *, void *), void *baton)
{
const uint8_t *ubytes = (void *)prefix;
#define QRDEBUG(query, cls, fmt, ...) do { \
unsigned _ind = 0; \
for (struct kr_query *q = (query); q; q = q->parent, _ind += 2); \
- log_debug("[%s] %*s" fmt, cls, _ind, "", ## __VA_ARGS__); \
+ kr_log_debug("[%s] %*s" fmt, cls, _ind, "", ## __VA_ARGS__); \
} while (0)
#else
#define QRDEBUG(query, cls, fmt, ...)
libkres_TARGET := -L$(abspath lib) -lkres
# Make library
+ifeq ($(BUILDMODE), static)
$(eval $(call make_static,libkres,lib,yes))
+else
+$(eval $(call make_lib,libkres,lib,yes,$(ABIVER)))
+endif
+
+# Generate pkg-config file
+libkres.pc:
+ @echo 'prefix='$(PREFIX) > $@
+ @echo 'exec_prefix=$${prefix}' >> $@
+ @echo 'libdir='$(LIBDIR) >> $@
+ @echo 'includedir='$(INCLUDEDIR) >> $@
+ @echo 'Name: libkres' >> $@
+ @echo 'Description: Knot DNS Resolver library' >> $@
+ @echo 'URL: https://www.knot-dns.cz' >> $@
+ @echo 'Version: $(MAJOR).$(MINOR).$(PATCH)' >> $@
+ @echo 'Libs: -L$${libdir} -lkres' >> $@
+ @echo 'Cflags: -I$${includedir}' >> $@
+libkres-pcinstall: libkres.pc libkres-install
+ $(INSTALL) -m 644 $< $(DESTDIR)$(LIBDIR)/pkgconfig
# Targets
lib: $(libkres)
-lib-install: libkres-install
+lib-install: libkres-install libkres-pcinstall
lib-clean: libkres-clean
-.PHONY: lib lib-install lib-clean
+.PHONY: lib lib-install lib-clean libkres.pc
* @param path module search path
* @return 0 or an error
*/
+KR_EXPORT
int kr_module_load(struct kr_module *module, const char *name, const char *path);
/**
*
* @param module module structure
*/
+KR_EXPORT
void kr_module_unload(struct kr_module *module);
/**
* @param addr_len address bytes length (type will be derived from this)
* @return 0 or an error code
*/
+KR_EXPORT
int kr_nsrep_set(struct kr_query *qry, uint8_t *addr, size_t addr_len);
/**
* @param ctx resolution context
* @return 0 or an error code
*/
+KR_EXPORT
int kr_nsrep_elect(struct kr_query *qry, struct kr_context *ctx);
/**
* @param ctx resolution context
* @return 0 or an error code
*/
+KR_EXPORT
int kr_nsrep_elect_addr(struct kr_query *qry, struct kr_context *ctx);
/**
* @param cache LRU cache
* @return 0 on success, error code on failure
*/
+KR_EXPORT
int kr_nsrep_update_rtt(struct kr_nsrep *ns, const struct sockaddr *addr, unsigned score, kr_nsrep_lru_t *cache);
/**
* @param cache LRU cache
* @return 0 on success, error code on failure
*/
+KR_EXPORT
int kr_nsrep_update_rep(struct kr_nsrep *ns, unsigned reputation, kr_nsrep_lru_t *cache);
* @param answer allocated packet for final answer
* @return CONSUME (expecting query)
*/
+KR_EXPORT
int kr_resolve_begin(struct kr_request *request, struct kr_context *ctx, knot_pkt_t *answer);
/**
* @param packet [in] input packet
* @return any state
*/
+KR_EXPORT
int kr_resolve_consume(struct kr_request *request, const struct sockaddr *src, knot_pkt_t *packet);
/**
* @param packet [out] packet to be filled with additional query
* @return any state
*/
+KR_EXPORT
int kr_resolve_produce(struct kr_request *request, struct sockaddr **dst, int *type, knot_pkt_t *packet);
/**
* @param state either DONE or FAIL state
* @return DONE
*/
+KR_EXPORT
int kr_resolve_finish(struct kr_request *request, int state);
/**
* @param request request state
* @return pointer to rplan
*/
+KR_EXPORT KR_PURE
struct kr_rplan *kr_resolve_plan(struct kr_request *request);
/**
* @param request request state
* @return mempool
*/
+KR_EXPORT KR_PURE
mm_ctx_t *kr_resolve_pool(struct kr_request *request);
{ 0, NULL }
};
+const lookup_table_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)
{
if (name == NULL) {
};
/** Query flag names table */
-extern const lookup_table_t query_flag_names[];
+KR_EXPORT KR_CONST
+const lookup_table_t *kr_query_flag_names(void);
/**
* Single query representation.
* @param request resolution request
* @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);
/**
* Deinitialize resolution plan, aborting any uncommited transactions.
* @param rplan plan instance
*/
+KR_EXPORT
void kr_rplan_deinit(struct kr_rplan *rplan);
/**
* @param rplan plan instance
* @return true or false
*/
+KR_EXPORT KR_PURE
bool kr_rplan_empty(struct kr_rplan *rplan);
/**
* @param type resolved type
* @return query instance or NULL
*/
+KR_EXPORT
struct kr_query *kr_rplan_push(struct kr_rplan *rplan, struct kr_query *parent,
const knot_dname_t *name, uint16_t cls, uint16_t type);
* @param qry resolved query
* @return 0 or an error
*/
+KR_EXPORT
int kr_rplan_pop(struct kr_rplan *rplan, struct kr_query *qry);
/**
* Return true if resolution chain satisfies given query.
*/
+KR_EXPORT KR_PURE
bool kr_rplan_satisfies(struct kr_query *closure, const knot_dname_t *name, uint16_t cls, uint16_t type);
/** Return last resolved query. */
+KR_EXPORT KR_PURE
struct kr_query *kr_rplan_resolved(struct kr_rplan *rplan);
/** Return query predecessor. */
+KR_EXPORT KR_PURE
struct kr_query *kr_rplan_next(struct kr_query *qry);
\ No newline at end of file
#include "lib/resolve.h"
/* Logging & debugging */
-bool _env_debug = false;
+static bool _env_debug = false;
/** @internal CSPRNG context */
static isaac_ctx ISAAC;
/*
* Cleanup callbacks.
*/
-void _cleanup_free(char **p)
+
+bool kr_debug_set(bool status)
{
- free(*p);
+ return _env_debug = status;
}
-void _cleanup_close(int *p)
+bool kr_debug_status(void)
{
- if (*p > 0) close(*p);
+ return _env_debug;
}
-void _cleanup_fclose(FILE **p)
+void kr_log_debug(const char *fmt, ...)
{
- if (*p) fclose(*p);
+ if (_env_debug) {
+ va_list args;
+ va_start(args, fmt);
+ vprintf(fmt, args);
+ va_end(args);
+ fflush(stdout);
+ }
}
char* kr_strcatdup(unsigned n, ...)
return isaac_next_uint(&ISAAC, max);
}
-int mm_reserve(void *baton, char **mem, size_t elm_size, size_t want, size_t *have)
+int kr_memreserve(void *baton, char **mem, size_t elm_size, size_t want, size_t *have)
{
if (*have >= want) {
return 0;
return ret;
}
-int kr_rrmap_key(char *key, const knot_dname_t *owner, uint16_t type, uint8_t rank)
+int kr_rrkey(char *key, const knot_dname_t *owner, uint16_t type, uint8_t rank)
{
if (!key || !owner) {
return kr_error(EINVAL);
}
/* Stash key = {[1] flags, [1-255] owner, [5] type, [1] \x00 } */
- char key[RRMAP_KEYSIZE];
+ char key[KR_RRKEY_LEN];
uint8_t extra_flags = 0;
uint16_t rrtype = rr->type;
/* Stash RRSIGs in a special cache, flag them and set type to its covering RR.
rrtype = knot_rrsig_type_covered(&rr->rrs, 0);
extra_flags |= KEY_FLAG_RRSIG;
}
- int ret = kr_rrmap_key(key, rr->owner, rrtype, rank);
+ int ret = kr_rrkey(key, rr->owner, rrtype, rank);
if (ret <= 0) {
return kr_error(EILSEQ);
}
int kr_rrarray_add(rr_array_t *array, const knot_rrset_t *rr, mm_ctx_t *pool)
{
- int ret = array_reserve_mm(*array, array->len + 1, mm_reserve, pool);
+ int ret = array_reserve_mm(*array, array->len + 1, kr_memreserve, pool);
if (ret != 0) {
return kr_error(ENOMEM);
}
/*
* Logging and debugging.
*/
-#define log_info(fmt, ...) printf((fmt), ## __VA_ARGS__)
-#define log_error(fmt, ...) fprintf(stderr, (fmt), ## __VA_ARGS__)
+#define kr_log_info(fmt, ...) printf((fmt), ## __VA_ARGS__)
+#define kr_log_error(fmt, ...) fprintf(stderr, (fmt), ## __VA_ARGS__)
#ifndef NDEBUG
-extern bool _env_debug; /* @internal cond variable */
/* Toggle debug messages */
-#define log_debug_enable(x) _env_debug = (x)
-#define log_debug_status() _env_debug
-/* Message logging */
-#define log_debug(fmt, ...) do { \
- if (_env_debug) { printf((fmt), ## __VA_ARGS__); fflush(stdout); } \
- } while (0)
+KR_EXPORT bool kr_debug_set(bool status);
+KR_EXPORT KR_PURE bool kr_debug_status(void);
+KR_EXPORT void kr_log_debug(const char *fmt, ...);
/* Debug block */
-#define WITH_DEBUG if(__builtin_expect(_env_debug, 0))
+#define WITH_DEBUG if(__builtin_expect(kr_debug_status(), 0))
#else
-#define log_debug_status() false
-#define log_debug_enable(x)
-#define log_debug(fmt, ...)
+#define kr_debug_status() false
+#define kr_debug_set(x)
+#define kr_log_debug(fmt, ...)
#define WITH_DEBUG if(0)
#endif
#define kr_rdataset_next(rd) (rd + knot_rdata_array_size(knot_rdata_rdlen(rd)))
/** Concatenate N strings. */
+KR_EXPORT
char* kr_strcatdup(unsigned n, ...);
/** Reseed CSPRNG context. */
int kr_rand_reseed(void);
/** Get pseudo-random value. */
+KR_EXPORT
unsigned kr_rand_uint(unsigned max);
/** Memory reservation routine for mm_ctx_t */
-int mm_reserve(void *baton, char **mem, size_t elm_size, size_t want, size_t *have);
+KR_EXPORT
+int kr_memreserve(void *baton, char **mem, size_t elm_size, size_t want, size_t *have);
/** @internal Fast packet reset. */
+KR_EXPORT
int kr_pkt_recycle(knot_pkt_t *pkt);
/** Construct and put record to packet. */
+KR_EXPORT
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);
/** Address bytes for given family. */
+KR_EXPORT KR_PURE
const char *kr_inaddr(const struct sockaddr *addr);
/** Address length for given family. */
+KR_EXPORT KR_PURE
int kr_inaddr_len(const struct sockaddr *addr);
/** Return address type for string. */
+KR_EXPORT KR_PURE
int kr_straddr_family(const char *addr);
/** Return address length in given family. */
+KR_EXPORT KR_CONST
int kr_family_len(int family);
/** Parse address and return subnet length (bits).
* @warning 'dst' must be at least `sizeof(struct in6_addr)` long. */
+KR_EXPORT
int kr_straddr_subnet(void *dst, const char *addr);
/** Compare memory bitwise. */
+KR_EXPORT KR_PURE
int kr_bitcmp(const char *a, const char *b, int bits);
/** @internal RR map flags. */
#define KEY_FLAG_RRSIG 0x02
#define KEY_FLAG_RANK(key) (key[0] >> 2)
#define KEY_COVERING_RRSIG(key) (key[0] & KEY_FLAG_RRSIG)
-/* Stash key = {[1] flags, [1-255] owner, [5] type, [1] \x00 } */
-#define RRMAP_KEYSIZE (9 + KNOT_DNAME_MAXLEN)
-/** @internal Create unique string key for RR. */
-int kr_rrmap_key(char *key, const knot_dname_t *owner, uint16_t type, uint8_t rank);
+/* Stash key = {[1] flags, [1-255] owner, [5] type, [1] \x00 } */
+#define KR_RRKEY_LEN (9 + KNOT_DNAME_MAXLEN)
+/** Create unique null-terminated string key for RR.
+ * @param key Destination buffer for key size, MUST be KR_RRKEY_LEN or larger.
+ * @param owner RR owner domain name.
+ * @param type RR type.
+ * @param rank RR rank (8 bit tag usable for anything).
+ * @return key length if successful or an error
+ * */
+KR_EXPORT
+int kr_rrkey(char *key, const knot_dname_t *owner, uint16_t type, uint8_t rank);
/** @internal Merges RRSets with matching owner name and type together.
* @note RRSIG RRSets are merged according the type covered fields.
/**
* Call module property.
*/
+KR_EXPORT
char *kr_module_call(struct kr_context *ctx, const char *module, const char *prop, const char *input);
return kr_ok();
}
/* Push new address */
- int ret = pack_reserve_mm(*pack, 1, rdlen, mm_reserve, cut->pool);
+ int ret = pack_reserve_mm(*pack, 1, rdlen, kr_memreserve, cut->pool);
if (ret != 0) {
return kr_error(ENOMEM);
}
#include "lib/generic/map.h"
#include "lib/generic/pack.h"
+#include "lib/defines.h"
#include "lib/cache.h"
struct kr_rplan;
* @param pool
* @return 0 or error code
*/
+KR_EXPORT
int kr_zonecut_init(struct kr_zonecut *cut, const knot_dname_t *name, mm_ctx_t *pool);
/**
* Clear the structure and free the address set.
* @param cut zone cut
*/
+KR_EXPORT
void kr_zonecut_deinit(struct kr_zonecut *cut);
/**
* @param cut zone cut to be set
* @param name new zone cut name
*/
+KR_EXPORT
void kr_zonecut_set(struct kr_zonecut *cut, const knot_dname_t *name);
/**
* @param src source zone cut
* @return 0 or an error code
*/
+KR_EXPORT
int kr_zonecut_copy(struct kr_zonecut *dst, const struct kr_zonecut *src);
/**
* @param src source zone cut
* @return 0 or an error code
*/
+KR_EXPORT
int kr_zonecut_copy_trust(struct kr_zonecut *dst, const struct kr_zonecut *src);
/**
* @param rdata nameserver address (as rdata)
* @return 0 or error code
*/
+KR_EXPORT
int kr_zonecut_add(struct kr_zonecut *cut, const knot_dname_t *ns, const knot_rdata_t *rdata);
/**
* @param rdata name server address
* @return 0 or error code
*/
+KR_EXPORT
int kr_zonecut_del(struct kr_zonecut *cut, const knot_dname_t *ns, const knot_rdata_t *rdata);
/**
* @param ns name server name
* @return pack of addresses or NULL
*/
+KR_EXPORT KR_PURE
pack_t *kr_zonecut_find(struct kr_zonecut *cut, const knot_dname_t *ns);
/**
* @param cut zone cut to be populated
* @return 0 or error code
*/
+KR_EXPORT
int kr_zonecut_set_sbelt(struct kr_context *ctx, struct kr_zonecut *cut);
/**
* @param secured set to true if want secured zone cut, will return false if it is provably insecure
* @return 0 or error code (ENOENT if it doesn't find anything)
*/
+KR_EXPORT
int kr_zonecut_find_cached(struct kr_context *ctx, struct kr_zonecut *cut, const knot_dname_t *name,
struct kr_cache_txn *txn, uint32_t timestamp, bool * restrict secured);
BINEXT :=
PLATFORM = Linux
ARCH := $(word 1, $(subst -, ,$(shell $(CC) -dumpmachine)))
+# Library versioning flags (platform-specific)
+SOVER =
+# Library versioned extension (platform-specific)
+SOVER_EXT = $(LIBEXT).$(1)
ifeq ($(OS),Windows_NT)
PLATFORM := Windows
RM := del
ifneq ($(HARDENING),no)
BINFLAGS += -Wl,-pie
endif
+ # Version is prepended to dylib
+ SOVER_EXT = .$(1)$(LIBEXT)
+ SOVER = $(if $(1), -compatibility_version $(2) -current_version $(1),)
else
PLATFORM := POSIX
LDFLAGS += -pthread -lm -Wl,-E
ifeq ($(4),-$(ARTYPE))
$(call quiet,AR,$$@) rcs $$@ $$($(1)_OBJ)
else
- $(call quiet,CCLD,$$@) $$($(1)_CFLAGS) $(BUILD_CFLAGS) $$($(1)_OBJ) -o $$@ $(4) $$($(1)_LDFLAGS) $$($(1)_LIBS) $(BUILD_LDFLAGS)
+ $(call quiet,CCLD,$$@) $$($(1)_CFLAGS) $(BUILD_CFLAGS) $$($(1)_OBJ) $(call SOVER,$(7),$(7)) -o $$@ $(4) $$($(1)_LIBS) $(BUILD_LDFLAGS) $$($(1)_LDFLAGS)
endif
# Additional rules
$(1)-clean:
$(RM) $(1).amalg.c $(1).amalg.o
endif
$(1)-install: $(2)/$(1)$(3)
+# Modules install to special path
ifneq ($(5),$(MODULEDIR))
$(INSTALL) -d $(DESTDIR)$(5)
endif
+# Versioned library install
+ifneq ($(strip $(7)),)
+ $(INSTALL) $(2)/$(1)$(3) $(DESTDIR)$(5)/$(1)$(call SOVER_EXT,$(7))
+ $(LN) -f $(1)$(call SOVER_EXT,$(7)) $(DESTDIR)$(5)/$(1)$(3)
+else
$(INSTALL) $(2)/$(1)$(3) $(DESTDIR)$(5)
+endif
ifneq ($$(strip $$($(1)_HEADERS)),)
$(INSTALL) -d $(DESTDIR)$(INCLUDEDIR)/$(1)
$(INSTALL) -m 644 $$($(1)_HEADERS) $(DESTDIR)$(INCLUDEDIR)/$(1)
.PHONY: $(1)-clean $(1)-install
endef
-# Make targets (name,path,amalgable yes|no)
+# Make targets (name,path,amalgable yes|no,abiver)
make_bin = $(call make_target,$(1),$(2),$(BINEXT),$(BINFLAGS),$(BINDIR),$(3))
-make_lib = $(call make_target,$(1),$(2),$(LIBEXT),-$(LIBTYPE),$(LIBDIR),$(3))
+make_lib = $(call make_target,$(1),$(2),$(LIBEXT),-$(LIBTYPE),$(LIBDIR),$(3),$(4))
make_module = $(call make_target,$(1),$(2),$(LIBEXT),-$(LIBTYPE),$(MODULEDIR),$(3))
make_shared = $(call make_target,$(1),$(2),$(MODEXT),-$(MODTYPE),$(LIBDIR),$(3))
make_static = $(call make_target,$(1),$(2),$(AREXT),-$(ARTYPE),$(LIBDIR),$(3))
#include <sys/socket.h>
#include <stdio.h>
+#include <contrib/cleanup.h>
#include "tests/test.h"
#include "lib/utils.h"
tests_DEPEND := $(libkres) $(mock_cmodule) $(mock_gomodule)
tests_LIBS := $(libkres_TARGET) $(libkres_LIBS) $(cmocka_LIBS)
+# Platform-specific library injection
+ifeq ($(PLATFORM),Darwin)
+ preload_syms := DYLD_FORCE_FLAT_NAMESPACE=1 DYLD_LIBRARY_PATH="$(DYLD_LIBRARY_PATH):$(abspath lib)"
+else
+ preload_syms := LD_LIBRARY_PATH="$(LD_LIBRARY_PATH):$(abspath lib)"
+endif
+
# Make test binaries
define make_test
$(1)_CFLAGS := -fPIE
$(1)_DEPEND := $(tests_DEPEND)
$(call make_bin,$(1),tests)
$(1): $$($(1))
- @$$<
+ @$(preload_syms) $$<
.PHONY: $(1)
endef