Classic DNS uses UDP for ordinary queries because one request and one response need no connection setup. Traditional UDP DNS assumed a 512-byte message. Larger answers set TC, telling the client to retry over TCP. TCP frames every DNS message with a two-byte length.
Zone transfers use TCP. Modern responses—especially DNSSEC responses—often need more than 512 bytes, so EDNS lets a client advertise a larger UDP receive size through an OPT pseudo-record. Internet paths can still drop fragmented UDP packets. A commonly conservative payload is 1232 bytes, large enough for useful DNSSEC answers while fitting the IPv6 minimum MTU without fragmentation under normal headers.
TCP is not merely an emergency protocol. Firewalls that assume DNS is UDP-only break standards-compliant resolution.
Cutting the last bytes off an encoded message creates a malformed packet. Correct truncation removes complete records, sets TC, updates section counts, and re-encodes. A useful removal order discards nonessential additional data before authority and answer data. OPT sometimes needs special treatment because it carries the EDNS response.
src/server.rs calculates a response limit from the
caller’s transport limit and the client’s EDNS advertisement. It caps
advertised UDP size, rejects multiple OPT records, responds to
unsupported EDNS versions, and constructs a full typed response. If
encoding exceeds the limit, truncate sets TC and removes
complete records in a defined order until the packet fits. The same core
response logic serves UDP and TCP without treating TCP as a giant UDP
datagram.