]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
module: detect discontinuous jumps in the system time
authorVítězslav Kříž <vitezslav.kriz@nic.cz>
Mon, 4 Dec 2017 11:34:33 +0000 (12:34 +0100)
committerPetr Špaček <petr.spacek@nic.cz>
Fri, 8 Dec 2017 14:43:44 +0000 (15:43 +0100)
Check differences between real and monotonic time.
It clears cache when this diffrence changes since
last cache clear.

daemon/bindings.c
daemon/lua/kres-gen.lua
daemon/lua/kres-gen.sh
daemon/lua/sandbox.lua
doc/modules.rst
lib/cache.c
lib/cache.h
modules/detect_time_jump/README.rst [new file with mode: 0644]
modules/detect_time_jump/detect_time_jump.lua [new file with mode: 0644]
modules/detect_time_jump/detect_time_jump.mk [new file with mode: 0644]
modules/modules.mk

index 742510b16c75ad2ecbfe6e33c9af5b9c2aa4aecd..140ec7df3c69acdd69cf04e9e93a45ec151d8e9d 100644 (file)
@@ -547,6 +547,23 @@ static int cache_count(lua_State *L)
        return 0;
 }
 
+/** Return time of last cache clear */
+static int cache_last_clear(lua_State *L)
+{
+       struct engine *engine = engine_luaget(L);
+       struct kr_cache *cache = &engine->resolver.cache;
+       lua_newtable(L);
+       lua_pushnumber(L, cache->last_clear_monotime);
+       lua_setfield(L, -2, "monotime");
+       lua_newtable(L);
+       lua_pushnumber(L, cache->last_clear_walltime.tv_sec);
+       lua_setfield(L, -2, "sec");
+       lua_pushnumber(L, cache->last_clear_walltime.tv_usec);
+       lua_setfield(L, -2, "usec");
+       lua_setfield(L, -2, "walltime");
+       return 1;
+}
+
 /** Return cache statistics. */
 static int cache_stats(lua_State *L)
 {
@@ -911,6 +928,7 @@ int lib_cache(lua_State *L)
                { "backends", cache_backends },
                { "count",  cache_count },
                { "stats",  cache_stats },
+               { "last_clear",  cache_last_clear },
                { "open",   cache_open },
                { "close",  cache_close },
                { "prune",  cache_prune },
index 20277e10dc09e5c19ac9557dcf2164002ecfa799..b76e5eb17f233b91c218a44f9f8a279541d0215f 100644 (file)
@@ -251,6 +251,7 @@ void kr_qflags_set(struct kr_qflags *, struct kr_qflags);
 void kr_qflags_clear(struct kr_qflags *, struct kr_qflags);
 int kr_zonecut_add(struct kr_zonecut *, const knot_dname_t *, const knot_rdata_t *);
 void kr_zonecut_set(struct kr_zonecut *, const knot_dname_t *);
+uint64_t kr_now();
 knot_rrset_t *kr_ta_get(map_t *, const knot_dname_t *);
 int kr_ta_add(map_t *, const knot_dname_t *, uint16_t, uint32_t, const uint8_t *, uint16_t);
 int kr_ta_del(map_t *, const knot_dname_t *);
index f6625c52b9a9a1114b9b25bc28428c58a640b04c..df066a2f6badbd5a33cf79c17b4ad0adf5d0971e 100755 (executable)
@@ -137,6 +137,7 @@ EOF
        kr_qflags_clear
        kr_zonecut_add
        kr_zonecut_set
+       kr_now
 # Trust anchors
        kr_ta_get
        kr_ta_add
index f90473ffb1c2d6ac6602929aeb9831eefb30348b..402db091fc44a405273b54cc14b704b7eea2393b 100644 (file)
@@ -206,6 +206,7 @@ end
 modules.load('ta_signal_query')
 modules.load('priming')
 modules.load('detect_time_skew')
+modules.load('detect_time_jump')
 
 -- Interactive command evaluation
 function eval_cmd(line, raw)
index f8e69edc1963c9bc0c0dc7043f3a78deb0551832..c68c9584a2ca87bcc07fc4c37a670a9b16fe95da 100644 (file)
@@ -28,3 +28,4 @@ Knot DNS Resolver modules
 .. include:: ../modules/ta_signal_query/README.rst
 .. include:: ../modules/priming/README.rst
 .. include:: ../modules/detect_time_skew/README.rst
+.. include:: ../modules/detect_time_jump/README.rst
index 6a9cb43caf23559904de12958a75d673d8230643..2e80fa653ba4f7916dfd05db74dc7ef5f684d39a 100644 (file)
@@ -17,6 +17,7 @@
 #include <assert.h>
 #include <time.h>
 #include <sys/stat.h>
+#include <sys/time.h>
 #include <unistd.h>
 #include <errno.h>
 #include <limits.h>
@@ -51,10 +52,10 @@ static inline int cache_purge(struct kr_cache *cache)
 }
 
 /** @internal Set time when clearing cache. */
