]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
layer/iterate: do DNS 0x20 only for outbound queries
authorMarek Vavruša <marek.vavrusa@nic.cz>
Tue, 14 Jul 2015 17:31:18 +0000 (19:31 +0200)
committerMarek Vavruša <marek.vavrusa@nic.cz>
Tue, 14 Jul 2015 17:50:13 +0000 (19:50 +0200)
no need to scramble queries satisfied from cache

lib/layer/iterate.c
lib/resolve.c

index da1b5a46f65110a32b7b325282b8d5fe390b0ac2..fb4e38c6a58b3e39a5914c6a88067bc1b680ee37 100644 (file)
@@ -14,7 +14,6 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <ctype.h>
 #include <sys/time.h>
 
 #include <libknot/descriptor.h>
@@ -57,39 +56,11 @@ static const knot_dname_t *minimized_qname(struct kr_query *query, uint16_t *qty
        return qname;
 }
 
-/* Randomize QNAME letter case.
- * This adds 32 bits of randomness at maximum, but that's more than an average domain name length.
- * https://tools.ietf.org/html/draft-vixie-dnsext-dns0x20-00
- */
-static void randomized_qname_case(knot_dname_t *qname, unsigned secret)
-{
-       unsigned k = 0;
-       while (*qname != '\0') {
-               for (unsigned i = *qname; i--;) {
-                       int chr = qname[i + 1];
-                       if (isalpha(chr)) {
-                               if (secret & (1 << k)) {
-                                       qname[i + 1] ^= 0x20;
-                               }
-                               k = (k + 1) % (sizeof(secret) * CHAR_BIT);
-                       }
-               }
-               qname = (uint8_t *)knot_wire_next_label(qname, NULL);
-       }
-}
-
 /** 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_min = minimized_qname(query, &qtype);
-
-       /* Construct expected randomized QNAME */
-       uint8_t qname[KNOT_DNAME_MAXLEN];
-       knot_dname_to_wire(qname, qname_min, sizeof(qname));
-       if (!(query->flags & (QUERY_CACHED|QUERY_SAFEMODE))) {
-               randomized_qname_case(qname, query->secret);
-       }
+       const knot_dname_t *qname = minimized_qname(query, &qtype);
 
        return query->id      == knot_wire_get_id(answer->wire) &&
               (query->sclass == KNOT_CLASS_ANY || query->sclass  == knot_pkt_qclass(answer)) &&
@@ -397,11 +368,6 @@ int kr_make_query(struct kr_query *query, knot_pkt_t *pkt)
                return ret;
        }
 
-       /* Randomize query case (if not in safemode) */
-       query->secret = (query->flags & QUERY_SAFEMODE) ? 0 : kr_rand_uint(UINT32_MAX);
-       knot_dname_t *qname_raw = (knot_dname_t *)knot_pkt_qname(pkt);
-       randomized_qname_case(qname_raw, query->secret);
-
        /* Query built, expect answer. */
        query->id = kr_rand_uint(UINT16_MAX);
        knot_wire_set_id(pkt->wire, query->id);
@@ -480,10 +446,6 @@ static int resolve(knot_layer_t *ctx, knot_pkt_t *pkt)
                return KNOT_STATE_DONE;
        }
 
-       /* Packet cleared, normalize QNAME. */
-       knot_dname_t *qname_raw = (knot_dname_t *)knot_pkt_qname(pkt);
-       knot_dname_to_lower(qname_raw);
-
        /* Check response code. */
 #ifndef NDEBUG
        lookup_table_t *rcode = lookup_by_id(knot_rcode_names, knot_wire_get_rcode(pkt->wire));
index 1e67c228237d9cf81f192c747ad0bd9f568da323..c81afd9f15c4684b10279f13903b0d5c4e5c1829 100644 (file)
@@ -14,6 +14,7 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <ctype.h>
 #include <stdio.h>
 #include <fcntl.h>
 #include <libknot/rrtype/rdname.h>
 
 #define DEBUG_MSG(fmt...) QRDEBUG(kr_rplan_current(rplan), "resl",  fmt)
 
