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])
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)
{
{ "prune", cache_prune },
{ "clear", cache_clear },
{ "get", cache_get },
+ { "max_ttl", cache_max_ttl },
+ { "min_ttl", cache_min_ttl },
{ NULL, NULL }
};
#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"
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;
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);
uint32_t insert; /**< Number of insertions */
uint32_t delete; /**< Number of deletions */
} stats;
+
+ uint32_t ttl_min, ttl_max; /**< Maximum TTL of inserted entries */
};
/**
#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.
.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);
}