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
Branches
Tags
No related merge requests found
......@@ -17,6 +17,7 @@
#include <libknot/descriptor.h>
#include <libknot/errcode.h>
#include <libknot/rrset.h>
#include <libknot/rrtype/rrsig.h>
#include <libknot/internal/mempool.h>
#include <libknot/rrtype/rdname.h>
......@@ -141,6 +142,26 @@ static int peek(knot_layer_t *ctx, knot_pkt_t *pkt)
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 */
struct stash_baton
{
......@@ -148,14 +169,24 @@ struct stash_baton
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 */
unsigned drift = baton->timestamp;
knot_rrset_t query_rrsig;
knot_rrset_init(&query_rrsig, rrsig->owner, rrsig->type, rrsig->rclass);
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);
}
......@@ -167,10 +198,6 @@ static int commit_rr(const char *key, void *val, void *data)
if (knot_rrset_ttl(rr) < 1) {
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 */
/** @todo This should check if less trusted data is in the cache,
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)
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 = {
.txn = txn,
.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. */
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
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 } */
char key[8 + 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
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);
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
!knot_dname_is_equal(rr->owner, ns_name)) {
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);
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,
stash_glue(stash, pkt, knot_ns_name(&rr->rrs, 0), pool);
}
/* 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();
}
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_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_
if (!knot_dname_is_equal(rr->owner, cname)) {
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 */
if (rr->type == KNOT_RRTYPE_CNAME) {
cname = knot_cname_name(&rr->rrs);
......@@ -293,10 +416,8 @@ static int stash(knot_layer_t *ctx, knot_pkt_t *pkt)
return ctx->state;
}
/* Stash in-bailiwick data from the AUTHORITY and ANSWER. */
map_t stash = map_make();
stash.malloc = (map_alloc_f) mm_alloc;
stash.free = (map_free_f) mm_free;
stash.baton = rplan->pool;
struct stash_data stash;
stash_data_init(&stash, rplan->pool);
int ret = stash_authority(qry, pkt, &stash, rplan->pool);
if (ret == 0 && knot_wire_get_aa(pkt->wire)) {
ret = stash_answer(qry, pkt, &stash, rplan->pool);
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment