Files
weave/nameserver/zone.go
T
Michael Bridgen ff45bcf945 Change Lookup method names
The Local was redundant (and inaccurate in the case of the mDNS client
implementation), and otherwise they are too nondescript.
2015-01-12 17:42:23 +00:00

136 lines
2.8 KiB
Go

package nameserver
import (
"github.com/miekg/dns"
. "github.com/zettio/weave/common"
"net"
"sync"
)
const (
RDNS_DOMAIN = "in-addr.arpa."
)
// +1 to also exclude a dot
var rdnsDomainLen = len(RDNS_DOMAIN) + 1
type Lookup interface {
LookupName(name string) (net.IP, error)
LookupInaddr(inaddr string) (string, error)
}
type Zone interface {
AddRecord(ident string, name string, ip net.IP) error
DeleteRecord(ident string, ip net.IP) error
DeleteRecordsFor(ident string) error
Lookup
}
type Record struct {
Ident string
Name string
IP net.IP
}
// Very simple data structure for now, with linear searching.
// TODO: make more sophisticated to improve performance.
type ZoneDb struct {
mx sync.RWMutex
recs []Record
}
type LookupError string
func (ops LookupError) Error() string {
return "Unable to find " + string(ops)
}
type DuplicateError struct {
}
func (dup DuplicateError) Error() string {
return "Tried to add a duplicate entry"
}
func (zone *ZoneDb) indexOf(match func(Record) bool) int {
for i, r := range zone.recs {
if match(r) {
return i
}
}
return -1
}
func (zone *ZoneDb) LookupName(name string) (net.IP, error) {
zone.mx.RLock()
defer zone.mx.RUnlock()
for _, r := range zone.recs {
if r.Name == name {
return r.IP, nil
}
}
return nil, LookupError(name)
}
func (zone *ZoneDb) LookupInaddr(inaddr string) (string, error) {
if revIP := net.ParseIP(inaddr[:len(inaddr)-rdnsDomainLen]); revIP != nil {
revIP4 := revIP.To4()
ip := []byte{revIP4[3], revIP4[2], revIP4[1], revIP4[0]}
Debug.Printf("[zonedb] Looking for address: %+v", ip)
zone.mx.RLock()
defer zone.mx.RUnlock()
for _, r := range zone.recs {
if r.IP.Equal(ip) {
return r.Name, nil
}
}
return "", LookupError(inaddr)
} else {
Warning.Printf("[zonedb] Asked to reverse lookup %s", inaddr)
return "", LookupError(inaddr)
}
}
func (zone *ZoneDb) AddRecord(ident string, name string, ip net.IP) error {
zone.mx.Lock()
defer zone.mx.Unlock()
fqdn := dns.Fqdn(name)
if index := zone.indexOf(
func(r Record) bool {
return r.Name == fqdn && r.IP.Equal(ip) && r.Ident == ident
}); index != -1 {
return DuplicateError{}
}
zone.recs = append(zone.recs, Record{ident, fqdn, ip})
return nil
}
func (zone *ZoneDb) DeleteRecord(ident string, ip net.IP) error {
zone.mx.Lock()
defer zone.mx.Unlock()
if index := zone.indexOf(
func(r Record) bool {
return r.Ident == ident && r.IP.Equal(ip)
}); index == -1 {
return LookupError(ident)
} else {
zone.recs = append(zone.recs[:index], zone.recs[index+1:]...)
}
return nil
}
func (zone *ZoneDb) DeleteRecordsFor(ident string) error {
zone.mx.Lock()
defer zone.mx.Unlock()
w := 0 // write index
for _, r := range zone.recs {
if r.Ident != ident {
zone.recs[w] = r
w++
}
}
zone.recs = zone.recs[:w]
return nil
}