From: Mark Andrews Date: Wed, 19 Mar 2014 18:00:55 +0000 (+1100) Subject: 3790. [bug] Handle broken nameservers that send BADVERS in X-Git-Tag: v9.10.0rc1~47 X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=09ab38c151751b76b8043275422239463eb70cbd;p=thirdparty%2Fbind9.git 3790. [bug] Handle broken nameservers that send BADVERS in response to unknown EDNS options. Maintain statistics on BADVERS responses. --- diff --git a/CHANGES b/CHANGES index e9109cb936d..6ae93e72adc 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,7 @@ +3790. [bug] Handle broken nameservers that send BADVERS in + response to unknown EDNS options. Maintain + statistics on BADVERS responses. + 3789. [bug] Null pointer dereference on rbt creation failure. 3788. [bug] dns_peer_getrequestsit was returning request_nsid by diff --git a/bin/named/statschannel.c b/bin/named/statschannel.c index 6052308477f..0764aa75b23 100644 --- a/bin/named/statschannel.c +++ b/bin/named/statschannel.c @@ -319,6 +319,7 @@ init_desc(void) { SET_RESSTATDESC(sitin, "SIT replies received", "SitIn"); SET_RESSTATDESC(sitok, "SIT client cookie ok", "SitClientOk"); #endif + SET_RESSTATDESC(badvers, "bad EDNS version", "BadEDNSVersion"); INSIST(i == dns_resstatscounter_max); diff --git a/lib/dns/include/dns/stats.h b/lib/dns/include/dns/stats.h index 059dcd487f7..534da4df4f8 100644 --- a/lib/dns/include/dns/stats.h +++ b/lib/dns/include/dns/stats.h @@ -72,9 +72,11 @@ enum { dns_resstatscounter_sitin = 37, dns_resstatscounter_sitok = 38, - dns_resstatscounter_max = 39, + dns_resstatscounter_badvers = 39, + dns_resstatscounter_max = 40, #else - dns_resstatscounter_max = 35, + dns_resstatscounter_badvers = 35, + dns_resstatscounter_max = 36, #endif /* diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 676d54817c3..068d0ced4eb 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -459,13 +459,14 @@ struct dns_resolver { #define VALID_RESOLVER(res) ISC_MAGIC_VALID(res, RES_MAGIC) /*% - * Private addrinfo flags. These must not conflict with DNS_FETCHOPT_NOEDNS0, - * which we also use as an addrinfo flag. + * Private addrinfo flags. These must not conflict with DNS_FETCHOPT_NOEDNS0 + * (0x008) which we also use as an addrinfo flag. */ #define FCTX_ADDRINFO_MARK 0x0001 #define FCTX_ADDRINFO_FORWARDER 0x1000 #define FCTX_ADDRINFO_TRIED 0x2000 #define FCTX_ADDRINFO_EDNSOK 0x4000 +#define FCTX_ADDRINFO_NOSIT 0x8000 #define UNMARKED(a) (((a)->flags & FCTX_ADDRINFO_MARK) \ == 0) @@ -473,6 +474,8 @@ struct dns_resolver { FCTX_ADDRINFO_FORWARDER) != 0) #define TRIED(a) (((a)->flags & \ FCTX_ADDRINFO_TRIED) != 0) +#define NOSIT(a) (((a)->flags & \ + FCTX_ADDRINFO_NOSIT) != 0) #define NXDOMAIN(r) (((r)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0) #define NEGATIVE(r) (((r)->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) @@ -2063,6 +2066,10 @@ resquery_send(resquery_t *query) { (void) dns_peer_getrequestsit(peer, &reqsit); #endif } +#ifdef ISC_PLATFORM_USESIT + if (NOSIT(query->addrinfo)) + reqsit = ISC_FALSE; +#endif if (reqnsid) { INSIST(ednsopt < DNS_EDNSOPTIONS); ednsopts[ednsopt].code = DNS_OPT_NSID; @@ -7499,6 +7506,19 @@ resquery_response(isc_task_t *task, isc_event_t *event) { unsigned int flags, mask; unsigned int version; + inc_stats(fctx->res, dns_resstatscounter_badvers); + +#ifdef ISC_PLATFORM_USESIT + /* + * Some servers return BADVERS to unknown + * EDNS options. This cannot be long term + * strategy. + */ + dns_adb_changeflags(fctx->adb, query->addrinfo, + FCTX_ADDRINFO_NOSIT, + FCTX_ADDRINFO_NOSIT); +#endif + resend = ISC_TRUE; INSIST(opt != NULL); version = (opt->ttl >> 16) & 0xff;