+/* Randomize QNAME letter case.
+ * This adds 32 bits of randomness at maximum, but that's more than an average domain name length.
+ * https://tools.ietf.org/html/draft-vixie-dnsext-dns0x20-00
+ */
+static void randomized_qname_case(knot_dname_t *qname, unsigned secret)
+{
+       unsigned k = 0;
+       while (*qname != '\0') {
+               for (unsigned i = *qname; i--;) {
+                       int chr = qname[i + 1];
+                       if (isalpha(chr)) {
+                               if (secret & (1 << k)) {
+                                       qname[i + 1] ^= 0x20;
+                               }
+                               k = (k + 1) % (sizeof(secret) * CHAR_BIT);
+                       }
+               }
+               qname = (uint8_t *)knot_wire_next_label(qname, NULL);
+       }
+}
+
 /** @internal Subtract time (best effort) */
 float time_diff(struct timeval *begin, struct timeval *end)
 {
@@ -245,8 +267,13 @@ static int answer_finalize(knot_pkt_t *answer)
 
 static int query_finalize(struct kr_request *request, knot_pkt_t *pkt)
 {
-       int ret = 0;
+       /* Randomize query case (if not in safemode) */
        struct kr_query *qry = kr_rplan_current(&request->rplan);
+       qry->secret = (qry->flags & QUERY_SAFEMODE) ? 0 : kr_rand_uint(UINT32_MAX);
+       knot_dname_t *qname_raw = (knot_dname_t *)knot_pkt_qname(pkt);
+       randomized_qname_case(qname_raw, qry->secret);
+
+       int ret = 0;
        knot_pkt_begin(pkt, KNOT_ADDITIONAL);
        if (!(qry->flags & QUERY_SAFEMODE)) {
                ret = edns_create(pkt, request->answer);
@@ -379,6 +406,11 @@ int kr_resolve_consume(struct kr_request *request, knot_pkt_t *packet)
                        return KNOT_STATE_CONSUME; /* Try again */
                }
        } else {
+               /* Packet cleared, derandomize QNAME. */
+               knot_dname_t *qname_raw = (knot_dname_t *)knot_pkt_qname(packet);
+               if (qname_raw && qry->secret != 0) {
+                       randomized_qname_case(qname_raw, qry->secret);
+               }
                state = knot_overlay_consume(&request->overlay, packet);
        }
 
@@ -428,6 +460,7 @@ int kr_resolve_produce(struct kr_request *request, struct sockaddr **dst, int *t
        int state = knot_overlay_produce(&request->overlay, packet);
        if (state != KNOT_STATE_FAIL && knot_wire_get_qr(packet->wire)) {
                /* Produced an answer, consume it. */
+               qry->secret = 0;
                request->overlay.state = KNOT_STATE_CONSUME;
                state = knot_overlay_consume(&request->overlay, packet);
        }
@@ -488,6 +521,12 @@ ns_election:
                return KNOT_STATE_PRODUCE;
        }
 
+       /* Prepare additional query */
+       int ret = query_finalize(request, packet);
+       if (ret != 0) {
+               return KNOT_STATE_FAIL;
+       }
+
 #ifndef NDEBUG
        char qname_str[KNOT_DNAME_MAXLEN], zonecut_str[KNOT_DNAME_MAXLEN], ns_str[SOCKADDR_STRLEN];
        knot_dname_to_str(qname_str, knot_pkt_qname(packet), sizeof(qname_str));
@@ -497,11 +536,6 @@ ns_election:
        DEBUG_MSG("=> querying: '%s' score: %u zone cut: '%s' m12n: '%s'\n", ns_str, qry->ns.score, zonecut_str, qname_str);
 #endif
 
-       /* Prepare additional query */
-       int ret = query_finalize(request, packet);
-       if (ret != 0) {
-               return KNOT_STATE_FAIL;
-       }
        gettimeofday(&qry->timestamp, NULL);
        *dst = &qry->ns.addr.ip;
        *type = (qry->flags & QUERY_TCP) ? SOCK_STREAM : SOCK_DGRAM;