]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
lib: stub NS reputation scoring, use glue presence as score for iter
authorMarek Vavruša <marek.vavrusa@nic.cz>
Sun, 15 Feb 2015 22:25:11 +0000 (23:25 +0100)
committerMarek Vavruša <marek.vavrusa@nic.cz>
Sun, 15 Feb 2015 22:25:11 +0000 (23:25 +0100)
lib/layer/iterate.c
lib/layer/iterate.h
lib/libkresolve.mk
lib/nsrep.c [new file with mode: 0644]
lib/nsrep.h [new file with mode: 0644]
lib/resolve.c
tests/pydnstest/scenario.py
tests/testdata/iter_minim_ns.rpl

index a15c3292ecbafa977309a6a877188c8fd21239a9..efeb1eec74ffbe506c2320b3b0de61d7d61da04a 100644 (file)
@@ -25,6 +25,7 @@
 #include "lib/resolve.h"
 #include "lib/rplan.h"
 #include "lib/defines.h"
+#include "lib/nsrep.h"
 
 #define DEBUG_MSG(fmt...) QRDEBUG(kr_rplan_current(param->rplan), "iter", fmt)
 
@@ -150,41 +151,78 @@ int rr_update_answer(const knot_rrset_t *rr, unsigned hint, struct kr_layer_para
        return KNOT_NS_PROC_DONE;
 }
 
-int rr_update_nameserver(const knot_rrset_t *rr, unsigned hint, struct kr_layer_param *param)
+static bool has_glue(const knot_dname_t *ns_name, knot_pkt_t *pkt)
+{
+       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 == KNOT_RRTYPE_A || rr->type == KNOT_RRTYPE_AAAA) &&
+                  (knot_dname_is_equal(ns_name, rr->owner))) {
+                       return true;
+               }
+       }
+       return false;
+}
+
+static int nameserver_score(const knot_rrset_t *rr, unsigned hint, knot_pkt_t *pkt, struct kr_layer_param *param)
 {
        struct kr_query *query = kr_rplan_current(param->rplan);
        const knot_dname_t *ns_name = knot_ns_name(&rr->rrs, hint);
+       int score = KR_NS_VALID + 1;
 
        /* 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 KR_NS_INVALID;
        }
 
        /* Ignore already resolved zone cut. */
        if (knot_dname_is_equal(rr->owner, query->zone_cut.name)) {
-               return KNOT_NS_PROC_MORE;
+               return KR_NS_VALID;
        }
 
-       /* Set zone cut to given name server. */
-       kr_set_zone_cut(&query->zone_cut, rr->owner, ns_name);
-       return KNOT_NS_PROC_DONE;
+       /* Check if contains glue. */
+       if (has_glue(ns_name, pkt)) {
+               score += 1;
+       }
+
+       return score;
 }
 
 static int process_authority(knot_pkt_t *pkt, struct kr_layer_param *param)
 {
+       struct kr_query *query = kr_rplan_current(param->rplan);
+       const knot_rrset_t *best_ns = NULL;
+       int best_score = 0;
+
+       /* AA, terminate resolution chain. */
+       if (knot_wire_get_aa(pkt->wire)) {
+               return KNOT_NS_PROC_MORE;
+       }
+
+       /* Elect best name server candidate. */
        const knot_pktsection_t *ns = knot_pkt_section(pkt, KNOT_AUTHORITY);
        for (unsigned i = 0; i < ns->count; ++i) {
                const knot_rrset_t *rr = knot_pkt_rr(ns, i);
                if (rr->type == KNOT_RRTYPE_NS) {
-                       int state = rr_update_nameserver(rr, 0, param);
-                       if (state != KNOT_NS_PROC_MORE) {
-                               return state;
+                       int score = nameserver_score(rr, 0, pkt, param);
+                       if (score < 0) {
+                               return KNOT_NS_PROC_FAIL;
+                       }
+                       if (score > best_score) {
+                               best_ns = rr;
+                               best_score = score;
                        }
                }
        }
 
+       /* Update name server candidate. */
+       if (best_ns != NULL) {
+               kr_set_zone_cut(&query->zone_cut, best_ns->owner, knot_ns_name(&best_ns->rrs, 0));
+               return KNOT_NS_PROC_DONE;
+       }
+
        return KNOT_NS_PROC_MORE;
 }
 
@@ -202,10 +240,6 @@ static int process_additional(knot_pkt_t *pkt, struct kr_layer_param *param)
                }
        }
 
-       /* Glue not found => resolve NS address. */
-       (void) kr_rplan_push(param->rplan, query, query->zone_cut.ns, KNOT_CLASS_IN, KNOT_RRTYPE_AAAA);
-       (void) kr_rplan_push(param->rplan, query, query->zone_cut.ns, KNOT_CLASS_IN, KNOT_RRTYPE_A);
-
        return KNOT_NS_PROC_DONE;
 }
 
