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>
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);
}
/* 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)) {
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;
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)
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);
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, ×tamp), 0);
assert_int_not_equal(kr_cache_peek(&global_txn, KR_CACHE_USER, NULL, KNOT_RRTYPE_TSIG, &entry, ×tamp), 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,
{
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 {
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);
/* 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, ×tamp);
+ int ret = kr_cache_peek_rr(txn, &cache_rr, &rank, &flags, ×tamp);
assert_int_equal(ret, kr_error(ESTALE));
kr_cache_txn_abort(txn);
}
/* 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);
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, ×tamp);
+ ret = kr_cache_peek_rr(txn, &cache_rr, &rank, &flags, ×tamp);
assert_int_equal(ret, KNOT_ENOENT);
kr_cache_txn_commit(txn);
}
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;
}