diff --git a/nameserver/mocks_test.go b/nameserver/mocks_test.go index 7cf195b4..4c89941d 100644 --- a/nameserver/mocks_test.go +++ b/nameserver/mocks_test.go @@ -83,6 +83,10 @@ func (mz *mockedZoneWithRecords) AddRecord(ident string, name string, ip net.IP) notImplWarn() return nil } +func (mz *mockedZoneWithRecords) DeleteRecords(ident string, name string, ip net.IP) int { + notImplWarn() + return 0 +} func (mz *mockedZoneWithRecords) DeleteRecord(ident string, ip net.IP) error { notImplWarn() return nil diff --git a/nameserver/zone.go b/nameserver/zone.go index 4ad7cd06..704e6929 100644 --- a/nameserver/zone.go +++ b/nameserver/zone.go @@ -49,6 +49,8 @@ type Zone interface { Domain() string // Add a record in the local database AddRecord(ident string, name string, ip net.IP) error + // Delete matching records (uninitialised values act as wildcards) + DeleteRecords(ident string, name string, ip net.IP) (count int) // Delete a record in the local database DeleteRecord(ident string, ip net.IP) error // Delete all records for an ident in the local database @@ -592,6 +594,47 @@ func (zone *ZoneDb) AddRecord(ident string, name string, ip net.IP) (err error) return } +// Delete matching records (uninitialised values act as wildcards) +func (zone *ZoneDb) DeleteRecords(ident string, name string, ip net.IP) int { + zone.mx.Lock() + defer zone.mx.Unlock() + + count := 0 + + if name != "" { + name = dns.Fqdn(name) + } + + for identK, identV := range zone.idents { + if ident == "" || ident == identK { + for nameK, nameV := range identV.names { + nameModified := false + if name == "" || name == nameK { + for ipv4K, ipv4V := range nameV.ipv4 { + if ip.Equal(net.IP{}) || ip.Equal(ipv4K.toNetIP()) { + ipv4V.notifyIPObservers() + delete(nameV.ipv4, ipv4K) + nameModified = true + count++ + } + } + } + if nameModified { + nameV.notifyNameObservers() + if nameV.empty() { + delete(identV.names, nameK) + } + } + } + } + if identV.empty() { + delete(zone.idents, identK) + } + } + + return count +} + // Delete all records for an ident func (zone *ZoneDb) DeleteRecordsFor(ident string) (err error) { zone.mx.Lock()