#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)
}
/* 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) {
};
/* 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 {
* 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;
struct stash_baton
{
struct kr_request *req;
+ struct kr_query *qry;
struct kr_cache_txn *txn;
unsigned timestamp;
uint32_t min_ttl;
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. */
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);
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 {
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));
}
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();
}
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);
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);
}
}
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;
/* 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;
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 */
return kr_error(ENOMEM);
}
next->flags |= QUERY_NO_MINIMIZE;
+ if (parent->flags & QUERY_DNSSEC_WANT) {
+ next->flags |= QUERY_DNSSEC_WANT;
+ }
return kr_ok();
}
}
/* Prepare additional query */
- int ret = query_finalize(request, packet);
+ int ret = query_finalize(request, qry, packet);
if (ret != 0) {
return KNOT_STATE_FAIL;
}
* .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) {
*/
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())
*
/* 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);
}
}