diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c index 90e8f0c0ad..ebd796ec65 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c @@ -4341,6 +4341,12 @@ recv_done(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region, dighost_comments(l, "BADVERS, retrying with EDNS version %u.", (unsigned int)newedns); l->edns = newedns; + /* + * Extract the server cookie so it can be sent in the retry. + */ + if (l->cookie == NULL && l->sendcookie) { + process_opt(l, msg); + } n = requeue_lookup(l, true); if (l->trace && l->trace_root) { n->rdtype = l->qrdtype; diff --git a/bin/tests/system/ednscompliance/ns1/named.conf.in b/bin/tests/system/ednscompliance/ns1/named.conf.in index 1334c85cf2..3a640fff22 100644 --- a/bin/tests/system/ednscompliance/ns1/named.conf.in +++ b/bin/tests/system/ednscompliance/ns1/named.conf.in @@ -21,6 +21,7 @@ options { listen-on-v6 { none; }; recursion no; dnssec-validation no; + server-id "ns1"; }; zone "." { diff --git a/bin/tests/system/ednscompliance/tests.sh b/bin/tests/system/ednscompliance/tests.sh index 515951adcf..3fae21142e 100644 --- a/bin/tests/system/ednscompliance/tests.sh +++ b/bin/tests/system/ednscompliance/tests.sh @@ -57,7 +57,7 @@ status=$((status + ret)) n=$((n + 1)) echo_i "Unknown EDNS version ($n)" ret=0 reason= -$DIG $DIGOPTS @10.53.0.1 +edns=100 +noednsnegotiation soa $zone >dig.out$n || ret=1 +$DIG $DIGOPTS @10.53.0.1 +edns=100 +nsid +noednsnegotiation soa $zone >dig.out$n || ret=1 grep "status: BADVERS," dig.out$n >/dev/null || { ret=1 reason="status" @@ -66,6 +66,14 @@ grep "EDNS: version: 0," dig.out$n >/dev/null || { ret=1 reason="version" } +grep "; COOKIE: .* (good)" dig.out$n >/dev/null || { + ret=1 + reason="cookie missing" +} +grep '; NSID: 6e 73 31 ("ns1")' dig.out$n >/dev/null || { + ret=1 + reason="nsid missing" +} grep "IN.SOA." dig.out$n >/dev/null && { ret=1 reason="soa" diff --git a/lib/ns/client.c b/lib/ns/client.c index 0b38ffc078..048a6c72b7 100644 --- a/lib/ns/client.c +++ b/lib/ns/client.c @@ -1550,17 +1550,6 @@ process_opt(ns_client_t *client, dns_rdataset_t *opt) { * XXXRTH need library support for this! */ client->ednsversion = (opt->ttl & 0x00FF0000) >> 16; - if (client->ednsversion > DNS_EDNS_VERSION) { - ns_stats_increment(client->manager->sctx->nsstats, - ns_statscounter_badednsver); - result = ns_client_addopt(client, client->message, - &client->opt); - if (result == ISC_R_SUCCESS) { - result = DNS_R_BADVERS; - } - ns_client_error(client, result); - return result; - } /* Check for NSID request */ result = dns_rdataset_first(opt); @@ -1572,6 +1561,17 @@ process_opt(ns_client_t *client, dns_rdataset_t *opt) { while (isc_buffer_remaininglength(&optbuf) >= 4) { optcode = isc_buffer_getuint16(&optbuf); optlen = isc_buffer_getuint16(&optbuf); + /* + * When returning BADVERSION, only process + * DNS_OPT_NSID or DNS_OPT_COOKIE options. + */ + if (client->ednsversion > DNS_EDNS_VERSION && + optcode != DNS_OPT_NSID && + optcode != DNS_OPT_COOKIE) + { + isc_buffer_forward(&optbuf, optlen); + continue; + } switch (optcode) { case DNS_OPT_NSID: if (!WANTNSID(client)) { @@ -1643,6 +1643,18 @@ process_opt(ns_client_t *client, dns_rdataset_t *opt) { } } + if (client->ednsversion > DNS_EDNS_VERSION) { + ns_stats_increment(client->manager->sctx->nsstats, + ns_statscounter_badednsver); + result = ns_client_addopt(client, client->message, + &client->opt); + if (result == ISC_R_SUCCESS) { + result = DNS_R_BADVERS; + } + ns_client_error(client, result); + return result; + } + ns_stats_increment(client->manager->sctx->nsstats, ns_statscounter_edns0in); client->attributes |= NS_CLIENTATTR_WANTOPT;