Skip to content
Snippets Groups Projects
Commit b0c31a9d authored by Karel Slaný's avatar Karel Slaný
Browse files

layer/rrcache: Implemented RRSIG caching without validation.

parent da79dc09
No related branches found
No related tags found
No related merge requests found
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <libknot/descriptor.h> #include <libknot/descriptor.h>
#include <libknot/errcode.h> #include <libknot/errcode.h>
#include <libknot/rrset.h> #include <libknot/rrset.h>
#include <libknot/rrtype/rrsig.h>
#include <libknot/internal/mempool.h> #include <libknot/internal/mempool.h>
#include <libknot/rrtype/rdname.h> #include <libknot/rrtype/rdname.h>
...@@ -141,6 +142,26 @@ static int peek(knot_layer_t *ctx, knot_pkt_t *pkt) ...@@ -141,6 +142,26 @@ static int peek(knot_layer_t *ctx, knot_pkt_t *pkt)
return ctx->state; return ctx->state;
} }
/** @internal Stashed data container. */
struct stash_data
{
map_t rrs;
map_t rrsigs;
};
static void stash_data_init(struct stash_data *stashd, mm_ctx_t *pool)
{
stashd->rrs = map_make();
stashd->rrs.malloc = (map_alloc_f) mm_alloc;
stashd->rrs.free = (map_free_f) mm_free;
stashd->rrs.baton = pool;
stashd->rrsigs = map_make();
stashd->rrsigs.malloc = (map_alloc_f) mm_alloc;
stashd->rrsigs.free = (map_free_f) mm_free;
stashd->rrsigs.baton = pool;
}
/** @internal Baton for stash_commit */ /** @internal Baton for stash_commit */
struct stash_baton struct stash_baton
{ {
...@@ -148,14 +169,24 @@ struct stash_baton ...@@ -148,14 +169,24 @@ struct stash_baton
unsigned timestamp; unsigned timestamp;
}; };
static int commit_rrsig(knot_rrset_t *rrsig, struct stash_baton *baton) static int commit_rrsig(const char *key, void *val, void *data)
{ {
/* Insert RRSIGs in special cache. */
knot_rrset_t *rrsig = val;
struct stash_baton *baton = data;
if (knot_rrset_ttl(rrsig) < 1) {
return kr_ok(); /* Ignore cache busters */
}
/* Check if already cached */
/** @todo This should check if less trusted data is in the cache,
for that the cache would need to trace data trust level.
*/
/* Check if already cached */ /* Check if already cached */
unsigned drift = baton->timestamp; unsigned drift = baton->timestamp;
knot_rrset_t query_rrsig; knot_rrset_t query_rrsig;
knot_rrset_init(&query_rrsig, rrsig->owner, rrsig->type, rrsig->rclass); knot_rrset_init(&query_rrsig, rrsig->owner, rrsig->type, rrsig->rclass);
if (kr_cache_peek_rrsig(baton->txn, &query_rrsig, &drift) == 0) { if (kr_cache_peek_rrsig(baton->txn, &query_rrsig, &drift) == 0) {
return kr_ok(); return kr_ok();
} }
return kr_cache_insert_rrsig(baton->txn, rrsig, rrsig->type, baton->timestamp); return kr_cache_insert_rrsig(baton->txn, rrsig, rrsig->type, baton->timestamp);
} }
...@@ -167,10 +198,6 @@ static int commit_rr(const char *key, void *val, void *data) ...@@ -167,10 +198,6 @@ static int commit_rr(const char *key, void *val, void *data)
if (knot_rrset_ttl(rr) < 1) { if (knot_rrset_ttl(rr) < 1) {
return kr_ok(); /* Ignore cache busters */ return kr_ok(); /* Ignore cache busters */
} }
/* Insert RRSIGs in special cache. */
if (rr->type == KR_CACHE_RRSIG) {
return commit_rrsig(rr, baton);
}
/* Check if already cached */ /* Check if already cached */
/** @todo This should check if less trusted data is in the cache, /** @todo This should check if less trusted data is in the cache,
for that the cache would need to trace data trust level. for that the cache would need to trace data trust level.
...@@ -184,16 +211,105 @@ static int commit_rr(const char *key, void *val, void *data) ...@@ -184,16 +211,105 @@ static int commit_rr(const char *key, void *val, void *data)
return kr_cache_insert_rr(baton->txn, rr, baton->timestamp); return kr_cache_insert_rr(baton->txn, rr, baton->timestamp);
} }
static int stash_commit(map_t *stash, unsigned timestamp, struct kr_cache_txn *txn) static int stash_commit(struct stash_data *stash, unsigned timestamp, struct kr_cache_txn *txn)
{ {
struct stash_baton baton = { struct stash_baton baton = {
.txn = txn, .txn = txn,
.timestamp = timestamp .timestamp = timestamp
}; };
return map_walk(stash, &commit_rr, &baton); int ret = map_walk(&stash->rrs, &commit_rr, &baton);
if (ret == 0) {
ret = map_walk(&stash->rrsigs, &commit_rrsig, &baton);
}
return ret;
}
static int merge_in_rrsigs(knot_rrset_t *cache_rr, const knot_rrset_t *rrsigset, const knot_rrset_t *rr,
mm_ctx_t *pool)
{
int ret = KNOT_EOK;
/* Find rrset corresponding to RRSIG. */
for (unsigned i = 0; i < rrsigset->rrs.rr_count; ++i) {
if ((knot_rrsig_type_covered(&rrsigset->rrs, i) == rr->type) &&
knot_dname_is_equal(cache_rr->owner, rrsigset->owner)) {
const knot_rdata_t *rdata = knot_rdataset_at(&rrsigset->rrs, i);
ret = knot_rdataset_add(&cache_rr->rrs, rdata, pool);
if (KNOT_EOK != ret) {
return ret;
}
}
}
return ret;
}
static int scan_for_rrsigs(knot_rrset_t *cache_rrsig, const knot_pktsection_t *section,
const knot_rrset_t *rr, mm_ctx_t *pool)
{
knot_rrset_init(cache_rrsig, rr->owner, rr->type, rr->rclass);
for (uint16_t i = 0; i < section->count; ++i) {
const knot_rrset_t *rrset = knot_pkt_rr(section, i);
if (KNOT_RRTYPE_RRSIG != rrset->type) {
continue;
}
int ret = merge_in_rrsigs(cache_rrsig, rrset, rr, pool);
if (KNOT_EOK != ret) {
knot_rrset_clear(cache_rrsig, pool);
return ret;
}
}
return kr_ok();
}
static int stash_add_rrsig(const knot_pktsection_t *section, map_t *stash,
const knot_rrset_t *rr, mm_ctx_t *pool)
{
/* Can't store RRSIG of RRSIG. */
if (rr->type == KNOT_RRTYPE_RRSIG) {
return kr_ok();
}
/* Stash key = {[1-255] owner, [1-5] type covered, [1] \x00 } */
char key[8 + KNOT_DNAME_MAXLEN];
int ret = knot_dname_to_wire((uint8_t *)key, rr->owner, KNOT_DNAME_MAXLEN);
if (ret <= 0) {
return ret;
}
knot_dname_to_lower((uint8_t *)key);
ret = snprintf(key + ret - 1, sizeof(key) - KNOT_DNAME_MAXLEN, "%hu", rr->type);
if (ret <= 0 || ret >= KNOT_DNAME_MAXLEN) {
return kr_error(EILSEQ);
}
/* Check if already exists */
knot_rrset_t *stashed = map_get(stash, key);
if (stashed) {
return kr_ok();
}
/* Construct RRSIG RRSet containing related data. */
knot_rrset_t cache_rrsig;
ret = scan_for_rrsigs(&cache_rrsig, section, rr, pool);
if (ret != 0) {
return ret;
}
if (cache_rrsig.rrs.rr_count) {
stashed = knot_rrset_copy(&cache_rrsig, pool);
if (!stashed) {
return kr_error(ENOMEM);
}
}
knot_rrset_clear(&cache_rrsig, pool);
if (stashed) {
return map_set(stash, key, stashed);
}
return kr_ok();
} }
static int stash_add(knot_pkt_t *pkt, map_t *stash, const knot_rrset_t *rr, mm_ctx_t *pool) static int stash_add(const knot_pkt_t *pkt, map_t *stash, const knot_rrset_t *rr, mm_ctx_t *pool)
{ {
/* Do not stash DNSSEC data if not secured. */ /* Do not stash DNSSEC data if not secured. */
bool dobit = knot_pkt_has_dnssec(pkt); bool dobit = knot_pkt_has_dnssec(pkt);
...@@ -201,6 +317,11 @@ static int stash_add(knot_pkt_t *pkt, map_t *stash, const knot_rrset_t *rr, mm_c ...@@ -201,6 +317,11 @@ static int stash_add(knot_pkt_t *pkt, map_t *stash, const knot_rrset_t *rr, mm_c
return kr_ok(); return kr_ok();
} }
/* Do not stash alone RRSIGs, these must be stashed together with signed RRs. */
if (dobit && (rr->type == KNOT_RRTYPE_RRSIG)) {
return kr_ok();
}
/* Stash key = {[1-255] owner, [1-5] type, [1] \x00 } */ /* Stash key = {[1-255] owner, [1-5] type, [1] \x00 } */
char key[8 + KNOT_DNAME_MAXLEN]; char key[8 + KNOT_DNAME_MAXLEN];
int ret = knot_dname_to_wire((uint8_t *)key, rr->owner, KNOT_DNAME_MAXLEN); int ret = knot_dname_to_wire((uint8_t *)key, rr->owner, KNOT_DNAME_MAXLEN);
...@@ -226,7 +347,7 @@ static int stash_add(knot_pkt_t *pkt, map_t *stash, const knot_rrset_t *rr, mm_c ...@@ -226,7 +347,7 @@ static int stash_add(knot_pkt_t *pkt, map_t *stash, const knot_rrset_t *rr, mm_c
return knot_rdataset_merge(&stashed->rrs, &rr->rrs, pool); return knot_rdataset_merge(&stashed->rrs, &rr->rrs, pool);
} }
static void stash_glue(map_t *stash, knot_pkt_t *pkt, const knot_dname_t *ns_name, mm_ctx_t *pool) static void stash_glue(struct stash_data *stash, knot_pkt_t *pkt, const knot_dname_t *ns_name, mm_ctx_t *pool)
{ {
const knot_pktsection_t *additional = knot_pkt_section(pkt, KNOT_ADDITIONAL); const knot_pktsection_t *additional = knot_pkt_section(pkt, KNOT_ADDITIONAL);
for (unsigned i = 0; i < additional->count; ++i) { for (unsigned i = 0; i < additional->count; ++i) {
...@@ -235,11 +356,11 @@ static void stash_glue(map_t *stash, knot_pkt_t *pkt, const knot_dname_t *ns_nam ...@@ -235,11 +356,11 @@ static void stash_glue(map_t *stash, knot_pkt_t *pkt, const knot_dname_t *ns_nam
!knot_dname_is_equal(rr->owner, ns_name)) { !knot_dname_is_equal(rr->owner, ns_name)) {
continue; continue;
} }
stash_add(pkt, stash, rr, pool); stash_add(pkt, &stash->rrs, rr, pool);
} }
} }
static int stash_authority(struct kr_query *qry, knot_pkt_t *pkt, map_t *stash, mm_ctx_t *pool) static int stash_authority(struct kr_query *qry, knot_pkt_t *pkt, struct stash_data *stash, mm_ctx_t *pool)
{ {
const knot_pktsection_t *authority = knot_pkt_section(pkt, KNOT_AUTHORITY); const knot_pktsection_t *authority = knot_pkt_section(pkt, KNOT_AUTHORITY);
for (unsigned i = 0; i < authority->count; ++i) { for (unsigned i = 0; i < authority->count; ++i) {
...@@ -253,12 +374,13 @@ static int stash_authority(struct kr_query *qry, knot_pkt_t *pkt, map_t *stash, ...@@ -253,12 +374,13 @@ static int stash_authority(struct kr_query *qry, knot_pkt_t *pkt, map_t *stash,
stash_glue(stash, pkt, knot_ns_name(&rr->rrs, 0), pool); stash_glue(stash, pkt, knot_ns_name(&rr->rrs, 0), pool);
} }
/* Stash record */ /* Stash record */
stash_add(pkt, stash, rr, pool); stash_add(pkt, &stash->rrs, rr, pool);
stash_add_rrsig(authority, &stash->rrsigs, rr, pool);
} }
return kr_ok(); return kr_ok();
} }
static int stash_answer(struct kr_query *qry, knot_pkt_t *pkt, map_t *stash, mm_ctx_t *pool) static int stash_answer(struct kr_query *qry, knot_pkt_t *pkt, struct stash_data *stash, mm_ctx_t *pool)
{ {
const knot_dname_t *cname = qry->sname; const knot_dname_t *cname = qry->sname;
const knot_pktsection_t *answer = knot_pkt_section(pkt, KNOT_ANSWER); const knot_pktsection_t *answer = knot_pkt_section(pkt, KNOT_ANSWER);
...@@ -268,7 +390,8 @@ static int stash_answer(struct kr_query *qry, knot_pkt_t *pkt, map_t *stash, mm_ ...@@ -268,7 +390,8 @@ static int stash_answer(struct kr_query *qry, knot_pkt_t *pkt, map_t *stash, mm_
if (!knot_dname_is_equal(rr->owner, cname)) { if (!knot_dname_is_equal(rr->owner, cname)) {
continue; continue;
} }
stash_add(pkt, stash, rr, pool); stash_add(pkt, &stash->rrs, rr, pool);
stash_add_rrsig(answer, &stash->rrsigs, rr, pool);
/* Follow CNAME chain */ /* Follow CNAME chain */
if (rr->type == KNOT_RRTYPE_CNAME) { if (rr->type == KNOT_RRTYPE_CNAME) {
cname = knot_cname_name(&rr->rrs); cname = knot_cname_name(&rr->rrs);
...@@ -293,10 +416,8 @@ static int stash(knot_layer_t *ctx, knot_pkt_t *pkt) ...@@ -293,10 +416,8 @@ static int stash(knot_layer_t *ctx, knot_pkt_t *pkt)
return ctx->state; return ctx->state;
} }
/* Stash in-bailiwick data from the AUTHORITY and ANSWER. */ /* Stash in-bailiwick data from the AUTHORITY and ANSWER. */
map_t stash = map_make(); struct stash_data stash;
stash.malloc = (map_alloc_f) mm_alloc; stash_data_init(&stash, rplan->pool);
stash.free = (map_free_f) mm_free;
stash.baton = rplan->pool;
int ret = stash_authority(qry, pkt, &stash, rplan->pool); int ret = stash_authority(qry, pkt, &stash, rplan->pool);
if (ret == 0 && knot_wire_get_aa(pkt->wire)) { if (ret == 0 && knot_wire_get_aa(pkt->wire)) {
ret = stash_answer(qry, pkt, &stash, rplan->pool); ret = stash_answer(qry, pkt, &stash, rplan->pool);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment