Commit 594de930 authored by Marek Vavrusa's avatar Marek Vavrusa Committed by Ondřej Surý

lib/cache: add configuration options to enforce cache.{min,max}_ttl()

parent 48ad6614
......@@ -796,6 +796,43 @@ daemons or manipulated from other processes, making for example synchronised loa
print('Insertions:', cache.stats().insert)
.. function:: cache.max_ttl([ttl])
:param number ttl: maximum cache TTL (default: 6 days)
:return: current maximum TTL
Get or set maximum cache TTL.
.. note:: The `ttl` value must be in range `(min_ttl, 4294967295)`.
.. warning:: This settings applies only to currently open cache, it will not persist if the cache is closed or reopened.
.. code-block:: lua
-- Get maximum TTL
cache.max_ttl()
518400
-- Set maximum TTL
cache.max_ttl(172800)
172800
.. function:: cache.min_ttl([ttl])
:param number ttl: minimum cache TTL (default: 0)
:return: current maximum TTL
Get or set minimum cache TTL. Any entry inserted into cache with TTL lower than minimal will be overriden to minimum TTL. Forcing TTL higher than specified violates DNS standards, use with care.
.. note:: The `ttl` value must be in range `<0, max_ttl)`.
.. warning:: This settings applies only to currently open cache, it will not persist if the cache is closed or reopened.
.. code-block:: lua
-- Get minimum TTL
cache.min_ttl()
0
-- Set minimum TTL
cache.min_ttl(5)
5
.. function:: cache.prune([max_count])
......
......@@ -504,6 +504,53 @@ static const struct kr_cdb_api *cache_select(struct engine *engine, const char *
return NULL;
}
static int cache_max_ttl(lua_State *L)
{
struct engine *engine = engine_luaget(L);
struct kr_cache *cache = &engine->resolver.cache;
int n = lua_gettop(L);
if (n > 0) {
if (!lua_isnumber(L, 1)) {
format_error(L, "expected 'max_ttl(number ttl)'");
lua_error(L);
}
uint32_t min = cache->ttl_min;
int64_t ttl = lua_tonumber(L, 1);
if (ttl < 0 || ttl <= min || ttl > UINT32_MAX) {
format_error(L, "max_ttl must be larger than minimum TTL, and in range <1, UINT32_MAX>'");
lua_error(L);
}
cache->ttl_max = ttl;
}
lua_pushinteger(L, cache->ttl_max);
return 1;
}
static int cache_min_ttl(lua_State *L)
{
struct engine *engine = engine_luaget(L);
struct kr_cache *cache = &engine->resolver.cache;
int n = lua_gettop(L);
if (n > 0) {
if (!lua_isnumber(L, 1)) {
format_error(L, "expected 'min_ttl(number ttl)'");
lua_error(L);
}
uint32_t max = cache->ttl_max;
int64_t ttl = lua_tonumber(L, 1);
if (ttl < 0 || ttl >= max || ttl > UINT32_MAX) {
format_error(L, "min_ttl must be smaller than maximum TTL, and in range <0, UINT32_MAX>'");
lua_error(L);
}
cache->ttl_min = ttl;
}
lua_pushinteger(L, cache->ttl_min);
return 1;
}
/** Open cache */
static int cache_open(lua_State *L)
{
......@@ -776,6 +823,8 @@ int lib_cache(lua_State *L)
{ "prune", cache_prune },
{ "clear", cache_clear },
{ "get", cache_get },
{ "max_ttl", cache_max_ttl },
{ "min_ttl", cache_min_ttl },
{ NULL, NULL }
};
......
......@@ -19,12 +19,14 @@
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <limits.h>
#include <libknot/errcode.h>
#include <libknot/descriptor.h>
#include <libknot/dname.h>
#include <libknot/rrtype/rrsig.h>
#include "contrib/ucw/lib.h"
#include "contrib/cleanup.h"
#include "lib/cache.h"
#include "lib/cdb_lmdb.h"
......@@ -92,6 +94,8 @@ int kr_cache_open(struct kr_cache *cache, const struct kr_cdb_api *api, struct k
return ret;
}
memset(&cache->stats, 0, sizeof(cache->stats));
cache->ttl_min = 0;
cache->ttl_max = KR_CACHE_DEFAULT_MAXTTL;
/* Check cache ABI version */
(void) assert_right_version(cache);
return 0;
......@@ -209,6 +213,11 @@ int kr_cache_insert(struct kr_cache *cache, uint8_t tag, const knot_dname_t *nam
return kr_error(EINVAL);
}
/* Enforce cache maximum TTL limits without TTL decay.
* Minimum TTL is enforced in specific caches as it requires
* rewriting of the records to avoid negative TTL when decayed. */
header->ttl = MIN(header->ttl, cache->ttl_max);
/* Prepare key/value for insertion. */
uint8_t keybuf[KEY_SIZE];
size_t key_len = cache_key(keybuf, tag, name, type);
......
......@@ -83,6 +83,8 @@ struct kr_cache
uint32_t insert; /**< Number of insertions */
uint32_t delete; /**< Number of deletions */
} stats;
uint32_t ttl_min, ttl_max; /**< Maximum TTL of inserted entries */
};
/**
......
......@@ -70,6 +70,7 @@ static inline int __attribute__((__cold__)) kr_error(int x) {
#define KR_EDNS_VERSION 0
#define KR_EDNS_PAYLOAD 4096 /* Default UDP payload (max unfragmented UDP is 1452B) */
#define KR_DEFAULT_TLS_PADDING 128 /* Default EDNS(0) Padding is 128 */
#define KR_CACHE_DEFAULT_MAXTTL (6 * 24 * 3600) /* 6 days, like the root NS TTL */
/*
* Address sanitizer hints.
......
......@@ -234,7 +234,7 @@ static int stash_commit(map_t *stash, struct kr_query *qry, struct kr_cache *cac
.qry = qry,
.cache = cache,
.timestamp = qry->timestamp.tv_sec,
.min_ttl = DEFAULT_MINTTL
.min_ttl = MAX(DEFAULT_MINTTL, cache->ttl_min),
};
return map_walk(stash, &commit_rr, &baton);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment