]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
rplan: per-query zone cut, iterator cleanup
authorMarek Vavruša <marek.vavrusa@nic.cz>
Wed, 21 Jan 2015 02:15:53 +0000 (03:15 +0100)
committerMarek Vavruša <marek.vavrusa@nic.cz>
Wed, 21 Jan 2015 02:15:53 +0000 (03:15 +0100)
lib/layer/iterate.c
lib/layer/itercache.c
lib/resolve.c
lib/rplan.c
lib/rplan.h

index 951254bba2a7cf3591c672e7336d9766cfb1a14d..a1bc780208685c4bdbc2e804af741994469d6119 100644 (file)
 
 #define DEBUG_MSG(fmt, ...) fprintf(stderr, "[qiter] " fmt, ## __VA_ARGS__)
 
-/*! \brief Fetch NS record address from additionals. */
-static int glue_ns_addr(const knot_pkt_t *pkt, struct sockaddr_storage *addr, const knot_dname_t *name, uint16_t type)
-{
-       const knot_pktsection_t *ar = knot_pkt_section(pkt, KNOT_ADDITIONAL);
-       for (unsigned i = 0; i < ar->count; ++i) {
-               const knot_rrset_t *rr = knot_pkt_rr(ar, i);
-               if (rr->type == type && knot_dname_is_equal(name, rr->owner)) {
-                       return kr_rrset_to_addr(addr, rr);
-               }
-       }
-
-       return KNOT_ENOENT;
-}
+/* Iterator often walks through packet section, this is an abstraction. */
+typedef int (*rr_callback_t)(const knot_rrset_t *, struct kr_layer_param *);
 
