]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
rrcache: fix prefetching of expiring insecure RRs
authorVladimír Čunát <vladimir.cunat@nic.cz>
Wed, 26 Jul 2017 16:21:01 +0000 (18:21 +0200)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Thu, 27 Jul 2017 11:49:32 +0000 (13:49 +0200)
Our security policy prevented those from reaching cache,
crippling the feature.

daemon/bindings.c
lib/layer/rrcache.c
modules/predict/predict.lua

index cd7affafb6c7ba8d27afa3c485f252416cc76197..853deb867099cb8f553880f14cb87e09bb1798a1 100644 (file)
@@ -1188,7 +1188,10 @@ static int wrk_resolve(lua_State *L)
                lua_error(L);
        }
        uint8_t dname[KNOT_DNAME_MAXLEN];
-       knot_dname_from_str(dname, lua_tostring(L, 1), sizeof(dname));
+       if (!knot_dname_from_str(dname, lua_tostring(L, 1), sizeof(dname))) {
+               lua_pushstring(L, "invalid qname");
+               lua_error(L);
+       };
        /* Check class and type */
        uint16_t rrtype = lua_tointeger(L, 2);
        if (!lua_isnumber(L, 2)) {
index d5a5d2bd4e6a3a7f3319e3dae89b6c1907bac375..2a25c1af25e8873850fdd7ca79f0ea7618ac6579 100644 (file)
@@ -88,7 +88,6 @@ static int loot_rr(struct kr_cache *cache, knot_pkt_t *pkt, const knot_dname_t *
                return kr_error(ENOENT);
        }
 
-       /* Mark as expiring if it has less than 1% TTL (or less than 5s) */
        if (is_expiring(&cache_rr, drift)) {
                qry->flags |= QUERY_EXPIRING;
        }
@@ -301,7 +300,19 @@ static int commit_rr(const char *key, void *val, void *data)
                 * This way they would have to hit the first answer (whenever TTL expires). */
                if (cached_rank >= 0) {
                        VERBOSE_MSG(baton->qry, "=> orig. rank: 0%0.2o\n", cached_rank);
-                       if (cached_rank >= rank) {
+                       bool accept = rank > cached_rank;
+                       /* Additionally accept equal rank if the cached RR is expiring.
+                        * This is primarily for prefetching from predict module. */
+                       if (rank == cached_rank) {
+                               uint32_t drift = baton->timestamp;
+                               knot_rrset_t cache_rr;
+                               knot_rrset_init(&cache_rr, rr->owner, rr->type, rr->rclass);
+                               int ret = kr_cache_peek_rr(baton->cache, &cache_rr, NULL, NULL, &drift);
+                               if (ret != kr_ok() || is_expiring(&cache_rr, drift)) {
+                                       accept = true;
+                               }
+                       }
+                       if (!accept) {
                                return kr_ok();
                        }
                }
index 153d534c083f9778ef0e93666be928e919d8f33d..4bc1acf3f104987bf224a470243b8f4315b44425 100644 (file)
@@ -31,7 +31,7 @@ function predict.drain(ev)
        local deleted = 0
        for key, val in pairs(predict.queue) do
                local qtype, qname = key:match('(%S*)%s(.*)')
-               worker.resolve(qname, kres.type[qtype], 1, kres.query.NO_CACHE)
+               worker.resolve(qname, kres.type[qtype], kres.class.IN, kres.query.NO_CACHE)
                predict.queue[key] = nil
                deleted = deleted + 1
                if deleted >= predict.batch then