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:
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user