-static int set_zone_cut(struct kr_rplan *rplan, knot_pkt_t *pkt, const knot_rrset_t *rr)
+/*! \brief Return minimized QNAME/QTYPE for current zone cut. */
+static const knot_dname_t *minimized_qname(struct kr_query *query, uint16_t *qtype)
 {
-       static const uint16_t type_list[] = { KNOT_RRTYPE_A, KNOT_RRTYPE_AAAA };
-
-       /* Set zone cut to given name server. */
-       const knot_dname_t *ns_name = knot_ns_name(&rr->rrs, 0);
-       kr_set_zone_cut(&rplan->zone_cut, rr->owner, ns_name);
-
-       /* Check if we can find a valid address in glue / cache */
-       for (unsigned i = 0; i < sizeof(type_list)/sizeof(uint16_t); ++i) {
+       /* Minimization disabled. */
+       const knot_dname_t *qname = query->sname;
+       if (query->flags & QUERY_NO_MINIMIZE) {
+               return qname;
+       }
 
-               /* Find address in the additionals (optional). */
-               int ret = glue_ns_addr(pkt, &rplan->zone_cut.addr, ns_name, type_list[i]);
-               if (ret == KNOT_EOK) {
-                       return KNOT_EOK;
-               }
+       /* Minimize name to contain current zone cut + 1 label. */
+       int cut_labels = knot_dname_labels(query->zone_cut.name, NULL);
+       int qname_labels = knot_dname_labels(qname, NULL);
+       while(qname_labels > cut_labels + 1) {
+               qname = knot_wire_next_label(qname, NULL);
+               qname_labels -= 1;
        }
 
-       /* Query for address records (if not glue). */
-       for (unsigned i = 0; i < sizeof(type_list)/sizeof(uint16_t); ++i) {
-               (void) kr_rplan_push(rplan, rplan->zone_cut.ns, KNOT_CLASS_IN, type_list[i]);
+       /* Hide QTYPE if minimized. */
+       if (qname != query->sname) {
+               *qtype = KNOT_RRTYPE_NS;
        }
 
-       return KNOT_EOK;
+       return qname;
+}
+
+/*! \brief Answer is paired to query. */
+static bool is_paired_to_query(const knot_pkt_t *answer, struct kr_query *query)
+{
+       uint16_t qtype = query->stype;
+       const knot_dname_t *qname = minimized_qname(query, &qtype);
+
+       return query->id      == knot_wire_get_id(answer->wire) &&
+              query->sclass  == knot_pkt_qclass(answer) &&
+              qtype          == knot_pkt_qtype(answer) &&
+              knot_dname_is_equal(qname, knot_pkt_qname(answer));
 }
 
 static void follow_cname_chain(const knot_dname_t **cname, const knot_rrset_t *rr,
@@ -82,12 +82,32 @@ static void follow_cname_chain(const knot_dname_t **cname, const knot_rrset_t *r
        }
 }
 
+static int update_nsaddr(const knot_rrset_t *rr, struct kr_query *query)
+{
+       if (rr->type == KNOT_RRTYPE_A || rr->type == KNOT_RRTYPE_AAAA) {
+               if (knot_dname_is_equal(query->zone_cut.ns, rr->owner)) {
+                       int ret = kr_rrset_to_addr(&query->zone_cut.addr, rr);
+                       if (ret == KNOT_EOK) {
+                               return KNOT_NS_PROC_DONE;
+                       }
+               }
+       }
+
+       return KNOT_NS_PROC_MORE;
+}
+
+static int update_parent(const knot_rrset_t *rr, struct kr_layer_param *param)
+{
+       return update_nsaddr(rr, kr_rplan_last(param->rplan));
+}
+
 /*! \brief Result updates the original query response. */
-static int update_answer(knot_pkt_t *answer, const knot_rrset_t *rr)
+static int update_answer(const knot_rrset_t *rr, struct kr_layer_param *param)
 {
+       knot_pkt_t *answer = param->answer;
        knot_rrset_t *rr_copy = knot_rrset_copy(rr, &answer->mm);
        if (rr_copy == NULL) {
-               return KNOT_ENOMEM;
+               return KNOT_NS_PROC_FAIL;
        }
 
        /* Write copied RR to the result packet. */
@@ -95,42 +115,52 @@ static int update_answer(knot_pkt_t *answer, const knot_rrset_t *rr)
        if (ret != KNOT_EOK) {
                knot_rrset_free(&rr_copy, &answer->mm);
                knot_wire_set_tc(answer->wire);
+               return KNOT_NS_PROC_DONE;
        }
 
        /* Free just the allocated container. */
        mm_free(&answer->mm, rr_copy);
-       return KNOT_EOK;
+
+       /* Update parent query as well. */
+       return update_parent(rr, param);
 }
 
-static int update_zone_cut(knot_pkt_t *pkt, struct kr_rplan *rplan, const knot_rrset_t *rr)
+static int update_nameserver(const knot_rrset_t *rr, struct kr_layer_param *param)
 {
-       int ret = KNOT_EOK;
+       struct kr_query *query = kr_rplan_current(param->rplan);
+       const knot_dname_t *ns_name = knot_ns_name(&rr->rrs, 0);
 
-       if (rr->type == KNOT_RRTYPE_A || rr->type == KNOT_RRTYPE_AAAA) {
-               if (knot_dname_is_equal(rplan->zone_cut.ns, rr->owner)) {
-                       ret = kr_rrset_to_addr(&rplan->zone_cut.addr, rr);
-               }
-       } else if (rr->type == KNOT_RRTYPE_NS) {
-               /* Authority MUST be at/below the authority of the nameserver, otherwise
-                * possible cache injection attempt. */
-               if (!knot_dname_in(rplan->zone_cut.name, rr->owner)) {
-                       DEBUG_MSG("NS in query outside of its authority => rejecting\n");
-                       return KNOT_EMALF;
-               }
-               /* Set the first nameserver address, rest will be cached. */
-               if (!knot_dname_is_equal(rr->owner, rplan->zone_cut.name)) {
-                       ret = set_zone_cut(rplan, pkt, rr);
-               } else {
-                       /* Zone cut not updated, referral loop. */
-                       ret = KNOT_EINVAL;
-               }
+       /* Authority MUST be at/below the authority of the nameserver, otherwise
+        * possible cache injection attempt. */
+       if (!knot_dname_in(query->zone_cut.name, rr->owner)) {
+               DEBUG_MSG("NS in query outside of its authority => rejecting\n");
+               return KNOT_NS_PROC_FAIL;
        }
 
-       return ret;
+       /* Ignore already resolved zone cut. */
+       if (knot_dname_is_equal(rr->owner, query->zone_cut.name)) {
+               return KNOT_NS_PROC_MORE;
+       }
+
+       /* Set zone cut to given name server. */
+       kr_set_zone_cut(&query->zone_cut, rr->owner, ns_name);
+       return KNOT_NS_PROC_DONE;
 }
 
-static int resolve_referral(knot_pkt_t *pkt, struct kr_layer_param *param)
+static int update_glue(const knot_rrset_t *rr, struct kr_layer_param *param)
 {
+       return update_nsaddr(rr, kr_rplan_current(param->rplan));
+}
+
+static int process_authority(knot_pkt_t *pkt, struct kr_layer_param *param)
+{
+       int state = KNOT_NS_PROC_MORE;
+
+       /* Answer declares AA, can't be referral. */
+       if (knot_wire_get_aa(pkt->wire)) {
+               return state;
+       }
+
        /* Update current zone cut from NS records. */
        const knot_pktsection_t *ns = knot_pkt_section(pkt, KNOT_AUTHORITY);
        for (unsigned i = 0; i < ns->count; ++i) {
@@ -138,85 +168,79 @@ static int resolve_referral(knot_pkt_t *pkt, struct kr_layer_param *param)
                if (rr->type != KNOT_RRTYPE_NS) {
                        continue;
                }
-               int ret = update_zone_cut(pkt, param->rplan, rr);
-               if (ret == KNOT_EOK) {
-                       return KNOT_NS_PROC_DONE;
+
+               state = update_nameserver(rr, param);
+               if (state != KNOT_NS_PROC_MORE) {
+                       break;
                }
        }
 
-       /* Dead end, either bogus or loop referral. */
-       struct kr_query *cur = kr_rplan_current(param->rplan);
-       if (cur != NULL) {
-               kr_rplan_pop(param->rplan, cur);
+       return state;
+}
+
+static int process_additional(knot_pkt_t *pkt, struct kr_layer_param *param)
+{
+       struct kr_query *query = kr_rplan_current(param->rplan);
+
+       /* Attempt to find glue for current nameserver. */
+       const knot_pktsection_t *ar = knot_pkt_section(pkt, KNOT_ADDITIONAL);
+       for (unsigned i = 0; i < ar->count; ++i) {
+               const knot_rrset_t *rr = knot_pkt_rr(ar, i);
+               int state = update_glue(rr, param);
+               if (state != KNOT_NS_PROC_MORE) {
+                       return state;
+               }
        }
 
-       return KNOT_NS_PROC_FAIL;
+       /* Glue not found => resolve NS address. */
+       (void) kr_rplan_push(param->rplan, query->zone_cut.ns, KNOT_CLASS_IN, KNOT_RRTYPE_AAAA);
+       (void) kr_rplan_push(param->rplan, query->zone_cut.ns, KNOT_CLASS_IN, KNOT_RRTYPE_A);
+
+       return KNOT_NS_PROC_DONE;
 }
 
-static int resolve_auth(knot_pkt_t *pkt, struct kr_layer_param *param)
+static int process_answer(knot_pkt_t *pkt, struct kr_layer_param *param)
 {
-       knot_pkt_t *answer = param->answer;
-       struct kr_query *cur = kr_rplan_current(param->rplan);
-       if (cur == NULL) {
-               return KNOT_NS_PROC_FAIL;
-       }
+       struct kr_query *query = kr_rplan_current(param->rplan);
 
-       /* Authoritative response for minimized QNAME.
+       /* Response for minimized QNAME.
         * NODATA   => may be empty non-terminal, retry (found zone cut)
         * NOERROR  => found zone cut, retry
         * NXDOMAIN => parent is zone cut, terminate
         */
-       const knot_pktsection_t *an = knot_pkt_section(pkt, KNOT_ANSWER);
-       bool is_minimized = (!knot_dname_is_equal(knot_pkt_qname(pkt), cur->sname));
+       bool is_minimized = (!knot_dname_is_equal(knot_pkt_qname(pkt), query->sname));
        bool is_noerror = (knot_wire_get_rcode(pkt->wire) == KNOT_RCODE_NOERROR);
        if (is_minimized && is_noerror) {
-               cur->flags |= QUERY_NO_MINIMIZE;
+               query->flags |= QUERY_NO_MINIMIZE;
                return KNOT_NS_PROC_DONE;
        }
 
-       /* Is relevant for original query? */
-       bool update_orig_answer = (cur == kr_rplan_last(param->rplan));
-       
-       /* Process answer records. */
-       const knot_dname_t *cname = cur->sname;
+       /* Does this answer update the final response? */
+       struct kr_query *parent_query = kr_rplan_last(param->rplan);
+       rr_callback_t callback = &update_parent;
+       if (query == parent_query) {
+               knot_wire_set_rcode(param->answer->wire, knot_wire_get_rcode(pkt->wire));
+               callback = &update_answer;
+       }
+
+       /* Process answer section records. */
+       const knot_dname_t *cname = query->sname;
+       const knot_pktsection_t *an = knot_pkt_section(pkt, KNOT_ANSWER);
        for (unsigned i = 0; i < an->count; ++i) {
                const knot_rrset_t *rr = knot_pkt_rr(an, i);
-
-               /* Update original answer or current zone cut. */
-               if (update_orig_answer && knot_pkt_qtype(pkt) == cur->stype) {
-                       if (update_answer(answer, rr) != KNOT_EOK) {
-                               return KNOT_NS_PROC_FAIL;
-                       }
-               } else {
-                       if (update_zone_cut(pkt, param->rplan, rr) != KNOT_EOK) {
-                               return KNOT_NS_PROC_FAIL;
-                       }
+               int state = callback(rr, param);
+               if (state == KNOT_NS_PROC_FAIL) {
+                       return state;
                }
-
-               /* Check canonical name. */
-               follow_cname_chain(&cname, rr, cur);
+               follow_cname_chain(&cname, rr, query);
        }
 
+       /* This is either declares AA or not, either way it resolves current query. */
+       kr_rplan_pop(param->rplan, query);
+
        /* Follow canonical name as next SNAME. */
-       if (cname != cur->sname) {
-               struct kr_query *next = kr_rplan_push(param->rplan, cname,
-                                                     cur->sclass, cur->stype);
-               if (next == NULL) {
-                       return KNOT_NS_PROC_FAIL;
-               }
-       }
-       
-       kr_rplan_pop(param->rplan, cur);
-
-       /* Authoritative answer to original response => DONE. */
-       if (update_orig_answer) {
-               knot_wire_set_rcode(answer->wire, knot_wire_get_rcode(pkt->wire));
-       } else {
-               /* Side-lookup, update authority. */
-               /* TODO: store zone-cut in query for side lookups */
-               cur = kr_rplan_current(param->rplan);
-               namedb_txn_t *txn = kr_rplan_txn_acquire(param->rplan, NAMEDB_RDONLY);
-               kr_find_zone_cut(&param->rplan->zone_cut, cur->sname, txn, cur->timestamp.tv_sec);
+       if (cname != query->sname) {
+               (void) kr_rplan_push(param->rplan, cname, query->sclass, query->stype);
        }
 
        return KNOT_NS_PROC_DONE;
@@ -229,48 +253,6 @@ static int resolve_error(knot_pkt_t *pkt, struct kr_layer_param *param, int errc
        return KNOT_NS_PROC_FAIL;
 }
 
-/*! \brief Return minimized QNAME/QTYPE for current zone cut. */
-static const knot_dname_t *minimized_qname(struct kr_query *query, struct kr_zonecut *cut, uint16_t *qtype)
-{
-       /* Minimization disabled. */
-       const knot_dname_t *qname = query->sname;
-       if (query->flags & QUERY_NO_MINIMIZE) {
-               return qname;
-       }
-
-       /* Minimize name to contain current zone cut + 1 label. */
-       int cut_labels = knot_dname_labels(cut->name, NULL);
-       int qname_labels = knot_dname_labels(qname, NULL);
-       while(qname_labels > cut_labels + 1) {
-               qname = knot_wire_next_label(qname, NULL);
-               qname_labels -= 1;
-       }
-
-       /* Hide QTYPE if minimized. */
-       if (qname != query->sname) {
-               *qtype = KNOT_RRTYPE_NS;
-       }
-
-       return qname;
-}
-
-/*! \brief Answer is paired to query. */
-static bool is_answer_to_query(const knot_pkt_t *answer, struct kr_rplan *rplan)
-{
-       struct kr_query *expect = kr_rplan_current(rplan);
-       if (expect == NULL) {
-               return -1;
-       }
-
-       uint16_t qtype = expect->stype;
-       const knot_dname_t *qname = minimized_qname(expect, &rplan->zone_cut, &qtype);
-
-       return expect->id      == knot_wire_get_id(answer->wire) &&
-              expect->sclass  == knot_pkt_qclass(answer) &&
-              qtype           == knot_pkt_qtype(answer) &&
-              knot_dname_is_equal(qname, knot_pkt_qname(answer));
-}
-
 /* State-less single resolution iteration step, not needed. */
 static int reset(knot_layer_t *ctx)  { return KNOT_NS_PROC_FULL; }
 static int finish(knot_layer_t *ctx) { return KNOT_NS_PROC_NOOP; }
@@ -286,25 +268,24 @@ static int prepare_query(knot_layer_t *ctx, knot_pkt_t *pkt)
 {
        assert(pkt && ctx);
        struct kr_layer_param *param = ctx->data;
-       struct kr_query *cur = kr_rplan_current(param->rplan);
-       if (cur == NULL || ctx->state == KNOT_NS_PROC_DONE) {
+       struct kr_query *query = kr_rplan_current(param->rplan);
+       if (query == NULL || ctx->state == KNOT_NS_PROC_DONE) {
                return ctx->state;
        }
 
        /* Minimize QNAME (if possible). */
-       struct kr_zonecut *zone_cut = &param->rplan->zone_cut;
-       uint16_t qtype = cur->stype;
-       const knot_dname_t *qname = minimized_qname(cur, zone_cut, &qtype);
+       uint16_t qtype = query->stype;
+       const knot_dname_t *qname = minimized_qname(query, &qtype);
 
        /* Form a query for the authoritative. */
        knot_pkt_clear(pkt);
-       int ret = knot_pkt_put_question(pkt, qname, cur->sclass, qtype);
+       int ret = knot_pkt_put_question(pkt, qname, query->sclass, qtype);
        if (ret != KNOT_EOK) {
                return KNOT_NS_PROC_FAIL;
        }
 
-       cur->id = knot_random_uint16_t();
-       knot_wire_set_id(pkt->wire, cur->id);
+       query->id = knot_random_uint16_t();
+       knot_wire_set_id(pkt->wire, query->id);
        
        /* Declare EDNS0 support. */
        knot_rrset_t opt_rr;
@@ -322,8 +303,8 @@ static int prepare_query(knot_layer_t *ctx, knot_pkt_t *pkt)
 
 #ifndef NDEBUG
        char name_str[KNOT_DNAME_MAXLEN], zonecut_str[KNOT_DNAME_MAXLEN], ns_str[KNOT_DNAME_MAXLEN], type_str[16];
-       knot_dname_to_str(ns_str, zone_cut->ns, sizeof(ns_str));
-       knot_dname_to_str(zonecut_str, zone_cut->name, sizeof(zonecut_str));
+       knot_dname_to_str(ns_str, query->zone_cut.ns, sizeof(ns_str));
+       knot_dname_to_str(zonecut_str, query->zone_cut.name, sizeof(zonecut_str));
        knot_dname_to_str(name_str, qname, sizeof(name_str));
        knot_rrtype_to_string(qtype, type_str, sizeof(type_str));
        DEBUG_MSG("query '%s %s' zone cut '%s' nameserver '%s'\n", name_str, type_str, zonecut_str, ns_str);
@@ -341,37 +322,30 @@ static int resolve(knot_layer_t *ctx, knot_pkt_t *pkt)
 {
        assert(pkt && ctx);
        struct kr_layer_param *param = ctx->data;
-       int state = ctx->state;
+       struct kr_query *query = kr_rplan_current(param->rplan);
+       if (query == NULL) {
+               return ctx->state;
+       }
 
        /* Check for packet processing errors first. */
        if (pkt->parsed < pkt->size) {
                return resolve_error(pkt, param, KNOT_EMALF);
-       }
-
-       /* Is this the droid we're looking for? */
-       if (!is_answer_to_query(pkt, param->rplan)) {
+       } else if (!is_paired_to_query(pkt, query)) {
                DEBUG_MSG("ignoring mismatching response\n");
                return KNOT_NS_PROC_MORE;
-       }
-       
-       /* Truncated response. */
-       if (knot_wire_get_tc(pkt->wire)) {
+       } else if (knot_wire_get_tc(pkt->wire)) {
                DEBUG_MSG("truncated response, failover to TCP\n");
                struct kr_query *cur = kr_rplan_current(param->rplan);
                if (cur) {
+                       /* Fail if already on TCP. */
+                       if (cur->flags & QUERY_TCP) {
+                               return resolve_error(pkt, param, KNOT_EMALF);
+                       }
                        cur->flags |= QUERY_TCP;
                }
                return KNOT_NS_PROC_DONE;
        }
 
-       /* TODO: classify response type
-        * 1. authoritative, noerror/nxdomain
-        *     cname chain => update current sname
-        *     qname is current ns => update ns address
-        *     qname is tail => original query
-        * 2. referral, update current zone cut
-        */
-
        /* Check response code. */
        switch(knot_wire_get_rcode(pkt->wire)) {
        case KNOT_RCODE_NOERROR:
@@ -381,11 +355,18 @@ static int resolve(knot_layer_t *ctx, knot_pkt_t *pkt)
                return resolve_error(pkt, param, KNOT_ERROR);
        }
 
-       /* Is the answer authoritative? */
-       if (knot_wire_get_aa(pkt->wire)) {
-               state = resolve_auth(pkt, param);
-       } else {
-               state = resolve_referral(pkt, param);
+       /* Resolve authority to see if it's referral or authoritative. */
+       int state = KNOT_NS_PROC_MORE;
+       state = process_authority(pkt, param);
+       switch(state) {
+       case KNOT_NS_PROC_MORE: /* Not referral, process answer. */
+               state = process_answer(pkt, param);
+               break;
+       case KNOT_NS_PROC_DONE: /* Referral, try to find glue. */
+               state = process_additional(pkt, param);
+               break;
+       default:
+               break;
        }
 
        return state;
index 07b31d7e8617de59641ef483597b4b347c4bc42c..068fdaf2d51d59f9930d464ebc71843c16b2363a 100644 (file)
@@ -100,7 +100,7 @@ static int read_cache(knot_layer_t *ctx, knot_pkt_t *pkt)
 
        /* Check if updating current zone cut. */
        if (cur != kr_rplan_last(param->rplan)) {
-               ret = read_cache_zonecut(&param->rplan->zone_cut, txn, &cache_rr, timestamp);
+               ret = read_cache_zonecut(&cur->zone_cut, txn, &cache_rr, timestamp);
                if (ret == KNOT_EOK) {
                        kr_rplan_pop(param->rplan, cur);
                        return KNOT_NS_PROC_DONE;
index 97316cf22300120b09d4d256a267b8922a0bba27..e13f10a2a0fb5c2dc201956b6cee2b3aec9ad44d 100755 (executable)
@@ -35,7 +35,7 @@
 #define ITER_LIMIT 50
 
 /*! \brief Invalidate current NS in cache. */
-static int invalidate_ns(struct kr_rplan *rplan, const struct kr_query *qry)
+static int invalidate_ns(struct kr_rplan *rplan, struct kr_query *qry)
 {
        namedb_txn_t *txn = kr_rplan_txn_acquire(rplan, 0);
        if (txn == NULL) {
@@ -44,11 +44,11 @@ static int invalidate_ns(struct kr_rplan *rplan, const struct kr_query *qry)
 
        /* TODO: selective removal */
        knot_rrset_t removed_rr;
-       knot_rrset_init(&removed_rr, rplan->zone_cut.name, KNOT_RRTYPE_NS, KNOT_CLASS_IN);
+       knot_rrset_init(&removed_rr, qry->zone_cut.name, KNOT_RRTYPE_NS, KNOT_CLASS_IN);
        (void) kr_cache_remove(txn, &removed_rr);
 
        /* Find new zone cut / nameserver */
-       kr_find_zone_cut(&rplan->zone_cut, qry->sname, txn, qry->timestamp.tv_sec);
+       kr_find_zone_cut(&qry->zone_cut, qry->sname, txn, qry->timestamp.tv_sec);
 
        /* Continue with querying */
        return KNOT_EOK;
@@ -62,13 +62,13 @@ static int iterate(struct knot_requestor *requestor, struct kr_layer_param *para
        struct kr_query *cur = kr_rplan_current(rplan);
 
        /* Invalid address for current zone cut. */
-       if (sockaddr_len((struct sockaddr *)&rplan->zone_cut.addr) < 1) {
+       if (sockaddr_len((struct sockaddr *)&cur->zone_cut.addr) < 1) {
                return invalidate_ns(rplan, cur);
        }
 
        /* Prepare query resolution. */
        int mode = (cur->flags & QUERY_TCP) ? 0 : KNOT_RQ_UDP;
-       struct sockaddr *ns_addr = (struct sockaddr *)&rplan->zone_cut.addr;
+       struct sockaddr *ns_addr = (struct sockaddr *)&cur->zone_cut.addr;
        knot_pkt_t *query = knot_pkt_new(NULL, KNOT_WIRE_MAX_PKTSIZE, requestor->mm);
        struct knot_request *tx = knot_request_make(requestor->mm, ns_addr, NULL, query, mode);
        knot_requestor_enqueue(requestor, tx);
@@ -104,7 +104,7 @@ int kr_resolve(struct kr_context* ctx, knot_pkt_t *answer,
        /* Push query to resolve plan and set initial zone cut. */
        struct kr_query *qry = kr_rplan_push(&rplan, qname, qclass, qtype);
        namedb_txn_t *txn = kr_rplan_txn_acquire(&rplan, NAMEDB_RDONLY);
-       kr_find_zone_cut(&rplan.zone_cut, qname, txn, qry->timestamp.tv_sec);
+       kr_find_zone_cut(&qry->zone_cut, qname, txn, qry->timestamp.tv_sec);
 
        struct kr_layer_param param;
        param.ctx = ctx;
index c253a73ad7fd5a5439a11e3f3de0a64ef78cc142..56c2c5187ec72a3a7f0e4f46bfb33ece444e9c3a 100644 (file)
@@ -54,7 +54,6 @@ void kr_rplan_init(struct kr_rplan *rplan, struct kr_context *context, mm_ctx_t
 {
        memset(rplan, 0, sizeof(struct kr_rplan));
 
-       rplan->state = KNOT_NS_PROC_MORE;
        rplan->pool = pool;
        rplan->context = context;
        init_list(&rplan->pending);
index cf87e862f578bd59e7b21715d77cb5db77458cd8..c4ebdded4bde4dea9e5387f3e9619738e7d838b5 100644 (file)
@@ -35,6 +35,7 @@ enum {
  */
 struct kr_query {
        node_t node;
+       struct kr_zonecut zone_cut;
        struct timeval timestamp;
        knot_dname_t *sname;
        uint16_t stype;
@@ -51,8 +52,6 @@ struct kr_query {
  * It also keeps a notion of current zone cut.
  */
 struct kr_rplan {
-       unsigned state;              /*!< Query resolution state. */
-       struct kr_zonecut zone_cut;
        unsigned txn_flags;          /*!< Current transaction flags. */
        namedb_txn_t txn;            /*!< Current transaction (may be r/o). */
        list_t pending;              /*!< List of pending queries. */