mirror of
https://github.com/coredns/coredns.git
synced 2026-08-20 23:08:28 -04:00
plugin/rewrite: apply rcode rewrites to responses with no records (#8421)
* plugin/rewrite: apply rcode rewrites to record-less responses An rcode rewrite rewrites the message-level RCODE, but the reverter only ran response rules from inside the per-record loops in WriteMsg. When a response carries no answer, authority or additional records - for example a bare SERVFAIL that a downstream plugin returns to a non-EDNS client - none of the loops iterate, so the rcode rewrite was silently skipped and the client received the original RCODE. Apply message-level response rules once when the response has no records, using a small marker interface that mirrors the existing requestExtraRevertRule pattern. This fixes the plugin's documented SERVFAIL-to-NOERROR use case for responses without records. Signed-off-by: Sueun Cho <sueun.dev@gmail.com> * plugin/rewrite: apply fallback rcode rewrites for continue Signed-off-by: Sueun Cho <sueun.dev@gmail.com> --------- Signed-off-by: Sueun Cho <sueun.dev@gmail.com>
This commit is contained in:
@@ -57,24 +57,28 @@ func (rw Rewrite) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg
|
||||
if !rw.DoRevert() {
|
||||
return plugin.NextOrFailure(rw.Name(), rw.Next, ctx, w, r)
|
||||
}
|
||||
rcode, err := plugin.NextOrFailure(rw.Name(), rw.Next, ctx, wr, r)
|
||||
if plugin.ClientWrite(rcode) {
|
||||
return rcode, err
|
||||
}
|
||||
// The next plugins didn't write a response, so write one now with the ResponseReverter.
|
||||
// If server.ServeDNS does this then it will create an answer mismatch.
|
||||
res := new(dns.Msg).SetRcode(r, rcode)
|
||||
state.SizeAndDo(res)
|
||||
wr.WriteMsg(res)
|
||||
// return success, so server does not write a second error response to client
|
||||
return dns.RcodeSuccess, err
|
||||
return rw.serveWithResponseReverter(ctx, wr, r, state)
|
||||
}
|
||||
}
|
||||
}
|
||||
if !rw.DoRevert() || len(wr.ResponseRules) == 0 {
|
||||
return plugin.NextOrFailure(rw.Name(), rw.Next, ctx, w, r)
|
||||
}
|
||||
return plugin.NextOrFailure(rw.Name(), rw.Next, ctx, wr, r)
|
||||
return rw.serveWithResponseReverter(ctx, wr, r, state)
|
||||
}
|
||||
|
||||
func (rw Rewrite) serveWithResponseReverter(ctx context.Context, wr *ResponseReverter, r *dns.Msg, state request.Request) (int, error) {
|
||||
rcode, err := plugin.NextOrFailure(rw.Name(), rw.Next, ctx, wr, r)
|
||||
if plugin.ClientWrite(rcode) {
|
||||
return rcode, err
|
||||
}
|
||||
// The next plugins didn't write a response, so write one now with the ResponseReverter.
|
||||
// If server.ServeDNS does this then it will bypass response rewrite rules.
|
||||
res := new(dns.Msg).SetRcode(r, rcode)
|
||||
state.SizeAndDo(res)
|
||||
wr.WriteMsg(res)
|
||||
// Return success so server does not write a second error response to the client.
|
||||
return dns.RcodeSuccess, err
|
||||
}
|
||||
|
||||
// Name implements the Handler interface.
|
||||
|
||||
Reference in New Issue
Block a user