dns

DNS client and server implementations using the Go project's dnsmessage package
Log | Files | Refs | README | LICENSE

commit 60703b621feba1f8aff3879589ef37a0b466801a
parent 2cf560f78905b6f035e5eb06dfeae712d2346370
Author: Oliver Lowe <o@olowe.co>
Date:   Sat, 18 Dec 2021 18:22:45 +1100

cmd/recursor: return error when no more servers to ask

So we eturn SERVFAIL correctly to clients, the same way that
Cloudflare, quad9 et al. do.

Diffstat:
Mcmd/recursor/resolve.go | 21++++-----------------
Mserver.go | 15+++++++++++++++
2 files changed, 19 insertions(+), 17 deletions(-)

diff --git a/cmd/recursor/resolve.go b/cmd/recursor/resolve.go @@ -37,19 +37,6 @@ func filterRRs(rrs []dnsmessage.Resource, n dnsmessage.Name, t dnsmessage.Type) return matches } -func nextServerAddrs(resources []dnsmessage.Resource) []net.IP { - var next []net.IP - for _, r := range resources { - switch b := r.Body.(type) { - case *dnsmessage.AResource: - next = append(next, net.IP(b.A[:])) - case *dnsmessage.AAAAResource: - next = append(next, net.IP(b.AAAA[:])) - } - } - return next -} - func resolveFromRoot(q dnsmessage.Question) (dnsmessage.Message, error) { return resolve(q, roots, 0) } @@ -116,15 +103,15 @@ func resolve(q dnsmessage.Question, next []net.IP, depth int) (dnsmessage.Messag continue } if len(rmsg.Answers) > 0 { - return resolve(q, nextServerAddrs(rmsg.Answers), depth+1) + return resolve(q, dns.ExtractIPs(rmsg.Answers), depth+1) } - return resolve(q, nextServerAddrs(rmsg.Additionals), depth+1) + return resolve(q, dns.ExtractIPs(rmsg.Additionals), depth+1) default: return rmsg, fmt.Errorf("unexpected authority resource type %s", a.Header.Type) } } } - // No real answer, no more servers to ask; return our best guess - return rmsg, nil + // return our best guess anyway + return rmsg, fmt.Errorf("resolve %s: no more nameservers to ask", q.Name) } diff --git a/server.go b/server.go @@ -148,3 +148,18 @@ func DefaultHandler(w ResponseWriter, msg *dnsmessage.Message) { rmsg.Header.RCode = dnsmessage.RCodeNotImplemented w.WriteMsg(rmsg) } + +// ExtractIPs extracts any IP addresses from resources. An empty slice is +// returned if there are no addresses. +func ExtractIPs(resources []dnsmessage.Resource) []net.IP { + var ips []net.IP + for _, r := range resources { + switch b := r.Body.(type) { + case *dnsmessage.AResource: + ips = append(ips, net.IP(b.A[:])) + case *dnsmessage.AAAAResource: + ips = append(ips, net.IP(b.AAAA[:])) + } + } + return ips +}