]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
layer/rrcache: record cache miss avoided for wcard answers
authorGrigorii Demidov <grigorii.demidov@nic.cz>
Mon, 4 Apr 2016 12:16:10 +0000 (14:16 +0200)
committerMarek Vavrusa <marek@vavrusa.com>
Thu, 14 Apr 2016 05:24:31 +0000 (22:24 -0700)
lib/layer/rrcache.c
tests/test_cache.c

index c9edde52e99e7f15beaff54d5ddda5b84e1b0e13..cd0e75475b85a1331c1aad734702a7b4d4ab7bc6 100644 (file)
@@ -14,6 +14,8 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <assert.h>
+
 #include <libknot/descriptor.h>
 #include <libknot/errcode.h>
 #include <libknot/rrset.h>
@@ -59,6 +61,14 @@ static int loot_rr(struct kr_cache_txn *txn, knot_pkt_t *pkt, const knot_dname_t
                qry->flags |= QUERY_EXPIRING;
        }
 
+       assert(flags != NULL);
+       if ((*flags) & KR_CACHE_FLAG_WCARD_PROOF) {
+               /* Record was found, but wildcard answer proof is needed.
+                * Do not update packet, try to fetch whole packet from pktcache instead. */
+               qry->flags |= QUERY_DNSSEC_WEXPAND;
+               return kr_error(ENOENT);
+       }
+
        /* Update packet question */
        if (!knot_dname_is_equal(knot_pkt_qname(pkt), name)) {
                kr_pkt_recycle(pkt);
@@ -87,10 +97,11 @@ static int loot_rrcache(struct kr_cache *cache, knot_pkt_t *pkt, struct kr_query
        }
        /* Lookup direct match first */
        uint8_t rank  = 0;
-       ret = loot_rr(&txn, pkt, qry->sname, qry->sclass, rrtype, qry, &rank, NULL, 0);
+       uint8_t flags = 0;
+       ret = loot_rr(&txn, pkt, qry->sname, qry->sclass, rrtype, qry, &rank, &flags, 0);
        if (ret != 0 && rrtype != KNOT_RRTYPE_CNAME) { /* Chase CNAME if no direct hit */
                rrtype = KNOT_RRTYPE_CNAME;
-               ret = loot_rr(&txn, pkt, qry->sname, qry->sclass, rrtype, qry, &rank, NULL, 0);
+               ret = loot_rr(&txn, pkt, qry->sname, qry->sclass, rrtype, qry, &rank, &flags, 0);
        }
        /* Record is flagged as INSECURE => doesn't have RRSIG. */
        if (ret == 0 && (rank & KR_RANK_INSECURE)) {
@@ -98,7 +109,7 @@ static int loot_rrcache(struct kr_cache *cache, knot_pkt_t *pkt, struct kr_query
                qry->flags &= ~QUERY_DNSSEC_WANT;
        /* Record may have RRSIG, try to find it. */
        } else if (ret == 0 && dobit) {
-               ret = loot_rr(&txn, pkt, qry->sname, qry->sclass, rrtype, qry, &rank, NULL, true);
+               ret = loot_rr(&txn, pkt, qry->sname, qry->sclass, rrtype, qry, &rank, &flags, true);
        }
        kr_cache_txn_abort(&txn);
        return ret;
@@ -202,7 +213,11 @@ static int commit_rr(const char *key, void *val, void *data)
 
        knot_rrset_t query_rr;
        knot_rrset_init(&query_rr, rr->owner, rr->type, rr->rclass);
-       return kr_cache_insert_rr(baton->txn, rr, rank, KR_CACHE_FLAG_NONE, baton->timestamp);
+       uint8_t flags = KR_CACHE_FLAG_NONE;
+       if ((rank & KR_RANK_AUTH) && (baton->qry->flags & QUERY_DNSSEC_WEXPAND)) {
+               flags |= KR_CACHE_FLAG_WCARD_PROOF;
+       }
+       return kr_cache_insert_rr(baton->txn, rr, rank, flags, baton->timestamp);
 }
 
 static int stash_commit(map_t *stash, struct kr_query *qry, struct kr_cache_txn *txn, struct kr_request *req)
@@ -303,11 +318,6 @@ static int rrcache_stash(knot_layer_t *ctx, knot_pkt_t *pkt)
        if (knot_wire_get_tc(pkt->wire)) {
                return ctx->state;
        }
-       /* Do not cache wildcard expanded anwsers,
-        * as they must deal with packet cache */
-       if (qry->flags & QUERY_DNSSEC_WEXPAND) {
-               return ctx->state;
-       }
 
        /* Cache only positive answers, not meta types or RRSIG. */
        const uint16_t qtype = knot_pkt_qtype(pkt);
index e5a64eb9281c2878049b11cd3aa9103326ea4a56..8fcd86ab9ef73d2805957e3eba9fd32721514a90 100644 (file)
@@ -243,10 +243,10 @@ static void test_invalid(void **state)
        assert_int_not_equal(kr_cache_txn_commit(NULL), 0);
        assert_int_not_equal(kr_cache_peek(NULL, KR_CACHE_USER, dname, KNOT_RRTYPE_TSIG, NULL, &timestamp), 0);
        assert_int_not_equal(kr_cache_peek(&global_txn, KR_CACHE_USER, NULL, KNOT_RRTYPE_TSIG, &entry, &timestamp), 0);
-       assert_int_not_equal(kr_cache_peek_rr(NULL, NULL, NULL, NULL), 0);
-       assert_int_not_equal(kr_cache_peek_rr(&global_txn, NULL, NULL, NULL), 0);
-       assert_int_not_equal(kr_cache_insert_rr(&global_txn, NULL, 0, 0), 0);
-       assert_int_not_equal(kr_cache_insert_rr(NULL, NULL, 0, 0), 0);
+       assert_int_not_equal(kr_cache_peek_rr(NULL, NULL, NULL, NULL, NULL), 0);
+       assert_int_not_equal(kr_cache_peek_rr(&global_txn, NULL, NULL, NULL, NULL), 0);
+       assert_int_not_equal(kr_cache_insert_rr(&global_txn, NULL, 0, 0, 0), 0);
+       assert_int_not_equal(kr_cache_insert_rr(NULL, NULL, 0, 0, 0), 0);
        assert_int_not_equal(kr_cache_insert(NULL, KR_CACHE_USER, dname,
                KNOT_RRTYPE_TSIG, &global_fake_ce, global_namedb_data), 0);
        assert_int_not_equal(kr_cache_insert(&global_txn, KR_CACHE_USER, NULL,
@@ -264,7 +264,7 @@ static void test_insert_rr(void **state)
 {
        test_random_rr(&global_rr, CACHE_TTL);
        struct kr_cache_txn *txn = test_txn_write(state);
-       int ret = kr_cache_insert_rr(txn, &global_rr, 0, CACHE_TIME);
+       int ret = kr_cache_insert_rr(txn, &global_rr, 0, 0, CACHE_TIME);
        if (ret == KNOT_EOK) {
                ret = kr_cache_txn_commit(txn);
        } else {
@@ -315,9 +315,10 @@ static void test_query(void **state)
        struct kr_cache_txn *txn = test_txn_rdonly(state);
 
        for (uint32_t timestamp = CACHE_TIME; timestamp < CACHE_TIME + CACHE_TTL; ++timestamp) {
-               uint16_t rank = 0;
+               uint8_t rank = 0;
+               uint8_t flags = 0;
                uint32_t drift = timestamp;
-               int query_ret = kr_cache_peek_rr(txn, &cache_rr, &rank, &drift);
+               int query_ret = kr_cache_peek_rr(txn, &cache_rr, &rank, &flags, &drift);
                bool rr_equal = knot_rrset_equal(&global_rr, &cache_rr, KNOT_RRSET_COMPARE_WHOLE);
                assert_int_equal(query_ret, KNOT_EOK);
                assert_true(rr_equal);
@@ -329,13 +330,14 @@ static void test_query(void **state)
 /* Test cache read (simulate aged entry) */
 static void test_query_aged(void **state)
 {
-       uint16_t rank = 0;
+       uint8_t rank = 0;
+       uint8_t flags = 0;
        uint32_t timestamp = CACHE_TIME + CACHE_TTL + 1;
        knot_rrset_t cache_rr;
        knot_rrset_init(&cache_rr, global_rr.owner, global_rr.type, global_rr.rclass);
 
        struct kr_cache_txn *txn = test_txn_rdonly(state);
-       int ret = kr_cache_peek_rr(txn, &cache_rr, &rank, &timestamp);
+       int ret = kr_cache_peek_rr(txn, &cache_rr, &rank, &flags, &timestamp);
        assert_int_equal(ret, kr_error(ESTALE));
        kr_cache_txn_abort(txn);
 }
@@ -343,7 +345,8 @@ static void test_query_aged(void **state)
 /* Test cache removal */
 static void test_remove(void **state)
 {
-       uint16_t rank = 0;
+       uint8_t rank = 0;
+       uint8_t flags = 0;
        uint32_t timestamp = CACHE_TIME;
        knot_rrset_t cache_rr;
        knot_rrset_init(&cache_rr, global_rr.owner, global_rr.type, global_rr.rclass);
@@ -351,7 +354,7 @@ static void test_remove(void **state)
        struct kr_cache_txn *txn = test_txn_write(state);
        int ret = kr_cache_remove(txn, KR_CACHE_RR, cache_rr.owner, cache_rr.type);
        assert_int_equal(ret, KNOT_EOK);
-       ret = kr_cache_peek_rr(txn, &cache_rr, &rank, &timestamp);
+       ret = kr_cache_peek_rr(txn, &cache_rr, &rank, &flags, &timestamp);
        assert_int_equal(ret, KNOT_ENOENT);
        kr_cache_txn_commit(txn);
 }
@@ -366,7 +369,7 @@ static void test_fill(void **state)
        for (unsigned i = 0; i < CACHE_SIZE; ++i) {
                knot_rrset_t rr;
                test_random_rr(&rr, CACHE_TTL);
-               ret = kr_cache_insert_rr(txn, &rr, 0, CACHE_TTL - 1);
+               ret = kr_cache_insert_rr(txn, &rr, 0, 0, CACHE_TTL - 1);
                if (ret != KNOT_EOK) {
                        break;
                }