plugin/transfer: collect all notify errors instead of shadowing (#8283)

* plugin/transfer: collect all notify errors instead of shadowing

Signed-off-by: ncesam <rybushkin09@bk.ru>

* plugin/transfer: add regression test for notify multiple failures

Signed-off-by: ncesam <rybushkin09@bk.ru>

---------

Signed-off-by: ncesam <rybushkin09@bk.ru>
This commit is contained in:
Ncesam
2026-07-16 05:05:01 +04:00
committed by GitHub
parent 530b0a5ff2
commit 99b683aa41
2 changed files with 65 additions and 3 deletions

View File

@@ -1,6 +1,7 @@
package transfer
import (
"errors"
"fmt"
"net"
@@ -25,17 +26,17 @@ func (t *Transfer) Notify(zone string) error {
}
c := notifyClient(x)
var err1 error
var errs error
for _, t := range x.to {
if t == "*" {
continue
}
if err := sendNotify(c, m, t); err != nil {
err1 = err
errs = errors.Join(errs, err)
}
}
log.Debugf("Sent notifies for zone %q to %v", zone, x.to)
return err1 // this only captures the last error
return errs
}
func notifyClient(x *xfr) *dns.Client {

View File

@@ -2,7 +2,10 @@ package transfer
import (
"net"
"strings"
"testing"
"github.com/miekg/dns"
)
func TestNotifyClientSource(t *testing.T) {
@@ -25,3 +28,61 @@ func TestNotifyClientSource(t *testing.T) {
t.Fatalf("expected source address %s, got %s", source, addr.IP)
}
}
func TestNotifyMultipleFailures(t *testing.T) {
// Start two local UDP listeners returning different rcodes
l1, err := net.ListenPacket("udp", "127.0.0.1:0")
if err != nil {
t.Fatalf("failed to listen: %v", err)
}
defer l1.Close()
l2, err := net.ListenPacket("udp", "127.0.0.1:0")
if err != nil {
t.Fatalf("failed to listen: %v", err)
}
defer l2.Close()
serve := func(conn net.PacketConn, rcode int) {
buf := make([]byte, 512)
for {
n, addr, err := conn.ReadFrom(buf)
if err != nil {
return
}
msg := new(dns.Msg)
if err := msg.Unpack(buf[:n]); err != nil {
continue
}
msg.SetReply(msg)
msg.Rcode = rcode
out, _ := msg.Pack()
conn.WriteTo(out, addr)
}
}
go serve(l1, dns.RcodeServerFailure)
go serve(l2, dns.RcodeRefused)
tr := &Transfer{
xfrs: []*xfr{
{
Zones: []string{"example.com."},
to: []string{l1.LocalAddr().String(), l2.LocalAddr().String()},
},
},
}
err = tr.Notify("example.com.")
if err == nil {
t.Fatal("expected error from Notify, got nil")
}
errStr := err.Error()
if !strings.Contains(errStr, l1.LocalAddr().String()) || !strings.Contains(errStr, "SERVFAIL") {
t.Errorf("expected error to contain %q and SERVFAIL, got: %v", l1.LocalAddr().String(), errStr)
}
if !strings.Contains(errStr, l2.LocalAddr().String()) || !strings.Contains(errStr, "REFUSED") {
t.Errorf("expected error to contain %q and REFUSED, got: %v", l2.LocalAddr().String(), errStr)
}
}