#include "lib/layer/iterate.h"
#include "lib/rplan.h"
+#define DEBUG_MSG(fmt, ...) fprintf(stderr, "[qiter] " fmt, ## __VA_ARGS__)
+
static int glue_record(knot_pkt_t *pkt, const knot_dname_t *dp, struct sockaddr *sa)
{
/* TODO: API call for find() */
}
static void follow_cname_chain(const knot_dname_t **cname, const knot_rrset_t *rr,
- struct kr_layer_param *param)
+ struct kr_context *resolve)
{
- struct kr_context *resolve = param->ctx;
struct kr_query *cur = kr_rplan_next(&resolve->rplan);
assert(cur);
kr_context_txn_release(txn);
/* Check canonical name. */
- follow_cname_chain(&cname, &an->rr[i], param);
+ follow_cname_chain(&cname, &an->rr[i], resolve);
}
/* Follow canonical name as next SNAME. */
return reset(ctx);
}
+static int prepare_query_cache(struct kr_context *resolve, struct kr_result *result, struct kr_query *next)
+{
+ int state = KNOT_NS_PROC_MORE;
+ knot_rrset_t cached_reply;
+ knot_rrset_init(&cached_reply, next->sname, next->stype, next->sclass);
+
+ struct kr_txn *txn = kr_context_txn_acquire(resolve, KR_CACHE_RDONLY);
+
+ /* Try to find a CNAME/DNAME chain first. */
+ bool found_hit = true;
+ cached_reply.type = KNOT_RRTYPE_CNAME;
+ if (kr_cache_query(txn, &cached_reply) != 0) {
+ cached_reply.type = next->stype;
+ if (kr_cache_query(txn, &cached_reply) != 0) {
+ found_hit = false;
+ }
+ }
+
+ /* Solve this from cache. */
+ if (found_hit) {
+ update_result(next, result, &cached_reply);
+ knot_wire_set_rcode(result->ans->wire, KNOT_RCODE_NOERROR);
+ resolve->resolved_qry = next;
+ state = KNOT_NS_PROC_DONE;
+
+ /* Follow the CNAME chain. */
+ if (cached_reply.type == KNOT_RRTYPE_CNAME) {
+ const knot_dname_t *cname = next->sname;
+ follow_cname_chain(&cname, &cached_reply, resolve);
+ if (kr_rplan_push(&resolve->rplan, cname,next->sclass, next->stype) == NULL) {
+ return KNOT_NS_PROC_FAIL;
+ }
+ }
+ }
+ kr_context_txn_release(txn);
+
+ knot_rdataset_clear(&cached_reply.rrs, resolve->pool);
+ return state;
+}
+
static int prepare_query(knot_layer_t *ctx, knot_pkt_t *pkt)
{
assert(pkt && ctx);
return -1;
}
- struct kr_txn *txn = kr_context_txn_acquire(resolve, KR_CACHE_RDONLY);
- knot_rrset_t cached_reply;
- knot_rrset_init(&cached_reply, next->sname, next->stype, next->sclass);
-
- if (kr_cache_query(txn, &cached_reply) == 0) {
- /* Solve this from cache. */
- update_result(next, result, &cached_reply);
- knot_rdataset_clear(&cached_reply.rrs, resolve->pool);
-
- /* Resolved current SNAME. */
- knot_wire_set_rcode(result->ans->wire, KNOT_RCODE_NOERROR);
- resolve->resolved_qry = next;
- kr_context_txn_release(txn);
- return KNOT_NS_PROC_DONE;
+ /* Attempt to satisfy query form the cache. */
+ int state = prepare_query_cache(resolve, result, next);
+ if (state != KNOT_NS_PROC_MORE) {
+ return state;
}
- knot_rdataset_clear(&cached_reply.rrs, resolve->pool);
- kr_context_txn_release(txn);
+ /* Form a query for the authoritative. */
knot_pkt_clear(pkt);
-
int ret = knot_pkt_put_question(pkt, next->sname, next->sclass, next->stype);
if (ret != KNOT_EOK) {
return KNOT_NS_PROC_FAIL;
knot_wire_set_id(pkt->wire, knot_random_uint16_t());
/* Query complete, expect answer. */
+ char query_str[KNOT_DNAME_MAXLEN];
+ knot_dname_to_str(query_str, next->sname, sizeof(query_str));
+ DEBUG_MSG("issued query for '%s/RRTYPE=%d'\n", query_str, next->stype);
return KNOT_NS_PROC_MORE;
}