diff --git a/plugin/autopath/autopath.go b/plugin/autopath/autopath.go index 59d0282bc..f221adc22 100644 --- a/plugin/autopath/autopath.go +++ b/plugin/autopath/autopath.go @@ -123,6 +123,10 @@ func (a *AutoPath) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Ms continue } + if nw.Msg == nil { + continue + } + if nw.Msg.Rcode == dns.RcodeNameError { continue } @@ -135,7 +139,7 @@ func (a *AutoPath) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Ms autoPathCount.WithLabelValues(metrics.WithServer(ctx)).Add(1) return rcode, err } - if plugin.ClientWrite(firstRcode) { + if plugin.ClientWrite(firstRcode) && firstReply != nil { w.WriteMsg(firstReply) } return firstRcode, firstErr diff --git a/plugin/autopath/autopath_test.go b/plugin/autopath/autopath_test.go index 89050bebf..673a6fb09 100644 --- a/plugin/autopath/autopath_test.go +++ b/plugin/autopath/autopath_test.go @@ -106,6 +106,29 @@ func TestAutoPathNoAnswer(t *testing.T) { } } +func TestAutoPathNilMsgFromNext(t *testing.T) { + ap := new(AutoPath) + ap.Zones = []string{"."} + // Simulate a plugin like acl's drop action that returns success + // without writing a response. + ap.Next = test.HandlerFunc(func(_ctx context.Context, _w dns.ResponseWriter, _r *dns.Msg) (int, error) { + return dns.RcodeSuccess, nil + }) + ap.search = []string{"example.org.", "example.com.", "com.", ""} + + m := new(dns.Msg) + m.SetQuestion("b.example.org.", dns.TypeA) + + rec := dnstest.NewRecorder(&test.ResponseWriter{}) + _, err := ap.ServeDNS(context.TODO(), rec, m) + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + if rec.Msg != nil { + t.Fatalf("Expected no client write, but the recorder got a message") + } +} + // nextHandler returns a Handler that returns an answer for the question in the // request per the domain->answer map. On success an RR will be returned: "qname 3600 IN A 127.0.0.53" func nextHandler(mm map[string]int) test.Handler {