]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
lib/cache: add configuration options to enforce cache.{min,max}_ttl()
authorMarek Vavrusa <marek@vavrusa.com>
Tue, 23 Aug 2016 05:58:08 +0000 (22:58 -0700)
committerOndřej Surý <ondrej@sury.org>
Mon, 16 Jan 2017 10:07:49 +0000 (11:07 +0100)
daemon/README.rst
daemon/bindings.c
lib/cache.c
lib/cache.h
lib/defines.h
lib/layer/rrcache.c

index 8431a44cdc2be6e17f09fa084700c3f55ccacee5..1291dd9e25f6952cd98aea5a222b20e8d159245e 100644 (file)
@@ -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])
 
index fb54af68ce711a115ee06b5ba7e37c47dfa2b845..ecc85d593ad7e2779271f840aaa259485286f5f1 100644 (file)
@@ -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 }
        };
 
index e3f356e20072ec4598d3aa4999a73d388331a888..9bfde3bbb1adedbd1833654be19d45755c809c4d 100644 (file)
 #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);
index c758a2900c1594c0cb29b19318e4ecda5bd636bf..528db0e2e174cc8e2e4f88b3a0a0e8b4ab47b021 100644 (file)
@@ -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 */
 };
 
 /**
index 40c5bcd9bfe3cd79a477fc83bdc0cd5c266adf81..e5dc1d6f4a207585a85531e796fc0d08271ce26d 100644 (file)
@@ -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.
index d47e7e2166ba4a0d5b457c137cc01f5e50f239c8..91e58bbd47b58a3398287ae56b83f06cdf6cbb1b 100644 (file)
@@ -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);
 }