]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- Fix caps-for-id fallback, and added fallback attempt when servers
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 24 Jun 2014 08:24:28 +0000 (08:24 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 24 Jun 2014 08:24:28 +0000 (08:24 +0000)
  drop 0x20 perturbed queries.

git-svn-id: file:///svn/unbound/trunk@3146 be551aaa-1e26-0410-a405-d3ace91eadb9

13 files changed:
daemon/worker.c
doc/Changelog
iterator/iterator.c
iterator/iterator.h
libunbound/libworker.c
libunbound/worker.h
services/outside_network.c
services/outside_network.h
smallapp/worker_cb.c
testcode/fake_event.c
util/fptr_wlist.c
util/fptr_wlist.h
util/module.h

index dbdf28c543c439cac66cb29cf286d805386ddf84..4611114ea1e0f846f0cabae1d849a01c7daa99ac 100644 (file)
@@ -1293,8 +1293,8 @@ worker_delete(struct worker* worker)
 struct outbound_entry*
 worker_send_query(uint8_t* qname, size_t qnamelen, uint16_t qtype,
        uint16_t qclass, uint16_t flags, int dnssec, int want_dnssec,
-       struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
-       size_t zonelen, struct module_qstate* q)
+       int nocaps, struct sockaddr_storage* addr, socklen_t addrlen,
+       uint8_t* zone, size_t zonelen, struct module_qstate* q)
 {
        struct worker* worker = q->env->worker;
        struct outbound_entry* e = (struct outbound_entry*)regional_alloc(
@@ -1303,7 +1303,7 @@ worker_send_query(uint8_t* qname, size_t qnamelen, uint16_t qtype,
                return NULL;
        e->qstate = q;
        e->qsent = outnet_serviced_query(worker->back, qname,
-               qnamelen, qtype, qclass, flags, dnssec, want_dnssec,
+               qnamelen, qtype, qclass, flags, dnssec, want_dnssec, nocaps,
                q->env->cfg->tcp_upstream, q->env->cfg->ssl_upstream, addr,
                addrlen, zone, zonelen, worker_handle_service_reply, e,
                worker->back->udp_buff);
@@ -1350,7 +1350,7 @@ struct outbound_entry* libworker_send_query(uint8_t* ATTR_UNUSED(qname),
        size_t ATTR_UNUSED(qnamelen), uint16_t ATTR_UNUSED(qtype), 
        uint16_t ATTR_UNUSED(qclass), uint16_t ATTR_UNUSED(flags), 
        int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec),
-       struct sockaddr_storage* ATTR_UNUSED(addr), 
+       int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr), 
        socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
        size_t ATTR_UNUSED(zonelen), struct module_qstate* ATTR_UNUSED(q))
 {
index af1f79a24cb006d961f8f802832712867bc6b64f..20ca8e7a0007cc5f2470d641b5020a837f17b592 100644 (file)
@@ -1,3 +1,7 @@
+24 June 2014: Wouter
+       - Fix caps-for-id fallback, and added fallback attempt when servers
+         drop 0x20 perturbed queries.
+
 17 June 2014: Wouter
        - iana portlist updated.
 
index f240f503489ef28d3fed13e9641b6addf400c2a3..df5f645cc28c896ced40eab33016aa16f2e4415d 100644 (file)
@@ -1854,8 +1854,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
                iq->qchase.qname, iq->qchase.qname_len, 
                iq->qchase.qtype, iq->qchase.qclass, 
                iq->chase_flags | (iq->chase_to_rd?BIT_RD:0), EDNS_DO|BIT_CD, 
-               iq->dnssec_expected, &target->addr, target->addrlen,
-               iq->dp->name, iq->dp->namelen, qstate);
+               iq->dnssec_expected, iq->caps_fallback, &target->addr,
+               target->addrlen, iq->dp->name, iq->dp->namelen, qstate);
        if(!outq) {
                log_addr(VERB_DETAIL, "error sending query to auth server", 
                        &target->addr, target->addrlen);
@@ -2765,6 +2765,21 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
        iq->response = NULL;
        iq->state = QUERY_RESP_STATE;
        if(event == module_event_noreply || event == module_event_error) {
+               if(event == module_event_noreply && iq->sent_count >= 3 &&
+                       qstate->env->cfg->use_caps_bits_for_id &&
+                       !iq->caps_fallback) {
+                       /* start fallback */
+                       iq->caps_fallback = 1;
+                       iq->caps_server = 0;
+                       iq->caps_reply = NULL;
+                       iq->state = QUERYTARGETS_STATE;
+                       iq->num_current_queries--;
+                       /* need fresh attempts for the 0x20 fallback, if
+                        * that was the cause for the failure */
+                       iter_dec_attempts(iq->dp, 3);
+                       verbose(VERB_DETAIL, "Capsforid: timeouts, starting fallback");
+                       goto handle_it;
+               }
                goto handle_it;
        }
        if( (event != module_event_reply && event != module_event_capsfail)
@@ -2813,7 +2828,7 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
                log_dns_msg("incoming scrubbed packet:", &iq->response->qinfo, 
                        iq->response->rep);
        
-       if(event == module_event_capsfail) {
+       if(event == module_event_capsfail || iq->caps_fallback) {
                if(!iq->caps_fallback) {
                        /* start fallback */
                        iq->caps_fallback = 1;
@@ -2825,7 +2840,11 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
                        goto handle_it;
                } else {
                        /* check if reply is the same, otherwise, fail */
-                       if(!reply_equal(iq->response->rep, iq->caps_reply,
+                       if(!iq->caps_reply) {
+                               iq->caps_reply = iq->response->rep;
+                               iq->caps_server = -1; /*become zero at ++,
+                               so that we start the full set of trials */
+                       } else if(!reply_equal(iq->response->rep, iq->caps_reply,
                                qstate->env->scratch)) {
                                verbose(VERB_DETAIL, "Capsforid fallback: "
                                        "getting different replies, failed");
index fc3d7285ae5d7294b3429655d65001b7375682db..0b91760d4a49f7defff74f7cc1e32e51c70e9235 100644 (file)
@@ -230,7 +230,8 @@ struct iter_qstate {
        int caps_fallback;
        /** state for capsfail: current server number to try */
        size_t caps_server;
-       /** state for capsfail: stored query for comparisons */
+       /** state for capsfail: stored query for comparisons. Can be NULL if
+        * no response had been seen prior to starting the fallback. */
        struct reply_info* caps_reply;
 
        /** Current delegation message - returned for non-RD queries */
index fa5418063fe30cad0d65ac5a1fb3eaf98d3b814d..c5807f062c02c931ce288a7f8435cf196da0983e 100644 (file)
@@ -821,8 +821,9 @@ void libworker_alloc_cleanup(void* arg)
 
 struct outbound_entry* libworker_send_query(uint8_t* qname, size_t qnamelen,
         uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec,
-       int want_dnssec, struct sockaddr_storage* addr, socklen_t addrlen,
-       uint8_t* zone, size_t zonelen, struct module_qstate* q)
+       int want_dnssec, int nocaps, struct sockaddr_storage* addr,
+       socklen_t addrlen, uint8_t* zone, size_t zonelen,
+       struct module_qstate* q)
 {
        struct libworker* w = (struct libworker*)q->env->worker;
        struct outbound_entry* e = (struct outbound_entry*)regional_alloc(
@@ -831,7 +832,7 @@ struct outbound_entry* libworker_send_query(uint8_t* qname, size_t qnamelen,
                return NULL;
        e->qstate = q;
        e->qsent = outnet_serviced_query(w->back, qname,
-               qnamelen, qtype, qclass, flags, dnssec, want_dnssec,
+               qnamelen, qtype, qclass, flags, dnssec, want_dnssec, nocaps,
                q->env->cfg->tcp_upstream, q->env->cfg->ssl_upstream, addr,
                addrlen, zone, zonelen, libworker_handle_service_reply, e,
                w->back->udp_buff);
@@ -953,7 +954,7 @@ struct outbound_entry* worker_send_query(uint8_t* ATTR_UNUSED(qname),
        size_t ATTR_UNUSED(qnamelen), uint16_t ATTR_UNUSED(qtype), 
        uint16_t ATTR_UNUSED(qclass), uint16_t ATTR_UNUSED(flags), 
        int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec),
-       struct sockaddr_storage* ATTR_UNUSED(addr), 
+       int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr), 
        socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
        size_t ATTR_UNUSED(zonelen), struct module_qstate* ATTR_UNUSED(q))
 {
index d8354c65438493876f072d4ec78172012d785646..824012a01848664ea552715e3fddf59b48b78b61 100644 (file)
@@ -58,6 +58,7 @@ struct tube;
  * @param flags: host order flags word, with opcode and CD bit.
  * @param dnssec: if set, EDNS record will have DO bit set.
  * @param want_dnssec: signatures needed.
+ * @param nocaps: ignore capsforid(if in config), do not perturb qname.
  * @param addr: where to.
  * @param addrlen: length of addr.
  * @param zone: delegation point name.
@@ -68,8 +69,9 @@ struct tube;
  */
 struct outbound_entry* libworker_send_query(uint8_t* qname, size_t qnamelen,
         uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec,
-       int want_dnssec, struct sockaddr_storage* addr, socklen_t addrlen,
-       uint8_t* zone, size_t zonelen, struct module_qstate* q);
+       int want_dnssec, int nocaps, struct sockaddr_storage* addr,
+       socklen_t addrlen, uint8_t* zone, size_t zonelen,
+       struct module_qstate* q);
 
 /** process incoming replies from the network */
 int libworker_handle_reply(struct comm_point* c, void* arg, int error,
@@ -111,6 +113,7 @@ void worker_sighandler(int sig, void* arg);
  * @param flags: host order flags word, with opcode and CD bit.
  * @param dnssec: if set, EDNS record will have DO bit set.
  * @param want_dnssec: signatures needed.
+ * @param nocaps: ignore capsforid(if in config), do not perturb qname.
  * @param addr: where to.
  * @param addrlen: length of addr.
  * @param zone: wireformat dname of the zone.
@@ -121,8 +124,9 @@ void worker_sighandler(int sig, void* arg);
  */
 struct outbound_entry* worker_send_query(uint8_t* qname, size_t qnamelen, 
        uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec, 
-       int want_dnssec, struct sockaddr_storage* addr, socklen_t addrlen,
-       uint8_t* zone, size_t zonelen, struct module_qstate* q);
+       int want_dnssec, int nocaps, struct sockaddr_storage* addr,
+       socklen_t addrlen, uint8_t* zone, size_t zonelen,
+       struct module_qstate* q);
 
 /** 
  * process control messages from the main thread. Frees the control 
index 4baa1080d2371f9a2e1059db8d771f513e8a086f..a2083db249063dacdb85b7867850865b4e98c87e 100644 (file)
@@ -1206,7 +1206,7 @@ lookup_serviced(struct outside_network* outnet, sldns_buffer* buff, int dnssec,
 /** Create new serviced entry */
 static struct serviced_query*
 serviced_create(struct outside_network* outnet, sldns_buffer* buff, int dnssec,
-       int want_dnssec, int tcp_upstream, int ssl_upstream,
+       int want_dnssec, int nocaps, int tcp_upstream, int ssl_upstream,
        struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
        size_t zonelen, int qtype)
 {
@@ -1233,6 +1233,7 @@ serviced_create(struct outside_network* outnet, sldns_buffer* buff, int dnssec,
        sq->qtype = qtype;
        sq->dnssec = dnssec;
        sq->want_dnssec = want_dnssec;
+       sq->nocaps = nocaps;
        sq->tcp_upstream = tcp_upstream;
        sq->ssl_upstream = ssl_upstream;
        memcpy(&sq->addr, addr, addrlen);
@@ -1350,7 +1351,7 @@ static void
 serviced_encode(struct serviced_query* sq, sldns_buffer* buff, int with_edns)
 {
        /* if we are using 0x20 bits for ID randomness, perturb them */
-       if(sq->outnet->use_caps_for_id) {
+       if(sq->outnet->use_caps_for_id && !sq->nocaps) {
                serviced_perturb_qname(sq->outnet->rnd, sq->qbuf, sq->qbuflen);
        }
        /* generate query */
@@ -1828,10 +1829,11 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
 struct serviced_query* 
 outnet_serviced_query(struct outside_network* outnet,
        uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
-       uint16_t flags, int dnssec, int want_dnssec, int tcp_upstream,
-       int ssl_upstream, struct sockaddr_storage* addr, socklen_t addrlen,
-       uint8_t* zone, size_t zonelen, comm_point_callback_t* callback,
-       void* callback_arg, sldns_buffer* buff)
+       uint16_t flags, int dnssec, int want_dnssec, int nocaps,
+       int tcp_upstream, int ssl_upstream, struct sockaddr_storage* addr,
+       socklen_t addrlen, uint8_t* zone, size_t zonelen,
+       comm_point_callback_t* callback, void* callback_arg,
+       sldns_buffer* buff)
 {
        struct serviced_query* sq;
        struct service_callback* cb;
@@ -1844,7 +1846,7 @@ outnet_serviced_query(struct outside_network* outnet,
                return NULL;
        if(!sq) {
                /* make new serviced query entry */
-               sq = serviced_create(outnet, buff, dnssec, want_dnssec,
+               sq = serviced_create(outnet, buff, dnssec, want_dnssec, nocaps,
                        tcp_upstream, ssl_upstream, addr, addrlen, zone,
                        zonelen, (int)qtype);
                if(!sq) {
index a56a205c3ba64281d88a7e4f0764326eff220d4e..b9124b57fbd7bf3ed94bda8a7a852b6d289a4669 100644 (file)
@@ -309,6 +309,8 @@ struct serviced_query {
        int dnssec;
        /** We want signatures, or else the answer is likely useless */
        int want_dnssec;
+       /** ignore capsforid */
+       int nocaps;
        /** tcp upstream used, use tcp, or ssl_upstream for SSL */
        int tcp_upstream, ssl_upstream;
        /** where to send it */
@@ -466,6 +468,7 @@ void pending_delete(struct outside_network* outnet, struct pending* p);
  *     If the value includes BIT_DO, DO bit is set when in EDNS queries.
  * @param want_dnssec: signatures are needed, without EDNS the answer is
  *     likely to be useless.
+ * @param nocaps: ignore use_caps_for_id and use unperturbed qname.
  * @param tcp_upstream: use TCP for upstream queries.
  * @param ssl_upstream: use SSL for upstream queries.
  * @param callback: callback function.
@@ -482,10 +485,11 @@ void pending_delete(struct outside_network* outnet, struct pending* p);
  */
 struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
        uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
-       uint16_t flags, int dnssec, int want_dnssec, int tcp_upstream,
-       int ssl_upstream, struct sockaddr_storage* addr, socklen_t addrlen,
-       uint8_t* zone, size_t zonelen, comm_point_callback_t* callback,
-       void* callback_arg, struct sldns_buffer* buff);
+       uint16_t flags, int dnssec, int want_dnssec, int nocaps,
+       int tcp_upstream, int ssl_upstream, struct sockaddr_storage* addr,
+       socklen_t addrlen, uint8_t* zone, size_t zonelen,
+       comm_point_callback_t* callback, void* callback_arg,
+       struct sldns_buffer* buff);
 
 /**
  * Remove service query callback.
index 035d9087aea5d6156dc2e7af0d7edb68307e9998..8193bec1b4d8a2372b068a6542943bdbcce1f57b 100644 (file)
@@ -103,7 +103,7 @@ struct outbound_entry* worker_send_query(uint8_t* ATTR_UNUSED(qname),
        size_t ATTR_UNUSED(qnamelen), uint16_t ATTR_UNUSED(qtype), 
        uint16_t ATTR_UNUSED(qclass), uint16_t ATTR_UNUSED(flags), 
        int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec),
-       struct sockaddr_storage* ATTR_UNUSED(addr), 
+       int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr), 
        socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
        size_t ATTR_UNUSED(zonelen), struct module_qstate* ATTR_UNUSED(q))
 {
@@ -135,7 +135,7 @@ struct outbound_entry* libworker_send_query(uint8_t* ATTR_UNUSED(qname),
        size_t ATTR_UNUSED(qnamelen), uint16_t ATTR_UNUSED(qtype), 
        uint16_t ATTR_UNUSED(qclass), uint16_t ATTR_UNUSED(flags), 
        int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec),
-       struct sockaddr_storage* ATTR_UNUSED(addr), 
+       int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr), 
        socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
        size_t ATTR_UNUSED(zonelen), struct module_qstate* ATTR_UNUSED(q))
 {
index 47e4b78da0bf9d4d50370a9bd6fbcce3d6a6b612..83ac805d51802a315c4482f13abc4bb4dace75c4 100644 (file)
@@ -1037,9 +1037,10 @@ pending_tcp_query(struct outside_network* outnet, sldns_buffer* packet,
 struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
         uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
        uint16_t flags, int dnssec, int ATTR_UNUSED(want_dnssec),
-       int ATTR_UNUSED(tcp_upstream), int ATTR_UNUSED(ssl_upstream),
-       struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
-       size_t zonelen, comm_point_callback_t* callback, void* callback_arg,
+       int ATTR_UNUSED(nocaps), int ATTR_UNUSED(tcp_upstream),
+       int ATTR_UNUSED(ssl_upstream), struct sockaddr_storage* addr,
+       socklen_t addrlen, uint8_t* zone, size_t zonelen,
+       comm_point_callback_t* callback, void* callback_arg,
        sldns_buffer* ATTR_UNUSED(buff))
 {
        struct replay_runtime* runtime = (struct replay_runtime*)outnet->base;
index 7aa773634a8804fd5db35856cbbb122a14f854e3..35fcd8c7eaa1937fcc670cfbc0f225c1ea4d9d0f 100644 (file)
@@ -258,7 +258,7 @@ fptr_whitelist_hash_markdelfunc(lruhash_markdelfunc_t fptr)
 int 
 fptr_whitelist_modenv_send_query(struct outbound_entry* (*fptr)(
         uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
-        uint16_t flags, int dnssec, int want_dnssec, 
+        uint16_t flags, int dnssec, int want_dnssec, int nocaps,
        struct sockaddr_storage* addr, socklen_t addrlen, 
        uint8_t* zone, size_t zonelen,
        struct module_qstate* q))
index b2925d6755d58c88ff78e6a297755b30a9ca8cf5..62692ba8b530f3522c55096a53993185247bebe1 100644 (file)
@@ -211,7 +211,7 @@ int fptr_whitelist_hash_markdelfunc(lruhash_markdelfunc_t fptr);
  */
 int fptr_whitelist_modenv_send_query(struct outbound_entry* (*fptr)(
        uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass, 
-       uint16_t flags, int dnssec, int want_dnssec,
+       uint16_t flags, int dnssec, int want_dnssec, int nocaps,
        struct sockaddr_storage* addr, socklen_t addrlen, 
        uint8_t* zone, size_t zonelen,
        struct module_qstate* q));
index dace1cf6ba2498f0cf4acc81c48030e0d81a5abc..f95ff6dc83729c58b273282930761a337723fdcc 100644 (file)
@@ -212,6 +212,8 @@ struct module_env {
         *      If BIT_CD is set, CD bit is set in queries with EDNS records.
         * @param want_dnssec: if set, the validator wants DNSSEC.  Without
         *      EDNS, the answer is likely to be useless for this domain.
+        * @param nocaps: do not use caps_for_id, use the qname as given.
+        *      (ignored if caps_for_id is disabled).
         * @param addr: where to.
         * @param addrlen: length of addr.
         * @param zone: delegation point name.
@@ -224,7 +226,7 @@ struct module_env {
         */
        struct outbound_entry* (*send_query)(uint8_t* qname, size_t qnamelen, 
                uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec, 
-               int want_dnssec, struct sockaddr_storage* addr, 
+               int want_dnssec, int nocaps, struct sockaddr_storage* addr, 
                socklen_t addrlen, uint8_t* zone, size_t zonelen,
                struct module_qstate* q);