coredns-rfc2136/notify.go

63 lines
2 KiB
Go
Raw Permalink Normal View History

package rfc2136
import (
"net"
"time"
"github.com/miekg/dns"
)
// notifyTimeout caps how long any single NOTIFY send can block before
// we give up. RFC 1996 §4 says the master MUST NOT block UPDATE
// acknowledgement on NOTIFY delivery — the secondaries will fall back
// to their own SOA refresh polling if NOTIFY is missed. 2s is plenty
// for a healthy secondary to ack via UDP; a slow/blackholed target
// just times out.
const notifyTimeout = 2 * time.Second
// defaultNotifyPort is appended to any target that doesn't already
// specify host:port. NOTIFY is always-over-port-53 in practice.
const defaultNotifyPort = "53"
// sendNotify dispatches fire-and-forget DNS NOTIFY messages (RFC 1996)
// to every configured secondary for the given zone. Each target gets
// its own goroutine so a slow/blackholed secondary can't slow
// propagation to its siblings.
//
// We do NOT wait for goroutines to finish — the UPDATE response goes
// back to the client immediately. Whether secondaries ack or not, the
// master's job is done; secondaries that miss the NOTIFY pick up the
// new serial on their next refresh poll.
//
// Failures are logged at Debug level. NOTIFY is best-effort; logging
// at Warning would flood the operator on every transient packet drop
// for secondaries that are intermittently reachable.
func sendNotify(zone string, targets []string) {
if len(targets) == 0 {
return
}
for _, t := range targets {
go notifyOne(zone, t)
}
}
// notifyOne sends one NOTIFY packet to `target` for `zone`. Target
// can be "host" (default port 53), "host:port", or "[ipv6]:port".
func notifyOne(zone, target string) {
addr := target
if _, _, err := net.SplitHostPort(addr); err != nil {
addr = net.JoinHostPort(addr, defaultNotifyPort)
}
msg := new(dns.Msg)
msg.SetNotify(dns.Fqdn(zone))
c := &dns.Client{Net: "udp", Timeout: notifyTimeout}
_, _, err := c.Exchange(msg, addr)
if err != nil {
log.Debugf("NOTIFY %s → %s failed: %v", zone, addr, err)
return
}
log.Debugf("NOTIFY %s → %s ok", zone, addr)
}