Add IsDuplicate function (#699)
The makes checking for duplicates more efficient, as you don't have to use String() and re-parse elements from it anymore. Fixes #679
This commit is contained in:
parent
f90eb8fb45
commit
df46691620
|
@ -0,0 +1,25 @@
|
||||||
|
package dns
|
||||||
|
|
||||||
|
//go:generate go run duplicate_generate.go
|
||||||
|
|
||||||
|
// IsDuplicate checks of r1 and r2 are duplicates of each other, excluding the TTL.
|
||||||
|
// So this means the header data is equal *and* the RDATA is the same. Return true
|
||||||
|
// is so, otherwise false.
|
||||||
|
// It's is a protocol violation to have identical RRs in a message.
|
||||||
|
func IsDuplicate(r1, r2 RR) bool {
|
||||||
|
if r1.Header().Class != r2.Header().Class {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Header().Rrtype != r2.Header().Rrtype {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !isDulicateName(r1.Header().Name, r2.Header().Name) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// ignore TTL
|
||||||
|
|
||||||
|
return isDuplicateRdata(r1, r2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// isDulicateName checks if the domain names s1 and s2 are equal.
|
||||||
|
func isDulicateName(s1, s2 string) bool { return equal(s1, s2) }
|
|
@ -0,0 +1,158 @@
|
||||||
|
//+build ignore
|
||||||
|
|
||||||
|
// types_generate.go is meant to run with go generate. It will use
|
||||||
|
// go/{importer,types} to track down all the RR struct types. Then for each type
|
||||||
|
// it will generate conversion tables (TypeToRR and TypeToString) and banal
|
||||||
|
// methods (len, Header, copy) based on the struct tags. The generated source is
|
||||||
|
// written to ztypes.go, and is meant to be checked into git.
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"go/format"
|
||||||
|
"go/importer"
|
||||||
|
"go/types"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
var packageHdr = `
|
||||||
|
// Code generated by "go run duplicate_generate.go"; DO NOT EDIT.
|
||||||
|
|
||||||
|
package dns
|
||||||
|
|
||||||
|
`
|
||||||
|
|
||||||
|
func getTypeStruct(t types.Type, scope *types.Scope) (*types.Struct, bool) {
|
||||||
|
st, ok := t.Underlying().(*types.Struct)
|
||||||
|
if !ok {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
if st.Field(0).Type() == scope.Lookup("RR_Header").Type() {
|
||||||
|
return st, false
|
||||||
|
}
|
||||||
|
if st.Field(0).Anonymous() {
|
||||||
|
st, _ := getTypeStruct(st.Field(0).Type(), scope)
|
||||||
|
return st, true
|
||||||
|
}
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Import and type-check the package
|
||||||
|
pkg, err := importer.Default().Import("github.com/miekg/dns")
|
||||||
|
fatalIfErr(err)
|
||||||
|
scope := pkg.Scope()
|
||||||
|
|
||||||
|
// Collect actual types (*X)
|
||||||
|
var namedTypes []string
|
||||||
|
for _, name := range scope.Names() {
|
||||||
|
o := scope.Lookup(name)
|
||||||
|
if o == nil || !o.Exported() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if st, _ := getTypeStruct(o.Type(), scope); st == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if name == "PrivateRR" || name == "RFC3597" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if name == "OPT" || name == "ANY" || name == "IXFR" || name == "AXFR" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
namedTypes = append(namedTypes, o.Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
b := &bytes.Buffer{}
|
||||||
|
b.WriteString(packageHdr)
|
||||||
|
|
||||||
|
// Generate the giant switch that calls the correct function for each type.
|
||||||
|
fmt.Fprint(b, "// isDuplicateRdata calls the rdata specific functions\n")
|
||||||
|
fmt.Fprint(b, "func isDuplicateRdata(r1, r2 RR) bool {\n")
|
||||||
|
fmt.Fprint(b, "switch r1.Header().Rrtype {\n")
|
||||||
|
|
||||||
|
for _, name := range namedTypes {
|
||||||
|
|
||||||
|
o := scope.Lookup(name)
|
||||||
|
_, isEmbedded := getTypeStruct(o.Type(), scope)
|
||||||
|
if isEmbedded {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fmt.Fprintf(b, "case Type%s:\nreturn isDuplicate%s(r1.(*%s), r2.(*%s))\n", name, name, name, name)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(b, "}\nreturn false\n}\n")
|
||||||
|
|
||||||
|
// Generate the duplicate check for each type.
|
||||||
|
fmt.Fprint(b, "// isDuplicate() functions\n\n")
|
||||||
|
for _, name := range namedTypes {
|
||||||
|
|
||||||
|
o := scope.Lookup(name)
|
||||||
|
st, isEmbedded := getTypeStruct(o.Type(), scope)
|
||||||
|
if isEmbedded {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fmt.Fprintf(b, "func isDuplicate%s(r1, r2 *%s) bool {\n", name, name)
|
||||||
|
for i := 1; i < st.NumFields(); i++ {
|
||||||
|
field := st.Field(i).Name()
|
||||||
|
o2 := func(s string) { fmt.Fprintf(b, s+"\n", field, field) }
|
||||||
|
o3 := func(s string) { fmt.Fprintf(b, s+"\n", field, field, field) }
|
||||||
|
|
||||||
|
// For some reason, a and aaaa don't pop up as *types.Slice here (mostly like because the are
|
||||||
|
// *indirectly* defined as a slice in the net package).
|
||||||
|
if _, ok := st.Field(i).Type().(*types.Slice); ok || st.Tag(i) == `dns:"a"` || st.Tag(i) == `dns:"aaaa"` {
|
||||||
|
o2("if len(r1.%s) != len(r2.%s) {\nreturn false\n}")
|
||||||
|
|
||||||
|
if st.Tag(i) == `dns:"cdomain-name"` || st.Tag(i) == `dns:"domain-name"` {
|
||||||
|
o3(`for i := 0; i < len(r1.%s); i++ {
|
||||||
|
if !isDulicateName(r1.%s[i], r2.%s[i]) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}`)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
o3(`for i := 0; i < len(r1.%s); i++ {
|
||||||
|
if r1.%s[i] != r2.%s[i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}`)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
switch st.Tag(i) {
|
||||||
|
case `dns:"-"`:
|
||||||
|
// ignored
|
||||||
|
case `dns:"cdomain-name"`, `dns:"domain-name"`:
|
||||||
|
o2("if !isDulicateName(r1.%s, r2.%s) {\nreturn false\n}")
|
||||||
|
default:
|
||||||
|
o2("if r1.%s != r2.%s {\nreturn false\n}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Fprintf(b, "return true\n}\n\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// gofmt
|
||||||
|
res, err := format.Source(b.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
b.WriteTo(os.Stderr)
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// write result
|
||||||
|
f, err := os.Create("zduplicate.go")
|
||||||
|
fatalIfErr(err)
|
||||||
|
defer f.Close()
|
||||||
|
f.Write(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func fatalIfErr(err error) {
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
package dns
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestDuplicateA(t *testing.T) {
|
||||||
|
a1, _ := NewRR("www.example.org. 2700 IN A 127.0.0.1")
|
||||||
|
a2, _ := NewRR("www.example.org. IN A 127.0.0.1")
|
||||||
|
if !IsDuplicate(a1, a2) {
|
||||||
|
t.Errorf("expected %s/%s to be duplicates, but got false", a1.String(), a2.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
a2, _ = NewRR("www.example.org. IN A 127.0.0.2")
|
||||||
|
if IsDuplicate(a1, a2) {
|
||||||
|
t.Errorf("expected %s/%s not to be duplicates, but got true", a1.String(), a2.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDuplicateTXT(t *testing.T) {
|
||||||
|
a1, _ := NewRR("www.example.org. IN TXT \"aa\"")
|
||||||
|
a2, _ := NewRR("www.example.org. IN TXT \"aa\"")
|
||||||
|
|
||||||
|
if !IsDuplicate(a1, a2) {
|
||||||
|
t.Errorf("expected %s/%s to be duplicates, but got false", a1.String(), a2.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
a2, _ = NewRR("www.example.org. IN TXT \"aa\" \"bb\"")
|
||||||
|
if IsDuplicate(a1, a2) {
|
||||||
|
t.Errorf("expected %s/%s not to be duplicates, but got true", a1.String(), a2.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
a1, _ = NewRR("www.example.org. IN TXT \"aa\" \"bc\"")
|
||||||
|
if IsDuplicate(a1, a2) {
|
||||||
|
t.Errorf("expected %s/%s not to be duplicates, but got true", a1.String(), a2.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDuplicateOwner(t *testing.T) {
|
||||||
|
a1, _ := NewRR("www.example.org. IN A 127.0.0.1")
|
||||||
|
a2, _ := NewRR("www.example.org. IN A 127.0.0.1")
|
||||||
|
if !IsDuplicate(a1, a2) {
|
||||||
|
t.Errorf("expected %s/%s to be duplicates, but got false", a1.String(), a2.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
a2, _ = NewRR("WWw.exaMPle.org. IN A 127.0.0.2")
|
||||||
|
if IsDuplicate(a1, a2) {
|
||||||
|
t.Errorf("expected %s/%s to be duplicates, but got false", a1.String(), a2.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDuplicateDomain(t *testing.T) {
|
||||||
|
a1, _ := NewRR("www.example.org. IN CNAME example.org.")
|
||||||
|
a2, _ := NewRR("www.example.org. IN CNAME example.org.")
|
||||||
|
if !IsDuplicate(a1, a2) {
|
||||||
|
t.Errorf("expected %s/%s to be duplicates, but got false", a1.String(), a2.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
a2, _ = NewRR("www.example.org. IN CNAME exAMPLe.oRG.")
|
||||||
|
if !IsDuplicate(a1, a2) {
|
||||||
|
t.Errorf("expected %s/%s to be duplicates, but got false", a1.String(), a2.String())
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,7 @@ package dns
|
||||||
// rrs.
|
// rrs.
|
||||||
// m is used to store the RRs temporary. If it is nil a new map will be allocated.
|
// m is used to store the RRs temporary. If it is nil a new map will be allocated.
|
||||||
func Dedup(rrs []RR, m map[string]RR) []RR {
|
func Dedup(rrs []RR, m map[string]RR) []RR {
|
||||||
|
|
||||||
if m == nil {
|
if m == nil {
|
||||||
m = make(map[string]RR)
|
m = make(map[string]RR)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,943 @@
|
||||||
|
// Code generated by "go run duplicate_generate.go"; DO NOT EDIT.
|
||||||
|
|
||||||
|
package dns
|
||||||
|
|
||||||
|
// isDuplicateRdata calls the rdata specific functions
|
||||||
|
func isDuplicateRdata(r1, r2 RR) bool {
|
||||||
|
switch r1.Header().Rrtype {
|
||||||
|
case TypeA:
|
||||||
|
return isDuplicateA(r1.(*A), r2.(*A))
|
||||||
|
case TypeAAAA:
|
||||||
|
return isDuplicateAAAA(r1.(*AAAA), r2.(*AAAA))
|
||||||
|
case TypeAFSDB:
|
||||||
|
return isDuplicateAFSDB(r1.(*AFSDB), r2.(*AFSDB))
|
||||||
|
case TypeAVC:
|
||||||
|
return isDuplicateAVC(r1.(*AVC), r2.(*AVC))
|
||||||
|
case TypeCAA:
|
||||||
|
return isDuplicateCAA(r1.(*CAA), r2.(*CAA))
|
||||||
|
case TypeCERT:
|
||||||
|
return isDuplicateCERT(r1.(*CERT), r2.(*CERT))
|
||||||
|
case TypeCNAME:
|
||||||
|
return isDuplicateCNAME(r1.(*CNAME), r2.(*CNAME))
|
||||||
|
case TypeCSYNC:
|
||||||
|
return isDuplicateCSYNC(r1.(*CSYNC), r2.(*CSYNC))
|
||||||
|
case TypeDHCID:
|
||||||
|
return isDuplicateDHCID(r1.(*DHCID), r2.(*DHCID))
|
||||||
|
case TypeDNAME:
|
||||||
|
return isDuplicateDNAME(r1.(*DNAME), r2.(*DNAME))
|
||||||
|
case TypeDNSKEY:
|
||||||
|
return isDuplicateDNSKEY(r1.(*DNSKEY), r2.(*DNSKEY))
|
||||||
|
case TypeDS:
|
||||||
|
return isDuplicateDS(r1.(*DS), r2.(*DS))
|
||||||
|
case TypeEID:
|
||||||
|
return isDuplicateEID(r1.(*EID), r2.(*EID))
|
||||||
|
case TypeEUI48:
|
||||||
|
return isDuplicateEUI48(r1.(*EUI48), r2.(*EUI48))
|
||||||
|
case TypeEUI64:
|
||||||
|
return isDuplicateEUI64(r1.(*EUI64), r2.(*EUI64))
|
||||||
|
case TypeGID:
|
||||||
|
return isDuplicateGID(r1.(*GID), r2.(*GID))
|
||||||
|
case TypeGPOS:
|
||||||
|
return isDuplicateGPOS(r1.(*GPOS), r2.(*GPOS))
|
||||||
|
case TypeHINFO:
|
||||||
|
return isDuplicateHINFO(r1.(*HINFO), r2.(*HINFO))
|
||||||
|
case TypeHIP:
|
||||||
|
return isDuplicateHIP(r1.(*HIP), r2.(*HIP))
|
||||||
|
case TypeKX:
|
||||||
|
return isDuplicateKX(r1.(*KX), r2.(*KX))
|
||||||
|
case TypeL32:
|
||||||
|
return isDuplicateL32(r1.(*L32), r2.(*L32))
|
||||||
|
case TypeL64:
|
||||||
|
return isDuplicateL64(r1.(*L64), r2.(*L64))
|
||||||
|
case TypeLOC:
|
||||||
|
return isDuplicateLOC(r1.(*LOC), r2.(*LOC))
|
||||||
|
case TypeLP:
|
||||||
|
return isDuplicateLP(r1.(*LP), r2.(*LP))
|
||||||
|
case TypeMB:
|
||||||
|
return isDuplicateMB(r1.(*MB), r2.(*MB))
|
||||||
|
case TypeMD:
|
||||||
|
return isDuplicateMD(r1.(*MD), r2.(*MD))
|
||||||
|
case TypeMF:
|
||||||
|
return isDuplicateMF(r1.(*MF), r2.(*MF))
|
||||||
|
case TypeMG:
|
||||||
|
return isDuplicateMG(r1.(*MG), r2.(*MG))
|
||||||
|
case TypeMINFO:
|
||||||
|
return isDuplicateMINFO(r1.(*MINFO), r2.(*MINFO))
|
||||||
|
case TypeMR:
|
||||||
|
return isDuplicateMR(r1.(*MR), r2.(*MR))
|
||||||
|
case TypeMX:
|
||||||
|
return isDuplicateMX(r1.(*MX), r2.(*MX))
|
||||||
|
case TypeNAPTR:
|
||||||
|
return isDuplicateNAPTR(r1.(*NAPTR), r2.(*NAPTR))
|
||||||
|
case TypeNID:
|
||||||
|
return isDuplicateNID(r1.(*NID), r2.(*NID))
|
||||||
|
case TypeNIMLOC:
|
||||||
|
return isDuplicateNIMLOC(r1.(*NIMLOC), r2.(*NIMLOC))
|
||||||
|
case TypeNINFO:
|
||||||
|
return isDuplicateNINFO(r1.(*NINFO), r2.(*NINFO))
|
||||||
|
case TypeNS:
|
||||||
|
return isDuplicateNS(r1.(*NS), r2.(*NS))
|
||||||
|
case TypeNSAPPTR:
|
||||||
|
return isDuplicateNSAPPTR(r1.(*NSAPPTR), r2.(*NSAPPTR))
|
||||||
|
case TypeNSEC:
|
||||||
|
return isDuplicateNSEC(r1.(*NSEC), r2.(*NSEC))
|
||||||
|
case TypeNSEC3:
|
||||||
|
return isDuplicateNSEC3(r1.(*NSEC3), r2.(*NSEC3))
|
||||||
|
case TypeNSEC3PARAM:
|
||||||
|
return isDuplicateNSEC3PARAM(r1.(*NSEC3PARAM), r2.(*NSEC3PARAM))
|
||||||
|
case TypeOPENPGPKEY:
|
||||||
|
return isDuplicateOPENPGPKEY(r1.(*OPENPGPKEY), r2.(*OPENPGPKEY))
|
||||||
|
case TypePTR:
|
||||||
|
return isDuplicatePTR(r1.(*PTR), r2.(*PTR))
|
||||||
|
case TypePX:
|
||||||
|
return isDuplicatePX(r1.(*PX), r2.(*PX))
|
||||||
|
case TypeRKEY:
|
||||||
|
return isDuplicateRKEY(r1.(*RKEY), r2.(*RKEY))
|
||||||
|
case TypeRP:
|
||||||
|
return isDuplicateRP(r1.(*RP), r2.(*RP))
|
||||||
|
case TypeRRSIG:
|
||||||
|
return isDuplicateRRSIG(r1.(*RRSIG), r2.(*RRSIG))
|
||||||
|
case TypeRT:
|
||||||
|
return isDuplicateRT(r1.(*RT), r2.(*RT))
|
||||||
|
case TypeSMIMEA:
|
||||||
|
return isDuplicateSMIMEA(r1.(*SMIMEA), r2.(*SMIMEA))
|
||||||
|
case TypeSOA:
|
||||||
|
return isDuplicateSOA(r1.(*SOA), r2.(*SOA))
|
||||||
|
case TypeSPF:
|
||||||
|
return isDuplicateSPF(r1.(*SPF), r2.(*SPF))
|
||||||
|
case TypeSRV:
|
||||||
|
return isDuplicateSRV(r1.(*SRV), r2.(*SRV))
|
||||||
|
case TypeSSHFP:
|
||||||
|
return isDuplicateSSHFP(r1.(*SSHFP), r2.(*SSHFP))
|
||||||
|
case TypeTA:
|
||||||
|
return isDuplicateTA(r1.(*TA), r2.(*TA))
|
||||||
|
case TypeTALINK:
|
||||||
|
return isDuplicateTALINK(r1.(*TALINK), r2.(*TALINK))
|
||||||
|
case TypeTKEY:
|
||||||
|
return isDuplicateTKEY(r1.(*TKEY), r2.(*TKEY))
|
||||||
|
case TypeTLSA:
|
||||||
|
return isDuplicateTLSA(r1.(*TLSA), r2.(*TLSA))
|
||||||
|
case TypeTSIG:
|
||||||
|
return isDuplicateTSIG(r1.(*TSIG), r2.(*TSIG))
|
||||||
|
case TypeTXT:
|
||||||
|
return isDuplicateTXT(r1.(*TXT), r2.(*TXT))
|
||||||
|
case TypeUID:
|
||||||
|
return isDuplicateUID(r1.(*UID), r2.(*UID))
|
||||||
|
case TypeUINFO:
|
||||||
|
return isDuplicateUINFO(r1.(*UINFO), r2.(*UINFO))
|
||||||
|
case TypeURI:
|
||||||
|
return isDuplicateURI(r1.(*URI), r2.(*URI))
|
||||||
|
case TypeX25:
|
||||||
|
return isDuplicateX25(r1.(*X25), r2.(*X25))
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// isDuplicate() functions
|
||||||
|
|
||||||
|
func isDuplicateA(r1, r2 *A) bool {
|
||||||
|
if len(r1.A) != len(r2.A) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i := 0; i < len(r1.A); i++ {
|
||||||
|
if r1.A[i] != r2.A[i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateAAAA(r1, r2 *AAAA) bool {
|
||||||
|
if len(r1.AAAA) != len(r2.AAAA) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i := 0; i < len(r1.AAAA); i++ {
|
||||||
|
if r1.AAAA[i] != r2.AAAA[i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateAFSDB(r1, r2 *AFSDB) bool {
|
||||||
|
if r1.Subtype != r2.Subtype {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !isDulicateName(r1.Hostname, r2.Hostname) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateAVC(r1, r2 *AVC) bool {
|
||||||
|
if len(r1.Txt) != len(r2.Txt) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i := 0; i < len(r1.Txt); i++ {
|
||||||
|
if r1.Txt[i] != r2.Txt[i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateCAA(r1, r2 *CAA) bool {
|
||||||
|
if r1.Flag != r2.Flag {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Tag != r2.Tag {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Value != r2.Value {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateCERT(r1, r2 *CERT) bool {
|
||||||
|
if r1.Type != r2.Type {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.KeyTag != r2.KeyTag {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Algorithm != r2.Algorithm {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Certificate != r2.Certificate {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateCNAME(r1, r2 *CNAME) bool {
|
||||||
|
if !isDulicateName(r1.Target, r2.Target) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateCSYNC(r1, r2 *CSYNC) bool {
|
||||||
|
if r1.Serial != r2.Serial {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Flags != r2.Flags {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if len(r1.TypeBitMap) != len(r2.TypeBitMap) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i := 0; i < len(r1.TypeBitMap); i++ {
|
||||||
|
if r1.TypeBitMap[i] != r2.TypeBitMap[i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateDHCID(r1, r2 *DHCID) bool {
|
||||||
|
if r1.Digest != r2.Digest {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateDNAME(r1, r2 *DNAME) bool {
|
||||||
|
if !isDulicateName(r1.Target, r2.Target) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateDNSKEY(r1, r2 *DNSKEY) bool {
|
||||||
|
if r1.Flags != r2.Flags {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Protocol != r2.Protocol {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Algorithm != r2.Algorithm {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.PublicKey != r2.PublicKey {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateDS(r1, r2 *DS) bool {
|
||||||
|
if r1.KeyTag != r2.KeyTag {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Algorithm != r2.Algorithm {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.DigestType != r2.DigestType {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Digest != r2.Digest {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateEID(r1, r2 *EID) bool {
|
||||||
|
if r1.Endpoint != r2.Endpoint {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateEUI48(r1, r2 *EUI48) bool {
|
||||||
|
if r1.Address != r2.Address {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateEUI64(r1, r2 *EUI64) bool {
|
||||||
|
if r1.Address != r2.Address {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateGID(r1, r2 *GID) bool {
|
||||||
|
if r1.Gid != r2.Gid {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateGPOS(r1, r2 *GPOS) bool {
|
||||||
|
if r1.Longitude != r2.Longitude {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Latitude != r2.Latitude {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Altitude != r2.Altitude {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateHINFO(r1, r2 *HINFO) bool {
|
||||||
|
if r1.Cpu != r2.Cpu {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Os != r2.Os {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateHIP(r1, r2 *HIP) bool {
|
||||||
|
if r1.HitLength != r2.HitLength {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.PublicKeyAlgorithm != r2.PublicKeyAlgorithm {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.PublicKeyLength != r2.PublicKeyLength {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Hit != r2.Hit {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.PublicKey != r2.PublicKey {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if len(r1.RendezvousServers) != len(r2.RendezvousServers) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i := 0; i < len(r1.RendezvousServers); i++ {
|
||||||
|
if !isDulicateName(r1.RendezvousServers[i], r2.RendezvousServers[i]) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateKX(r1, r2 *KX) bool {
|
||||||
|
if r1.Preference != r2.Preference {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !isDulicateName(r1.Exchanger, r2.Exchanger) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateL32(r1, r2 *L32) bool {
|
||||||
|
if r1.Preference != r2.Preference {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if len(r1.Locator32) != len(r2.Locator32) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i := 0; i < len(r1.Locator32); i++ {
|
||||||
|
if r1.Locator32[i] != r2.Locator32[i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateL64(r1, r2 *L64) bool {
|
||||||
|
if r1.Preference != r2.Preference {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Locator64 != r2.Locator64 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateLOC(r1, r2 *LOC) bool {
|
||||||
|
if r1.Version != r2.Version {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Size != r2.Size {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.HorizPre != r2.HorizPre {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.VertPre != r2.VertPre {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Latitude != r2.Latitude {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Longitude != r2.Longitude {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Altitude != r2.Altitude {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateLP(r1, r2 *LP) bool {
|
||||||
|
if r1.Preference != r2.Preference {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !isDulicateName(r1.Fqdn, r2.Fqdn) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateMB(r1, r2 *MB) bool {
|
||||||
|
if !isDulicateName(r1.Mb, r2.Mb) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateMD(r1, r2 *MD) bool {
|
||||||
|
if !isDulicateName(r1.Md, r2.Md) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateMF(r1, r2 *MF) bool {
|
||||||
|
if !isDulicateName(r1.Mf, r2.Mf) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateMG(r1, r2 *MG) bool {
|
||||||
|
if !isDulicateName(r1.Mg, r2.Mg) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateMINFO(r1, r2 *MINFO) bool {
|
||||||
|
if !isDulicateName(r1.Rmail, r2.Rmail) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !isDulicateName(r1.Email, r2.Email) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateMR(r1, r2 *MR) bool {
|
||||||
|
if !isDulicateName(r1.Mr, r2.Mr) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateMX(r1, r2 *MX) bool {
|
||||||
|
if r1.Preference != r2.Preference {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !isDulicateName(r1.Mx, r2.Mx) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateNAPTR(r1, r2 *NAPTR) bool {
|
||||||
|
if r1.Order != r2.Order {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Preference != r2.Preference {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Flags != r2.Flags {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Service != r2.Service {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Regexp != r2.Regexp {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !isDulicateName(r1.Replacement, r2.Replacement) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateNID(r1, r2 *NID) bool {
|
||||||
|
if r1.Preference != r2.Preference {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.NodeID != r2.NodeID {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateNIMLOC(r1, r2 *NIMLOC) bool {
|
||||||
|
if r1.Locator != r2.Locator {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateNINFO(r1, r2 *NINFO) bool {
|
||||||
|
if len(r1.ZSData) != len(r2.ZSData) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i := 0; i < len(r1.ZSData); i++ {
|
||||||
|
if r1.ZSData[i] != r2.ZSData[i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateNS(r1, r2 *NS) bool {
|
||||||
|
if !isDulicateName(r1.Ns, r2.Ns) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateNSAPPTR(r1, r2 *NSAPPTR) bool {
|
||||||
|
if !isDulicateName(r1.Ptr, r2.Ptr) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateNSEC(r1, r2 *NSEC) bool {
|
||||||
|
if !isDulicateName(r1.NextDomain, r2.NextDomain) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if len(r1.TypeBitMap) != len(r2.TypeBitMap) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i := 0; i < len(r1.TypeBitMap); i++ {
|
||||||
|
if r1.TypeBitMap[i] != r2.TypeBitMap[i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateNSEC3(r1, r2 *NSEC3) bool {
|
||||||
|
if r1.Hash != r2.Hash {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Flags != r2.Flags {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Iterations != r2.Iterations {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.SaltLength != r2.SaltLength {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Salt != r2.Salt {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.HashLength != r2.HashLength {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.NextDomain != r2.NextDomain {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if len(r1.TypeBitMap) != len(r2.TypeBitMap) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i := 0; i < len(r1.TypeBitMap); i++ {
|
||||||
|
if r1.TypeBitMap[i] != r2.TypeBitMap[i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateNSEC3PARAM(r1, r2 *NSEC3PARAM) bool {
|
||||||
|
if r1.Hash != r2.Hash {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Flags != r2.Flags {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Iterations != r2.Iterations {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.SaltLength != r2.SaltLength {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Salt != r2.Salt {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateOPENPGPKEY(r1, r2 *OPENPGPKEY) bool {
|
||||||
|
if r1.PublicKey != r2.PublicKey {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicatePTR(r1, r2 *PTR) bool {
|
||||||
|
if !isDulicateName(r1.Ptr, r2.Ptr) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicatePX(r1, r2 *PX) bool {
|
||||||
|
if r1.Preference != r2.Preference {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !isDulicateName(r1.Map822, r2.Map822) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !isDulicateName(r1.Mapx400, r2.Mapx400) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateRKEY(r1, r2 *RKEY) bool {
|
||||||
|
if r1.Flags != r2.Flags {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Protocol != r2.Protocol {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Algorithm != r2.Algorithm {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.PublicKey != r2.PublicKey {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateRP(r1, r2 *RP) bool {
|
||||||
|
if !isDulicateName(r1.Mbox, r2.Mbox) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !isDulicateName(r1.Txt, r2.Txt) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateRRSIG(r1, r2 *RRSIG) bool {
|
||||||
|
if r1.TypeCovered != r2.TypeCovered {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Algorithm != r2.Algorithm {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Labels != r2.Labels {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.OrigTtl != r2.OrigTtl {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Expiration != r2.Expiration {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Inception != r2.Inception {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.KeyTag != r2.KeyTag {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !isDulicateName(r1.SignerName, r2.SignerName) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Signature != r2.Signature {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateRT(r1, r2 *RT) bool {
|
||||||
|
if r1.Preference != r2.Preference {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !isDulicateName(r1.Host, r2.Host) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateSMIMEA(r1, r2 *SMIMEA) bool {
|
||||||
|
if r1.Usage != r2.Usage {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Selector != r2.Selector {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.MatchingType != r2.MatchingType {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Certificate != r2.Certificate {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateSOA(r1, r2 *SOA) bool {
|
||||||
|
if !isDulicateName(r1.Ns, r2.Ns) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !isDulicateName(r1.Mbox, r2.Mbox) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Serial != r2.Serial {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Refresh != r2.Refresh {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Retry != r2.Retry {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Expire != r2.Expire {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Minttl != r2.Minttl {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateSPF(r1, r2 *SPF) bool {
|
||||||
|
if len(r1.Txt) != len(r2.Txt) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i := 0; i < len(r1.Txt); i++ {
|
||||||
|
if r1.Txt[i] != r2.Txt[i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateSRV(r1, r2 *SRV) bool {
|
||||||
|
if r1.Priority != r2.Priority {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Weight != r2.Weight {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Port != r2.Port {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !isDulicateName(r1.Target, r2.Target) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateSSHFP(r1, r2 *SSHFP) bool {
|
||||||
|
if r1.Algorithm != r2.Algorithm {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Type != r2.Type {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.FingerPrint != r2.FingerPrint {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateTA(r1, r2 *TA) bool {
|
||||||
|
if r1.KeyTag != r2.KeyTag {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Algorithm != r2.Algorithm {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.DigestType != r2.DigestType {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Digest != r2.Digest {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateTALINK(r1, r2 *TALINK) bool {
|
||||||
|
if !isDulicateName(r1.PreviousName, r2.PreviousName) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !isDulicateName(r1.NextName, r2.NextName) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateTKEY(r1, r2 *TKEY) bool {
|
||||||
|
if !isDulicateName(r1.Algorithm, r2.Algorithm) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Inception != r2.Inception {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Expiration != r2.Expiration {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Mode != r2.Mode {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Error != r2.Error {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.KeySize != r2.KeySize {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Key != r2.Key {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.OtherLen != r2.OtherLen {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.OtherData != r2.OtherData {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateTLSA(r1, r2 *TLSA) bool {
|
||||||
|
if r1.Usage != r2.Usage {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Selector != r2.Selector {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.MatchingType != r2.MatchingType {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Certificate != r2.Certificate {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateTSIG(r1, r2 *TSIG) bool {
|
||||||
|
if !isDulicateName(r1.Algorithm, r2.Algorithm) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.TimeSigned != r2.TimeSigned {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Fudge != r2.Fudge {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.MACSize != r2.MACSize {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.MAC != r2.MAC {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.OrigId != r2.OrigId {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Error != r2.Error {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.OtherLen != r2.OtherLen {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.OtherData != r2.OtherData {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateTXT(r1, r2 *TXT) bool {
|
||||||
|
if len(r1.Txt) != len(r2.Txt) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i := 0; i < len(r1.Txt); i++ {
|
||||||
|
if r1.Txt[i] != r2.Txt[i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateUID(r1, r2 *UID) bool {
|
||||||
|
if r1.Uid != r2.Uid {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateUINFO(r1, r2 *UINFO) bool {
|
||||||
|
if r1.Uinfo != r2.Uinfo {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateURI(r1, r2 *URI) bool {
|
||||||
|
if r1.Priority != r2.Priority {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Weight != r2.Weight {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Target != r2.Target {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDuplicateX25(r1, r2 *X25) bool {
|
||||||
|
if r1.PSDNAddress != r2.PSDNAddress {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
Loading…
Reference in New Issue