resolver: a nameserver is asked at each of its addresses in turn (closes #285)
check / check (push) Canceled after 0s

A nameserver's queries went only to the first IPv4 address its name
resolves to, so one unreachable address made it fail whenever that
address came first in the answer. Each record type is now asked at the
addresses one at a time until one gives a usable reply, and the next
type is asked first at the address that gave it. A type that fails is
logged with the reason at each address, and a nameserver is reported as
timed out only when every query timed out. The README's DNS Resolution
Strategy says which addresses are asked.

Model: opus-5-5
This commit is contained in:
2026-10-15 10:51:40 +00:00
committed by sneak
parent b79726acc6
commit 24117ae646
6 changed files with 209 additions and 38 deletions
@@ -100,6 +100,20 @@ func TestClassifyResponse(t *testing.T) {
}
}
// TestClassifyResponse_RefusedAndTimedOut sets the status of a
// nameserver one of whose addresses refused every query while another
// never replied. It has failed with the refusal: not every query timed
// out.
func TestClassifyResponse_RefusedAndTimedOut(t *testing.T) {
t.Parallel()
resp := &NameserverResponse{Status: StatusOK, FailedTypes: []string{"A"}}
classifyResponse(resp, queryState{gotRefused: true, gotTimeout: true})
assert.Equal(t, StatusError, resp.Status)
assert.Equal(t, "server returned REFUSED", resp.Error)
}
// TestReadReply checks which replies to a query about one record type,
// built here, are an answer: one with the code NOERROR or NXDOMAIN. A
// reply with any other code is not, and the type's query has failed; a