forked from TrueCloudLab/lego
1558 lines
39 KiB
Go
1558 lines
39 KiB
Go
|
package dns
|
||
|
|
||
|
import (
|
||
|
"errors"
|
||
|
"fmt"
|
||
|
"reflect"
|
||
|
"strings"
|
||
|
"sync"
|
||
|
"time"
|
||
|
|
||
|
"github.com/akamai/AkamaiOPEN-edgegrid-golang/client-v1"
|
||
|
)
|
||
|
|
||
|
type name struct {
|
||
|
recordType string
|
||
|
name string
|
||
|
}
|
||
|
|
||
|
var (
|
||
|
cnameNames []name
|
||
|
nonCnameNames []name
|
||
|
zoneWriteLock sync.Mutex
|
||
|
)
|
||
|
|
||
|
// Zone represents a DNS zone
|
||
|
type Zone struct {
|
||
|
Token string `json:"token"`
|
||
|
Zone struct {
|
||
|
Name string `json:"name,omitempty"`
|
||
|
A []*ARecord `json:"a,omitempty"`
|
||
|
Aaaa []*AaaaRecord `json:"aaaa,omitempty"`
|
||
|
Afsdb []*AfsdbRecord `json:"afsdb,omitempty"`
|
||
|
Cname []*CnameRecord `json:"cname,omitempty"`
|
||
|
Dnskey []*DnskeyRecord `json:"dnskey,omitempty"`
|
||
|
Ds []*DsRecord `json:"ds,omitempty"`
|
||
|
Hinfo []*HinfoRecord `json:"hinfo,omitempty"`
|
||
|
Loc []*LocRecord `json:"loc,omitempty"`
|
||
|
Mx []*MxRecord `json:"mx,omitempty"`
|
||
|
Naptr []*NaptrRecord `json:"naptr,omitempty"`
|
||
|
Ns []*NsRecord `json:"ns,omitempty"`
|
||
|
Nsec3 []*Nsec3Record `json:"nsec3,omitempty"`
|
||
|
Nsec3param []*Nsec3paramRecord `json:"nsec3param,omitempty"`
|
||
|
Ptr []*PtrRecord `json:"ptr,omitempty"`
|
||
|
Rp []*RpRecord `json:"rp,omitempty"`
|
||
|
Rrsig []*RrsigRecord `json:"rrsig,omitempty"`
|
||
|
Soa *SoaRecord `json:"soa,omitempty"`
|
||
|
Spf []*SpfRecord `json:"spf,omitempty"`
|
||
|
Srv []*SrvRecord `json:"srv,omitempty"`
|
||
|
Sshfp []*SshfpRecord `json:"sshfp,omitempty"`
|
||
|
Txt []*TxtRecord `json:"txt,omitempty"`
|
||
|
} `json:"zone"`
|
||
|
}
|
||
|
|
||
|
// NewZone creates a new Zone
|
||
|
func NewZone(hostname string) *Zone {
|
||
|
zone := &Zone{Token: "new"}
|
||
|
zone.Zone.Soa = NewSoaRecord()
|
||
|
zone.Zone.Name = hostname
|
||
|
return zone
|
||
|
}
|
||
|
|
||
|
// GetZone retrieves a DNS Zone for a given hostname
|
||
|
func GetZone(hostname string) (*Zone, error) {
|
||
|
zone := NewZone(hostname)
|
||
|
req, err := client.NewRequest(
|
||
|
Config,
|
||
|
"GET",
|
||
|
"/config-dns/v1/zones/"+hostname,
|
||
|
nil,
|
||
|
)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
res, err := client.Do(Config, req)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
if client.IsError(res) && res.StatusCode != 404 {
|
||
|
return nil, client.NewAPIError(res)
|
||
|
} else if res.StatusCode == 404 {
|
||
|
return nil, &ZoneError{zoneName: hostname}
|
||
|
} else {
|
||
|
err = client.BodyJSON(res, &zone)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return zone, nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Save updates the Zone
|
||
|
func (zone *Zone) Save() error {
|
||
|
// This lock will restrict the concurrency of API calls
|
||
|
// to 1 save request at a time. This is needed for the Soa.Serial value which
|
||
|
// is required to be incremented for every subsequent update to a zone
|
||
|
// so we have to save just one request at a time to ensure this is always
|
||
|
// incremented properly
|
||
|
zoneWriteLock.Lock()
|
||
|
defer zoneWriteLock.Unlock()
|
||
|
|
||
|
valid, f := zone.validateCnames()
|
||
|
if valid == false {
|
||
|
var msg string
|
||
|
for _, v := range f {
|
||
|
msg = msg + fmt.Sprintf("\n%s Record '%s' conflicts with CNAME", v.recordType, v.name)
|
||
|
}
|
||
|
return &ZoneError{
|
||
|
zoneName: zone.Zone.Name,
|
||
|
apiErrorMessage: "All CNAMEs must be unique in the zone" + msg,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
req, err := client.NewJSONRequest(
|
||
|
Config,
|
||
|
"POST",
|
||
|
"/config-dns/v1/zones/"+zone.Zone.Name,
|
||
|
zone,
|
||
|
)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
res, err := client.Do(Config, req)
|
||
|
|
||
|
// Network error
|
||
|
if err != nil {
|
||
|
return &ZoneError{
|
||
|
zoneName: zone.Zone.Name,
|
||
|
httpErrorMessage: err.Error(),
|
||
|
err: err,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// API error
|
||
|
if client.IsError(res) {
|
||
|
err := client.NewAPIError(res)
|
||
|
return &ZoneError{zoneName: zone.Zone.Name, apiErrorMessage: err.Detail, err: err}
|
||
|
}
|
||
|
|
||
|
for {
|
||
|
updatedZone, err := GetZone(zone.Zone.Name)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
if updatedZone.Token != zone.Token {
|
||
|
*zone = *updatedZone
|
||
|
break
|
||
|
}
|
||
|
time.Sleep(time.Second)
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) Delete() error {
|
||
|
// remove all the records except for SOA
|
||
|
// which is required and save the zone
|
||
|
zone.Zone.A = nil
|
||
|
zone.Zone.Aaaa = nil
|
||
|
zone.Zone.Afsdb = nil
|
||
|
zone.Zone.Cname = nil
|
||
|
zone.Zone.Dnskey = nil
|
||
|
zone.Zone.Ds = nil
|
||
|
zone.Zone.Hinfo = nil
|
||
|
zone.Zone.Loc = nil
|
||
|
zone.Zone.Mx = nil
|
||
|
zone.Zone.Naptr = nil
|
||
|
zone.Zone.Ns = nil
|
||
|
zone.Zone.Nsec3 = nil
|
||
|
zone.Zone.Nsec3param = nil
|
||
|
zone.Zone.Ptr = nil
|
||
|
zone.Zone.Rp = nil
|
||
|
zone.Zone.Rrsig = nil
|
||
|
zone.Zone.Spf = nil
|
||
|
zone.Zone.Srv = nil
|
||
|
zone.Zone.Sshfp = nil
|
||
|
zone.Zone.Txt = nil
|
||
|
|
||
|
return zone.Save()
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) AddRecord(recordPtr interface{}) error {
|
||
|
switch recordPtr.(type) {
|
||
|
case *ARecord:
|
||
|
zone.addARecord(recordPtr.(*ARecord))
|
||
|
case *AaaaRecord:
|
||
|
zone.addAaaaRecord(recordPtr.(*AaaaRecord))
|
||
|
case *AfsdbRecord:
|
||
|
zone.addAfsdbRecord(recordPtr.(*AfsdbRecord))
|
||
|
case *CnameRecord:
|
||
|
zone.addCnameRecord(recordPtr.(*CnameRecord))
|
||
|
case *DnskeyRecord:
|
||
|
zone.addDnskeyRecord(recordPtr.(*DnskeyRecord))
|
||
|
case *DsRecord:
|
||
|
zone.addDsRecord(recordPtr.(*DsRecord))
|
||
|
case *HinfoRecord:
|
||
|
zone.addHinfoRecord(recordPtr.(*HinfoRecord))
|
||
|
case *LocRecord:
|
||
|
zone.addLocRecord(recordPtr.(*LocRecord))
|
||
|
case *MxRecord:
|
||
|
zone.addMxRecord(recordPtr.(*MxRecord))
|
||
|
case *NaptrRecord:
|
||
|
zone.addNaptrRecord(recordPtr.(*NaptrRecord))
|
||
|
case *NsRecord:
|
||
|
zone.addNsRecord(recordPtr.(*NsRecord))
|
||
|
case *Nsec3Record:
|
||
|
zone.addNsec3Record(recordPtr.(*Nsec3Record))
|
||
|
case *Nsec3paramRecord:
|
||
|
zone.addNsec3paramRecord(recordPtr.(*Nsec3paramRecord))
|
||
|
case *PtrRecord:
|
||
|
zone.addPtrRecord(recordPtr.(*PtrRecord))
|
||
|
case *RpRecord:
|
||
|
zone.addRpRecord(recordPtr.(*RpRecord))
|
||
|
case *RrsigRecord:
|
||
|
zone.addRrsigRecord(recordPtr.(*RrsigRecord))
|
||
|
case *SoaRecord:
|
||
|
zone.addSoaRecord(recordPtr.(*SoaRecord))
|
||
|
case *SpfRecord:
|
||
|
zone.addSpfRecord(recordPtr.(*SpfRecord))
|
||
|
case *SrvRecord:
|
||
|
zone.addSrvRecord(recordPtr.(*SrvRecord))
|
||
|
case *SshfpRecord:
|
||
|
zone.addSshfpRecord(recordPtr.(*SshfpRecord))
|
||
|
case *TxtRecord:
|
||
|
zone.addTxtRecord(recordPtr.(*TxtRecord))
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) RemoveRecord(recordPtr interface{}) error {
|
||
|
switch recordPtr.(type) {
|
||
|
case *ARecord:
|
||
|
return zone.removeARecord(recordPtr.(*ARecord))
|
||
|
case *AaaaRecord:
|
||
|
return zone.removeAaaaRecord(recordPtr.(*AaaaRecord))
|
||
|
case *AfsdbRecord:
|
||
|
return zone.removeAfsdbRecord(recordPtr.(*AfsdbRecord))
|
||
|
case *CnameRecord:
|
||
|
return zone.removeCnameRecord(recordPtr.(*CnameRecord))
|
||
|
case *DnskeyRecord:
|
||
|
return zone.removeDnskeyRecord(recordPtr.(*DnskeyRecord))
|
||
|
case *DsRecord:
|
||
|
return zone.removeDsRecord(recordPtr.(*DsRecord))
|
||
|
case *HinfoRecord:
|
||
|
return zone.removeHinfoRecord(recordPtr.(*HinfoRecord))
|
||
|
case *LocRecord:
|
||
|
return zone.removeLocRecord(recordPtr.(*LocRecord))
|
||
|
case *MxRecord:
|
||
|
return zone.removeMxRecord(recordPtr.(*MxRecord))
|
||
|
case *NaptrRecord:
|
||
|
return zone.removeNaptrRecord(recordPtr.(*NaptrRecord))
|
||
|
case *NsRecord:
|
||
|
return zone.removeNsRecord(recordPtr.(*NsRecord))
|
||
|
case *Nsec3Record:
|
||
|
return zone.removeNsec3Record(recordPtr.(*Nsec3Record))
|
||
|
case *Nsec3paramRecord:
|
||
|
return zone.removeNsec3paramRecord(recordPtr.(*Nsec3paramRecord))
|
||
|
case *PtrRecord:
|
||
|
return zone.removePtrRecord(recordPtr.(*PtrRecord))
|
||
|
case *RpRecord:
|
||
|
return zone.removeRpRecord(recordPtr.(*RpRecord))
|
||
|
case *RrsigRecord:
|
||
|
return zone.removeRrsigRecord(recordPtr.(*RrsigRecord))
|
||
|
case *SoaRecord:
|
||
|
return zone.removeSoaRecord(recordPtr.(*SoaRecord))
|
||
|
case *SpfRecord:
|
||
|
return zone.removeSpfRecord(recordPtr.(*SpfRecord))
|
||
|
case *SrvRecord:
|
||
|
return zone.removeSrvRecord(recordPtr.(*SrvRecord))
|
||
|
case *SshfpRecord:
|
||
|
return zone.removeSshfpRecord(recordPtr.(*SshfpRecord))
|
||
|
case *TxtRecord:
|
||
|
return zone.removeTxtRecord(recordPtr.(*TxtRecord))
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) addARecord(record *ARecord) {
|
||
|
zone.Zone.A = append(zone.Zone.A, record)
|
||
|
nonCnameNames = append(nonCnameNames, name{recordType: "A", name: record.Name})
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) addAaaaRecord(record *AaaaRecord) {
|
||
|
zone.Zone.Aaaa = append(zone.Zone.Aaaa, record)
|
||
|
nonCnameNames = append(nonCnameNames, name{recordType: "AAAA", name: record.Name})
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) addAfsdbRecord(record *AfsdbRecord) {
|
||
|
zone.Zone.Afsdb = append(zone.Zone.Afsdb, record)
|
||
|
nonCnameNames = append(nonCnameNames, name{recordType: "AFSDB", name: record.Name})
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) addCnameRecord(record *CnameRecord) {
|
||
|
zone.Zone.Cname = append(zone.Zone.Cname, record)
|
||
|
cnameNames = append(cnameNames, name{recordType: "CNAME", name: record.Name})
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) addDnskeyRecord(record *DnskeyRecord) {
|
||
|
zone.Zone.Dnskey = append(zone.Zone.Dnskey, record)
|
||
|
nonCnameNames = append(nonCnameNames, name{recordType: "DNSKEY", name: record.Name})
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) addDsRecord(record *DsRecord) {
|
||
|
zone.Zone.Ds = append(zone.Zone.Ds, record)
|
||
|
nonCnameNames = append(nonCnameNames, name{recordType: "DS", name: record.Name})
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) addHinfoRecord(record *HinfoRecord) {
|
||
|
zone.Zone.Hinfo = append(zone.Zone.Hinfo, record)
|
||
|
nonCnameNames = append(nonCnameNames, name{recordType: "HINFO", name: record.Name})
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) addLocRecord(record *LocRecord) {
|
||
|
zone.Zone.Loc = append(zone.Zone.Loc, record)
|
||
|
nonCnameNames = append(nonCnameNames, name{recordType: "LOC", name: record.Name})
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) addMxRecord(record *MxRecord) {
|
||
|
zone.Zone.Mx = append(zone.Zone.Mx, record)
|
||
|
nonCnameNames = append(nonCnameNames, name{recordType: "MX", name: record.Name})
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) addNaptrRecord(record *NaptrRecord) {
|
||
|
zone.Zone.Naptr = append(zone.Zone.Naptr, record)
|
||
|
nonCnameNames = append(nonCnameNames, name{recordType: "NAPTR", name: record.Name})
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) addNsRecord(record *NsRecord) {
|
||
|
zone.Zone.Ns = append(zone.Zone.Ns, record)
|
||
|
nonCnameNames = append(nonCnameNames, name{recordType: "NS", name: record.Name})
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) addNsec3Record(record *Nsec3Record) {
|
||
|
zone.Zone.Nsec3 = append(zone.Zone.Nsec3, record)
|
||
|
nonCnameNames = append(nonCnameNames, name{recordType: "NSEC3", name: record.Name})
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) addNsec3paramRecord(record *Nsec3paramRecord) {
|
||
|
zone.Zone.Nsec3param = append(zone.Zone.Nsec3param, record)
|
||
|
nonCnameNames = append(nonCnameNames, name{recordType: "NSEC3PARAM", name: record.Name})
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) addPtrRecord(record *PtrRecord) {
|
||
|
zone.Zone.Ptr = append(zone.Zone.Ptr, record)
|
||
|
nonCnameNames = append(nonCnameNames, name{recordType: "PTR", name: record.Name})
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) addRpRecord(record *RpRecord) {
|
||
|
zone.Zone.Rp = append(zone.Zone.Rp, record)
|
||
|
nonCnameNames = append(nonCnameNames, name{recordType: "RP", name: record.Name})
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) addRrsigRecord(record *RrsigRecord) {
|
||
|
zone.Zone.Rrsig = append(zone.Zone.Rrsig, record)
|
||
|
nonCnameNames = append(nonCnameNames, name{recordType: "RRSIG", name: record.Name})
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) addSoaRecord(record *SoaRecord) {
|
||
|
// Only one SOA records is allowed
|
||
|
zone.Zone.Soa = record
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) addSpfRecord(record *SpfRecord) {
|
||
|
zone.Zone.Spf = append(zone.Zone.Spf, record)
|
||
|
nonCnameNames = append(nonCnameNames, name{recordType: "SPF", name: record.Name})
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) addSrvRecord(record *SrvRecord) {
|
||
|
zone.Zone.Srv = append(zone.Zone.Srv, record)
|
||
|
nonCnameNames = append(nonCnameNames, name{recordType: "SRV", name: record.Name})
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) addSshfpRecord(record *SshfpRecord) {
|
||
|
zone.Zone.Sshfp = append(zone.Zone.Sshfp, record)
|
||
|
nonCnameNames = append(nonCnameNames, name{recordType: "SSHFP", name: record.Name})
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) addTxtRecord(record *TxtRecord) {
|
||
|
zone.Zone.Txt = append(zone.Zone.Txt, record)
|
||
|
nonCnameNames = append(nonCnameNames, name{recordType: "TXT", name: record.Name})
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) removeARecord(record *ARecord) error {
|
||
|
for key, r := range zone.Zone.A {
|
||
|
if reflect.DeepEqual(r, record) {
|
||
|
records := zone.Zone.A[:key]
|
||
|
if len(zone.Zone.A) > key {
|
||
|
if len(zone.Zone.A) > key {
|
||
|
zone.Zone.A = append(records, zone.Zone.A[key+1:]...)
|
||
|
} else {
|
||
|
zone.Zone.A = records
|
||
|
}
|
||
|
}
|
||
|
zone.removeNonCnameName(record.Name)
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return errors.New("A Record not found")
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) removeAaaaRecord(record *AaaaRecord) error {
|
||
|
for key, r := range zone.Zone.Aaaa {
|
||
|
if reflect.DeepEqual(r, record) {
|
||
|
records := zone.Zone.Aaaa[:key]
|
||
|
if len(zone.Zone.Aaaa) > key {
|
||
|
zone.Zone.Aaaa = append(records, zone.Zone.Aaaa[key+1:]...)
|
||
|
} else {
|
||
|
zone.Zone.Aaaa = records
|
||
|
}
|
||
|
zone.removeNonCnameName(record.Name)
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return errors.New("AAAA Record not found")
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) removeAfsdbRecord(record *AfsdbRecord) error {
|
||
|
for key, r := range zone.Zone.Afsdb {
|
||
|
if reflect.DeepEqual(r, record) {
|
||
|
records := zone.Zone.Afsdb[:key]
|
||
|
if len(zone.Zone.Afsdb) > key {
|
||
|
zone.Zone.Afsdb = append(records, zone.Zone.Afsdb[key+1:]...)
|
||
|
} else {
|
||
|
zone.Zone.Afsdb = records
|
||
|
}
|
||
|
zone.removeNonCnameName(record.Name)
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return errors.New("Afsdb Record not found")
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) removeCnameRecord(record *CnameRecord) error {
|
||
|
for key, r := range zone.Zone.Cname {
|
||
|
if reflect.DeepEqual(r, record) {
|
||
|
records := zone.Zone.Cname[:key]
|
||
|
if len(zone.Zone.Cname) > key {
|
||
|
zone.Zone.Cname = append(records, zone.Zone.Cname[key+1:]...)
|
||
|
} else {
|
||
|
zone.Zone.Cname = records
|
||
|
}
|
||
|
zone.removeNonCnameName(record.Name)
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return errors.New("Cname Record not found")
|
||
|
|
||
|
zone.removeCnameName(record.Name)
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) removeDnskeyRecord(record *DnskeyRecord) error {
|
||
|
for key, r := range zone.Zone.Dnskey {
|
||
|
if reflect.DeepEqual(r, record) {
|
||
|
records := zone.Zone.Dnskey[:key]
|
||
|
if len(zone.Zone.Dnskey) > key {
|
||
|
zone.Zone.Dnskey = append(records, zone.Zone.Dnskey[key+1:]...)
|
||
|
} else {
|
||
|
zone.Zone.Dnskey = records
|
||
|
}
|
||
|
zone.removeNonCnameName(record.Name)
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return errors.New("Dnskey Record not found")
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) removeDsRecord(record *DsRecord) error {
|
||
|
for key, r := range zone.Zone.Ds {
|
||
|
if reflect.DeepEqual(r, record) {
|
||
|
records := zone.Zone.Ds[:key]
|
||
|
if len(zone.Zone.Ds) > key {
|
||
|
zone.Zone.Ds = append(records, zone.Zone.Ds[key+1:]...)
|
||
|
} else {
|
||
|
zone.Zone.Ds = records
|
||
|
}
|
||
|
zone.removeNonCnameName(record.Name)
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return errors.New("Ds Record not found")
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) removeHinfoRecord(record *HinfoRecord) error {
|
||
|
for key, r := range zone.Zone.Hinfo {
|
||
|
if reflect.DeepEqual(r, record) {
|
||
|
records := zone.Zone.Hinfo[:key]
|
||
|
if len(zone.Zone.Hinfo) > key {
|
||
|
zone.Zone.Hinfo = append(records, zone.Zone.Hinfo[key+1:]...)
|
||
|
} else {
|
||
|
zone.Zone.Hinfo = records
|
||
|
}
|
||
|
zone.removeNonCnameName(record.Name)
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return errors.New("Hinfo Record not found")
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) removeLocRecord(record *LocRecord) error {
|
||
|
for key, r := range zone.Zone.Loc {
|
||
|
if reflect.DeepEqual(r, record) {
|
||
|
records := zone.Zone.Loc[:key]
|
||
|
if len(zone.Zone.Loc) > key {
|
||
|
zone.Zone.Loc = append(records, zone.Zone.Loc[key+1:]...)
|
||
|
} else {
|
||
|
zone.Zone.Loc = records
|
||
|
}
|
||
|
zone.removeNonCnameName(record.Name)
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return errors.New("Loc Record not found")
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) removeMxRecord(record *MxRecord) error {
|
||
|
for key, r := range zone.Zone.Mx {
|
||
|
if reflect.DeepEqual(r, record) {
|
||
|
records := zone.Zone.Mx[:key]
|
||
|
if len(zone.Zone.Mx) > key {
|
||
|
zone.Zone.Mx = append(records, zone.Zone.Mx[key+1:]...)
|
||
|
} else {
|
||
|
zone.Zone.Mx = records
|
||
|
}
|
||
|
zone.removeNonCnameName(record.Name)
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return errors.New("Mx Record not found")
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) removeNaptrRecord(record *NaptrRecord) error {
|
||
|
for key, r := range zone.Zone.Naptr {
|
||
|
if reflect.DeepEqual(r, record) {
|
||
|
records := zone.Zone.Naptr[:key]
|
||
|
if len(zone.Zone.Naptr) > key {
|
||
|
zone.Zone.Naptr = append(records, zone.Zone.Naptr[key+1:]...)
|
||
|
} else {
|
||
|
zone.Zone.Naptr = records
|
||
|
}
|
||
|
zone.removeNonCnameName(record.Name)
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return errors.New("Naptr Record not found")
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) removeNsRecord(record *NsRecord) error {
|
||
|
for key, r := range zone.Zone.Ns {
|
||
|
if reflect.DeepEqual(r, record) {
|
||
|
records := zone.Zone.Ns[:key]
|
||
|
if len(zone.Zone.Ns) > key {
|
||
|
zone.Zone.Ns = append(records, zone.Zone.Ns[key+1:]...)
|
||
|
} else {
|
||
|
zone.Zone.Ns = records
|
||
|
}
|
||
|
zone.removeNonCnameName(record.Name)
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return errors.New("Ns Record not found")
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) removeNsec3Record(record *Nsec3Record) error {
|
||
|
for key, r := range zone.Zone.Nsec3 {
|
||
|
if reflect.DeepEqual(r, record) {
|
||
|
records := zone.Zone.Nsec3[:key]
|
||
|
if len(zone.Zone.Nsec3) > key {
|
||
|
zone.Zone.Nsec3 = append(records, zone.Zone.Nsec3[key+1:]...)
|
||
|
} else {
|
||
|
zone.Zone.Nsec3 = records
|
||
|
}
|
||
|
zone.removeNonCnameName(record.Name)
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return errors.New("Nsec3 Record not found")
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) removeNsec3paramRecord(record *Nsec3paramRecord) error {
|
||
|
for key, r := range zone.Zone.Nsec3param {
|
||
|
if reflect.DeepEqual(r, record) {
|
||
|
records := zone.Zone.Nsec3param[:key]
|
||
|
if len(zone.Zone.Nsec3param) > key {
|
||
|
zone.Zone.Nsec3param = append(records, zone.Zone.Nsec3param[key+1:]...)
|
||
|
} else {
|
||
|
zone.Zone.Nsec3param = records
|
||
|
}
|
||
|
zone.removeNonCnameName(record.Name)
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return errors.New("Nsec3param Record not found")
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) removePtrRecord(record *PtrRecord) error {
|
||
|
for key, r := range zone.Zone.Ptr {
|
||
|
if reflect.DeepEqual(r, record) {
|
||
|
records := zone.Zone.Ptr[:key]
|
||
|
if len(zone.Zone.Ptr) > key {
|
||
|
zone.Zone.Ptr = append(records, zone.Zone.Ptr[key+1:]...)
|
||
|
} else {
|
||
|
zone.Zone.Ptr = records
|
||
|
}
|
||
|
zone.removeNonCnameName(record.Name)
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return errors.New("Ptr Record not found")
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) removeRpRecord(record *RpRecord) error {
|
||
|
for key, r := range zone.Zone.Rp {
|
||
|
if reflect.DeepEqual(r, record) {
|
||
|
records := zone.Zone.Rp[:key]
|
||
|
if len(zone.Zone.Rp) > key {
|
||
|
zone.Zone.Rp = append(records, zone.Zone.Rp[key+1:]...)
|
||
|
} else {
|
||
|
zone.Zone.Rp = records
|
||
|
}
|
||
|
zone.removeNonCnameName(record.Name)
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return errors.New("Rp Record not found")
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) removeRrsigRecord(record *RrsigRecord) error {
|
||
|
for key, r := range zone.Zone.Rrsig {
|
||
|
if reflect.DeepEqual(r, record) {
|
||
|
records := zone.Zone.Rrsig[:key]
|
||
|
if len(zone.Zone.Rrsig) > key {
|
||
|
zone.Zone.Rrsig = append(records, zone.Zone.Rrsig[key+1:]...)
|
||
|
} else {
|
||
|
zone.Zone.Rrsig = records
|
||
|
}
|
||
|
zone.removeNonCnameName(record.Name)
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return errors.New("Rrsig Record not found")
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) removeSoaRecord(record *SoaRecord) error {
|
||
|
if reflect.DeepEqual(zone.Zone.Soa, record) {
|
||
|
zone.Zone.Soa = nil
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
return errors.New("SOA Record does not match")
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) removeSpfRecord(record *SpfRecord) error {
|
||
|
for key, r := range zone.Zone.Spf {
|
||
|
if reflect.DeepEqual(r, record) {
|
||
|
records := zone.Zone.Spf[:key]
|
||
|
if len(zone.Zone.Spf) > key {
|
||
|
zone.Zone.Spf = append(records, zone.Zone.Spf[key+1:]...)
|
||
|
} else {
|
||
|
zone.Zone.Spf = records
|
||
|
}
|
||
|
zone.removeNonCnameName(record.Name)
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return errors.New("Spf Record not found")
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) removeSrvRecord(record *SrvRecord) error {
|
||
|
for key, r := range zone.Zone.Srv {
|
||
|
if reflect.DeepEqual(r, record) {
|
||
|
records := zone.Zone.Srv[:key]
|
||
|
if len(zone.Zone.Srv) > key {
|
||
|
zone.Zone.Srv = append(records, zone.Zone.Srv[key+1:]...)
|
||
|
} else {
|
||
|
zone.Zone.Srv = records
|
||
|
}
|
||
|
zone.removeNonCnameName(record.Name)
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return errors.New("Srv Record not found")
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) removeSshfpRecord(record *SshfpRecord) error {
|
||
|
for key, r := range zone.Zone.Sshfp {
|
||
|
if reflect.DeepEqual(r, record) {
|
||
|
records := zone.Zone.Sshfp[:key]
|
||
|
if len(zone.Zone.Sshfp) > key {
|
||
|
zone.Zone.Sshfp = append(records, zone.Zone.Sshfp[key+1:]...)
|
||
|
} else {
|
||
|
zone.Zone.Sshfp = records
|
||
|
}
|
||
|
zone.removeNonCnameName(record.Name)
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return errors.New("Sshfp Record not found")
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) removeTxtRecord(record *TxtRecord) error {
|
||
|
for key, r := range zone.Zone.Txt {
|
||
|
if reflect.DeepEqual(r, record) {
|
||
|
records := zone.Zone.Txt[:key]
|
||
|
if len(zone.Zone.Txt) > key {
|
||
|
zone.Zone.Txt = append(records, zone.Zone.Txt[key+1:]...)
|
||
|
} else {
|
||
|
zone.Zone.Txt = records
|
||
|
}
|
||
|
zone.removeNonCnameName(record.Name)
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return errors.New("Txt Record not found")
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) PreMarshalJSON() error {
|
||
|
if zone.Zone.Soa.Serial > 0 {
|
||
|
zone.Zone.Soa.Serial = zone.Zone.Soa.Serial + 1
|
||
|
} else {
|
||
|
zone.Zone.Soa.Serial = uint(time.Now().Unix())
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) validateCnames() (bool, []name) {
|
||
|
var valid bool = true
|
||
|
var failedRecords []name
|
||
|
for _, v := range cnameNames {
|
||
|
for _, vv := range nonCnameNames {
|
||
|
if v.name == vv.name {
|
||
|
valid = false
|
||
|
failedRecords = append(failedRecords, vv)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return valid, failedRecords
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) removeCnameName(host string) {
|
||
|
for i, v := range cnameNames {
|
||
|
if v.name == host {
|
||
|
r := cnameNames[:i]
|
||
|
cnameNames = append(r, cnameNames[i+1:]...)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) removeNonCnameName(host string) {
|
||
|
for i, v := range nonCnameNames {
|
||
|
if v.name == host {
|
||
|
r := nonCnameNames[:i]
|
||
|
nonCnameNames = append(r, nonCnameNames[i+1:]...)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) FindRecords(recordType string, options map[string]interface{}) []DNSRecord {
|
||
|
switch strings.ToUpper(recordType) {
|
||
|
case "A":
|
||
|
return zone.findARecord(options)
|
||
|
case "AAAA":
|
||
|
return zone.findAaaaRecord(options)
|
||
|
case "AFSDB":
|
||
|
return zone.findAfsdbRecord(options)
|
||
|
case "CNAME":
|
||
|
return zone.findCnameRecord(options)
|
||
|
case "DNSKEY":
|
||
|
return zone.findDnskeyRecord(options)
|
||
|
case "DS":
|
||
|
return zone.findDsRecord(options)
|
||
|
case "HINFO":
|
||
|
return zone.findHinfoRecord(options)
|
||
|
case "LOC":
|
||
|
return zone.findLocRecord(options)
|
||
|
case "MX":
|
||
|
return zone.findMxRecord(options)
|
||
|
case "NAPTR":
|
||
|
return zone.findNaptrRecord(options)
|
||
|
case "NS":
|
||
|
return zone.findNsRecord(options)
|
||
|
case "NSEC3":
|
||
|
return zone.findNsec3Record(options)
|
||
|
case "NSEC3PARAM":
|
||
|
return zone.findNsec3paramRecord(options)
|
||
|
case "PTR":
|
||
|
return zone.findPtrRecord(options)
|
||
|
case "RP":
|
||
|
return zone.findRpRecord(options)
|
||
|
case "RRSIG":
|
||
|
return zone.findRrsigRecord(options)
|
||
|
case "SPF":
|
||
|
return zone.findSpfRecord(options)
|
||
|
case "SRV":
|
||
|
return zone.findSrvRecord(options)
|
||
|
case "SSHFP":
|
||
|
return zone.findSshfpRecord(options)
|
||
|
case "TXT":
|
||
|
return zone.findTxtRecord(options)
|
||
|
}
|
||
|
|
||
|
return make([]DNSRecord, 0)
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) findARecord(options map[string]interface{}) []DNSRecord {
|
||
|
found := make([]DNSRecord, 0)
|
||
|
matchesNeeded := len(options)
|
||
|
for _, record := range zone.Zone.A {
|
||
|
matchCounter := 0
|
||
|
if name, ok := options["name"]; ok && record.Name == name.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if target, ok := options["target"]; ok && record.Target == target.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if active, ok := options["active"]; ok && record.Active == active.(bool) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if ttl, ok := options["ttl"]; ok && record.TTL == ttl.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if matchCounter >= matchesNeeded {
|
||
|
found = append(found, record)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return found
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) findAaaaRecord(options map[string]interface{}) []DNSRecord {
|
||
|
found := make([]DNSRecord, 0)
|
||
|
matchesNeeded := len(options)
|
||
|
for _, record := range zone.Zone.Aaaa {
|
||
|
matchCounter := 0
|
||
|
if name, ok := options["name"]; ok && record.Name == name.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if target, ok := options["target"]; ok && record.Target == target.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if active, ok := options["active"]; ok && record.Active == active.(bool) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if ttl, ok := options["ttl"]; ok && record.TTL == ttl.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if matchCounter >= matchesNeeded {
|
||
|
found = append(found, record)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return found
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) findAfsdbRecord(options map[string]interface{}) []DNSRecord {
|
||
|
found := make([]DNSRecord, 0)
|
||
|
matchesNeeded := len(options)
|
||
|
for _, record := range zone.Zone.Afsdb {
|
||
|
matchCounter := 0
|
||
|
if name, ok := options["name"]; ok && record.Name == name.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if target, ok := options["target"]; ok && record.Target == target.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if active, ok := options["active"]; ok && record.Active == active.(bool) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if ttl, ok := options["ttl"]; ok && record.TTL == ttl.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if subtype, ok := options["subtype"]; ok && record.Subtype == subtype.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if matchCounter >= matchesNeeded {
|
||
|
found = append(found, record)
|
||
|
}
|
||
|
}
|
||
|
return found
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) findCnameRecord(options map[string]interface{}) []DNSRecord {
|
||
|
found := make([]DNSRecord, 0)
|
||
|
matchesNeeded := len(options)
|
||
|
for _, record := range zone.Zone.Cname {
|
||
|
matchCounter := 0
|
||
|
if name, ok := options["name"]; ok && record.Name == name.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if target, ok := options["target"]; ok && record.Target == target.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if active, ok := options["active"]; ok && record.Active == active.(bool) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if ttl, ok := options["ttl"]; ok && record.TTL == ttl.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if matchCounter >= matchesNeeded {
|
||
|
found = append(found, record)
|
||
|
}
|
||
|
}
|
||
|
return found
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) findDnskeyRecord(options map[string]interface{}) []DNSRecord {
|
||
|
found := make([]DNSRecord, 0)
|
||
|
matchesNeeded := len(options)
|
||
|
for _, record := range zone.Zone.Dnskey {
|
||
|
matchCounter := 0
|
||
|
if name, ok := options["name"]; ok && record.Name == name.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if active, ok := options["active"]; ok && record.Active == active.(bool) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if ttl, ok := options["ttl"]; ok && record.TTL == ttl.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if flags, ok := options["flags"]; ok && record.Flags == flags.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if protocol, ok := options["protocol"]; ok && record.Protocol == protocol.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if algorithm, ok := options["algorithm"]; ok && record.Algorithm == algorithm.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if key, ok := options["key"]; ok && record.Key == key.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if matchCounter >= matchesNeeded {
|
||
|
found = append(found, record)
|
||
|
}
|
||
|
}
|
||
|
return found
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) findDsRecord(options map[string]interface{}) []DNSRecord {
|
||
|
found := make([]DNSRecord, 0)
|
||
|
matchesNeeded := len(options)
|
||
|
for _, record := range zone.Zone.Ds {
|
||
|
matchCounter := 0
|
||
|
if name, ok := options["name"]; ok && record.Name == name.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if active, ok := options["active"]; ok && record.Active == active.(bool) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if ttl, ok := options["ttl"]; ok && record.TTL == ttl.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if keytag, ok := options["keytag"]; ok && record.Keytag == keytag.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if algorithm, ok := options["algorithm"]; ok && record.Algorithm == algorithm.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if digesttype, ok := options["digesttype"]; ok && record.DigestType == digesttype.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if digest, ok := options["digest"]; ok && record.Digest == digest.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if matchCounter >= matchesNeeded {
|
||
|
found = append(found, record)
|
||
|
}
|
||
|
}
|
||
|
return found
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) findHinfoRecord(options map[string]interface{}) []DNSRecord {
|
||
|
found := make([]DNSRecord, 0)
|
||
|
matchesNeeded := len(options)
|
||
|
for _, record := range zone.Zone.Hinfo {
|
||
|
matchCounter := 0
|
||
|
if name, ok := options["name"]; ok && record.Name == name.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if active, ok := options["active"]; ok && record.Active == active.(bool) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if ttl, ok := options["ttl"]; ok && record.TTL == ttl.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if hardware, ok := options["hardware"]; ok && record.Hardware == hardware.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if software, ok := options["software"]; ok && record.Software == software.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if matchCounter >= matchesNeeded {
|
||
|
found = append(found, record)
|
||
|
}
|
||
|
}
|
||
|
return found
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) findLocRecord(options map[string]interface{}) []DNSRecord {
|
||
|
found := make([]DNSRecord, 0)
|
||
|
matchesNeeded := len(options)
|
||
|
for _, record := range zone.Zone.Loc {
|
||
|
matchCounter := 0
|
||
|
if name, ok := options["name"]; ok && record.Name == name.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if active, ok := options["active"]; ok && record.Active == active.(bool) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if ttl, ok := options["ttl"]; ok && record.TTL == ttl.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if target, ok := options["target"]; ok && record.Target == target.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if matchCounter >= matchesNeeded {
|
||
|
found = append(found, record)
|
||
|
}
|
||
|
}
|
||
|
return found
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) findMxRecord(options map[string]interface{}) []DNSRecord {
|
||
|
found := make([]DNSRecord, 0)
|
||
|
matchesNeeded := len(options)
|
||
|
for _, record := range zone.Zone.Mx {
|
||
|
matchCounter := 0
|
||
|
if name, ok := options["name"]; ok && record.Name == name.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if active, ok := options["active"]; ok && record.Active == active.(bool) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if ttl, ok := options["ttl"]; ok && record.TTL == ttl.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if target, ok := options["target"]; ok && record.Target == target.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if priority, ok := options["priority"]; ok && record.Priority == priority.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if matchCounter >= matchesNeeded {
|
||
|
found = append(found, record)
|
||
|
}
|
||
|
}
|
||
|
return found
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) findNaptrRecord(options map[string]interface{}) []DNSRecord {
|
||
|
found := make([]DNSRecord, 0)
|
||
|
matchesNeeded := len(options)
|
||
|
for _, record := range zone.Zone.Naptr {
|
||
|
matchCounter := 0
|
||
|
if name, ok := options["name"]; ok && record.Name == name.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if active, ok := options["active"]; ok && record.Active == active.(bool) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if ttl, ok := options["ttl"]; ok && record.TTL == ttl.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if order, ok := options["order"]; ok && record.Order == order.(uint16) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if preference, ok := options["preference"]; ok && record.Preference == preference.(uint16) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if flags, ok := options["flags"]; ok && record.Flags == flags.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if service, ok := options["service"]; ok && record.Service == service.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if regexp, ok := options["regexp"]; ok && record.Regexp == regexp.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if replacement, ok := options["replacement"]; ok && record.Replacement == replacement.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if matchCounter >= matchesNeeded {
|
||
|
found = append(found, record)
|
||
|
}
|
||
|
}
|
||
|
return found
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) findNsRecord(options map[string]interface{}) []DNSRecord {
|
||
|
found := make([]DNSRecord, 0)
|
||
|
matchesNeeded := len(options)
|
||
|
for _, record := range zone.Zone.Ns {
|
||
|
matchCounter := 0
|
||
|
if name, ok := options["name"]; ok && record.Name == name.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if active, ok := options["active"]; ok && record.Active == active.(bool) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if ttl, ok := options["ttl"]; ok && record.TTL == ttl.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if target, ok := options["target"]; ok && record.Target == target.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if matchCounter >= matchesNeeded {
|
||
|
found = append(found, record)
|
||
|
}
|
||
|
}
|
||
|
return found
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) findNsec3Record(options map[string]interface{}) []DNSRecord {
|
||
|
found := make([]DNSRecord, 0)
|
||
|
matchesNeeded := len(options)
|
||
|
for _, record := range zone.Zone.Nsec3 {
|
||
|
matchCounter := 0
|
||
|
if name, ok := options["name"]; ok && record.Name == name.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if active, ok := options["active"]; ok && record.Active == active.(bool) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if ttl, ok := options["ttl"]; ok && record.TTL == ttl.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if algorithm, ok := options["algorithm"]; ok && record.Algorithm == algorithm.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if flags, ok := options["flags"]; ok && record.Flags == flags.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if iterations, ok := options["iterations"]; ok && record.Iterations == iterations.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if salt, ok := options["salt"]; ok && record.Salt == salt.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if nextHashedOwnerName, ok := options["nextHashedOwnerName"]; ok && record.NextHashedOwnerName == nextHashedOwnerName.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if typeBitmaps, ok := options["typeBitmaps"]; ok && record.TypeBitmaps == typeBitmaps.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if matchCounter >= matchesNeeded {
|
||
|
found = append(found, record)
|
||
|
}
|
||
|
}
|
||
|
return found
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) findNsec3paramRecord(options map[string]interface{}) []DNSRecord {
|
||
|
found := make([]DNSRecord, 0)
|
||
|
matchesNeeded := len(options)
|
||
|
for _, record := range zone.Zone.Nsec3param {
|
||
|
matchCounter := 0
|
||
|
if name, ok := options["name"]; ok && record.Name == name.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if active, ok := options["active"]; ok && record.Active == active.(bool) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if ttl, ok := options["ttl"]; ok && record.TTL == ttl.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if algorithm, ok := options["algorithm"]; ok && record.Algorithm == algorithm.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if flags, ok := options["flags"]; ok && record.Flags == flags.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if iterations, ok := options["iterations"]; ok && record.Iterations == iterations.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if salt, ok := options["salt"]; ok && record.Salt == salt.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if matchCounter >= matchesNeeded {
|
||
|
found = append(found, record)
|
||
|
}
|
||
|
}
|
||
|
return found
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) findPtrRecord(options map[string]interface{}) []DNSRecord {
|
||
|
found := make([]DNSRecord, 0)
|
||
|
matchesNeeded := len(options)
|
||
|
for _, record := range zone.Zone.Ptr {
|
||
|
matchCounter := 0
|
||
|
if name, ok := options["name"]; ok && record.Name == name.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if active, ok := options["active"]; ok && record.Active == active.(bool) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if ttl, ok := options["ttl"]; ok && record.TTL == ttl.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if target, ok := options["target"]; ok && record.Target == target.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if matchCounter >= matchesNeeded {
|
||
|
found = append(found, record)
|
||
|
}
|
||
|
}
|
||
|
return found
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) findRpRecord(options map[string]interface{}) []DNSRecord {
|
||
|
found := make([]DNSRecord, 0)
|
||
|
matchesNeeded := len(options)
|
||
|
for _, record := range zone.Zone.Rp {
|
||
|
matchCounter := 0
|
||
|
if name, ok := options["name"]; ok && record.Name == name.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if active, ok := options["active"]; ok && record.Active == active.(bool) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if ttl, ok := options["ttl"]; ok && record.TTL == ttl.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if mailbox, ok := options["mailbox"]; ok && record.Mailbox == mailbox.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if txt, ok := options["txt"]; ok && record.Txt == txt.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if matchCounter >= matchesNeeded {
|
||
|
found = append(found, record)
|
||
|
}
|
||
|
}
|
||
|
return found
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) findRrsigRecord(options map[string]interface{}) []DNSRecord {
|
||
|
found := make([]DNSRecord, 0)
|
||
|
matchesNeeded := len(options)
|
||
|
for _, record := range zone.Zone.Rrsig {
|
||
|
matchCounter := 0
|
||
|
if name, ok := options["name"]; ok && record.Name == name.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if active, ok := options["active"]; ok && record.Active == active.(bool) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if ttl, ok := options["ttl"]; ok && record.TTL == ttl.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if typeCovered, ok := options["typeCovered"]; ok && record.TypeCovered == typeCovered.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if algorithm, ok := options["algorithm"]; ok && record.Algorithm == algorithm.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if originalTTL, ok := options["originalTTL"]; ok && record.OriginalTTL == originalTTL.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if expiration, ok := options["expiration"]; ok && record.Expiration == expiration.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if inception, ok := options["inception"]; ok && record.Inception == inception.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if keytag, ok := options["keytag"]; ok && record.Keytag == keytag.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if signer, ok := options["signer"]; ok && record.Signer == signer.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if signature, ok := options["signature"]; ok && record.Signature == signature.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if labels, ok := options["labels"]; ok && record.Labels == labels.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if matchCounter >= matchesNeeded {
|
||
|
found = append(found, record)
|
||
|
}
|
||
|
}
|
||
|
return found
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) findSpfRecord(options map[string]interface{}) []DNSRecord {
|
||
|
found := make([]DNSRecord, 0)
|
||
|
matchesNeeded := len(options)
|
||
|
for _, record := range zone.Zone.Spf {
|
||
|
matchCounter := 0
|
||
|
if name, ok := options["name"]; ok && record.Name == name.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if active, ok := options["active"]; ok && record.Active == active.(bool) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if ttl, ok := options["ttl"]; ok && record.TTL == ttl.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if target, ok := options["target"]; ok && record.Target == target.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if matchCounter >= matchesNeeded {
|
||
|
found = append(found, record)
|
||
|
}
|
||
|
}
|
||
|
return found
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) findSrvRecord(options map[string]interface{}) []DNSRecord {
|
||
|
found := make([]DNSRecord, 0)
|
||
|
matchesNeeded := len(options)
|
||
|
for _, record := range zone.Zone.Srv {
|
||
|
matchCounter := 0
|
||
|
if name, ok := options["name"]; ok && record.Name == name.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if active, ok := options["active"]; ok && record.Active == active.(bool) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if ttl, ok := options["ttl"]; ok && record.TTL == ttl.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if target, ok := options["target"]; ok && record.Target == target.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if priority, ok := options["priority"]; ok && record.Priority == priority.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if weight, ok := options["weight"]; ok && record.Weight == weight.(uint16) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if port, ok := options["port"]; ok && record.Port == port.(uint16) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if matchCounter >= matchesNeeded {
|
||
|
found = append(found, record)
|
||
|
}
|
||
|
}
|
||
|
return found
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) findSshfpRecord(options map[string]interface{}) []DNSRecord {
|
||
|
found := make([]DNSRecord, 0)
|
||
|
matchesNeeded := len(options)
|
||
|
for _, record := range zone.Zone.Sshfp {
|
||
|
matchCounter := 0
|
||
|
if name, ok := options["name"]; ok && record.Name == name.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if active, ok := options["active"]; ok && record.Active == active.(bool) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if ttl, ok := options["ttl"]; ok && record.TTL == ttl.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if algorithm, ok := options["algorithm"]; ok && record.Algorithm == algorithm.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if fingerprintType, ok := options["fingerprintType"]; ok && record.FingerprintType == fingerprintType.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if fingerprint, ok := options["fingerprint"]; ok && record.Fingerprint == fingerprint.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if matchCounter >= matchesNeeded {
|
||
|
found = append(found, record)
|
||
|
}
|
||
|
}
|
||
|
return found
|
||
|
}
|
||
|
|
||
|
func (zone *Zone) findTxtRecord(options map[string]interface{}) []DNSRecord {
|
||
|
found := make([]DNSRecord, 0)
|
||
|
matchesNeeded := len(options)
|
||
|
for _, record := range zone.Zone.Txt {
|
||
|
matchCounter := 0
|
||
|
if name, ok := options["name"]; ok && record.Name == name.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if active, ok := options["active"]; ok && record.Active == active.(bool) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if ttl, ok := options["ttl"]; ok && record.TTL == ttl.(int) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if target, ok := options["target"]; ok && record.Target == target.(string) {
|
||
|
matchCounter++
|
||
|
}
|
||
|
|
||
|
if matchCounter >= matchesNeeded {
|
||
|
found = append(found, record)
|
||
|
}
|
||
|
}
|
||
|
return found
|
||
|
}
|