]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Handle FORMERR on unknown EDNS option that are echoed
authorMark Andrews <marka@isc.org>
Mon, 8 May 2023 07:39:51 +0000 (17:39 +1000)
committerOndřej Surý <ondrej@isc.org>
Mon, 26 Jun 2023 14:36:11 +0000 (16:36 +0200)
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 f3b24ba789bed8e561519909709e1671bb290c7f)

lib/dns/include/dns/message.h
lib/dns/resolver.c

index d769fe94dc244074b7833a0bece8f898cab2d977..b5d9a5a1681b8482a09f35cf7c67799b6a360abf 100644 (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;
index 0dddb43de7f25bfc1e8d201daf8a08171b8e17a5..f2c2e1caceb6691348819b5ebcb3f62a2291f521 100644 (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