From: Andréas Leroux Date: Fri, 13 Feb 2026 08:25:55 +0000 (+0100) Subject: s4/dns_server: truncate large dns packets over udp and set truncated flag X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cc07c37fca2d6431e702a8073958742095761a2d;p=thirdparty%2Fsamba.git s4/dns_server: truncate large dns packets over udp and set truncated flag 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 Reviewed-by: Douglas Bagnall Reviewed-by: Gary Lockyer Autobuild-User(master): Jennifer Sutton Autobuild-Date(master): Wed Apr 1 05:08:14 UTC 2026 on atb-devel-224 --- diff --git a/selftest/knownfail.d/dns b/selftest/knownfail.d/dns index 998c50cb320..056270b30bb 100644 --- a/selftest/knownfail.d/dns +++ b/selftest/knownfail.d/dns @@ -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\) diff --git a/source4/dns_server/dns_server.c b/source4/dns_server/dns_server.c index 4e6e0d32a6c..2c666e84ea9 100644 --- a/source4/dns_server/dns_server.c +++ b/source4/dns_server/dns_server.c @@ -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))); diff --git a/source4/dns_server/dns_server.h b/source4/dns_server/dns_server.h index f4e5a61c43f..fa50ca3e23c 100644 --- a/source4/dns_server/dns_server.h +++ b/source4/dns_server/dns_server.h @@ -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;