index f9338c73196dcf506b2986742cfe1df0b4686193..a5821ac9bc7bd51f88a7d7fbe450d58019e0cdd4 100644 (file)
@@ -33,9 +33,3 @@ int rr_update_parent(const knot_rrset_t *rr, unsigned hint, struct kr_layer_para
  * \note When \a hint is KNOT_PF_FREE, RR is treated as a copy and answer takes its ownership.
  */
 int rr_update_answer(const knot_rrset_t *rr, unsigned hint, struct kr_layer_param *param);
-
-/*!
- * \brief Result updates current nameserver.
- * \note Hint is an index of chosen RR in the set.
- */
-int rr_update_nameserver(const knot_rrset_t *rr, unsigned hint, struct kr_layer_param *param);
index 09a1badb4ff040e9e34c579bed71cf93c6e2b1f5..9dddbb69b519d0332592a141d0c5075795a8de58 100644 (file)
@@ -3,6 +3,7 @@ libkresolve_SOURCES := \
        lib/layer/itercache.c  \
        lib/layer/static.c     \
        lib/layer/stats.c      \
+       lib/nsrep.c            \
        lib/context.c          \
        lib/resolve.c          \
        lib/zonecut.c          \
@@ -15,6 +16,7 @@ libkresolve_HEADERS := \
        lib/layer/static.h     \
        lib/layer/stats.h      \
        lib/layer.h            \
+       lib/nsrep.h            \
        lib/context.h          \
        lib/resolve.h          \
        lib/zonecut.h          \
diff --git a/lib/nsrep.c b/lib/nsrep.c
new file mode 100644 (file)
index 0000000..bc19c28
--- /dev/null
@@ -0,0 +1,7 @@
+#include "lib/nsrep.h"
+
+int kr_nsrep_score(const knot_dname_t *ns, struct kr_layer_param *param)
+{
+       /* TODO: stub, always returns valid */
+       return KR_NS_VALID;
+}
\ No newline at end of file
diff --git a/lib/nsrep.h b/lib/nsrep.h
new file mode 100644 (file)
index 0000000..b92eda5
--- /dev/null
@@ -0,0 +1,31 @@
+/*  Copyright (C) 2014 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "lib/layer.h"
+
+enum kr_ns_score {
+    KR_NS_INVALID = 1,
+    KR_NS_VALID   = 0
+};
+
+/*! \brief Return name server score (KR_NS_VALID is baseline, the higher the better).
+ * \param ns evaluated NS name
+ * \param param layer parameters
+ * \return enum kr_ns_score or higher positive value
+ */
+int kr_nsrep_score(const knot_dname_t *ns, struct kr_layer_param *param);
\ No newline at end of file
index 1ba465a50dea2579e6f549e555d30bd49078171c..b936185bc51b56d3a2fb5f426a2b365f69d4aed3 100755 (executable)
@@ -18,6 +18,7 @@
 
 #include <libknot/internal/mempool.h>
 #include <libknot/processing/requestor.h>
+#include <libknot/rrtype/rdname.h>
 #include <libknot/descriptor.h>
 #include <dnssec/random.h>
 
@@ -66,13 +67,15 @@ static int invalidate_ns(struct kr_rplan *rplan, struct kr_query *qry)
        /* Remove record(s) */
        if (cached.rrs.rr_count == 0) {
                (void) kr_cache_remove(txn, &cached);
+               kr_find_zone_cut(&qry->zone_cut, qry->sname, txn, qry->timestamp.tv_sec);
        } else {
                (void) kr_cache_insert(txn, &cached, qry->timestamp.tv_sec);
+               kr_set_zone_cut(&qry->zone_cut, cached.owner, knot_ns_name(&cached.rrs, 0));
        }
        knot_rrset_clear(&cached, rplan->pool);
 
        /* Update zone cut and continue. */
-       return kr_find_zone_cut(&qry->zone_cut, qry->sname, txn, qry->timestamp.tv_sec);
+       return KNOT_EOK;
 }
 
 static int iterate(struct knot_requestor *requestor, struct kr_layer_param *param)
@@ -91,8 +94,10 @@ static int iterate(struct knot_requestor *requestor, struct kr_layer_param *para
 
        /* Invalid address for current zone cut. */
        if (sockaddr_len((struct sockaddr *)&cur->zone_cut.addr) < 1) {
-               DEBUG_MSG("=> ns missing A/AAAA, invalidating\n");
-               return invalidate_ns(rplan, cur);
+               DEBUG_MSG("=> ns missing A/AAAA, fetching\n");
+               (void) kr_rplan_push(rplan, cur, cur->zone_cut.ns, KNOT_CLASS_IN, KNOT_RRTYPE_AAAA);
+               (void) kr_rplan_push(rplan, cur, cur->zone_cut.ns, KNOT_CLASS_IN, KNOT_RRTYPE_A);
+               return KNOT_EOK;
        }
 
        /* Prepare query resolution. */
index 5d1d89f95ce0d42f739e8d01367a4c7221515e54..6170724e133219dd2143faa46297f545f89cf7eb 100644 (file)
@@ -28,10 +28,16 @@ class Entry:
         if code == 'opcode':
             return self.__compare_val(expected.opcode(), msg.opcode())
         elif code == 'qtype':
+            if len(expected.question) == 0:
+                return True
             return self.__compare_val(expected.question[0].rdtype, msg.question[0].rdtype)
         elif code == 'qname':
+            if len(expected.question) == 0:
+                return True
             return self.__compare_val(expected.question[0].name, msg.question[0].name)
         elif code == 'subdomain':
+            if len(expected.question) == 0:
+                return True
             return self.__compare_sub(expected.question[0].name, msg.question[0].name)
         elif code == 'flags':
             return self.__compare_val(dns.flags.to_text(expected.flags), dns.flags.to_text(msg.flags))
index 34da53be6ab0bd5439cbc22fe636033eea7de668..da704dd4c5ecd0ddc615c3a34d342bce89c62c49 100644 (file)
@@ -25,6 +25,34 @@ SECTION ADDITIONAL
 K.ROOT-SERVERS.NET.    IN      A       193.0.14.129
 ENTRY_END
 
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS     K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET.    IN      A       193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN NS
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+ENTRY_END
+
 ENTRY_BEGIN
 MATCH opcode qtype qname
 ADJUST copy_id