← First Pair Library

6 UDP, TCP, EDNS, and truncation

6.1 Why there are two transports

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.

6.2 Truncation must preserve a valid message

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.