diff options
Diffstat (limited to 'plugin/cache/cache.go')
-rw-r--r-- | plugin/cache/cache.go | 31 |
1 files changed, 30 insertions, 1 deletions
diff --git a/plugin/cache/cache.go b/plugin/cache/cache.go index 59439653f..58a73e72c 100644 --- a/plugin/cache/cache.go +++ b/plugin/cache/cache.go @@ -38,7 +38,9 @@ type Cache struct { duration time.Duration percentage int - staleUpTo time.Duration + // Stale serve + staleUpTo time.Duration + verifyStale bool // Testing. now func() time.Time @@ -227,6 +229,33 @@ func (w *ResponseWriter) Write(buf []byte) (int, error) { return n, err } +// verifyStaleResponseWriter is a response writer that only writes messages if they should replace a +// stale cache entry, and otherwise discards them. +type verifyStaleResponseWriter struct { + *ResponseWriter + refreshed bool // set to true if the last WriteMsg wrote to ResponseWriter, false otherwise. +} + +// newVerifyStaleResponseWriter returns a ResponseWriter to be used when verifying stale cache +// entries. It only forward writes if an entry was successfully refreshed according to RFC8767, +// section 4 (response is NoError or NXDomain), and ignores any other response. +func newVerifyStaleResponseWriter(w *ResponseWriter) *verifyStaleResponseWriter { + return &verifyStaleResponseWriter{ + w, + false, + } +} + +// WriteMsg implements the dns.ResponseWriter interface. +func (w *verifyStaleResponseWriter) WriteMsg(res *dns.Msg) error { + w.refreshed = false + if res.Rcode == dns.RcodeSuccess || res.Rcode == dns.RcodeNameError { + w.refreshed = true + return w.ResponseWriter.WriteMsg(res) // stores to the cache and send to client + } + return nil // else discard +} + const ( maxTTL = dnsutil.MaximumDefaulTTL minTTL = dnsutil.MinimalDefaultTTL |