]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
.
authorVladimír Čunát <vladimir.cunat@nic.cz>
Mon, 16 Oct 2017 14:16:14 +0000 (16:16 +0200)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Mon, 16 Oct 2017 14:16:14 +0000 (16:16 +0200)
lib/cache.c
lib/layer/iterate.c
lib/resolve.c
lib/resolve.h

index c4006269cffb500244e2669ab033f7534f2025a0..3a64a8ad17a78409c136d7b12f694ecfffb04c15 100644 (file)
@@ -849,6 +849,7 @@ int cache_lmdb_peek(kr_layer_t *ctx, knot_pkt_t *pkt)
        /** 1b. otherwise, find the longest prefix NS/xNAME (with OK time+rank). [...] */
        k->dname = qry->sname;
        const struct entry_h *eh = closest_NS(ctx, k);
+#if 0
        if (!eh) { /* fall back to root hints? */
                ret = kr_zonecut_set_sbelt(req->ctx, &qry->zone_cut);
                if (ret) return KR_STATE_FAIL;
@@ -858,6 +859,7 @@ int cache_lmdb_peek(kr_layer_t *ctx, knot_pkt_t *pkt)
                //qry->flags.AWAIT_CUT = false;
                return ctx->state;
        }
+#endif
        switch (k->type) {
        // FIXME xNAME: return/generate whatever is required
        case KNOT_RRTYPE_NS:
@@ -867,12 +869,14 @@ int cache_lmdb_peek(kr_layer_t *ctx, knot_pkt_t *pkt)
                return ctx->state;
        }
 
+#if 0
        /* Now `eh` points to the closest NS record that we've found,
         * and that's the only place to start - we may either find
         * a negative proof or we may query upstream from that point. */
        kr_zonecut_set(&qry->zone_cut, k->dname);
        ret = kr_make_query(qry, pkt); // FIXME: probably not yet - qname minimization
        if (ret) return KR_STATE_FAIL;
+#endif
 
 
        /* Note: up to here we can run on any cache backend,
@@ -959,9 +963,9 @@ int cache_lmdb_stash(kr_layer_t *ctx, knot_pkt_t *pkt)
         */
 
        const uint32_t min_ttl = MAX(DEFAULT_MINTTL, req->ctx->cache.ttl_min);
