Handle FORMERR on unknown EDNS option that are echoed

If the resolver received a FORMERR response to a request with
an DNS COOKIE option present that echoes the option back, resend
the request without an DNS COOKIE option present.
This commit is contained in:
Mark Andrews
2023-05-08 17:39:51 +10:00
parent 88cf7e7e9a
commit f3b24ba789
2 changed files with 27 additions and 11 deletions

View File

@@ -279,6 +279,7 @@ struct dns_message {
unsigned int free_saved : 1;
unsigned int cc_ok : 1;
unsigned int cc_bad : 1;
unsigned int cc_echoed : 1;
unsigned int tkey : 1;
unsigned int rdclass_set : 1;
unsigned int fuzzing : 1;

View File

@@ -7996,10 +7996,15 @@ rctx_opt(respctx_t *rctx) {
}
/* Cookie OK */
query->rmessage->cc_ok = 1;
inc_stats(fctx->res, dns_resstatscounter_cookieok);
dns_adb_setcookie(fctx->adb, query->addrinfo, optvalue,
optlen);
if (optlen == CLIENT_COOKIE_SIZE) {
query->rmessage->cc_echoed = 1;
} else {
query->rmessage->cc_ok = 1;
inc_stats(fctx->res,
dns_resstatscounter_cookieok);
dns_adb_setcookie(fctx->adb, query->addrinfo,
optvalue, optlen);
}
break;
default:
break;
@@ -9663,13 +9668,23 @@ rctx_badserver(respctx_t *rctx, isc_result_t result) {
add_bad_edns(fctx, &query->addrinfo->sockaddr);
inc_stats(fctx->res, dns_resstatscounter_edns0fail);
} else if (rcode == dns_rcode_formerr) {
/*
* The server (or forwarder) doesn't understand us,
* but others might.
*/
rctx->next_server = true;
rctx->broken_server = DNS_R_REMOTEFORMERR;
log_formerr(fctx, "server sent FORMERR");
if (query->rmessage->cc_echoed) {
/*
* Retry without DNS COOKIE.
*/
query->addrinfo->flags |= FCTX_ADDRINFO_NOCOOKIE;
rctx->resend = true;
log_formerr(fctx, "server sent FORMERR with echoed DNS "
"COOKIE");
} else {
/*
* The server (or forwarder) doesn't understand us,
* but others might.
*/
rctx->next_server = true;
rctx->broken_server = DNS_R_REMOTEFORMERR;
log_formerr(fctx, "server sent FORMERR");
}
} else if (rcode == dns_rcode_badvers) {
unsigned int version;
#if DNS_EDNS_VERSION > 0