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.

(cherry picked from commit f3b24ba789)
This commit is contained in:
Mark Andrews 2023-05-08 17:39:51 +10:00 committed by Ondřej Surý
parent a0d672f0c5
commit e7e29278a8
No known key found for this signature in database
GPG key ID: 2820F37E873DEA41
2 changed files with 30 additions and 13 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

@ -8380,12 +8380,18 @@ rctx_opt(respctx_t *rctx) {
memcmp(cookie, optvalue,
CLIENT_COOKIE_SIZE) == 0)
{
query->rmessage->cc_ok = 1;
inc_stats(fctx->res,
dns_resstatscounter_cookieok);
addrinfo = query->addrinfo;
dns_adb_setcookie(fctx->adb, 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);
addrinfo = query->addrinfo;
dns_adb_setcookie(
fctx->adb, addrinfo,
optvalue, optlen);
}
} else {
query->rmessage->cc_bad = 1;
}
@ -10061,13 +10067,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