The Local was redundant (and inaccurate in the case of the mDNS client implementation), and otherwise they are too nondescript.
136 lines
2.8 KiB
Go
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
|
|
}
|