]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Convert responses to bytes before logging them in asyncserver
authorŠtěpán Balážik <stepan@isc.org>
Wed, 21 Jan 2026 18:34:29 +0000 (19:34 +0100)
committerŠtěpán Balážik <stepan@isc.org>
Fri, 17 Apr 2026 14:26:07 +0000 (14:26 +0000)
Ensure that the actual packet contents are logged including the TSIG
record which is calculated on `to_wire` call.

bin/tests/system/isctest/asyncserver.py

index 53cdfeb47c1ba5a5e03c9fea44e7167be3ddc553..dd9f6239166e265c7c2fa54a9d2fd149e6d6fce8 100644 (file)
@@ -1390,6 +1390,24 @@ class AsyncDnsServer(AsyncServer):
         )
         logging.debug("[OUT] %s", response.hex())
 
+    def _prepare_response_wire(
+        self, qctx: QueryContext, response: dns.message.Message | bytes | None
+    ) -> bytes | None:
+        def prepend_length_unless_udp(payload: bytes) -> bytes:
+            if qctx.protocol == DnsProtocol.UDP:
+                return payload
+            return len(payload).to_bytes(2, byteorder="big") + payload
+
+        match response:
+            case dns.message.Message(wire=bytes() as payload) | (bytes() as payload):
+                # Calling to_wire() on a Message again may result in a different TSIG
+                # signature being generated, which would be incorrect.
+                return prepend_length_unless_udp(payload)
+            case dns.message.Message(wire=None):
+                return prepend_length_unless_udp(response.to_wire(max_size=65535))
+            case _:
+                return None
+
     async def _handle_query(
         self, wire: bytes, socket: Peer, peer: Peer, protocol: DnsProtocol
     ) -> AsyncGenerator[bytes, None]:
@@ -1406,14 +1424,12 @@ class AsyncDnsServer(AsyncServer):
         self._log_query(qctx)
         responses = self._prepare_responses(qctx)
         async for response in responses:
+            # Call _prepare_response_wire before logging the response, so that TSIG
+            # records are properly included in the logged response.
+            response_wire = self._prepare_response_wire(qctx, response)
             self._log_response(qctx, response)
-            if response:
-                if isinstance(response, dns.message.Message):
-                    response = response.to_wire(max_size=65535)
-                if protocol == DnsProtocol.UDP:
-                    yield response
-                else:
-                    yield len(payload).to_bytes(2, byteorder="big") + payload
+            if response_wire is not None:
+                yield response_wire
 
     def _parse_message(self, wire: bytes) -> dns.message.Message:
         try: