mirror of
https://github.com/coredns/coredns.git
synced 2025-12-12 05:15:12 -05:00
Merge pull request #58 from miekg/dnssec-serving-nsec
Get positive dnssec stuff going
This commit is contained in:
@@ -8,17 +8,20 @@ import (
|
||||
|
||||
// Less returns <0 when a is less than b, 0 when they are equal and
|
||||
// >0 when a is larger than b.
|
||||
// The function order names in DNSSEC canonical order.
|
||||
// The function orders names in DNSSEC canonical order: RFC 4034s section-6.1
|
||||
//
|
||||
// See http://bert-hubert.blogspot.co.uk/2015/10/how-to-do-fast-canonical-ordering-of.html
|
||||
// for a blog article on how we do this. And https://tools.ietf.org/html/rfc4034#section-6.1 .
|
||||
// for a blog article on this implementation:
|
||||
func Less(a, b string) int {
|
||||
i := 1
|
||||
aj := len(a)
|
||||
bj := len(b)
|
||||
for {
|
||||
ai, _ := dns.PrevLabel(a, i)
|
||||
bi, _ := dns.PrevLabel(b, i)
|
||||
ai, oka := dns.PrevLabel(a, i)
|
||||
bi, okb := dns.PrevLabel(b, i)
|
||||
if oka && okb {
|
||||
return 0
|
||||
}
|
||||
// sadly this []byte will allocate...
|
||||
ab := []byte(a[ai:aj])
|
||||
toLowerAndDDD(ab)
|
||||
|
||||
@@ -21,8 +21,7 @@ func TestCnameLookup(t *testing.T) {
|
||||
defer delete(t, etc, serv.Key)
|
||||
}
|
||||
for _, tc := range dnsTestCasesCname {
|
||||
m := new(dns.Msg)
|
||||
m.SetQuestion(dns.Fqdn(tc.Qname), tc.Qtype)
|
||||
m := tc.Msg()
|
||||
|
||||
rec := middleware.NewResponseRecorder(&middleware.TestResponseWriter{})
|
||||
_, err := etc.ServeDNS(ctx, rec, m)
|
||||
|
||||
@@ -23,8 +23,7 @@ func TestGroupLookup(t *testing.T) {
|
||||
defer delete(t, etc, serv.Key)
|
||||
}
|
||||
for _, tc := range dnsTestCasesGroup {
|
||||
m := new(dns.Msg)
|
||||
m.SetQuestion(dns.Fqdn(tc.Qname), tc.Qtype)
|
||||
m := tc.Msg()
|
||||
|
||||
rec := middleware.NewResponseRecorder(&middleware.TestResponseWriter{})
|
||||
_, err := etc.ServeDNS(ctx, rec, m)
|
||||
|
||||
@@ -26,8 +26,7 @@ func TestMultiLookup(t *testing.T) {
|
||||
defer delete(t, etcMulti, serv.Key)
|
||||
}
|
||||
for _, tc := range dnsTestCasesMulti {
|
||||
m := new(dns.Msg)
|
||||
m.SetQuestion(dns.Fqdn(tc.Qname), tc.Qtype)
|
||||
m := tc.Msg()
|
||||
|
||||
rec := middleware.NewResponseRecorder(&middleware.TestResponseWriter{})
|
||||
_, err := etcMulti.ServeDNS(ctx, rec, m)
|
||||
|
||||
@@ -25,8 +25,7 @@ func TestOtherLookup(t *testing.T) {
|
||||
defer delete(t, etc, serv.Key)
|
||||
}
|
||||
for _, tc := range dnsTestCasesOther {
|
||||
m := new(dns.Msg)
|
||||
m.SetQuestion(dns.Fqdn(tc.Qname), tc.Qtype)
|
||||
m := tc.Msg()
|
||||
|
||||
rec := middleware.NewResponseRecorder(&middleware.TestResponseWriter{})
|
||||
_, err := etc.ServeDNS(ctx, rec, m)
|
||||
|
||||
@@ -65,8 +65,7 @@ func TestLookup(t *testing.T) {
|
||||
defer delete(t, etc, serv.Key)
|
||||
}
|
||||
for _, tc := range dnsTestCases {
|
||||
m := new(dns.Msg)
|
||||
m.SetQuestion(dns.Fqdn(tc.Qname), tc.Qtype)
|
||||
m := tc.Msg()
|
||||
|
||||
rec := middleware.NewResponseRecorder(&middleware.TestResponseWriter{})
|
||||
_, err := etc.ServeDNS(ctx, rec, m)
|
||||
|
||||
64
middleware/file/closest.go
Normal file
64
middleware/file/closest.go
Normal file
@@ -0,0 +1,64 @@
|
||||
package file
|
||||
|
||||
import "github.com/miekg/dns"
|
||||
|
||||
// ClosestEncloser returns the closest encloser for rr.
|
||||
func (z *Zone) ClosestEncloser(rr dns.RR) string {
|
||||
// tree/tree.go does not store a parent *Node pointer, so we can't
|
||||
// just follow up the tree. TODO(miek): fix.
|
||||
|
||||
offset, end := dns.NextLabel(rr.Header().Name, 0)
|
||||
for !end {
|
||||
elem := z.Tree.Get(rr)
|
||||
if elem != nil {
|
||||
return elem.Name()
|
||||
}
|
||||
rr.Header().Name = rr.Header().Name[offset:]
|
||||
|
||||
offset, end = dns.NextLabel(rr.Header().Name, offset)
|
||||
}
|
||||
|
||||
return z.SOA.Header().Name
|
||||
}
|
||||
|
||||
// nameErrorProof finds the closest encloser and return an NSEC that proofs
|
||||
// the wildcard does not exist and an NSEC that proofs the name does no exist.
|
||||
func (z *Zone) nameErrorProof(rr dns.RR) []dns.RR {
|
||||
elem := z.Tree.Prev(rr)
|
||||
if elem == nil {
|
||||
return nil
|
||||
}
|
||||
nsec := z.lookupNSEC(elem, true)
|
||||
nsecIndex := 0
|
||||
for i := 0; i < len(nsec); i++ {
|
||||
if nsec[i].Header().Rrtype == dns.TypeNSEC {
|
||||
nsecIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
ce := z.ClosestEncloser(rr)
|
||||
wildcard := "*." + ce
|
||||
rr.Header().Name = wildcard
|
||||
elem = z.Tree.Prev(rr)
|
||||
if elem == nil {
|
||||
// Root?
|
||||
return nil
|
||||
}
|
||||
nsec1 := z.lookupNSEC(elem, true)
|
||||
nsec1Index := 0
|
||||
for i := 0; i < len(nsec1); i++ {
|
||||
if nsec1[i].Header().Rrtype == dns.TypeNSEC {
|
||||
nsec1Index = i
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Check for duplicate NSEC.
|
||||
if nsec[nsecIndex].Header().Name == nsec1[nsec1Index].Header().Name &&
|
||||
nsec[nsecIndex].(*dns.NSEC).NextDomain == nsec1[nsec1Index].(*dns.NSEC).NextDomain {
|
||||
return nsec
|
||||
}
|
||||
|
||||
return append(nsec, nsec1...)
|
||||
}
|
||||
37
middleware/file/closest_test.go
Normal file
37
middleware/file/closest_test.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package file
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
func TestClosestEncloser(t *testing.T) {
|
||||
z, err := Parse(strings.NewReader(dbMiekNL), testzone, "stdin")
|
||||
if err != nil {
|
||||
t.Fatalf("expect no error when reading zone, got %q", err)
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
in, out string
|
||||
}{
|
||||
{"miek.nl.", "miek.nl."},
|
||||
{"www.miek.nl.", "www.miek.nl."},
|
||||
|
||||
{"blaat.miek.nl.", "miek.nl."},
|
||||
{"blaat.www.miek.nl.", "www.miek.nl."},
|
||||
{"www.blaat.miek.nl.", "miek.nl."},
|
||||
{"blaat.a.miek.nl.", "a.miek.nl."},
|
||||
}
|
||||
|
||||
mk, _ := dns.TypeToRR[dns.TypeA]
|
||||
rr := mk()
|
||||
for _, tc := range tests {
|
||||
rr.Header().Name = tc.in
|
||||
ce := z.ClosestEncloser(rr)
|
||||
if ce != tc.out {
|
||||
t.Errorf("expected ce to be %s for %s, got %s", tc.out, tc.in, ce)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,55 +14,90 @@ import (
|
||||
|
||||
var dnssecTestCases = []coretest.Case{
|
||||
{
|
||||
Qname: "miek.nl.", Qtype: dns.TypeSOA,
|
||||
Qname: "miek.nl.", Qtype: dns.TypeSOA, Do: true,
|
||||
Answer: []dns.RR{
|
||||
// because we sort, this look fishy, but it is OK.
|
||||
coretest.RRSIG("miek.nl. 1800 IN RRSIG SOA 8 2 1800 20160426031301 20160327031301 12051 miek.nl. FIrzy07acBbtyQczy1dc="),
|
||||
coretest.SOA("miek.nl. 1800 IN SOA linode.atoom.net. miek.miek.nl. 1282630057 14400 3600 604800 14400"),
|
||||
},
|
||||
},
|
||||
{
|
||||
Qname: "miek.nl.", Qtype: dns.TypeAAAA,
|
||||
Qname: "miek.nl.", Qtype: dns.TypeAAAA, Do: true,
|
||||
Answer: []dns.RR{
|
||||
coretest.AAAA("miek.nl. 1800 IN AAAA 2a01:7e00::f03c:91ff:fef1:6735"),
|
||||
coretest.RRSIG("miek.nl. 1800 IN RRSIG AAAA 8 2 1800 20160426031301 20160327031301 12051 miek.nl. SsRT="),
|
||||
},
|
||||
},
|
||||
{
|
||||
Qname: "miek.nl.", Qtype: dns.TypeMX,
|
||||
Qname: "miek.nl.", Qtype: dns.TypeMX, Do: true,
|
||||
Answer: []dns.RR{
|
||||
coretest.MX("miek.nl. 1800 IN MX 1 aspmx.l.google.com."),
|
||||
coretest.MX("miek.nl. 1800 IN MX 10 aspmx2.googlemail.com."),
|
||||
coretest.MX("miek.nl. 1800 IN MX 10 aspmx3.googlemail.com."),
|
||||
coretest.MX("miek.nl. 1800 IN MX 5 alt1.aspmx.l.google.com."),
|
||||
coretest.MX("miek.nl. 1800 IN MX 5 alt2.aspmx.l.google.com."),
|
||||
coretest.RRSIG("miek.nl. 1800 IN RRSIG MX 8 2 1800 20160426031301 20160327031301 12051 miek.nl. kLqG+iOr="),
|
||||
},
|
||||
},
|
||||
{
|
||||
Qname: "www.miek.nl.", Qtype: dns.TypeA,
|
||||
Qname: "www.miek.nl.", Qtype: dns.TypeA, Do: true,
|
||||
Answer: []dns.RR{
|
||||
coretest.CNAME("www.miek.nl. 1800 IN CNAME a.miek.nl."),
|
||||
},
|
||||
|
||||
Extra: []dns.RR{
|
||||
coretest.A("a.miek.nl. 1800 IN A 139.162.196.78"),
|
||||
coretest.AAAA("a.miek.nl. 1800 IN AAAA 2a01:7e00::f03c:91ff:fef1:6735"),
|
||||
coretest.RRSIG("a.miek.nl. 1800 IN RRSIG A 8 3 1800 20160426031301 20160327031301 12051 miek.nl. lxLotCjWZ3kihTxk="),
|
||||
},
|
||||
},
|
||||
{
|
||||
Qname: "a.miek.nl.", Qtype: dns.TypeSRV,
|
||||
// NoData
|
||||
Qname: "a.miek.nl.", Qtype: dns.TypeSRV, Do: true,
|
||||
Ns: []dns.RR{
|
||||
coretest.NSEC("a.miek.nl. 14400 IN NSEC archive.miek.nl. A AAAA RRSIG NSEC"),
|
||||
coretest.RRSIG("a.miek.nl. 14400 IN RRSIG NSEC 8 3 14400 20160426031301 20160327031301 12051 miek.nl. GqnF6cutipmSHEao="),
|
||||
coretest.RRSIG("miek.nl. 1800 IN RRSIG SOA 8 2 1800 20160426031301 20160327031301 12051 miek.nl. FIrzy07acBbtyQczy1dc="),
|
||||
coretest.SOA("miek.nl. 1800 IN SOA linode.atoom.net. miek.miek.nl. 1282630057 14400 3600 604800 14400"),
|
||||
},
|
||||
},
|
||||
{
|
||||
Qname: "b.miek.nl.", Qtype: dns.TypeA,
|
||||
Qname: "b.miek.nl.", Qtype: dns.TypeA, Do: true,
|
||||
Rcode: dns.RcodeNameError,
|
||||
Ns: []dns.RR{
|
||||
coretest.NSEC("archive.miek.nl. 14400 IN NSEC go.dns.miek.nl. CNAME RRSIG NSEC"),
|
||||
coretest.RRSIG("archive.miek.nl. 14400 IN RRSIG NSEC 8 3 14400 20160426031301 20160327031301 12051 miek.nl. jEpx8lcp4do5fWXg="),
|
||||
coretest.NSEC("miek.nl. 14400 IN NSEC a.miek.nl. A NS SOA MX AAAA RRSIG NSEC DNSKEY"),
|
||||
coretest.RRSIG("miek.nl. 14400 IN RRSIG NSEC 8 2 14400 20160426031301 20160327031301 12051 miek.nl. mFfc3r/9PSC1H6oSpdC"),
|
||||
coretest.RRSIG("miek.nl. 1800 IN RRSIG SOA 8 2 1800 20160426031301 20160327031301 12051 miek.nl. FIrzy07acBbtyQczy1dc="),
|
||||
coretest.SOA("miek.nl. 1800 IN SOA linode.atoom.net. miek.miek.nl. 1282630057 14400 3600 604800 14400"),
|
||||
},
|
||||
},
|
||||
{
|
||||
Qname: "b.blaat.miek.nl.", Qtype: dns.TypeA, Do: true,
|
||||
Rcode: dns.RcodeNameError,
|
||||
Ns: []dns.RR{
|
||||
coretest.NSEC("archive.miek.nl. 14400 IN NSEC go.dns.miek.nl. CNAME RRSIG NSEC"),
|
||||
coretest.RRSIG("archive.miek.nl. 14400 IN RRSIG NSEC 8 3 14400 20160426031301 20160327031301 12051 miek.nl. jEpx8lcp4do5fWXg="),
|
||||
coretest.NSEC("miek.nl. 14400 IN NSEC a.miek.nl. A NS SOA MX AAAA RRSIG NSEC DNSKEY"),
|
||||
coretest.RRSIG("miek.nl. 14400 IN RRSIG NSEC 8 2 14400 20160426031301 20160327031301 12051 miek.nl. mFfc3r/9PSC1H6oSpdC"),
|
||||
coretest.RRSIG("miek.nl. 1800 IN RRSIG SOA 8 2 1800 20160426031301 20160327031301 12051 miek.nl. FIrzy07acBbtyQczy1dc="),
|
||||
coretest.SOA("miek.nl. 1800 IN SOA linode.atoom.net. miek.miek.nl. 1282630057 14400 3600 604800 14400"),
|
||||
},
|
||||
},
|
||||
{
|
||||
Qname: "b.a.miek.nl.", Qtype: dns.TypeA, Do: true,
|
||||
Rcode: dns.RcodeNameError,
|
||||
Ns: []dns.RR{
|
||||
// dedupped NSEC, because 1 nsec tells all
|
||||
coretest.NSEC("a.miek.nl. 14400 IN NSEC archive.miek.nl. A AAAA RRSIG NSEC"),
|
||||
coretest.RRSIG("a.miek.nl. 14400 IN RRSIG NSEC 8 3 14400 20160426031301 20160327031301 12051 miek.nl. GqnF6cut/RRGPQ1QGQE1ipmSHEao="),
|
||||
coretest.RRSIG("miek.nl. 1800 IN RRSIG SOA 8 2 1800 20160426031301 20160327031301 12051 miek.nl. FIrzy07acBbtyQczy1dc="),
|
||||
coretest.SOA("miek.nl. 1800 IN SOA linode.atoom.net. miek.miek.nl. 1282630057 14400 3600 604800 14400"),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// TODO(miek): enable
|
||||
func testLookupDNSSEC(t *testing.T) {
|
||||
func TestLookupDNSSEC(t *testing.T) {
|
||||
zone, err := Parse(strings.NewReader(dbMiekNL_signed), testzone, "stdin")
|
||||
if err != nil {
|
||||
t.Fatalf("expect no error when reading zone, got %q", err)
|
||||
@@ -72,8 +107,7 @@ func testLookupDNSSEC(t *testing.T) {
|
||||
ctx := context.TODO()
|
||||
|
||||
for _, tc := range dnssecTestCases {
|
||||
m := new(dns.Msg)
|
||||
m.SetQuestion(dns.Fqdn(tc.Qname), tc.Qtype)
|
||||
m := tc.Msg()
|
||||
|
||||
rec := middleware.NewResponseRecorder(&middleware.TestResponseWriter{})
|
||||
_, err := fm.ServeDNS(ctx, rec, m)
|
||||
|
||||
@@ -39,7 +39,7 @@ func (f File) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (i
|
||||
return xfr.ServeDNS(ctx, w, r)
|
||||
}
|
||||
|
||||
rrs, extra, result := z.Lookup(qname, state.QType(), state.Do())
|
||||
answer, ns, extra, result := z.Lookup(qname, state.QType(), state.Do())
|
||||
|
||||
m := new(dns.Msg)
|
||||
m.SetReply(r)
|
||||
@@ -47,18 +47,17 @@ func (f File) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (i
|
||||
|
||||
switch result {
|
||||
case Success:
|
||||
// case?
|
||||
m.Answer = rrs
|
||||
m.Answer = answer
|
||||
m.Ns = ns
|
||||
m.Extra = extra
|
||||
// Ns section
|
||||
case NameError:
|
||||
m.Ns = ns
|
||||
m.Rcode = dns.RcodeNameError
|
||||
fallthrough
|
||||
case NoData:
|
||||
// case?
|
||||
m.Ns = rrs
|
||||
default:
|
||||
// TODO
|
||||
m.Ns = ns
|
||||
case ServerFailure:
|
||||
return dns.RcodeServerFailure, nil
|
||||
}
|
||||
m, _ = state.Scrub(m)
|
||||
w.WriteMsg(m)
|
||||
@@ -78,6 +77,11 @@ func Parse(f io.Reader, origin, fileName string) (*Zone, error) {
|
||||
z.SOA = x.RR.(*dns.SOA)
|
||||
continue
|
||||
}
|
||||
if x.RR.Header().Rrtype == dns.TypeRRSIG {
|
||||
if x, ok := x.RR.(*dns.RRSIG); ok && x.TypeCovered == dns.TypeSOA {
|
||||
z.SIG = append(z.SIG, x)
|
||||
}
|
||||
}
|
||||
z.Insert(x.RR)
|
||||
}
|
||||
return z, nil
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package file
|
||||
|
||||
import "github.com/miekg/dns"
|
||||
import (
|
||||
"github.com/miekg/coredns/middleware/file/tree"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
// Result is the result of a Lookup
|
||||
type Result int
|
||||
@@ -8,19 +12,17 @@ type Result int
|
||||
const (
|
||||
Success Result = iota
|
||||
NameError
|
||||
NoData // aint no offical NoData return code.
|
||||
NoData
|
||||
ServerFailure
|
||||
)
|
||||
|
||||
// Lookup looks up qname and qtype in the zone, when do is true DNSSEC are included as well.
|
||||
// Two sets of records are returned, one for the answer and one for the additional section.
|
||||
func (z *Zone) Lookup(qname string, qtype uint16, do bool) ([]dns.RR, []dns.RR, Result) {
|
||||
// TODO(miek): implement DNSSEC
|
||||
// Three sets of records are returned, one for the answer, one for authority and one for the additional section.
|
||||
func (z *Zone) Lookup(qname string, qtype uint16, do bool) ([]dns.RR, []dns.RR, []dns.RR, Result) {
|
||||
var rr dns.RR
|
||||
mk, known := dns.TypeToRR[qtype]
|
||||
if !known {
|
||||
return nil, nil, NameError
|
||||
// Uhm...?
|
||||
// rr = new(RFC3597)
|
||||
return nil, nil, nil, ServerFailure
|
||||
} else {
|
||||
rr = mk()
|
||||
}
|
||||
@@ -28,41 +30,106 @@ func (z *Zone) Lookup(qname string, qtype uint16, do bool) ([]dns.RR, []dns.RR,
|
||||
return z.lookupSOA(do)
|
||||
}
|
||||
|
||||
// Misuse rr to be a question.
|
||||
rr.Header().Rrtype = qtype
|
||||
rr.Header().Name = qname
|
||||
|
||||
elem := z.Tree.Get(rr)
|
||||
if elem == nil {
|
||||
return []dns.RR{z.SOA}, nil, NameError
|
||||
if elem == nil {
|
||||
return z.nameError(elem, rr, do)
|
||||
}
|
||||
}
|
||||
|
||||
rrs := elem.Types(dns.TypeCNAME)
|
||||
if len(rrs) > 0 { // should only ever be 1 actually; TODO(miek) check for this?
|
||||
// lookup target from the cname
|
||||
rr.Header().Name = rrs[0].(*dns.CNAME).Target
|
||||
elem := z.Tree.Get(rr)
|
||||
if elem == nil {
|
||||
return rrs, nil, Success
|
||||
}
|
||||
return rrs, elem.All(), Success
|
||||
return z.lookupCNAME(rrs, rr, do)
|
||||
}
|
||||
|
||||
rrs = elem.Types(qtype)
|
||||
if len(rrs) == 0 {
|
||||
return []dns.RR{z.SOA}, nil, NoData
|
||||
}
|
||||
// Need to check sub-type on RRSIG records to only include the correctly
|
||||
// typed ones.
|
||||
return rrs, nil, Success
|
||||
return z.noData(elem, do)
|
||||
}
|
||||
|
||||
func (z *Zone) lookupSOA(do bool) ([]dns.RR, []dns.RR, Result) {
|
||||
return []dns.RR{z.SOA}, nil, Success
|
||||
if do {
|
||||
sigs := elem.Types(dns.TypeRRSIG)
|
||||
sigs = signatureForSubType(sigs, qtype)
|
||||
if len(sigs) > 0 {
|
||||
rrs = append(rrs, sigs...)
|
||||
}
|
||||
}
|
||||
return rrs, nil, nil, Success
|
||||
}
|
||||
|
||||
func (z *Zone) noData(elem *tree.Elem, do bool) ([]dns.RR, []dns.RR, []dns.RR, Result) {
|
||||
soa, _, _, _ := z.lookupSOA(do)
|
||||
nsec := z.lookupNSEC(elem, do)
|
||||
return nil, append(soa, nsec...), nil, Success
|
||||
}
|
||||
|
||||
func (z *Zone) nameError(elem *tree.Elem, rr dns.RR, do bool) ([]dns.RR, []dns.RR, []dns.RR, Result) {
|
||||
ret := []dns.RR{z.SOA}
|
||||
if do {
|
||||
ret = append(ret, z.SIG...)
|
||||
ret = append(ret, z.nameErrorProof(rr)...)
|
||||
}
|
||||
return nil, ret, nil, NameError
|
||||
}
|
||||
|
||||
func (z *Zone) lookupSOA(do bool) ([]dns.RR, []dns.RR, []dns.RR, Result) {
|
||||
if do {
|
||||
ret := append([]dns.RR{z.SOA}, z.SIG...)
|
||||
return ret, nil, nil, Success
|
||||
}
|
||||
return []dns.RR{z.SOA}, nil, nil, Success
|
||||
}
|
||||
|
||||
// lookupNSEC looks up nsec and sigs.
|
||||
func (z *Zone) lookupNSEC(elem *tree.Elem, do bool) []dns.RR {
|
||||
if !do {
|
||||
return nil
|
||||
}
|
||||
nsec := elem.Types(dns.TypeNSEC)
|
||||
if do {
|
||||
sigs := elem.Types(dns.TypeRRSIG)
|
||||
sigs = signatureForSubType(sigs, dns.TypeNSEC)
|
||||
if len(sigs) > 0 {
|
||||
nsec = append(nsec, sigs...)
|
||||
}
|
||||
}
|
||||
return nsec
|
||||
}
|
||||
|
||||
func (z *Zone) lookupCNAME(rrs []dns.RR, rr dns.RR, do bool) ([]dns.RR, []dns.RR, []dns.RR, Result) {
|
||||
elem := z.Tree.Get(rr)
|
||||
if elem == nil {
|
||||
return rrs, nil, nil, Success
|
||||
}
|
||||
extra := cnameForType(elem.All(), rr.Header().Rrtype)
|
||||
if do {
|
||||
sigs := elem.Types(dns.TypeRRSIG)
|
||||
sigs = signatureForSubType(sigs, rr.Header().Rrtype)
|
||||
if len(sigs) > 0 {
|
||||
extra = append(extra, sigs...)
|
||||
}
|
||||
}
|
||||
return rrs, nil, extra, Success
|
||||
}
|
||||
|
||||
func cnameForType(targets []dns.RR, origQtype uint16) []dns.RR {
|
||||
ret := []dns.RR{}
|
||||
for _, target := range targets {
|
||||
if target.Header().Rrtype == origQtype {
|
||||
ret = append(ret, target)
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// signatureForSubType range through the signature and return the correct
|
||||
// ones for the subtype.
|
||||
func (z *Zone) signatureForSubType(rrs []dns.RR, subtype uint16, do bool) []dns.RR {
|
||||
if !do {
|
||||
return nil
|
||||
}
|
||||
func signatureForSubType(rrs []dns.RR, subtype uint16) []dns.RR {
|
||||
sigs := []dns.RR{}
|
||||
for _, sig := range rrs {
|
||||
if s, ok := sig.(*dns.RRSIG); ok {
|
||||
|
||||
@@ -43,7 +43,6 @@ var dnsTestCases = []coretest.Case{
|
||||
|
||||
Extra: []dns.RR{
|
||||
coretest.A("a.miek.nl. 1800 IN A 139.162.196.78"),
|
||||
coretest.AAAA("a.miek.nl. 1800 IN AAAA 2a01:7e00::f03c:91ff:fef1:6735"),
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -61,7 +60,10 @@ var dnsTestCases = []coretest.Case{
|
||||
},
|
||||
}
|
||||
|
||||
const testzone = "miek.nl."
|
||||
const (
|
||||
testzone = "miek.nl."
|
||||
testzone1 = "dnssex.nl."
|
||||
)
|
||||
|
||||
func TestLookup(t *testing.T) {
|
||||
zone, err := Parse(strings.NewReader(dbMiekNL), testzone, "stdin")
|
||||
@@ -73,8 +75,7 @@ func TestLookup(t *testing.T) {
|
||||
ctx := context.TODO()
|
||||
|
||||
for _, tc := range dnsTestCases {
|
||||
m := new(dns.Msg)
|
||||
m.SetQuestion(dns.Fqdn(tc.Qname), tc.Qtype)
|
||||
m := tc.Msg()
|
||||
|
||||
rec := middleware.NewResponseRecorder(&middleware.TestResponseWriter{})
|
||||
_, err := fm.ServeDNS(ctx, rec, m)
|
||||
|
||||
@@ -13,12 +13,11 @@
|
||||
// Heavily modified by Miek Gieben for use in DNS zones.
|
||||
package tree
|
||||
|
||||
// TODO(miek): locking? lockfree
|
||||
// TODO(miek): locking? lockfree would be nice. Will probably go for fine grained locking on the name level.
|
||||
// TODO(miek): fix docs
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/miekg/coredns/middleware"
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
@@ -47,7 +46,7 @@ func newElem(rr dns.RR) *Elem {
|
||||
return &e
|
||||
}
|
||||
|
||||
// Types returns the types from with type qtype from e.
|
||||
// Types returns the RRs with type qtype from e.
|
||||
func (e *Elem) Types(qtype uint16) []dns.RR {
|
||||
if rrs, ok := e.m[qtype]; ok {
|
||||
// TODO(miek): length should never be zero here.
|
||||
@@ -56,6 +55,7 @@ func (e *Elem) Types(qtype uint16) []dns.RR {
|
||||
return nil
|
||||
}
|
||||
|
||||
// All returns all RRs from e, regardless of type.
|
||||
func (e *Elem) All() []dns.RR {
|
||||
list := []dns.RR{}
|
||||
for _, rrs := range e.m {
|
||||
@@ -64,6 +64,15 @@ func (e *Elem) All() []dns.RR {
|
||||
return list
|
||||
}
|
||||
|
||||
// Return the domain name for this element.
|
||||
func (e *Elem) Name() string {
|
||||
for _, rrs := range e.m {
|
||||
return rrs[0].Header().Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Insert inserts rr into e. If rr is equal to existing rrs this is a noop.
|
||||
func (e *Elem) Insert(rr dns.RR) {
|
||||
t := rr.Header().Rrtype
|
||||
if e.m == nil {
|
||||
@@ -110,26 +119,14 @@ func (e *Elem) Delete(rr dns.RR) (empty bool) {
|
||||
return
|
||||
}
|
||||
|
||||
// TODO(miek): need case ignore compare that is more efficient.
|
||||
func Less(a *Elem, rr dns.RR) int {
|
||||
aname := ""
|
||||
for _, ar := range a.m {
|
||||
aname = strings.ToLower(ar[0].Header().Name)
|
||||
break
|
||||
}
|
||||
rname := strings.ToLower(rr.Header().Name)
|
||||
if aname == rname {
|
||||
return 0
|
||||
}
|
||||
if aname < rname {
|
||||
return -1
|
||||
}
|
||||
return 1
|
||||
return middleware.Less(rr.Header().Name, a.Name())
|
||||
}
|
||||
|
||||
// Assuming the same type and name this will check if the rdata is equal as well.
|
||||
func equalRdata(a, b dns.RR) bool {
|
||||
switch x := a.(type) {
|
||||
// TODO(miek): more types, i.e. all types.
|
||||
case *dns.A:
|
||||
return x.A.Equal(b.(*dns.A).A)
|
||||
case *dns.AAAA:
|
||||
@@ -259,8 +256,7 @@ func (t *Tree) Len() int {
|
||||
return t.Count
|
||||
}
|
||||
|
||||
// Get returns the first match of q in the Tree. If insertion without
|
||||
// replacement is used, this is probably not what you want.
|
||||
// Get returns the first match of rr in the Tree.
|
||||
func (t *Tree) Get(rr dns.RR) *Elem {
|
||||
if t.Root == nil {
|
||||
return nil
|
||||
@@ -287,11 +283,8 @@ func (n *Node) search(rr dns.RR) *Node {
|
||||
return n
|
||||
}
|
||||
|
||||
// Insert inserts the Comparable e into the Tree at the first match found
|
||||
// with e or when a nil node is reached. Insertion without replacement can
|
||||
// specified by ensuring that e.Compare() never returns 0. If insert without
|
||||
// replacement is performed, a distinct query Comparable must be used that
|
||||
// can return 0 with a Compare() call.
|
||||
// Insert inserts rr into the Tree at the first match found
|
||||
// with e or when a nil node is reached.
|
||||
func (t *Tree) Insert(rr dns.RR) {
|
||||
var d int
|
||||
t.Root, d = t.Root.insert(rr)
|
||||
@@ -340,8 +333,7 @@ func (n *Node) insert(rr dns.RR) (root *Node, d int) {
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteMin deletes the node with the minimum value in the tree. If insertion without
|
||||
// replacement has been used, the left-most minimum will be deleted.
|
||||
// DeleteMin deletes the node with the minimum value in the tree.
|
||||
func (t *Tree) DeleteMin() {
|
||||
if t.Root == nil {
|
||||
return
|
||||
@@ -369,8 +361,7 @@ func (n *Node) deleteMin() (root *Node, d int) {
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteMax deletes the node with the maximum value in the tree. If insertion without
|
||||
// replacement has been used, the right-most maximum will be deleted.
|
||||
// DeleteMax deletes the node with the maximum value in the tree.
|
||||
func (t *Tree) DeleteMax() {
|
||||
if t.Root == nil {
|
||||
return
|
||||
@@ -401,7 +392,7 @@ func (n *Node) deleteMax() (root *Node, d int) {
|
||||
return
|
||||
}
|
||||
|
||||
// Delete removes rr from the tree, is the node turns empty, that node is return with DeleteNode.
|
||||
// Delete removes rr from the tree, is the node turns empty, that node is deleted with DeleteNode.
|
||||
func (t *Tree) Delete(rr dns.RR) {
|
||||
if t.Root == nil {
|
||||
return
|
||||
@@ -420,9 +411,7 @@ func (t *Tree) Delete(rr dns.RR) {
|
||||
}
|
||||
}
|
||||
|
||||
// DeleteNode deletes the node that matches e according to Compare(). Note that Compare must
|
||||
// identify the target node uniquely and in cases where non-unique keys are used,
|
||||
// attributes used to break ties must be used to determine tree ordering during insertion.
|
||||
// DeleteNode deletes the node that matches rr according to Less().
|
||||
func (t *Tree) DeleteNode(rr dns.RR) {
|
||||
if t.Root == nil {
|
||||
return
|
||||
@@ -469,8 +458,7 @@ func (n *Node) delete(rr dns.RR) (root *Node, d int) {
|
||||
return
|
||||
}
|
||||
|
||||
// Return the minimum value stored in the tree. This will be the left-most minimum value if
|
||||
// insertion without replacement has been used.
|
||||
// Min returns the minimum value stored in the tree.
|
||||
func (t *Tree) Min() *Elem {
|
||||
if t.Root == nil {
|
||||
return nil
|
||||
@@ -484,8 +472,7 @@ func (n *Node) min() *Node {
|
||||
return n
|
||||
}
|
||||
|
||||
// Return the maximum value stored in the tree. This will be the right-most maximum value if
|
||||
// insertion without replacement has been used.
|
||||
// Max returns the maximum value stored in the tree.
|
||||
func (t *Tree) Max() *Elem {
|
||||
if t.Root == nil {
|
||||
return nil
|
||||
@@ -499,8 +486,8 @@ func (n *Node) max() *Node {
|
||||
return n
|
||||
}
|
||||
|
||||
// Floor returns the greatest value equal to or less than the query q according to q.Compare().
|
||||
func (t *Tree) Floor(rr dns.RR) *Elem {
|
||||
// Prev returns the greatest value equal to or less than the rr according to Less().
|
||||
func (t *Tree) Prev(rr dns.RR) *Elem {
|
||||
if t.Root == nil {
|
||||
return nil
|
||||
}
|
||||
@@ -528,10 +515,8 @@ func (n *Node) floor(rr dns.RR) *Node {
|
||||
return n
|
||||
}
|
||||
|
||||
// TODO(successor, predecessor)
|
||||
|
||||
// Ceil returns the smallest value equal to or greater than the query q according to q.Compare().
|
||||
func (t *Tree) Ceil(rr dns.RR) *Elem {
|
||||
// Next returns the smallest value equal to or greater than the rr according to Less().
|
||||
func (t *Tree) Next(rr dns.RR) *Elem {
|
||||
if t.Root == nil {
|
||||
return nil
|
||||
}
|
||||
@@ -559,6 +544,33 @@ func (n *Node) ceil(rr dns.RR) *Node {
|
||||
return n
|
||||
}
|
||||
|
||||
// Do performs fn on all values stored in the tree. A boolean is returned indicating whether the
|
||||
// Do traversal was interrupted by an Operation returning true. If fn alters stored values' sort
|
||||
// relationships, future tree operation behaviors are undefined.
|
||||
func (t *Tree) Do(fn func(e *Elem) bool) bool {
|
||||
if t.Root == nil {
|
||||
return false
|
||||
}
|
||||
return t.Root.do(fn)
|
||||
}
|
||||
|
||||
func (n *Node) do(fn func(e *Elem) bool) (done bool) {
|
||||
if n.Left != nil {
|
||||
done = n.Left.do(fn)
|
||||
if done {
|
||||
return
|
||||
}
|
||||
}
|
||||
done = fn(n.Elem)
|
||||
if done {
|
||||
return
|
||||
}
|
||||
if n.Right != nil {
|
||||
done = n.Right.do(fn)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
/*
|
||||
Copyright ©2012 The bíogo Authors. All rights reserved.
|
||||
|
||||
|
||||
222
middleware/file/wildcard_test.go
Normal file
222
middleware/file/wildcard_test.go
Normal file
@@ -0,0 +1,222 @@
|
||||
package file
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/miekg/coredns/middleware"
|
||||
coretest "github.com/miekg/coredns/middleware/testing"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
var dnssecWildcardTestCases = []coretest.Case{
|
||||
{
|
||||
Qname: "blaat.dnssex.nl.", Qtype: dns.TypeTXT, Do: true,
|
||||
Answer: []dns.RR{},
|
||||
},
|
||||
}
|
||||
|
||||
func testLookupDNSSECWildcard(t *testing.T) {
|
||||
zone, err := Parse(strings.NewReader(dbMiekNL_signed), testzone1, "stdin")
|
||||
if err != nil {
|
||||
t.Fatalf("expect no error when reading zone, got %q", err)
|
||||
}
|
||||
|
||||
fm := File{Next: coretest.ErrorHandler(), Zones: Zones{Z: map[string]*Zone{testzone1: zone}, Names: []string{testzone1}}}
|
||||
ctx := context.TODO()
|
||||
|
||||
for _, tc := range dnssecWildcardTestCases {
|
||||
m := tc.Msg()
|
||||
|
||||
rec := middleware.NewResponseRecorder(&middleware.TestResponseWriter{})
|
||||
_, err := fm.ServeDNS(ctx, rec, m)
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got %v\n", err)
|
||||
return
|
||||
}
|
||||
resp := rec.Msg()
|
||||
|
||||
sort.Sort(coretest.RRSet(resp.Answer))
|
||||
sort.Sort(coretest.RRSet(resp.Ns))
|
||||
sort.Sort(coretest.RRSet(resp.Extra))
|
||||
|
||||
if resp.Rcode != tc.Rcode {
|
||||
t.Errorf("rcode is %q, expected %q", dns.RcodeToString[resp.Rcode], dns.RcodeToString[tc.Rcode])
|
||||
t.Logf("%v\n", resp)
|
||||
continue
|
||||
}
|
||||
|
||||
if len(resp.Answer) != len(tc.Answer) {
|
||||
t.Errorf("answer for %q contained %d results, %d expected", tc.Qname, len(resp.Answer), len(tc.Answer))
|
||||
t.Logf("%v\n", resp)
|
||||
continue
|
||||
}
|
||||
if len(resp.Ns) != len(tc.Ns) {
|
||||
t.Errorf("authority for %q contained %d results, %d expected", tc.Qname, len(resp.Ns), len(tc.Ns))
|
||||
t.Logf("%v\n", resp)
|
||||
continue
|
||||
}
|
||||
if len(resp.Extra) != len(tc.Extra) {
|
||||
t.Errorf("additional for %q contained %d results, %d expected", tc.Qname, len(resp.Extra), len(tc.Extra))
|
||||
t.Logf("%v\n", resp)
|
||||
continue
|
||||
}
|
||||
|
||||
if !coretest.CheckSection(t, tc, coretest.Answer, resp.Answer) {
|
||||
t.Logf("%v\n", resp)
|
||||
}
|
||||
if !coretest.CheckSection(t, tc, coretest.Ns, resp.Ns) {
|
||||
t.Logf("%v\n", resp)
|
||||
}
|
||||
if !coretest.CheckSection(t, tc, coretest.Extra, resp.Extra) {
|
||||
t.Logf("%v\n", resp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const dbMiekNL_wildcard_signed = `
|
||||
; File written on Tue Mar 29 21:02:24 2016
|
||||
; dnssec_signzone version 9.10.3-P4-Ubuntu
|
||||
dnssex.nl. 1800 IN SOA linode.atoom.net. miek.miek.nl. (
|
||||
1459281744 ; serial
|
||||
14400 ; refresh (4 hours)
|
||||
3600 ; retry (1 hour)
|
||||
604800 ; expire (1 week)
|
||||
14400 ; minimum (4 hours)
|
||||
)
|
||||
1800 RRSIG SOA 8 2 1800 (
|
||||
20160428190224 20160329190224 14460 dnssex.nl.
|
||||
CA/Y3m9hCOiKC/8ieSOv8SeP964BUdG/8MC3
|
||||
WtKljUosK9Z9bBGrVizDjjqgq++lyH8BZJcT
|
||||
aabAsERs4xj5PRtcxicwQXZACX5VYjXHQeZm
|
||||
CyytFU5wq2gcXSmvUH86zZzftx3RGPvn1aOo
|
||||
TlcvoC3iF8fYUCpROlUS0YR8Cdw= )
|
||||
1800 NS omval.tednet.nl.
|
||||
1800 NS linode.atoom.net.
|
||||
1800 NS ns-ext.nlnetlabs.nl.
|
||||
1800 RRSIG NS 8 2 1800 (
|
||||
20160428190224 20160329190224 14460 dnssex.nl.
|
||||
dLIeEvP86jj5nd3orv9bH7hTvkblF4Na0sbl
|
||||
k6fJA6ha+FPN1d6Pig3NNEEVQ/+wlOp/JTs2
|
||||
v07L7roEEUCbBprI8gMSld2gFDwNLW3DAB4M
|
||||
WD/oayYdAnumekcLzhgvWixTABjWAGRTGQsP
|
||||
sVDFXsGMf9TGGC9FEomgkCVeNC0= )
|
||||
1800 A 139.162.196.78
|
||||
1800 RRSIG A 8 2 1800 (
|
||||
20160428190224 20160329190224 14460 dnssex.nl.
|
||||
LKJKLzPiSEDWOLAag2YpfD5EJCuDcEAJu+FZ
|
||||
Xy+4VyOv9YvRHCTL4vbrevOo5+XymY2RxU1q
|
||||
j+6leR/Fe7nlreSj2wzAAk2bIYn4m6r7hqeO
|
||||
aKZsUFfpX8cNcFtGEywfHndCPELbRxFeEziP
|
||||
utqHFLPNMX5nYCpS28w4oJ5sAnM= )
|
||||
1800 TXT "Doing It Safe Is Better"
|
||||
1800 RRSIG TXT 8 2 1800 (
|
||||
20160428190224 20160329190224 14460 dnssex.nl.
|
||||
f6S+DUfJK1UYdOb3AHgUXzFTTtu+yLp/Fv7S
|
||||
Hv0CAGhXAVw+nBbK719igFvBtObS33WKwzxD
|
||||
1pQNMaJcS6zeevtD+4PKB1KDC4fyJffeEZT6
|
||||
E30jGR8Y29/xA+Fa4lqDNnj9zP3b8TiABCle
|
||||
ascY5abkgWCALLocFAzFJQ/27YQ= )
|
||||
1800 AAAA 2a01:7e00::f03c:91ff:fef1:6735
|
||||
1800 RRSIG AAAA 8 2 1800 (
|
||||
20160428190224 20160329190224 14460 dnssex.nl.
|
||||
PWcPSawEUBAfCuv0liEOQ8RYe7tfNW4rubIJ
|
||||
LE+dbrub1DUer3cWrDoCYFtOufvcbkYJQ2CQ
|
||||
AGjJmAQ5J2aqYDOPMrKa615V0KT3ifbZJcGC
|
||||
gkIic4U/EXjaQpRoLdDzR9MyVXOmbA6sKYzj
|
||||
ju1cNkLqM8D7Uunjl4pIr6rdSFo= )
|
||||
14400 NSEC *.dnssex.nl. A NS SOA TXT AAAA RRSIG NSEC DNSKEY
|
||||
14400 RRSIG NSEC 8 2 14400 (
|
||||
20160428190224 20160329190224 14460 dnssex.nl.
|
||||
oIvM6JZIlNc1aNKGTxv58ApSnDr1nDPPgnD9
|
||||
9oJZRIn7eb5WnpeDz2H3z5+x6Bhlp5hJJaUp
|
||||
KJ3Ss6Jg/IDnrmIvKmgq6L6gHj1Y1IiHmmU8
|
||||
VeZTRzdTsDx/27OsN23roIvsytjveNSEMfIm
|
||||
iLZ23x5kg1kBdJ9p3xjYHm5lR+8= )
|
||||
1800 DNSKEY 256 3 8 (
|
||||
AwEAAazSO6uvLPEVknDA8yxjFe8nnAMU7txp
|
||||
wb19k55hQ81WV3G4bpBM1NdN6sbYHrkXaTNx
|
||||
2bQWAkvX6pz0XFx3z/MPhW+vkakIWFYpyQ7R
|
||||
AT5LIJfToVfiCDiyhhF0zVobKBInO9eoGjd9
|
||||
BAW3TUt+LmNAO/Ak5D5BX7R3CuA7v9k7
|
||||
) ; ZSK; alg = RSASHA256; key id = 14460
|
||||
1800 DNSKEY 257 3 8 (
|
||||
AwEAAbyeaV9zg0IqdtgYoqK5jJ239anzwG2i
|
||||
gvH1DxSazLyaoNvEkCIvPgMLW/JWfy7Z1mQp
|
||||
SMy9DtzL5pzRyQgw7kIeXLbi6jufUFd9pxN+
|
||||
xnzKLf9mY5AcnGToTrbSL+jnMT67wG+c34+Q
|
||||
PeVfucHNUePBxsbz2+4xbXiViSQyCQGv
|
||||
) ; KSK; alg = RSASHA256; key id = 18772
|
||||
1800 RRSIG DNSKEY 8 2 1800 (
|
||||
20160428190224 20160329190224 14460 dnssex.nl.
|
||||
cFSFtJE+DBGNxb52AweFaVHBe5Ue5MDpqNdC
|
||||
TIneUnEhP2m+vK4zJ/TraK0WdQFpsX63pod8
|
||||
PZ9y03vHUfewivyonCCBD3DcNdoU9subhN22
|
||||
tez9Ct8Z5/9E4RAz7orXal4M1VUEhRcXSEH8
|
||||
SJW20mfVsqJAiKqqNeGB/pAj23I= )
|
||||
1800 RRSIG DNSKEY 8 2 1800 (
|
||||
20160428190224 20160329190224 18772 dnssex.nl.
|
||||
oiiwo/7NYacePqohEp50261elhm6Dieh4j2S
|
||||
VZGAHU5gqLIQeW9CxKJKtSCkBVgUo4cvO4Rn
|
||||
2tzArAuclDvBrMXRIoct8u7f96moeFE+x5FI
|
||||
DYqICiV6k449ljj9o4t/5G7q2CRsEfxZKpTI
|
||||
A/L0+uDk0RwVVzL45+TnilcsmZs= )
|
||||
*.dnssex.nl. 1800 IN TXT "Doing It Safe Is Better"
|
||||
1800 RRSIG TXT 8 2 1800 (
|
||||
20160428190224 20160329190224 14460 dnssex.nl.
|
||||
FUZSTyvZfeuuOpCmNzVKOfITRHJ6/ygjmnnb
|
||||
XGBxVUyQjoLuYXwD5XqZWGw4iKH6QeSDfGCx
|
||||
4MPqA4qQmW7Wwth7mat9yMfA4+p2sO84bysl
|
||||
7/BG9+W2G+q1uQiM9bX9V42P2X/XuW5Y/t9Y
|
||||
8u1sljQ7D8WwS6naH/vbaJxnDBw= )
|
||||
14400 NSEC a.dnssex.nl. TXT RRSIG NSEC
|
||||
14400 RRSIG NSEC 8 2 14400 (
|
||||
20160428190224 20160329190224 14460 dnssex.nl.
|
||||
os6INm6q2eXknD5z8TpfbK00uxVbQefMvHcR
|
||||
/RNX/kh0xXvzAaaDOV+Ge/Ko+2dXnKP+J1LY
|
||||
G9ffXNpdbaQy5ygzH5F041GJst4566GdG/jt
|
||||
7Z7vLHYxEBTpZfxo+PLsXQXH3VTemZyuWyDf
|
||||
qJzafXJVH1F0nDrcXmMlR6jlBHA= )
|
||||
www.dnssex.nl. 1800 IN CNAME a.dnssex.nl.
|
||||
1800 RRSIG CNAME 8 3 1800 (
|
||||
20160428190224 20160329190224 14460 dnssex.nl.
|
||||
Omv42q/uVvdNsWQoSrQ6m6w6U7r7Abga7uF4
|
||||
25b3gZlse0C+WyMyGFMGUbapQm7azvBpreeo
|
||||
uKJHjzd+ufoG+Oul6vU9vyoj+ejgHzGLGbJQ
|
||||
HftfP+UqP5SWvAaipP/LULTWKPuiBcLDLiBI
|
||||
PGTfsq0DB6R+qCDTV0fNnkgxEBQ= )
|
||||
14400 NSEC dnssex.nl. CNAME RRSIG NSEC
|
||||
14400 RRSIG NSEC 8 3 14400 (
|
||||
20160428190224 20160329190224 14460 dnssex.nl.
|
||||
TBN3ddfZW+kC84/g3QlNNJMeLZoyCalPQylt
|
||||
KXXLPGuxfGpl3RYRY8KaHbP+5a8MnHjqjuMB
|
||||
Lofb7yKMFxpSzMh8E36vnOqry1mvkSakNj9y
|
||||
9jM8PwDjcpYUwn/ql76MsmNgEV5CLeQ7lyH4
|
||||
AOrL79yOSQVI3JHJIjKSiz88iSw= )
|
||||
a.dnssex.nl. 1800 IN A 139.162.196.78
|
||||
1800 RRSIG A 8 3 1800 (
|
||||
20160428190224 20160329190224 14460 dnssex.nl.
|
||||
OXHpFj9nSpKi5yA/ULH7MOpGAWfyJ2yC/2xa
|
||||
Pw0fqSY4QvcRt+V3adcFA4H9+P1b32GpxEjB
|
||||
lXmCJID+H4lYkhUR4r4IOZBVtKG2SJEBZXip
|
||||
pH00UkOIBiXxbGzfX8VL04v2G/YxUgLW57kA
|
||||
aknaeTOkJsO20Y+8wmR9EtzaRFI= )
|
||||
1800 AAAA 2a01:7e00::f03c:91ff:fef1:6735
|
||||
1800 RRSIG AAAA 8 3 1800 (
|
||||
20160428190224 20160329190224 14460 dnssex.nl.
|
||||
jrepc/VnRzJypnrG0WDEqaAr3HMjWrPxJNX0
|
||||
86gbFjZG07QxBmrA1rj0jM9YEWTjjyWb2tT7
|
||||
lQhzKDYX/0XdOVUeeOM4FoSks80V+pWR8fvj
|
||||
AZ5HmX69g36tLosMDKNR4lXcrpv89QovG4Hr
|
||||
/r58fxEKEFJqrLDjMo6aOrg+uKA= )
|
||||
14400 NSEC www.dnssex.nl. A AAAA RRSIG NSEC
|
||||
14400 RRSIG NSEC 8 3 14400 (
|
||||
20160428190224 20160329190224 14460 dnssex.nl.
|
||||
S+UM62wXRNNFN3QDWK5YFWUbHBXC4aqaqinZ
|
||||
A2ZDeC+IQgyw7vazPz7cLI5T0YXXks0HTMlr
|
||||
soEjKnnRZsqSO9EuUavPNE1hh11Jjm0fB+5+
|
||||
+Uro0EmA5Dhgc0Z2VpbXVQEhNDf/pI1gem15
|
||||
RffN2tBYNykZn4Has2ySgRaaRYQ= )`
|
||||
@@ -27,11 +27,26 @@ type Case struct {
|
||||
Qname string
|
||||
Qtype uint16
|
||||
Rcode int
|
||||
Do bool
|
||||
Answer []dns.RR
|
||||
Ns []dns.RR
|
||||
Extra []dns.RR
|
||||
}
|
||||
|
||||
func (c Case) Msg() *dns.Msg {
|
||||
m := new(dns.Msg)
|
||||
m.SetQuestion(dns.Fqdn(c.Qname), c.Qtype)
|
||||
if c.Do {
|
||||
o := new(dns.OPT)
|
||||
o.Hdr.Name = "."
|
||||
o.Hdr.Rrtype = dns.TypeOPT
|
||||
o.SetDo()
|
||||
o.SetUDPSize(4096)
|
||||
m.Extra = []dns.RR{o}
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func A(rr string) *dns.A { r, _ := dns.NewRR(rr); return r.(*dns.A) }
|
||||
func AAAA(rr string) *dns.AAAA { r, _ := dns.NewRR(rr); return r.(*dns.AAAA) }
|
||||
func CNAME(rr string) *dns.CNAME { r, _ := dns.NewRR(rr); return r.(*dns.CNAME) }
|
||||
@@ -41,6 +56,8 @@ func NS(rr string) *dns.NS { r, _ := dns.NewRR(rr); return r.(*dns.NS) }
|
||||
func PTR(rr string) *dns.PTR { r, _ := dns.NewRR(rr); return r.(*dns.PTR) }
|
||||
func TXT(rr string) *dns.TXT { r, _ := dns.NewRR(rr); return r.(*dns.TXT) }
|
||||
func MX(rr string) *dns.MX { r, _ := dns.NewRR(rr); return r.(*dns.MX) }
|
||||
func RRSIG(rr string) *dns.RRSIG { r, _ := dns.NewRR(rr); return r.(*dns.RRSIG) }
|
||||
func NSEC(rr string) *dns.NSEC { r, _ := dns.NewRR(rr); return r.(*dns.NSEC) }
|
||||
|
||||
func CheckSection(t *testing.T, tc Case, sect Section, rr []dns.RR) bool {
|
||||
section := []dns.RR{}
|
||||
@@ -86,6 +103,25 @@ func CheckSection(t *testing.T, tc Case, sect Section, rr []dns.RR) bool {
|
||||
t.Errorf("rr %d should have a Target of %q, but has %q", i, section[i].(*dns.SRV).Target, x.Target)
|
||||
return false
|
||||
}
|
||||
case *dns.RRSIG:
|
||||
if x.TypeCovered != section[i].(*dns.RRSIG).TypeCovered {
|
||||
t.Errorf("rr %d should have a TypeCovered of %d, but has %d", i, section[i].(*dns.RRSIG).TypeCovered, x.TypeCovered)
|
||||
return false
|
||||
}
|
||||
if x.Labels != section[i].(*dns.RRSIG).Labels {
|
||||
t.Errorf("rr %d should have a Labels of %d, but has %d", i, section[i].(*dns.RRSIG).Labels, x.Labels)
|
||||
return false
|
||||
}
|
||||
if x.SignerName != section[i].(*dns.RRSIG).SignerName {
|
||||
t.Errorf("rr %d should have a SignerName of %d, but has %d", i, section[i].(*dns.RRSIG).SignerName, x.SignerName)
|
||||
return false
|
||||
}
|
||||
case *dns.NSEC:
|
||||
if x.NextDomain != section[i].(*dns.NSEC).NextDomain {
|
||||
t.Errorf("rr %d should have a NextDomain of %d, but has %d", i, section[i].(*dns.NSEC).NextDomain, x.NextDomain)
|
||||
return false
|
||||
}
|
||||
// TypeBitMap
|
||||
case *dns.A:
|
||||
if x.A.String() != section[i].(*dns.A).A.String() {
|
||||
t.Errorf("rr %d should have a Address of %q, but has %q", i, section[i].(*dns.A).A.String(), x.A.String())
|
||||
|
||||
Reference in New Issue
Block a user