Skip to content
Snippets Groups Projects
Commit 480d94bc authored by Marek Vavruša's avatar Marek Vavruša
Browse files

lib/resolve: better processing for RD=0 or ANY

if the query has RD=0 or is ANY, only cache is probed
for ANY, only A/AAAA/MX is checked and no query is
forwarded to the authoritatives
parent 3edf53ca
No related branches found
No related tags found
No related merge requests found
......@@ -154,15 +154,14 @@ int kr_rrset_validate(const knot_pkt_t *pkt, knot_section_t section_id,
return kr_error(EINVAL);
}
int ret = kr_error(ENOENT);
for (unsigned i = 0; i < keys->rrs.rr_count; ++i) {
ret = kr_rrset_validate_with_key(pkt, section_id, covered, keys, i, NULL, zone_name, timestamp, has_nsec3);
int ret = kr_rrset_validate_with_key(pkt, section_id, covered, keys, i, NULL, zone_name, timestamp, has_nsec3);
if (ret == 0) {
break;
return ret;
}
}
return ret;
return kr_error(ENOENT);
}
int kr_rrset_validate_with_key(const knot_pkt_t *pkt, knot_section_t section_id,
......
......@@ -77,7 +77,7 @@ static int loot_rr(struct kr_cache_txn *txn, knot_pkt_t *pkt, const knot_dname_t
}
/** @internal Try to find a shortcut directly to searched record. */
static int loot_cache(struct kr_cache *cache, knot_pkt_t *pkt, struct kr_query *qry, bool dobit)
static int loot_cache(struct kr_cache *cache, knot_pkt_t *pkt, struct kr_query *qry, uint16_t rrtype, bool dobit)
{
struct kr_cache_txn txn;
int ret = kr_cache_txn_begin(cache, &txn, NAMEDB_RDONLY);
......@@ -86,7 +86,6 @@ static int loot_cache(struct kr_cache *cache, knot_pkt_t *pkt, struct kr_query *
}
/* Lookup direct match first */
uint16_t rank = 0;
uint16_t rrtype = qry->stype;
ret = loot_rr(&txn, pkt, qry->sname, qry->sclass, rrtype, qry, &rank, 0);
if (ret != 0 && rrtype != KNOT_RRTYPE_CNAME) { /* Chase CNAME if no direct hit */
rrtype = KNOT_RRTYPE_CNAME;
......@@ -120,7 +119,19 @@ 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, (qry->flags & QUERY_DNSSEC_WANT));
int ret = -1;
if (qry->stype != KNOT_RRTYPE_ANY) {
ret = loot_cache(cache, pkt, qry, qry->stype, (qry->flags & QUERY_DNSSEC_WANT));
} else {
/* ANY query are used by either qmail or certain versions of Firefox.
* Probe cache for a few interesting records. */
static uint16_t any_types[] = { KNOT_RRTYPE_A, KNOT_RRTYPE_AAAA, KNOT_RRTYPE_MX };
for (size_t i = 0; i < sizeof(any_types)/sizeof(any_types[0]); ++i) {
if (loot_cache(cache, pkt, qry, any_types[i], (qry->flags & QUERY_DNSSEC_WANT)) == 0) {
ret = 0; /* At least single record matches */
}
}
}
if (ret == 0) {
DEBUG_MSG("=> satisfied from cache\n");
qry->flags |= QUERY_CACHED|QUERY_NO_MINIMIZE;
......
......@@ -77,7 +77,7 @@ static int invalidate_ns(struct kr_rplan *rplan, struct kr_query *qry)
static int ns_fetch_cut(struct kr_query *qry, struct kr_request *req, bool secured)
{
int ret = kr_error(ENOENT);
int ret = 0;
/* Find closest zone cut from cache */
struct kr_cache_txn txn;
......@@ -92,6 +92,8 @@ static int ns_fetch_cut(struct kr_query *qry, struct kr_request *req, bool secur
ret = kr_zonecut_find_cached(req->ctx, &qry->zone_cut, qry->sname, &txn, qry->timestamp.tv_sec, secured);
}
kr_cache_txn_abort(&txn);
} else {
ret = kr_error(ENOENT);
}
return ret;
}
......@@ -177,9 +179,6 @@ static int edns_create(knot_pkt_t *pkt, knot_pkt_t *template, struct kr_request
static int answer_prepare(knot_pkt_t *answer, knot_pkt_t *query, struct kr_request *req)
{
if (!knot_wire_get_rd(query->wire)) {
return kr_error(ENOSYS); /* Only recursive service */
}
if (knot_pkt_init_response(answer, query) != 0) {
return kr_error(ENOMEM); /* Failed to initialize answer */
}
......@@ -494,6 +493,12 @@ int kr_resolve_produce(struct kr_request *request, struct sockaddr **dst, int *t
return kr_rplan_empty(rplan) ? KNOT_STATE_DONE : KNOT_STATE_PRODUCE;
}
/* This query has RD=0 or is ANY, stop here. */
if (qry->stype == KNOT_RRTYPE_ANY || !knot_wire_get_rd(request->answer->wire)) {
DEBUG_MSG("=> qtype is ANY or RD=0, bail out\n");
return KNOT_STATE_FAIL;
}
/* Update zone cut, spawn new subrequests. */
int state = zone_cut_check(request, qry, packet);
switch(state) {
......@@ -513,7 +518,7 @@ ns_election:
}
if (qry->flags & (QUERY_AWAIT_IPV4|QUERY_AWAIT_IPV6)) {
kr_nsrep_elect_addr(qry, request->ctx);
} else if (!(qry->flags & QUERY_TCP)) { /* Keep address when TCP retransmit. */
} else if (!qry->ns.name || !(qry->flags & QUERY_TCP)) { /* Keep address when TCP retransmit. */
/* Root DNSKEY must be fetched from the hints to avoid chicken and egg problem. */
if (qry->sname[0] == '\0' && qry->stype == KNOT_RRTYPE_DNSKEY) {
DEBUG_MSG("=> priming root DNSKEY\n");
......
......@@ -69,7 +69,7 @@ static int answer_query(knot_pkt_t *pkt, pack_t *addr_set, struct kr_query *qry)
addr = pack_obj_next(addr);
}
int ret = kr_error(ENOENT);
int ret = 0;
if (!knot_rrset_empty(&rr)) {
/* Update packet question */
if (!knot_dname_is_equal(knot_pkt_qname(pkt), qname)) {
......@@ -78,6 +78,8 @@ static int answer_query(knot_pkt_t *pkt, pack_t *addr_set, struct kr_query *qry)
}
/* Append to packet */
ret = knot_pkt_put(pkt, KNOT_COMPR_HINT_QNAME, &rr, KNOT_PF_FREE);
} else {
ret = kr_error(ENOENT);
}
/* Clear RR if failed */
if (ret != 0) {
......
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