return kr_ok();
}
-static int merge_in_rrsigs(knot_rrset_t *cache_rr, const knot_rrset_t *rrsigset, uint16_t typec, mm_ctx_t *pool)
+static int validate_rrsig(const knot_rrset_t *rrsig, size_t pos, const knot_rrset_t *rr,
+ struct kr_cache_txn *txn, struct kr_request *req)
{
+ struct kr_rplan *rplan = &req->rplan;
+ struct kr_query *qry = kr_rplan_current(rplan);
+ uint32_t timestamp = qry->timestamp.tv_sec;
+
+ const knot_dname_t *signer = knot_rrsig_signer_name(&rrsig->rrs, pos);
+
+ knot_rrset_t dnskey_rr;
+ knot_rrset_init(&dnskey_rr, (knot_dname_t *)signer, KNOT_RRTYPE_DNSKEY, rr->rclass);
+ int ret = kr_cache_peek_rr(txn, &dnskey_rr, ×tamp);
+ if (ret != 0) {
+ DEBUG_MSG("<= missing DNSKEY\n");
+ return KNOT_DNSSEC_ENOKEY;
+ }
+
+ return kr_ok();
+}
+
+static int merge_in_rrsigs(knot_rrset_t *cache_rr, const knot_rrset_t *rrsigset, const knot_rrset_t *rr,
+ struct kr_cache_txn *txn, struct kr_request *req)
+{
+ struct kr_rplan *rplan = &req->rplan;
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) == typec) &&
+ if ((knot_rrsig_type_covered(&rrsigset->rrs, i) == rr->type) &&
knot_dname_is_equal(cache_rr->owner, rrsigset->owner)) {
+ ret = validate_rrsig(rrsigset, i, rr, txn, req);
+ switch (ret) {
+ case KNOT_DNSSEC_ENOKEY:
+#ifndef NDEBUG
+ {
+ char name_str[KNOT_DNAME_MAXLEN], type_str[16];
+ knot_dname_to_str(name_str, knot_rrsig_signer_name(&rrsigset->rrs, i), sizeof(name_str));
+ knot_rrtype_to_string(rr->type, type_str, sizeof(type_str));
+ DEBUG_MSG_NOPLAN("%s() Missing DNSKEY for '%s %s'.\n", __func__, type_str, name_str);
+ }
+#endif
+ break;
+ case 0:
+ break;
+ default:
+ return ret;
+ break;
+ }
+
const knot_rdata_t *rdata = knot_rdataset_at(&rrsigset->rrs, i);
- ret = knot_rdataset_add(&cache_rr->rrs, rdata, pool);
+ ret = knot_rdataset_add(&cache_rr->rrs, rdata, rplan->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, struct kr_request *req)
+{
+ struct kr_rplan *rplan = &req->rplan;
+ struct kr_cache *cache = &req->ctx->cache;
+
+ struct kr_cache_txn txn;
+ int ret = kr_cache_txn_begin(cache, &txn, 0);
+ if (0 != ret) {
+ return ret;
+ }
+
+ 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;
+ }
+ /* Currently only merge. Signature check is missing. */
+ int ret = merge_in_rrsigs(cache_rrsig, rrset, rr, &txn, req);
+ if (KNOT_EOK != ret) {
+ knot_rrset_clear(cache_rrsig, rplan->pool);
+ kr_cache_txn_abort(&txn);
+ return ret;
+ }
+ }
+
+ kr_cache_txn_abort(&txn);
+ return kr_ok();
+}
+
static int stash_add_rrsig(map_t *stash, const knot_pktsection_t *section,
- const knot_rrset_t *rr, mm_ctx_t *pool)
+ const knot_rrset_t *rr, struct kr_request *req)
{
if (rr->type == KNOT_RRTYPE_RRSIG) {
return kr_ok();
}
+ struct kr_rplan *rplan = &req->rplan;
+
/* 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);
/* Construct RRSIG RRSet containing related data. */
knot_rrset_t cache_rrsig;
- 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;
- }
- /* Currently only merge. Signature check is missing. */
- ret = merge_in_rrsigs(&cache_rrsig, rrset, rr->type, pool);
- if (KNOT_EOK != ret) {
- knot_rrset_clear(&cache_rrsig, pool);
- return ret;
- }
+ ret = scan_for_rrsigs(&cache_rrsig, section, rr, req);
+ if (ret != 0) {
+ return ret;
}
if (cache_rrsig.rrs.rr_count) {
- stashed = knot_rrset_copy(&cache_rrsig, pool);
+ stashed = knot_rrset_copy(&cache_rrsig, rplan->pool);
if (!stashed) {
return kr_error(ENOMEM);
}
}
- knot_rrset_clear(&cache_rrsig, pool);
+ knot_rrset_clear(&cache_rrsig, rplan->pool);
if (stashed) {
return map_set(stash, key, stashed);
}
}
}
-static int stash_authority(struct kr_query *qry, knot_pkt_t *pkt, map_t *stash, mm_ctx_t *pool)
+static int stash_authority(map_t *stash, knot_pkt_t *pkt, struct kr_request *req)
{
+ struct kr_rplan *rplan = &req->rplan;
+ struct kr_query *qry = kr_rplan_current(rplan);
const knot_pktsection_t *authority = knot_pkt_section(pkt, KNOT_AUTHORITY);
for (unsigned i = 0; i < authority->count; ++i) {
const knot_rrset_t *rr = knot_pkt_rr(authority, i);
}
/* Look up glue records for NS */
if (rr->type == KNOT_RRTYPE_NS) {
- stash_glue(stash, pkt, knot_ns_name(&rr->rrs, 0), pool);
+ stash_glue(stash, pkt, knot_ns_name(&rr->rrs, 0), rplan->pool);
}
/* Ignore RRSIGs directly. */
if (rr->type == KNOT_RRTYPE_RRSIG) {
continue;
}
/* Stash record */
- stash_add_rrsig(stash, authority, rr, pool);
+ stash_add_rrsig(stash, authority, rr, req);
}
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(map_t *stash, knot_pkt_t *pkt, struct kr_request *req)
{
+ struct kr_rplan *rplan = &req->rplan;
+ struct kr_query *qry = kr_rplan_current(rplan);
const knot_dname_t *cname = qry->sname;
const knot_pktsection_t *answer = knot_pkt_section(pkt, KNOT_ANSWER);
for (unsigned i = 0; i < answer->count; ++i) {
if (rr->type == KNOT_RRTYPE_RRSIG) {
continue;
}
- stash_add_rrsig(stash, answer, rr, pool);
+ stash_add_rrsig(stash, answer, rr, req);
/* Follow CNAME chain */
if (rr->type == KNOT_RRTYPE_CNAME) {
cname = knot_cname_name(&rr->rrs);
return kr_ok();
}
+static int scan_rrsigs(map_t *stash, knot_pkt_t *pkt, struct kr_request *req)
+{
+ int ret = stash_authority(stash, pkt, req);
+ if (ret == 0 && knot_wire_get_aa(pkt->wire)) {
+ ret = stash_answer(stash, pkt, req);
+ }
+ return ret;
+}
+
static int stash(knot_layer_t *ctx, knot_pkt_t *pkt)
{
/* Do nothing when no DNSSEC required. */
stash_rrsig.malloc = (map_alloc_f) mm_alloc;
stash_rrsig.free = (map_free_f) mm_free;
stash_rrsig.baton = rplan->pool;
- int ret = stash_authority(qry, pkt, &stash_rrsig, rplan->pool);
- if (ret == 0 && knot_wire_get_aa(pkt->wire)) {
- ret = stash_answer(qry, pkt, &stash_rrsig, rplan->pool);
- }
+ int ret = scan_rrsigs(&stash_rrsig, pkt, req);
/* Cache stashed records */
if (ret == 0) {
/* Open write transaction */