From: Wouter Wijngaards Date: Thu, 15 Sep 2011 14:32:17 +0000 (+0000) Subject: After UDP timeout EDNS1480 probe, stop fragmentation caused trouble. X-Git-Tag: release-1.4.14rc1~75 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1af30c02fc33468bc386eeea9f945842b145c8de;p=thirdparty%2Funbound.git After UDP timeout EDNS1480 probe, stop fragmentation caused trouble. git-svn-id: file:///svn/unbound/trunk@2492 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/doc/Changelog b/doc/Changelog index 02617d94e..d29bb4fcf 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -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 diff --git a/services/outside_network.c b/services/outside_network.c index 5397e8afb..b7bc5ff75 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -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)) { diff --git a/services/outside_network.h b/services/outside_network.h index 493e43010..1ee2f1015 100644 --- a/services/outside_network.h +++ b/services/outside_network.h @@ -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;