]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s4/dns_server: truncate large dns packets over udp and set truncated flag
authorAndréas Leroux <aleroux@tranquil.it>
Fri, 13 Feb 2026 08:25:55 +0000 (09:25 +0100)
committerJennifer Sutton <jsutton@samba.org>
Wed, 1 Apr 2026 05:08:14 +0000 (05:08 +0000)
Large DNS response must be truncated over UDP, letting client retry over TCP. Current threshold is set to 1232 as it is regarded as a safe size.
Truncated packets have no answers nor record, only the packet header and initial question(s).

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15988

Signed-off-by: Andréas Leroux <aleroux@tranquil.it>
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Gary Lockyer <gary@catalyst.net.nz>
Autobuild-User(master): Jennifer Sutton <jsutton@samba.org>
Autobuild-Date(master): Wed Apr  1 05:08:14 UTC 2026 on atb-devel-224

selftest/knownfail.d/dns
source4/dns_server/dns_server.c
source4/dns_server/dns_server.h

index 998c50cb32039b4c00a8d52c9288b61416fe666b..056270b30bb4e25b6fe5d75ce2bc761a8f964a73 100644 (file)
@@ -58,7 +58,8 @@ samba.tests.dns.__main__.TestZones.test_basic_scavenging\(vampire_dc:local\)
 samba.tests.dns.__main__.TestZones.test_dns_tombstone_custom_match_rule\(vampire_dc:local\)
 samba.tests.dns.__main__.TestZones.test_dynamic_record_static_update\(vampire_dc:local\)
 samba.tests.dns.__main__.TestZones.test_static_record_dynamic_update\(vampire_dc:local\)
-samba.tests.dns.__main__.TestUDPTruncation.test_udp_truncates_large_packets
+# We can't create our records on a RODC, therefore can't test large packets
+samba.tests.dns.__main__.TestUDPTruncation.test_udp_truncates_large_packets\(rodc:local\)
 
 samba.tests.dns.__main__.TestComplexQueries.test_cname_two_chain\(vampire_dc:local\)
 samba.tests.dns.__main__.TestComplexQueries.test_one_a_query\(vampire_dc:local\)
index 4e6e0d32a6cf35fee3343ae5b3ff4e17dced0241..2c666e84ea921500de471374df52de9c1eb226e5 100644 (file)
@@ -594,9 +594,29 @@ static void dns_udp_call_process_done(struct tevent_req *subreq)
                subreq, struct dns_udp_call);
        struct dns_udp_socket *sock = call->sock;
        struct dns_server *dns = sock->dns_socket->dns;
+       struct dns_process_state *state = tevent_req_data(
+               subreq, struct dns_process_state);
        WERROR err;
 
        err = dns_process_recv(subreq, call, &call->out);
+       /*
+       * If a UDP response exceeds the threshold, set the TC flag and return an
+       * empty response, expecting the client to retry over TCP as required by
+       * RFC 1035 Section 4.2.1 ("the message was truncated due to length greater
+       * than that permitted on the transmission channel").
+       */
+       if (W_ERROR_IS_OK(err) && call->out.length > DNS_MAX_UDP_PACKET_LENGTH) {
+               state->out_packet.operation |= DNS_FLAG_TRUNCATION;
+               state->out_packet.ancount = 0;
+               state->out_packet.nscount = 0;
+               state->out_packet.arcount = 0;
+               TALLOC_FREE(call->out.data);
+               err = dns_process_recv(subreq, call, &call->out);
+               if (!W_ERROR_IS_OK(err)) {
+                       DBG_WARNING("Failed to build truncated DNS packet: %s!\n",
+                               win_errstr(err));
+               }
+       }
        TALLOC_FREE(subreq);
        if (!W_ERROR_IS_OK(err)) {
                DEBUG(1, ("dns_process returned %s\n", win_errstr(err)));
index f4e5a61c43f78e519d60507e514c1f96eb6e50df..fa50ca3e23c7ca2a8a5e1cfbca3c35e990b40e69 100644 (file)
@@ -37,6 +37,11 @@ struct dns_server_tkey {
 };
 
 #define TKEY_BUFFER_SIZE 128
+/*
+* We use 1232 as a conservative safe UDP size since Samba currently does not
+* support EDNS(0).
+*/
+#define DNS_MAX_UDP_PACKET_LENGTH ( 1232 )
 
 struct dns_server_tkey_store {
        struct dns_server_tkey **tkeys;