diff options
author | 2016-03-27 07:37:23 +0100 | |
---|---|---|
committer | 2016-03-28 10:15:05 +0100 | |
commit | 5387c162c994d7d81ccf21c8c8f9d9959ed27240 (patch) | |
tree | f10c1777f3cd96a42c67b8c955c737c88aa58744 /middleware/file/file.go | |
parent | 9eeb2b02595664e861ae639933555b3ed507c93d (diff) | |
download | coredns-5387c162c994d7d81ccf21c8c8f9d9959ed27240.tar.gz coredns-5387c162c994d7d81ccf21c8c8f9d9959ed27240.tar.zst coredns-5387c162c994d7d81ccf21c8c8f9d9959ed27240.zip |
Implement a DNS zone
Full implementation, DNS (and in the future DNSSEC). Returns answer in a
hopefully standards compliant way.
Testing with my miek.nl zone are included as well.
This should correctly handle nodata, nxdomain and cnames.
Diffstat (limited to 'middleware/file/file.go')
-rw-r--r-- | middleware/file/file.go | 94 |
1 files changed, 44 insertions, 50 deletions
diff --git a/middleware/file/file.go b/middleware/file/file.go index 3827664bc..b9f53003a 100644 --- a/middleware/file/file.go +++ b/middleware/file/file.go @@ -6,12 +6,13 @@ package file // have some fluff for DNSSEC (and be memory efficient). import ( - "strings" - - "golang.org/x/net/context" + "io" + "log" "github.com/miekg/coredns/middleware" + "github.com/miekg/dns" + "golang.org/x/net/context" ) type ( @@ -21,9 +22,8 @@ type ( // Maybe a list of all zones as well, as a []string? } - Zone []dns.RR Zones struct { - Z map[string]Zone // utterly braindead impl. TODO(miek): fix + Z map[string]*Zone Names []string } ) @@ -35,57 +35,51 @@ func (f File) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (i if zone == "" { return f.Next.ServeDNS(ctx, w, r) } + z, ok := f.Zones.Z[zone] + if !ok { + return f.Next.ServeDNS(ctx, w, r) + } - names, nodata := f.Zones.Z[zone].lookup(qname, state.QType()) - var answer *dns.Msg - switch { - case nodata: - answer = state.AnswerMessage() - answer.Ns = names - case len(names) == 0: - answer = state.AnswerMessage() - answer.Ns = names - answer.Rcode = dns.RcodeNameError - case len(names) > 0: - answer = state.AnswerMessage() - answer.Answer = names + rrs, extra, result := z.Lookup(qname, state.QType(), state.Do()) + + m := new(dns.Msg) + m.SetReply(r) + m.Authoritative, m.RecursionAvailable, m.Compress = true, true, true + + switch result { + case Success: + // case? + m.Answer = rrs + m.Extra = extra + // Ns section + case NameError: + m.Rcode = dns.RcodeNameError + fallthrough + case NoData: + // case? + m.Ns = rrs default: - answer = state.ErrorMessage(dns.RcodeServerFailure) + // TODO } - // Check return size, etc. TODO(miek) - w.WriteMsg(answer) - return 0, nil + // sizing and Do bit RRSIG + w.WriteMsg(m) + return dns.RcodeSuccess, nil } -// Lookup will try to find qname and qtype in z. It returns the -// records found *or* a boolean saying NODATA. If the answer -// is NODATA then the RR returned is the SOA record. -// -// TODO(miek): EXTREMELY STUPID IMPLEMENTATION. -// Doesn't do much, no delegation, no cname, nothing really, etc. -// TODO(miek): even NODATA looks broken -func (z Zone) lookup(qname string, qtype uint16) ([]dns.RR, bool) { - var ( - nodata bool - rep []dns.RR - soa dns.RR - ) - - for _, rr := range z { - if rr.Header().Rrtype == dns.TypeSOA { - soa = rr +// Parse parses the zone in filename and returns a new Zone or an error. +func Parse(f io.Reader, origin, fileName string) (*Zone, error) { + tokens := dns.ParseZone(f, dns.Fqdn(origin), fileName) + z := NewZone(origin) + for x := range tokens { + if x.Error != nil { + log.Printf("[ERROR] failed to parse %s: %v", origin, x.Error) + return nil, x.Error } - // Match function in Go DNS? - if strings.ToLower(rr.Header().Name) == qname { - if rr.Header().Rrtype == qtype { - rep = append(rep, rr) - nodata = false - } - + if x.RR.Header().Rrtype == dns.TypeSOA { + z.SOA = x.RR.(*dns.SOA) + continue } + z.Insert(x.RR) } - if nodata { - return []dns.RR{soa}, true - } - return rep, false + return z, nil } |