]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
After UDP timeout EDNS1480 probe, stop fragmentation caused trouble.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Thu, 15 Sep 2011 14:32:17 +0000 (14:32 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Thu, 15 Sep 2011 14:32:17 +0000 (14:32 +0000)
git-svn-id: file:///svn/unbound/trunk@2492 be551aaa-1e26-0410-a405-d3ace91eadb9

doc/Changelog
services/outside_network.c
services/outside_network.h

index 02617d94e62fdb3b37516a2331ecbd6e5f5576eb..d29bb4fcfdfa246eacf94e1c174fbde5ab346e7d 100644 (file)
@@ -1,6 +1,7 @@
 15 September 2011: Wouter
        - release 1.4.13.
        - trunk contains 1.4.14 in development.
+       - Unbound probes at EDNS1480 if there an EDNS0 timeout.
 
 12 September 2011: Wouter
        - Reverted dns EDNS backoff fix, it did not help and needs
index 5397e8afb5e3668d9e2abbb11afb95d5c2dc8781..b7bc5ff754082beadd209880a22db64c7dfc81f3 100644 (file)
@@ -1280,7 +1280,19 @@ serviced_encode(struct serviced_query* sq, ldns_buffer* buff, int with_edns)
                edns.edns_present = 1;
                edns.ext_rcode = 0;
                edns.edns_version = EDNS_ADVERTISED_VERSION;
-               edns.udp_size = EDNS_ADVERTISED_SIZE;
+               if(sq->status == serviced_query_UDP_EDNS_FRAG) {
+                       if(addr_is_ip6(&sq->addr, sq->addrlen)) {
+                               if(EDNS_FRAG_SIZE_IP6 < EDNS_ADVERTISED_SIZE)
+                                       edns.udp_size = EDNS_FRAG_SIZE_IP6;
+                               else    edns.udp_size = EDNS_ADVERTISED_SIZE;
+                       } else {
+                               if(EDNS_FRAG_SIZE_IP4 < EDNS_ADVERTISED_SIZE)
+                                       edns.udp_size = EDNS_FRAG_SIZE_IP4;
+                               else    edns.udp_size = EDNS_ADVERTISED_SIZE;
+                       }
+               } else {
+                       edns.udp_size = EDNS_ADVERTISED_SIZE;
+               }
                edns.bits = 0;
                if(sq->dnssec & EDNS_DO)
                        edns.bits = EDNS_DO;
@@ -1564,6 +1576,20 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
                         * by EDNS. */
                        sq->status = serviced_query_UDP_EDNS;
                }
+               if(sq->status == serviced_query_UDP_EDNS) {
+                       /* fallback to 1480/1280 */
+                       sq->status = serviced_query_UDP_EDNS_FRAG;
+                       log_name_addr(VERB_ALGO, "try edns1xx0", sq->qbuf+10,
+                               &sq->addr, sq->addrlen);
+                       if(!serviced_udp_send(sq, c->buffer)) {
+                               serviced_callbacks(sq, NETEVENT_CLOSED, c, rep);
+                       }
+                       return 0;
+               }
+               if(sq->status == serviced_query_UDP_EDNS_FRAG) {
+                       /* fragmentation size did not fix it */
+                       sq->status = serviced_query_UDP_EDNS;
+               }
                sq->retry++;
                if(!(rto=infra_rtt_update(outnet->infra, &sq->addr, sq->addrlen,
                        -1, sq->last_rtt, (uint32_t)now.tv_sec)))
@@ -1589,7 +1615,8 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
                return 0;
        }
        if(!fallback_tcp) {
-           if(sq->status == serviced_query_UDP_EDNS 
+           if( (sq->status == serviced_query_UDP_EDNS 
+               ||sq->status == serviced_query_UDP_EDNS_FRAG)
                && (LDNS_RCODE_WIRE(ldns_buffer_begin(c->buffer)) 
                        == LDNS_RCODE_FORMERR || LDNS_RCODE_WIRE(
                        ldns_buffer_begin(c->buffer)) == LDNS_RCODE_NOTIMPL)) {
index 493e43010e030a524411b6ed3cae842e0cfe74a8..1ee2f1015a922c6c84bf16d4ecd3ab740448f537 100644 (file)
@@ -274,6 +274,11 @@ struct service_callback {
        void* cb_arg;
 };
 
+/** fallback size for fragmentation for EDNS in IPv4 */
+#define EDNS_FRAG_SIZE_IP4 1480
+/** fallback size for EDNS in IPv6, fits one fragment with ip6-tunnel-ids */
+#define EDNS_FRAG_SIZE_IP6 1260
+
 /**
  * Query service record.
  * Contains query and destination. UDP, TCP, EDNS are all tried.
@@ -314,7 +319,9 @@ struct serviced_query {
                /** probe to test noEDNS0 (EDNS gives FORMERRorNOTIMP) */
                serviced_query_UDP_EDNS_fallback,
                /** probe to test TCP noEDNS0 (EDNS gives FORMERRorNOTIMP) */
-               serviced_query_TCP_EDNS_fallback
+               serviced_query_TCP_EDNS_fallback,
+               /** send UDP query with EDNS1480 (or 1280) */
+               serviced_query_UDP_EDNS_FRAG
        }       
                /** variable with current status */ 
                status;