coredns/middleware/file/file.go
Miek Gieben 6445a3f2f0 Cleanup docs and the chaos middleware
Make the CH middleware actually work. Needs a bit of a hack to route

the fake version.bind and friends zone to the correct handler. Fiddle

with the order in directive.go so that CH queries get logged as well.



Secondly add class rewriting to the rewrite middleware handler and also

log the class by default.
2016-04-04 15:45:17 +01:00

99 lines
2.1 KiB
Go

package file
import (
"fmt"
"io"
"log"
"github.com/miekg/coredns/middleware"
"github.com/miekg/dns"
"golang.org/x/net/context"
)
type (
File struct {
Next middleware.Handler
Zones Zones
}
Zones struct {
Z map[string]*Zone
Names []string
}
)
func (f File) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
state := middleware.State{W: w, Req: r}
if state.QClass() != dns.ClassINET {
return dns.RcodeServerFailure, fmt.Errorf("file: can only deal with ClassINET")
}
qname := state.Name()
zone := middleware.Zones(f.Zones.Names).Matches(qname)
if zone == "" {
return f.Next.ServeDNS(ctx, w, r)
}
z, ok := f.Zones.Z[zone]
if !ok {
return f.Next.ServeDNS(ctx, w, r)
}
if z == nil {
return dns.RcodeServerFailure, nil
}
if z.Expired != nil && *z.Expired {
return dns.RcodeServerFailure, nil
}
if state.Proto() != "udp" && state.QType() == dns.TypeAXFR {
xfr := Xfr{z}
return xfr.ServeDNS(ctx, w, r)
}
answer, ns, 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:
m.Answer = answer
m.Ns = ns
m.Extra = extra
case NameError:
m.Ns = ns
m.Rcode = dns.RcodeNameError
fallthrough
case NoData:
m.Ns = ns
case ServerFailure:
return dns.RcodeServerFailure, nil
}
m, _ = state.Scrub(m)
w.WriteMsg(m)
return dns.RcodeSuccess, nil
}
// 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
}
if x.RR.Header().Rrtype == dns.TypeSOA {
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
}