Description
Long history: https://gist.github.com/aojea/32aeaa86aacebcdd93596ecb70fcba4f
DNS UDP messages may be truncated if there are many records,
https://www.rfc-editor.org/rfc/rfc1035#section-4.2.1
Messages carried by UDP are restricted to 512 bytes (not counting
the IP or UDP headers). Longer messages are truncated and the TC
bit is set in the header.
However, TCP also have a size limitation of 65535 bytes
https://www.rfc-editor.org/rfc/rfc1035#section-4.2.2
The message is prefixed with a two byte length field which gives
the message length, excluding the two byte length field.
These limitations makes that the maximum possible number of A records per RRSet is ~ 4090.
There are environments like Kubernetes that may have larger number of records (5000+) that does not fit in a single message. In this cases, the DNS server sets the Truncated bit on the message to indicate that it could not send the full answer despite is using TCP, see coredns/coredns#3660 (comment)
The existing golang resolver returns errNoAnswerFromDNSServer
if it receives a TCP response, discarding all the existing records in the response.
On the contrary, the glibc resolver returns the existing records in the TCP response despite it has the truncated bit set.
We should have the same behaviour in both resolvers, and only retry when the TC bit is set and the connection is UDP,
otherwise, we'll never being able to get an answer and the client will receive an errNoAnswerFromDNSServer, that is not the same behavior as in the glibc resolver.