Commit 2a9ed2ef authored by Marek Vavruša's avatar Marek Vavruša

lib: turn on DO=1 per query, fixed caching of DNSSEC data

subrequests may be insecure (e.g. out of bailiwick insecure NS),
but the final answer may be secured
the commit also fixes caching in this case
parent cbd8f55b
......@@ -26,9 +26,9 @@
#define DEFAULT_MAXTTL (15 * 60)
#define DEFAULT_NOTTL (5) /* Short-time "no data" retention to avoid bursts */
static inline uint8_t get_tag(struct kr_request *req)
static inline uint8_t get_tag(struct kr_query *qry)
{
return (req->options & QUERY_DNSSEC_WANT) ? KR_CACHE_SEC : KR_CACHE_PKT;
return (qry->flags & QUERY_DNSSEC_WANT) ? KR_CACHE_SEC : KR_CACHE_PKT;
}
static uint32_t limit_ttl(uint32_t ttl)
......@@ -115,7 +115,7 @@ static int peek(knot_layer_t *ctx, knot_pkt_t *pkt)
}
/* Fetch either answer to original or minimized query */
uint8_t tag = get_tag(req);
uint8_t tag = get_tag(qry);
int ret = loot_cache(&txn, pkt, tag, qry);
kr_cache_txn_abort(&txn);
if (ret == 0) {
......@@ -197,7 +197,7 @@ static int stash(knot_layer_t *ctx, knot_pkt_t *pkt)
};
/* Stash answer in the cache */
int ret = kr_cache_insert(&txn, get_tag(req), qname, qtype, &header, data);
int ret = kr_cache_insert(&txn, get_tag(qry), qname, qtype, &header, data);
if (ret != 0) {
kr_cache_txn_abort(&txn);
} else {
......
......@@ -125,7 +125,7 @@ static int peek(knot_layer_t *ctx, knot_pkt_t *pkt)
* Only one step of the chain is resolved at a time.
*/
struct kr_cache *cache = &req->ctx->cache;
int ret = loot_cache(cache, pkt, qry, req->options & QUERY_DNSSEC_WANT);
int ret = loot_cache(cache, pkt, qry, (qry->flags & QUERY_DNSSEC_WANT));
if (ret == 0) {
DEBUG_MSG("=> satisfied from cache\n");
qry->flags |= QUERY_CACHED|QUERY_NO_MINIMIZE;
......@@ -141,6 +141,7 @@ static int peek(knot_layer_t *ctx, knot_pkt_t *pkt)
struct stash_baton
{
struct kr_request *req;
struct kr_query *qry;
struct kr_cache_txn *txn;
unsigned timestamp;
uint32_t min_ttl;
......@@ -149,7 +150,7 @@ struct stash_baton
static int commit_rrsig(struct stash_baton *baton, knot_rrset_t *rr)
{
/* If not doing secure resolution, ignore (unvalidated) RRSIGs. */
if (!(baton->req->options & QUERY_DNSSEC_WANT)) {
if (!(baton->qry->flags & QUERY_DNSSEC_WANT)) {
return kr_ok();
}
/* Commit covering RRSIG to a separate cache namespace. */
......@@ -197,12 +198,13 @@ 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, struct kr_request *req)
static int stash_commit(map_t *stash, struct kr_query *qry, struct kr_cache_txn *txn, struct kr_request *req)
{
struct stash_baton baton = {
.req = req,
.qry = qry,
.txn = txn,
.timestamp = timestamp,
.timestamp = qry->timestamp.tv_sec,
.min_ttl = DEFAULT_MINTTL
};
return map_walk(stash, &commit_rr, &baton);
......@@ -339,7 +341,7 @@ static int stash(knot_layer_t *ctx, knot_pkt_t *pkt)
struct kr_cache *cache = &req->ctx->cache;
struct kr_cache_txn txn;
if (kr_cache_txn_begin(cache, &txn, 0) == 0) {
ret = stash_commit(&stash, qry->timestamp.tv_sec, &txn, req);
ret = stash_commit(&stash, qry, &txn, req);
if (ret == 0) {
kr_cache_txn_commit(&txn);
} else {
......
......@@ -154,10 +154,6 @@ static int edns_put(knot_pkt_t *pkt)
static int edns_create(knot_pkt_t *pkt, knot_pkt_t *template, struct kr_request *req)
{
pkt->opt_rr = knot_rrset_copy(req->ctx->opt_rr, &pkt->mm);
/* Set DO bit if set (DNSSEC requested). */
if (knot_pkt_has_dnssec(template) || (req->options & QUERY_DNSSEC_WANT)) {
knot_edns_set_do(pkt->opt_rr);
}
return knot_pkt_reserve(pkt, knot_edns_wire_size(pkt->opt_rr));
}
......@@ -175,6 +171,10 @@ static int answer_prepare(knot_pkt_t *answer, knot_pkt_t *query, struct kr_reque
if (ret != 0){
return ret;
}
/* Set DO bit if set (DNSSEC requested). */
if (knot_pkt_has_dnssec(query)) {
knot_edns_set_do(answer->opt_rr);
}
}
return kr_ok();
}
......@@ -197,10 +197,9 @@ static int answer_finalize(struct kr_request *request, int state)
return kr_ok();
}
static int query_finalize(struct kr_request *request, knot_pkt_t *pkt)
static int query_finalize(struct kr_request *request, struct kr_query *qry, knot_pkt_t *pkt)
{
/* Randomize query case (if not in safemode) */
struct kr_query *qry = kr_rplan_current(&request->rplan);
qry->secret = (qry->flags & QUERY_SAFEMODE) ? 0 : kr_rand_uint(UINT32_MAX);
knot_dname_t *qname_raw = (knot_dname_t *)knot_pkt_qname(pkt);
randomized_qname_case(qname_raw, qry->secret);
......@@ -209,7 +208,10 @@ static int query_finalize(struct kr_request *request, knot_pkt_t *pkt)
knot_pkt_begin(pkt, KNOT_ADDITIONAL);
if (!(qry->flags & QUERY_SAFEMODE)) {
ret = edns_create(pkt, request->answer, request);
if (ret == 0) {
if (ret == 0) { /* Enable DNSSEC for query. */
if (qry->flags & QUERY_DNSSEC_WANT) {
knot_edns_set_do(pkt->opt_rr);
}
ret = edns_put(pkt);
}
}
......@@ -229,9 +231,12 @@ int kr_resolve_begin(struct kr_request *request, struct kr_context *ctx, knot_pk
return KNOT_STATE_CONSUME;
}
int kr_resolve_query(struct kr_request *request, const knot_dname_t *qname, uint16_t qclass, uint16_t qtype)
static int resolve_query(struct kr_request *request, const knot_pkt_t *packet)
{
struct kr_rplan *rplan = &request->rplan;
const knot_dname_t *qname = knot_pkt_qname(packet);
uint16_t qclass = knot_pkt_qclass(packet);
uint16_t qtype = knot_pkt_qtype(packet);
struct kr_query *qry = kr_rplan_push(rplan, NULL, qname, qclass, qtype);
if (!qry) {
return KNOT_STATE_FAIL;
......@@ -239,6 +244,9 @@ int kr_resolve_query(struct kr_request *request, const knot_dname_t *qname, uint
/* Deferred zone cut lookup for this query. */
qry->flags |= QUERY_AWAIT_CUT;
if (knot_pkt_has_dnssec(packet)) {
qry->flags |= QUERY_DNSSEC_WANT;
}
/* Initialize answer packet */
knot_pkt_t *answer = request->answer;
......@@ -266,11 +274,7 @@ int kr_resolve_consume(struct kr_request *request, knot_pkt_t *packet)
if (answer_prepare(request->answer, packet, request) != 0) {
return KNOT_STATE_FAIL;
}
/* Start query resolution */
const knot_dname_t *qname = knot_pkt_qname(packet);
uint16_t qclass = knot_pkt_qclass(packet);
uint16_t qtype = knot_pkt_qtype(packet);
return kr_resolve_query(request, qname, qclass, qtype);
return resolve_query(request, packet);
}
/* Different processing for network error */
......@@ -336,6 +340,9 @@ static int zone_cut_subreq(struct kr_rplan *rplan, struct kr_query *parent,
return kr_error(ENOMEM);
}
next->flags |= QUERY_NO_MINIMIZE;
if (parent->flags & QUERY_DNSSEC_WANT) {
next->flags |= QUERY_DNSSEC_WANT;
}
return kr_ok();
}
......@@ -472,7 +479,7 @@ int kr_resolve_produce(struct kr_request *request, struct sockaddr **dst, int *t
}
/* Prepare additional query */
int ret = query_finalize(request, packet);
int ret = query_finalize(request, qry, packet);
if (ret != 0) {
return KNOT_STATE_FAIL;
}
......
......@@ -42,8 +42,10 @@
* .alloc = (mm_alloc_t) mp_alloc
* }
* };
* kr_resolve_begin(&req, ctx, answer);
* int state = kr_resolve_query(&req, qname, qclass, qtype);
*
* // Setup and provide input query
* int state = kr_resolve_begin(&req, ctx, final_answer);
* state = kr_resolve_consume(&req, query);
*
* // Generate answer
* while (state == KNOT_STATE_PRODUCE) {
......@@ -126,16 +128,6 @@ struct kr_request {
*/
int kr_resolve_begin(struct kr_request *request, struct kr_context *ctx, knot_pkt_t *answer);
/**
* Push new query for resolution to the state.
* @param request request state (if already has a question, this will be resolved first)
* @param qname
* @param qclass
* @param qtype
* @return PRODUCE|FAIL
*/
int kr_resolve_query(struct kr_request *request, const knot_dname_t *qname, uint16_t qclass, uint16_t qtype);
/**
* Consume input packet (may be either first query or answer to query originated from kr_resolve_produce())
*
......
......@@ -162,7 +162,7 @@ static int collect(knot_layer_t *ctx)
/* Query parameters and transport mode */
if (knot_pkt_has_edns(param->answer)) {
stat_const_add(data, metric_query_edns, 1);
if (param->options & QUERY_DNSSEC_WANT) {
if (knot_pkt_has_dnssec(param->answer)) {
stat_const_add(data, metric_query_dnssec, 1);
}
}
......
Markdown is supported
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