diff --git a/middleware/file/dnssec_test.go b/middleware/file/dnssec_test.go index 4b6888a82..6ea4f95c1 100644 --- a/middleware/file/dnssec_test.go +++ b/middleware/file/dnssec_test.go @@ -53,6 +53,8 @@ var dnssecTestCases = []coretest.Case{ { 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"), }, diff --git a/middleware/file/file.go b/middleware/file/file.go index 2e04dbe92..97e916116 100644 --- a/middleware/file/file.go +++ b/middleware/file/file.go @@ -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()) + an, ns, extra, result := z.Lookup(qname, state.QType(), state.Do()) m := new(dns.Msg) m.SetReply(r) @@ -48,17 +48,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 = an 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) diff --git a/middleware/file/lookup.go b/middleware/file/lookup.go index 20ec1ce00..34fb0252c 100644 --- a/middleware/file/lookup.go +++ b/middleware/file/lookup.go @@ -1,6 +1,9 @@ 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,18 +11,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) { +// 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 { - an, ad, _ := z.lookupSOA(do) - return an, ad, NameError - // Uhm...? rr = new(RFC3597) ?? + return nil, nil, nil, ServerFailure } else { rr = mk() } @@ -32,8 +34,7 @@ func (z *Zone) Lookup(qname string, qtype uint16, do bool) ([]dns.RR, []dns.RR, rr.Header().Name = qname elem := z.Tree.Get(rr) if elem == nil { - an, ad, _ := z.lookupSOA(do) - return an, ad, NameError + return z.nameError(elem, rr, do) } rrs := elem.Types(dns.TypeCNAME) @@ -44,8 +45,7 @@ func (z *Zone) Lookup(qname string, qtype uint16, do bool) ([]dns.RR, []dns.RR, rrs = elem.Types(qtype) if len(rrs) == 0 { - an, ad, _ := z.lookupSOA(do) - return an, ad, NoData + return z.noData(elem, do) } if do { sigs := elem.Types(dns.TypeRRSIG) @@ -54,21 +54,53 @@ func (z *Zone) Lookup(qname string, qtype uint16, do bool) ([]dns.RR, []dns.RR, rrs = append(rrs, sigs...) } } - return rrs, nil, Success + return rrs, nil, nil, Success } -func (z *Zone) lookupSOA(do bool) ([]dns.RR, []dns.RR, Result) { +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) { if do { ret := append([]dns.RR{z.SOA}, z.SIG...) - return ret, nil, Success + return nil, ret, nil, Success } - return []dns.RR{z.SOA}, nil, Success + // NSECs! + return nil, []dns.RR{z.SOA}, nil, Success } -func (z *Zone) lookupCNAME(rrs []dns.RR, rr dns.RR, do bool) ([]dns.RR, []dns.RR, Result) { +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, Success + return rrs, nil, nil, Success } extra := cnameForType(elem.All(), rr.Header().Rrtype) if do { @@ -78,7 +110,7 @@ func (z *Zone) lookupCNAME(rrs []dns.RR, rr dns.RR, do bool) ([]dns.RR, []dns.RR extra = append(extra, sigs...) } } - return rrs, extra, Success + return rrs, nil, extra, Success } func cnameForType(targets []dns.RR, origQtype uint16) []dns.RR {