-static void reset_time(struct kr_cache *cache)
+static void reset_timestamps(struct kr_cache *cache)
 {
        cache->last_clear_monotime = kr_now();
-       gettimeofday(&cache->last_clear_timestamp, NULL);
+       gettimeofday(&cache->last_clear_walltime, NULL);
 }
 
 /** @internal Open cache db transaction and check internal data version. */
@@ -104,6 +105,7 @@ int kr_cache_open(struct kr_cache *cache, const struct kr_cdb_api *api, struct k
        cache->ttl_min = 0;
        cache->ttl_max = KR_CACHE_DEFAULT_MAXTTL;
        /* Check cache ABI version */
+       reset_timestamps(cache);
        (void) assert_right_version(cache);
        return 0;
 }
@@ -282,6 +284,7 @@ int kr_cache_clear(struct kr_cache *cache)
        }
        int ret = cache_purge(cache);
        if (ret == 0) {
+               reset_timestamps(cache);
                ret = assert_right_version(cache);
        }
        return ret;
index 8552575af978f08a3be9251c3b41ab28d0409277..b6fd92ea0cfc210e2d6628ac92ce4f35cc050fc4 100644 (file)
@@ -77,6 +77,8 @@ struct kr_cache
        } stats;
 
        uint32_t ttl_min, ttl_max; /**< Maximum TTL of inserted entries */
+       struct timeval last_clear_walltime; /**< Time of last cache clear */
+       uint64_t last_clear_monotime;  /**< Last cache clear in monotonic time */
 };
 
 /**
diff --git a/modules/detect_time_jump/README.rst b/modules/detect_time_jump/README.rst
new file mode 100644 (file)
index 0000000..7057867
--- /dev/null
@@ -0,0 +1,14 @@
+.. _mod-detect_time_jump:
+
+Detect discontinuous jumps in the system time
+---------------------------------------------
+
+This module detect discontinuous jumps in the system time when resolver
+is running. It clears cache when some time jumps occurs. 
+
+Time jumps is ussualy created by NTP time change or by admin intervention.
+These change can affect cache records as they store timestamp and TTL in real 
+time.
+
+If you want to preserve cache during time travel you should disable
+this module by modules.unload('detect_time_jump').
diff --git a/modules/detect_time_jump/detect_time_jump.lua b/modules/detect_time_jump/detect_time_jump.lua
new file mode 100644 (file)
index 0000000..c43b8b5
--- /dev/null
@@ -0,0 +1,41 @@
+-- Module interface
+local ffi = require('ffi')
+
+local mod = {}
+mod.threshold = 10 * min
+local event_id = nil
+
+-- Get time of last cache clear. Compute difference between realtime
+-- adn monotonic time. Compute difference of actual realtime and monotonic
+-- time. In ideal case these differences should be almost same.
+-- If they differ more than mod.threshold value then clear cache.
+local function check_time()
+       local clear_time = cache.last_clear()
+       local cache_timeshift = clear_time.walltime.sec * 1000 - clear_time.monotime
+       local actual_timeshift = os.time() * 1000 - tonumber(ffi.C.kr_now())
+       local time_diff = math.abs(cache_timeshift - actual_timeshift)
+       log("check_time, %d", time_diff)
+       if time_diff > mod.threshold then
+               log("Detected time change, clearing cache\n" ..
+               "But what does that mean? It means your future hasn't been written yet."
+               )
+               cache.clear()
+       end
+end
+
+function mod.init()
+       if event_id then
+               error("Module is already loaded.")
+       else
+               event_id = event.recurrent(1 * min , check_time)
+       end
+end
+
+function mod.deinit()
+       if event_id then
+               event.cancel(event_id)
+               event_id = nil
+       end
+end
+
+return mod
diff --git a/modules/detect_time_jump/detect_time_jump.mk b/modules/detect_time_jump/detect_time_jump.mk
new file mode 100644 (file)
index 0000000..04df607
--- /dev/null
@@ -0,0 +1,2 @@
+detect_time_jump_SOURCES := detect_time_jump.lua
+$(call make_lua_module,detect_time_jump)
index 3df953c0a623bf8eb50d9b83f05b18c677ee0325..78f24c836c5e1f882a2573dce8df986fc82a756d 100644 (file)
@@ -35,7 +35,8 @@ modules_TARGETS += etcd \
                    version \
                    ta_signal_query \
                    priming \
-                   detect_time_skew
+                   detect_time_skew \
+                   detect_time_jump
 endif
 
 # Make C module