diff -ur bind-9.6.0-P1.pristine/lib/dns/resolver.c bind-9.6.0-P1/lib/dns/resolver.c --- bind-9.6.0-P1.pristine/lib/dns/resolver.c 2008-11-06 18:52:34.000000000 -0600 +++ bind-9.6.0-P1/lib/dns/resolver.c 2009-03-16 21:15:44.000000000 -0500 @@ -222,6 +222,7 @@ * is used for EDNS0 black hole detection. */ unsigned int timeouts; + /*% * Look aside state for DS lookups. */ @@ -245,6 +246,7 @@ */ isc_uint32_t rand_buf; isc_uint32_t rand_bits; + isc_boolean_t timeout; }; #define FCTX_MAGIC ISC_MAGIC('F', '!', '!', '!') @@ -1575,28 +1577,44 @@ DNS_FETCHOPT_NOEDNS0); } - /* Sync NOEDNS0 flag in addrinfo->flags and options now */ + /* Sync NOEDNS0 flag in addrinfo->flags and options now. */ if ((query->addrinfo->flags & DNS_FETCHOPT_NOEDNS0) != 0) query->options |= DNS_FETCHOPT_NOEDNS0; /* + * Handle timeouts by reducing the UDP response size to 512 bytes + * then if that doesn't work disabling EDNS (includes DO) and CD. + * + * These timeout can be due to: + * * broken nameservers that don't respond to EDNS queries. + * * broken/misconfigured firewalls and NAT implementations + * that don't handle IP fragmentation. + * * broken/misconfigured firewalls that don't handle responses + * greater than 512 bytes. + * * broken/misconfigured firewalls that don't handle EDNS, DO + * or CD. + * * packet loss / link outage. + */ + if (fctx->timeout) { + if ((triededns512(fctx, &query->addrinfo->sockaddr) || + fctx->timeouts >= (MAX_EDNS0_TIMEOUTS * 2)) && + (query->options & DNS_FETCHOPT_NOEDNS0) == 0) { + query->options |= DNS_FETCHOPT_NOEDNS0; + fctx->reason = "disabling EDNS"; + } else if ((triededns(fctx, &query->addrinfo->sockaddr) || + fctx->timeouts >= MAX_EDNS0_TIMEOUTS) && + (query->options & DNS_FETCHOPT_NOEDNS0) == 0) { + query->options |= DNS_FETCHOPT_EDNS512; + fctx->reason = "reducing the advertised EDNS UDP " + "packet size to 512 octets"; + } + fctx->timeout = ISC_FALSE; + } + + /* * Use EDNS0, unless the caller doesn't want it, or we know that * the remote server doesn't like it. */ - - if ((triededns512(fctx, &query->addrinfo->sockaddr) || - fctx->timeouts >= (MAX_EDNS0_TIMEOUTS * 2)) && - (query->options & DNS_FETCHOPT_NOEDNS0) == 0) { - query->options |= DNS_FETCHOPT_NOEDNS0; - fctx->reason = "disabling EDNS"; - } else if ((triededns(fctx, &query->addrinfo->sockaddr) || - fctx->timeouts >= MAX_EDNS0_TIMEOUTS) && - (query->options & DNS_FETCHOPT_NOEDNS0) == 0) { - query->options |= DNS_FETCHOPT_EDNS512; - fctx->reason = "reducing the advertised EDNS UDP packet " - "size to 512 octets"; - } - if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0) { if ((query->addrinfo->flags & DNS_FETCHOPT_NOEDNS0) == 0) { unsigned int version = 0; /* Default version. */ @@ -2909,6 +2927,7 @@ isc_result_t result; fctx->timeouts++; + fctx->timeout = ISC_TRUE; /* * We could cancel the running queries here, or we could let * them keep going. Since we normally use separate sockets for @@ -3242,6 +3261,7 @@ fctx->reason = NULL; fctx->rand_buf = 0; fctx->rand_bits = 0; + fctx->timeout = ISC_FALSE; dns_name_init(&fctx->nsname, NULL); fctx->nsfetch = NULL; @@ -4508,7 +4528,8 @@ */ ttl = fctx->res->view->maxncachettl; if (fctx->type == dns_rdatatype_soa && - covers == dns_rdatatype_any) + covers == dns_rdatatype_any && + fctx->res->zero_no_soa_ttl) ttl = 0; result = ncache_adderesult(fctx->rmessage, fctx->cache, node, @@ -5768,6 +5789,7 @@ } fctx->timeouts = 0; + fctx->timeout = ISC_FALSE; /* * XXXRTH We should really get the current time just once. We diff -ur bind-9.6.0-P1.pristine/lib/dns/validator.c bind-9.6.0-P1/lib/dns/validator.c --- bind-9.6.0-P1.pristine/lib/dns/validator.c 2008-11-14 17:47:33.000000000 -0600 +++ bind-9.6.0-P1/lib/dns/validator.c 2009-03-16 21:13:56.000000000 -0500 @@ -218,6 +218,37 @@ return (ISC_TRUE); } +/* + * Check that we have atleast one supported algorithm in the DLV RRset. + */ +static inline isc_boolean_t +dlv_algorithm_supported(dns_validator_t *val) { + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdata_dlv_t dlv; + isc_result_t result; + + for (result = dns_rdataset_first(&val->dlv); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&val->dlv)) { + dns_rdata_reset(&rdata); + dns_rdataset_current(&val->dlv, &rdata); + result = dns_rdata_tostruct(&rdata, &dlv, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + + if (!dns_resolver_algorithm_supported(val->view->resolver, + val->event->name, + dlv.algorithm)) + continue; + + if (dlv.digest_type != DNS_DSDIGEST_SHA256 && + dlv.digest_type != DNS_DSDIGEST_SHA1) + continue; + + return (ISC_TRUE); + } + return (ISC_FALSE); +} + /*% * Look in the NSEC record returned from a DS query to see if there is * a NS RRset at this name. If it is found we are at a delegation point. @@ -2957,19 +2988,36 @@ sizeof(namebuf)); dns_rdataset_clone(&val->frdataset, &val->dlv); val->havedlvsep = ISC_TRUE; - validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found", namebuf); - dlv_validator_start(val); + if (dlv_algorithm_supported(val)) { + validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found", + namebuf); + dlv_validator_start(val); + } else { + validator_log(val, ISC_LOG_DEBUG(3), + "DLV %s found with no supported algorithms", + namebuf); + markanswer(val); + validator_done(val, ISC_R_SUCCESS); + } } else if (eresult == DNS_R_NXRRSET || eresult == DNS_R_NXDOMAIN || eresult == DNS_R_NCACHENXRRSET || eresult == DNS_R_NCACHENXDOMAIN) { - result = finddlvsep(val, ISC_TRUE); + result = finddlvsep(val, ISC_TRUE); if (result == ISC_R_SUCCESS) { - dns_name_format(dns_fixedname_name(&val->dlvsep), - namebuf, sizeof(namebuf)); - validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found", - namebuf); - dlv_validator_start(val); + if (dlv_algorithm_supported(val)) { + dns_name_format(dns_fixedname_name(&val->dlvsep), + namebuf, sizeof(namebuf)); + validator_log(val, ISC_LOG_DEBUG(3), + "DLV %s found", namebuf); + dlv_validator_start(val); + } else { + validator_log(val, ISC_LOG_DEBUG(3), + "DLV %s found with no supported " + "algorithms", namebuf); + markanswer(val); + validator_done(val, ISC_R_SUCCESS); + } } else if (result == ISC_R_NOTFOUND) { validator_log(val, ISC_LOG_DEBUG(3), "DLV not found"); markanswer(val); @@ -3032,9 +3080,16 @@ } dns_name_format(dns_fixedname_name(&val->dlvsep), namebuf, sizeof(namebuf)); - validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found", namebuf); - dlv_validator_start(val); - return (DNS_R_WAIT); + if (dlv_algorithm_supported(val)) { + validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found", namebuf); + dlv_validator_start(val); + return (DNS_R_WAIT); + } + validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found with no supported " + "algorithms", namebuf); + markanswer(val); + validator_done(val, ISC_R_SUCCESS); + return (ISC_R_SUCCESS); } /*%