diff --git a/plugin/cache/cache.go b/plugin/cache/cache.go index bc82bb604..69de55f17 100644 --- a/plugin/cache/cache.go +++ b/plugin/cache/cache.go @@ -163,6 +163,9 @@ func (w *ResponseWriter) WriteMsg(res *dns.Msg) error { var duration time.Duration if mt == response.NameError || mt == response.NoData { duration = computeTTL(msgTTL, w.minnttl, w.nttl) + } else if mt == response.ServerError { + // use default ttl which is 5s + duration = minTTL } else { duration = computeTTL(msgTTL, w.minpttl, w.pttl) } @@ -206,7 +209,7 @@ func (w *ResponseWriter) set(m *dns.Msg, key uint64, mt response.Type, duration i := newItem(m, w.now(), duration) w.pcache.Add(key, i) - case response.NameError, response.NoData: + case response.NameError, response.NoData, response.ServerError: i := newItem(m, w.now(), duration) w.ncache.Add(key, i) diff --git a/plugin/cache/cache_test.go b/plugin/cache/cache_test.go index 790dce7fb..7c65bca64 100644 --- a/plugin/cache/cache_test.go +++ b/plugin/cache/cache_test.go @@ -87,6 +87,34 @@ var cacheTestCases = []cacheTestCase{ }, shouldCache: true, }, + { + RecursionAvailable: true, Authoritative: false, + Case: test.Case{ + Rcode: dns.RcodeServerFailure, + Qname: "example.org.", Qtype: dns.TypeA, + Ns: []dns.RR{}, + }, + in: test.Case{ + Rcode: dns.RcodeServerFailure, + Qname: "example.org.", Qtype: dns.TypeA, + Ns: []dns.RR{}, + }, + shouldCache: true, + }, + { + RecursionAvailable: true, Authoritative: false, + Case: test.Case{ + Rcode: dns.RcodeNotImplemented, + Qname: "example.org.", Qtype: dns.TypeA, + Ns: []dns.RR{}, + }, + in: test.Case{ + Rcode: dns.RcodeNotImplemented, + Qname: "example.org.", Qtype: dns.TypeA, + Ns: []dns.RR{}, + }, + shouldCache: true, + }, { RecursionAvailable: true, Authoritative: true, Case: test.Case{ diff --git a/plugin/pkg/response/typify.go b/plugin/pkg/response/typify.go index 9faa17d7b..f4dd91fa4 100644 --- a/plugin/pkg/response/typify.go +++ b/plugin/pkg/response/typify.go @@ -15,6 +15,8 @@ const ( NoError Type = iota // NameError is a NXDOMAIN in header, SOA in auth. NameError + // ServerError is a set of errors we want to cache, for now it containers SERVFAIL and NOTIMPL. + ServerError // NoData indicates name found, but not the type: NOERROR in header, SOA in auth. NoData // Delegation is a msg with a pointer to another nameserver: NOERROR in header, NS in auth, optionally fluff in additional (not checked). @@ -28,13 +30,14 @@ const ( ) var toString = map[Type]string{ - NoError: "NOERROR", - NameError: "NXDOMAIN", - NoData: "NODATA", - Delegation: "DELEGATION", - Meta: "META", - Update: "UPDATE", - OtherError: "OTHERERROR", + NoError: "NOERROR", + NameError: "NXDOMAIN", + ServerError: "SERVERERROR", + NoData: "NODATA", + Delegation: "DELEGATION", + Meta: "META", + Update: "UPDATE", + OtherError: "OTHERERROR", } func (t Type) String() string { return toString[t] } @@ -106,6 +109,10 @@ func Typify(m *dns.Msg, t time.Time) (Type, *dns.OPT) { return NameError, opt } + if m.Rcode == dns.RcodeServerFailure || m.Rcode == dns.RcodeNotImplemented { + return ServerError, opt + } + if ns > 0 && m.Rcode == dns.RcodeSuccess { return Delegation, opt }