From de42425bbd6f51edf2abc0e57d4d3e3dd2e92159 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= Date: Thu, 21 May 2026 11:52:56 +0200 Subject: [PATCH] Fix flawed response logic for COOKIE-less queries The "yield" keyword does not cause a function to return. By design, get_responses() may yield multiple DNS responses in a single call. As currently implemented, CookieHandler.get_responses() sends two responses to each client query that does not contain a COOKIE option. Make the logic in that method consistent with code comments by only sending one response to every query - either SERVFAIL or BADCOOKIE, never both. --- bin/tests/system/resend_loop/ans3/ans.py | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/bin/tests/system/resend_loop/ans3/ans.py b/bin/tests/system/resend_loop/ans3/ans.py index 69ea0be6c7..47275bf377 100644 --- a/bin/tests/system/resend_loop/ans3/ans.py +++ b/bin/tests/system/resend_loop/ans3/ans.py @@ -73,21 +73,17 @@ class CookieHandler(DomainHandler): async def get_responses( self, qctx: QueryContext ) -> AsyncGenerator[DnsResponseSend, None]: - - # Check for client cookie - cookie = _get_cookie(qctx) - - # If missing cookie entirely, just return SERVFAIL - if cookie is None: + if cookie := _get_cookie(qctx): + # If there is a client cookie, mock BADCOOKIE to trigger + # the resend loop logic. + qctx.response.use_edns(options=[cookie]) + qctx.response.set_rcode(dns.rcode.BADCOOKIE) + yield DnsResponseSend(qctx.response) + else: + # If missing cookie entirely, just return SERVFAIL qctx.response.set_rcode(dns.rcode.SERVFAIL) yield DnsResponseSend(qctx.response) - # If there is a client cookie, mock BADCOOKIE to trigger - # the resend loop logic. - qctx.response.use_edns(options=[cookie]) - qctx.response.set_rcode(dns.rcode.BADCOOKIE) - yield DnsResponseSend(qctx.response) - def resend_server() -> AsyncDnsServer: server = AsyncDnsServer(default_aa=True, default_rcode=dns.rcode.NOERROR)