+       ranked_rr_array_t *selected[] = kr_request_selected(req);
        for (int psec = KNOT_ANSWER; psec <= KNOT_AUTHORITY; ++psec) {
-               const ranked_rr_array_t *arr = psec == KNOT_ANSWER
-                       ? &req->answ_selected : &req->auth_selected;
+               const ranked_rr_array_t *arr = selected[psec];
                /* uncached entries are located at the end */
                for (ssize_t i = arr->len - 1; i >= 0; --i) {
                        ranked_rr_array_entry_t *entry = arr->at[i];
@@ -1217,8 +1221,16 @@ int kr_cache_peek_exact(struct kr_cache *cache, const knot_dname_t *name, uint16
                        struct kr_cache_p *peek)
 {
        struct key k_storage, *k = &k_storage;
+
+       WITH_VERBOSE {
+               VERBOSE_MSG(NULL, "_peek_exact: ");
+               kr_rrtype_print(type, "", " ");
+               kr_dname_print(name, "", " ");
+       }
+
        int ret = knot_dname_lf(k->buf, name, NULL);
        if (ret) {
+               kr_log_verbose("ERROR!\n");
                return KR_STATE_FAIL;
        }
        k->name_len = k->buf[0];
@@ -1232,10 +1244,12 @@ int kr_cache_peek_exact(struct kr_cache *cache, const knot_dname_t *name, uint16
        knot_db_val_t val = { };
        ret = cache_op(cache, read, &key, &val, 1);
        if (ret) {
+               kr_log_verbose("miss\n");
                return ret;
        }
        const struct entry_h *eh = entry_h_consistent(val, ktype);
        if (!eh || (type == KNOT_RRTYPE_NS && !eh->has_ns)) {
+               kr_log_verbose("miss\n");
                return kr_error(ENOENT);
        }
        *peek = (struct kr_cache_p){
@@ -1245,6 +1259,7 @@ int kr_cache_peek_exact(struct kr_cache *cache, const knot_dname_t *name, uint16
                .data = val.data,
                .data_bound = val.data + val.len,
        };
+       kr_log_verbose("hit\n");
        return kr_ok();
 }
 
@@ -1275,11 +1290,12 @@ static const struct entry_h *closest_NS(kr_layer_t *ctx, struct key *k)
                        if (new_ttl < 0) break;
                        // FIXME: xNAME
                        //uint16_t ktype = exact_match ? KNOT_RRTYPE_CNAME : KNOT_RRTYPE_DNAME;
-                       if (eh->has_ns && !eh->is_negative) {
-                               /* any kr_rank is accepted, as insecure or even nonauth is OK */
-                               k->type = KNOT_RRTYPE_NS;
-                               return eh;
+                       if (!eh->has_ns || eh->is_negative) {
+                               break;
                        }
+                       /* any kr_rank is accepted, as insecure or even nonauth is OK */
+                       k->type = KNOT_RRTYPE_NS;
+                       return eh;
                        }
                case (-abs(ENOENT)):
                        break;
index 52e0cec90daa261b035d224667b92af16438c41a..bf1208cc9da397c84b8e95d6df03189217a91b2a 100644 (file)
@@ -178,8 +178,10 @@ static int update_nsaddr(const knot_rrset_t *rr, struct kr_query *query)
 }
 
 /** @internal From \a pkt, fetch glue records for name \a ns, and update the cut etc. */
-static void fetch_glue(knot_pkt_t *pkt, const knot_dname_t *ns, struct kr_request *req)
+static void fetch_glue(knot_pkt_t *pkt, const knot_dname_t *ns, bool in_bailiwick,
+                       struct kr_request *req, const struct kr_query *qry)
 {
+       ranked_rr_array_t *selected[] = kr_request_selected(req);
        for (knot_section_t i = KNOT_ANSWER; i <= KNOT_ADDITIONAL; ++i) {
                const knot_pktsection_t *sec = knot_pkt_section(pkt, i);
                for (unsigned k = 0; k < sec->count; ++k) {
@@ -191,6 +193,12 @@ static void fetch_glue(knot_pkt_t *pkt, const knot_dname_t *ns, struct kr_reques
                            (rr->type != KNOT_RRTYPE_AAAA)) {
                                continue;
                        }
+
+                       uint8_t rank = (in_bailiwick && i == KNOT_ANSWER)
+                               ? (KR_RANK_INITIAL | KR_RANK_AUTH) : KR_RANK_OMIT;
+                       (void) kr_ranked_rrarray_add(selected[i], rr, rank,
+                                                       false, qry->uid, &req->pool);
+
                        if ((rr->type == KNOT_RRTYPE_A) &&
                            (req->ctx->options.NO_IPV4)) {
                                continue;
@@ -205,7 +213,7 @@ static void fetch_glue(knot_pkt_t *pkt, const knot_dname_t *ns, struct kr_reques
 }
 
 /** Attempt to find glue for given nameserver name (best effort). */
-static int has_glue(knot_pkt_t *pkt, const knot_dname_t *ns)
+static bool has_glue(knot_pkt_t *pkt, const knot_dname_t *ns)
 {
        for (knot_section_t i = KNOT_ANSWER; i <= KNOT_ADDITIONAL; ++i) {
                const knot_pktsection_t *sec = knot_pkt_section(pkt, i);
@@ -213,11 +221,11 @@ static int has_glue(knot_pkt_t *pkt, const knot_dname_t *ns)
                        const knot_rrset_t *rr = knot_pkt_rr(sec, k);
                        if (knot_dname_is_equal(ns, rr->owner) &&
                            (rr->type == KNOT_RRTYPE_A || rr->type == KNOT_RRTYPE_AAAA)) {
-                               return 1;
+                               return true;
                        }
                }
        }
-       return 0;
+       return false;
 }
 
 /** @internal Update the cut with another NS(+glue) record.
@@ -267,24 +275,31 @@ static int update_cut(knot_pkt_t *pkt, const knot_rrset_t *rr,
        /* Fetch glue for each NS */
        for (unsigned i = 0; i < rr->rrs.rr_count; ++i) {
                const knot_dname_t *ns_name = knot_ns_name(&rr->rrs, i);
-               int glue_records = has_glue(pkt, ns_name);
                /* Glue is mandatory for NS below zone */
-               if (!glue_records && knot_dname_in(rr->owner, ns_name)) {
-                       VERBOSE_MSG("<= authority: missing mandatory glue, rejecting\n");
+               if (knot_dname_in(rr->owner, ns_name) && !has_glue(pkt, ns_name)) {
+                       VERBOSE_MSG("<= authority: missing mandatory glue, skipping NS ");
+                       WITH_VERBOSE {
+                               kr_dname_print(ns_name, "", "\n");
+                       }
                        continue;
                }
-               kr_zonecut_add(cut, ns_name, NULL);
+               int ret = kr_zonecut_add(cut, ns_name, NULL);
+               assert(!ret);
+
                /* Choose when to use glue records. */
+               bool in_bailiwick = knot_dname_in(current_cut, ns_name);
+               bool do_fetch;
                if (qry->flags.PERMISSIVE) {
-                       fetch_glue(pkt, ns_name, req);
+                       do_fetch = true;
                } else if (qry->flags.STRICT) {
                        /* Strict mode uses only mandatory glue. */
-                       if (knot_dname_in(cut->name, ns_name))
-                               fetch_glue(pkt, ns_name, req);
+                       do_fetch = knot_dname_in(cut->name, ns_name);
                } else {
                        /* Normal mode uses in-bailiwick glue. */
-                       if (knot_dname_in(current_cut, ns_name))
-                               fetch_glue(pkt, ns_name, req);
+                       do_fetch = in_bailiwick;
+               }
+               if (do_fetch) {
+                       fetch_glue(pkt, ns_name, in_bailiwick, req, qry);
                }
        }
 
index 1a506fa79466b2d5173aedab166a51e5773f81bd..ced2cd15020cf297139afe344e2e16338ec56b9e 100644 (file)
@@ -718,6 +718,7 @@ int kr_resolve_begin(struct kr_request *request, struct kr_context *ctx, knot_pk
        array_init(request->additional);
        array_init(request->answ_selected);
        array_init(request->auth_selected);
+       array_init(request->add_selected);
        request->answ_validated = false;
        request->auth_validated = false;
 
@@ -1419,7 +1420,11 @@ ns_election:
                }
                kr_nsrep_elect(qry, request->ctx);
                if (qry->ns.score > KR_NS_MAX_SCORE) {
-                       VERBOSE_MSG(qry, "=> no valid NS left\n");
+                       if (!qry->zone_cut.nsset.root) {
+                               VERBOSE_MSG(qry, "=> no NS with an address\n");
+                       } else {
+                               VERBOSE_MSG(qry, "=> no valid NS left\n");
+                       }
                        ITERATE_LAYERS(request, qry, reset);
                        kr_rplan_pop(rplan, qry);
                        return KR_STATE_PRODUCE;
index 43b5f9f3d46775c5d5cf66df651968d6f47677d4..69624c04f2be1c4caa8ac4bb1e8225997c81e058 100644 (file)
@@ -194,6 +194,7 @@ struct kr_request {
        int state;
        ranked_rr_array_t answ_selected;
        ranked_rr_array_t auth_selected;
+       ranked_rr_array_t add_selected;
        rr_array_t additional;
        bool answ_validated; /**< internal to validator; beware of caching, etc. */
        bool auth_validated; /**< see answ_validated ^^ ; TODO */
@@ -202,6 +203,13 @@ struct kr_request {
        knot_mm_t pool;
 };
 
+/** Initializer for an array of *_selected. */
+#define kr_request_selected(req) { \
+       [KNOT_ANSWER] = &(req)->answ_selected, \
+       [KNOT_AUTHORITY] = &(req)->auth_selected, \
+       [KNOT_ADDITIONAL] = &(req)->add_selected, \
+       }
+
 /**
  * Begin name resolution.
  *