mirror of
https://github.com/coredns/coredns.git
synced 2026-10-09 03:55:21 -04:00
plugin/dnstap: tap deferred error responses (#8549)
When the plugin chain returns an error rcode without writing a response (it falls off the end, or returns SERVFAIL/REFUSED/FORMERR/NOTIMP), the server generates and sends the error to the client after dnstap's ServeDNS returns, so ResponseWriter.WriteMsg is never called and no CLIENT_RESPONSE dnstap message is emitted. dnstap consumers then see a CLIENT_QUERY with no matching CLIENT_RESPONSE. Synthesize the deferred response and tap it as a CLIENT_RESPONSE, mirroring the deferred-response handling already added to plugin/log. Fixes #6532 Signed-off-by: Saleh <root@lr0.org>
This commit is contained in:
@@ -91,7 +91,22 @@ func (h *Dnstap) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg)
|
||||
// forwarder. Otherwise, the tap messages will come out out of order.
|
||||
h.tapQuery(ctx, w, r, rw.queryTime)
|
||||
|
||||
return plugin.NextOrFailure(h.Name(), h.Next, ctx, rw, r)
|
||||
rcode, err := plugin.NextOrFailure(h.Name(), h.Next, ctx, rw, r)
|
||||
|
||||
// When the plugin chain returns an error rcode without having written a
|
||||
// response (e.g. it falls off the end, or returns SERVFAIL/REFUSED/FORMERR/
|
||||
// NOTIMP), the server generates and sends the error response to the client
|
||||
// after ServeDNS returns, so ResponseWriter.WriteMsg is never called and no
|
||||
// CLIENT_RESPONSE is tapped. Synthesize the deferred response so dnstap
|
||||
// consumers see a CLIENT_RESPONSE matching what the client receives, rather
|
||||
// than a CLIENT_QUERY with no matching response (#6532).
|
||||
if !rw.written && !plugin.ClientWrite(rcode) {
|
||||
deferred := new(dns.Msg)
|
||||
deferred.SetRcode(r, rcode)
|
||||
rw.tapResponse(deferred)
|
||||
}
|
||||
|
||||
return rcode, err
|
||||
}
|
||||
|
||||
// Name implements the plugin.Plugin interface.
|
||||
|
||||
Reference in New Issue
Block a user