]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
lib: cleanup of zone cut resolution code
authorMarek Vavruša <marek.vavrusa@nic.cz>
Fri, 18 Sep 2015 20:11:33 +0000 (22:11 +0200)
committerMarek Vavruša <marek.vavrusa@nic.cz>
Fri, 18 Sep 2015 20:11:33 +0000 (22:11 +0200)
lib/resolve.c

index f7f6f0aa86ae8a359996644ac3f74043ee211109..ae623568de2947767b15208390abad847d4369b1 100644 (file)
@@ -322,46 +322,36 @@ int kr_resolve_consume(struct kr_request *request, knot_pkt_t *packet)
        return kr_rplan_empty(&request->rplan) ? KNOT_STATE_DONE : KNOT_STATE_PRODUCE;
 }
 
-int kr_resolve_produce(struct kr_request *request, struct sockaddr **dst, int *type, knot_pkt_t *packet)
+/** @internal Spawn subrequest in current zone cut (no minimization or lookup). */
+static int zone_cut_subreq(struct kr_rplan *rplan, struct kr_query *parent,
+                           const knot_dname_t *qname, uint16_t qtype)
 {
-       struct kr_rplan *rplan = &request->rplan;
-       struct kr_query *qry = kr_rplan_current(rplan);
-       unsigned ns_election_iter = 0;
-       
-       /* No query left for resolution */
-       if (kr_rplan_empty(rplan)) {
-               return KNOT_STATE_FAIL;
-       }
-
-       /* Resolve current query and produce dependent or finish */
-       ITERATE_LAYERS(request, produce, packet);
-       if (request->state != KNOT_STATE_FAIL && knot_wire_get_qr(packet->wire)) {
-               /* Produced an answer, consume it. */
-               qry->secret = 0;
-               request->state = KNOT_STATE_CONSUME;
-               ITERATE_LAYERS(request, consume, packet);
+       struct kr_query *next = kr_rplan_push(rplan, parent, qname, parent->sclass, qtype);
+       if (!next) {
+               return kr_error(ENOMEM);
        }
-       switch(request->state) {
-       case KNOT_STATE_FAIL: return request->state; break;
-       case KNOT_STATE_CONSUME: break;
-       case KNOT_STATE_DONE:
-       default: /* Current query is done */
-               if (qry->flags & QUERY_RESOLVED) {
-                       kr_rplan_pop(rplan, qry);
-               }
-               ITERATE_LAYERS(request, reset);
-               return kr_rplan_empty(rplan) ? KNOT_STATE_DONE : KNOT_STATE_PRODUCE;
+       kr_zonecut_set(&next->zone_cut, parent->zone_cut.name);
+       if (kr_zonecut_copy(&next->zone_cut, &parent->zone_cut) != 0 ||
+           kr_zonecut_copy_trust(&next->zone_cut, &parent->zone_cut) != 0) {
+               return kr_error(ENOMEM);
        }
+       next->flags |= QUERY_NO_MINIMIZE;
+       return kr_ok();
+}
 
-       /* The query wasn't resolved from cache,
-        * now it's the time to look up closest zone cut from cache.
-        */
-        /* Always try with DNSSEC if it finds island of trust. */
-        /* @todo this interface is going to change */
-       if (kr_ta_contains(&global_trust_anchors, qry->zone_cut.name)) {
+/** @internal Check current zone cut status and credibility, spawn subrequests if needed. */
+static int zone_cut_check(struct kr_request *request, struct kr_query *qry, knot_pkt_t *packet)
+{
+       struct kr_rplan *rplan = &request->rplan;
+
+       /* Always try with DNSSEC if it finds an island of trust. */
+       if (!(request->options & QUERY_DNSSEC_WANT) &&
+           kr_ta_contains(&global_trust_anchors, qry->zone_cut.name)) {
                request->options |= QUERY_DNSSEC_WANT;
                DEBUG_MSG(">< entered island of trust\n");
        }
+       /* The query wasn't resolved from cache,
+        * now it's the time to look up closest zone cut from cache. */
        bool want_secured = (request->options & QUERY_DNSSEC_WANT);
        if (qry->flags & QUERY_AWAIT_CUT) {
                int ret = ns_fetch_cut(qry, request, want_secured);
@@ -377,18 +367,9 @@ int kr_resolve_produce(struct kr_request *request, struct sockaddr **dst, int *t
                qry->flags &= ~QUERY_AWAIT_CUT;
        }
 
-       /* fetch missing DS record. */
+       /* Missing delegation signature, fetch it first. */
        if ((qry->flags & QUERY_AWAIT_DS) && (qry->zone_cut.missing_name)) {
-               struct kr_query *next = kr_rplan_push(rplan, qry, qry->zone_cut.missing_name, KNOT_CLASS_IN, KNOT_RRTYPE_DS);
-               if (!next) {
-                       return KNOT_STATE_FAIL;
-               }
-               kr_zonecut_set(&next->zone_cut, qry->zone_cut.parent_name);
-               int ret = kr_zonecut_copy(&next->zone_cut, &qry->zone_cut);
-               if (ret != 0) {
-                       return KNOT_STATE_FAIL;
-               }
-               ret = kr_zonecut_copy_trust(&next->zone_cut, &qry->zone_cut);
+               int ret = zone_cut_subreq(rplan, qry, qry->zone_cut.missing_name, KNOT_RRTYPE_DS);
                if (ret != 0) {
                        return KNOT_STATE_FAIL;
                }
@@ -396,33 +377,67 @@ int kr_resolve_produce(struct kr_request *request, struct sockaddr **dst, int *t
                knot_rrset_free(&qry->zone_cut.key, qry->zone_cut.pool);
                knot_rrset_free(&qry->zone_cut.trust_anchor, qry->zone_cut.pool);
                qry->flags &= ~QUERY_AWAIT_DS;
-               return KNOT_STATE_PRODUCE;
+               return KNOT_STATE_DONE;
        }
 
        /* Try to fetch missing DNSKEY. */
        if (want_secured && !qry->zone_cut.key && qry->stype != KNOT_RRTYPE_DNSKEY) {
-               struct kr_query *next = kr_rplan_push(rplan, qry, qry->zone_cut.name, KNOT_CLASS_IN, KNOT_RRTYPE_DNSKEY);
-               if (!next) {
-                       return KNOT_STATE_FAIL;
-               }
-               kr_zonecut_set(&next->zone_cut, qry->zone_cut.name);
-               int ret = kr_zonecut_copy(&next->zone_cut, &qry->zone_cut);
+               int ret = zone_cut_subreq(rplan, qry, qry->zone_cut.name, KNOT_RRTYPE_DNSKEY);
                if (ret != 0) {
                        return KNOT_STATE_FAIL;
                }
-               ret = kr_zonecut_copy_trust(&next->zone_cut, &qry->zone_cut);
-               if (ret != 0) {
-                       return KNOT_STATE_FAIL;
+               return KNOT_STATE_DONE;
+       }
+
+       return KNOT_STATE_PRODUCE;      
+}
+
+int kr_resolve_produce(struct kr_request *request, struct sockaddr **dst, int *type, knot_pkt_t *packet)
+{
+       struct kr_rplan *rplan = &request->rplan;
+       struct kr_query *qry = kr_rplan_current(rplan);
+       unsigned ns_election_iter = 0;
+       
+       /* No query left for resolution */
+       if (kr_rplan_empty(rplan)) {
+               return KNOT_STATE_FAIL;
+       }
+
+       /* Resolve current query and produce dependent or finish */
+       ITERATE_LAYERS(request, produce, packet);
+       if (request->state != KNOT_STATE_FAIL && knot_wire_get_qr(packet->wire)) {
+               /* Produced an answer, consume it. */
+               qry->secret = 0;
+               request->state = KNOT_STATE_CONSUME;
+               ITERATE_LAYERS(request, consume, packet);
+       }
+       switch(request->state) {
+       case KNOT_STATE_FAIL: return request->state;
+       case KNOT_STATE_CONSUME: break;
+       case KNOT_STATE_DONE:
+       default: /* Current query is done */
+               if (qry->flags & QUERY_RESOLVED) {
+                       kr_rplan_pop(rplan, qry);
                }
-               return KNOT_STATE_PRODUCE;
+               ITERATE_LAYERS(request, reset);
+               return kr_rplan_empty(rplan) ? KNOT_STATE_DONE : KNOT_STATE_PRODUCE;
        }
+
+       /* Update zone cut, spawn new subrequests. */
+       int state = zone_cut_check(request, qry, packet);
+       switch(state) {
+       case KNOT_STATE_FAIL: return KNOT_STATE_FAIL;
+       case KNOT_STATE_DONE: return KNOT_STATE_PRODUCE;
+       default: break;
+       }
+
 ns_election:
 
        /* If the query has already selected a NS and is waiting for IPv4/IPv6 record,
         * elect best address only, otherwise elect a completely new NS.
         */
        if(++ns_election_iter >= KR_ITER_LIMIT) {
-               DEBUG_MSG("=> couldn't agree NS decision, report this\n");
+               DEBUG_MSG("=> couldn't converge NS selection, bail out\n");
                return KNOT_STATE_FAIL;
        }
        if (qry->flags & (QUERY_AWAIT_IPV4|QUERY_AWAIT_IPV6)) {