From 6c084214ca838150bc5fddb74cc862230ff44073 Mon Sep 17 00:00:00 2001 From: Dan Fuhry Date: Thu, 15 May 2025 17:43:19 -0400 Subject: [PATCH] machines/coredns_plugin: use RWMutex to guard registryStore reads --- machines/coredns_plugin/registry.go | 44 ++++++++++++++++++++--- machines/coredns_plugin/registry_store.go | 16 ++++++--- 2 files changed, 50 insertions(+), 10 deletions(-) diff --git a/machines/coredns_plugin/registry.go b/machines/coredns_plugin/registry.go index 0769e3b..b4da663 100644 --- a/machines/coredns_plugin/registry.go +++ b/machines/coredns_plugin/registry.go @@ -138,6 +138,9 @@ func (r *registry) Shutdown() error { } func (r *registry) defaultDomain() *machines.Domain { + r.store.mu.RLock() + defer r.store.mu.RUnlock() + if r.defDomain != "" { if d, ok := r.store.Domains[r.defDomain]; ok && d != nil { return d @@ -202,6 +205,9 @@ func (r *registry) defaultDomain() *machines.Domain { } func (r *registry) domainFromQuestion(ques dns.Question) *machines.Domain { + r.store.mu.RLock() + defer r.store.mu.RUnlock() + qname := strings.ToLower(strings.TrimSuffix(ques.Name, ".")) for _, domain := range r.store.Domains { if qname == domain.Name || strings.HasSuffix(qname, "."+domain.Name) { @@ -266,10 +272,15 @@ func (r *registry) LookupRecord(ques dns.Question) (int, []dns.RR) { if defDomain := r.defaultDomain(); defDomain != nil { if qname == defDomain.ReverseDNSZoneIPv4 || qname == defDomain.ReverseDNSZoneIPv6 { - return r.lookupApex(ques, defDomain) + code, rrs := r.lookupApex(ques, defDomain) + r.log.V(1).Infof("lookupApex(%s): %+v", qname, rrs) + return code, rrs } } + r.store.mu.RLock() + defer r.store.mu.RUnlock() + for _, domain := range r.store.Domains { myfqdn := fmt.Sprintf("%s.%s", myHostname, domain.Name) @@ -342,6 +353,9 @@ func (r *registry) LookupHost(qname string) (*Result, error) { return r.lookupReverseIPv6(fqdn) } + r.store.mu.RLock() + defer r.store.mu.RUnlock() + var basename, domainName string var domain *machines.Domain @@ -372,6 +386,9 @@ func (r *registry) LookupHost(qname string) (*Result, error) { } func (r *registry) lookupHostLastSeenIface(basename string) (*Result, error) { + r.store.mu.RLock() + defer r.store.mu.RUnlock() + hostID, ok := r.store.HostNames[basename] if !ok { // host not found @@ -404,6 +421,9 @@ func (r *registry) lookupHostLastSeenIface(basename string) (*Result, error) { return nil, nil } + r.log.V(1).Infof("lookupHostLastSeenIface(%s) result: domain %s, host %s, iface %s", + basename, domain.Name, host.Name, iface.Name) + return &Result{ domain: domain, host: host, @@ -412,6 +432,9 @@ func (r *registry) lookupHostLastSeenIface(basename string) (*Result, error) { } func (r *registry) lookupHostWithIface(basename string) (*Result, error) { + r.store.mu.RLock() + defer r.store.mu.RUnlock() + ifaceID, ok := r.store.HostInterfaceNames[basename] if !ok { // host not found @@ -447,6 +470,9 @@ func (r *registry) lookupHostWithIface(basename string) (*Result, error) { return nil, nil } + r.log.V(1).Infof("lookupHostWithIface(%s) result: domain %s, host %s, iface %s", + basename, domain.Name, host.Name, iface.Name) + return &Result{ domain: domain, host: host, @@ -469,6 +495,9 @@ func (r *registry) lookupReverseIPv4(ptrName string) (*Result, error) { return nil, fmt.Errorf("failed to parse IP") } + r.store.mu.RLock() + defer r.store.mu.RUnlock() + var domain *machines.Domain for _, d := range r.store.Domains { if !ip.Mask(d.IPv4PrefixLength.IPMask()).Equal(d.IPv4Address.AsIP()) { @@ -514,6 +543,8 @@ func (r *registry) lookupReverseIPv4(ptrName string) (*Result, error) { } if domain != nil && host != nil && iface != nil { + r.log.V(1).Infof("lookupReverseIPv4(%s) result: domain %s, host %s, iface %s", + ptrName, domain.Name, host.Name, iface.Name) return &Result{ domain: domain, host: host, @@ -540,7 +571,10 @@ func (r *registry) lookupReverseIPv6(ptrName string) (*Result, error) { return nil, fmt.Errorf("failed to parse IP") } - r.log.V(1).Debugf("processing PTR lookup for IP %s", ip.String()) + r.log.V(3).Debugf("processing PTR lookup for IP %s", ip.String()) + + r.store.mu.RLock() + defer r.store.mu.RUnlock() var domain *machines.Domain for _, d := range r.store.Domains { @@ -556,7 +590,7 @@ func (r *registry) lookupReverseIPv6(ptrName string) (*Result, error) { } routerAddress := r.store.Addrs.IPv6[domain.IPv6Address.String()].Address - r.log.Debugf("routerAddress = %s", routerAddress) + r.log.V(3).Debugf("routerAddress = %s", routerAddress) if ip.Equal(routerAddress.AsIP()) { return &Result{ domain: domain, @@ -588,6 +622,8 @@ func (r *registry) lookupReverseIPv6(ptrName string) (*Result, error) { } if domain != nil && host != nil && iface != nil { + r.log.V(1).Infof("lookupReverseIPv6(%s) result: domain %s, host %s, iface %s", + ptrName, domain.Name, host.Name, iface.Name) return &Result{ domain: domain, host: host, @@ -603,8 +639,6 @@ func (r *registry) lookupApex(ques dns.Question, domain *machines.Domain) (int, qname := strings.TrimSuffix(ques.Name, ".") defDomain := r.defaultDomain() - r.log.V(2).Debugf("lookupApex(%s)", ques.Name) - switch ques.Qtype { case dns.TypeSOA: return dns.RcodeSuccess, []dns.RR{ diff --git a/machines/coredns_plugin/registry_store.go b/machines/coredns_plugin/registry_store.go index 8958365..37df43d 100644 --- a/machines/coredns_plugin/registry_store.go +++ b/machines/coredns_plugin/registry_store.go @@ -16,7 +16,7 @@ import ( ) type registryStore struct { - mu sync.Mutex `json:"-"` + mu sync.RWMutex `json:"-"` log log.Logger lastRefresh time.Time @@ -54,8 +54,8 @@ func init() { } func (rs *registryStore) initialized() bool { - rs.mu.Lock() - defer rs.mu.Unlock() + rs.mu.RLock() + defer rs.mu.RUnlock() return rs.Sites != nil && rs.Domains != nil && rs.Hosts != nil && rs.Ifaces != nil && rs.Records != nil } @@ -70,8 +70,8 @@ func (rs *registryStore) saveState() error { } // wait to acquire lock until after initialization check to avoid deadlock - rs.mu.Lock() - defer rs.mu.Unlock() + rs.mu.RLock() + defer rs.mu.RUnlock() contents, err := json.Marshal(rs) if err != nil { @@ -279,6 +279,9 @@ func (rs *registryStore) patchIface(iface *machines.Iface) { } func (rs *registryStore) DomainForFqdn(qname string) *machines.Domain { + rs.mu.RLock() + defer rs.mu.RUnlock() + for _, domain := range rs.Domains { if strings.HasSuffix(qname, "."+domain.Name) { return domain @@ -289,6 +292,9 @@ func (rs *registryStore) DomainForFqdn(qname string) *machines.Domain { } func (rs *registryStore) DomainForAddress(addr net.Addr) *machines.Domain { + rs.mu.RLock() + defer rs.mu.RUnlock() + udpAddr, ok := addr.(*net.UDPAddr) if !ok { return nil -- 2.50.1