package yamlzone import ( "context" "fmt" "strconv" "github.com/coredns/caddy" "github.com/coredns/coredns/core/dnsserver" "github.com/coredns/coredns/plugin" clog "github.com/coredns/coredns/plugin/pkg/log" "github.com/coredns/coredns/request" "github.com/miekg/dns" ) type YamlPlugin struct { Next plugin.Handler Zone *Zone Config YamlPluginConfig } type YamlPluginConfig struct { DefaultTtl uint64 } var log = clog.NewWithPlugin("yaml") func (y YamlPlugin) lookupRRs(qname string, qtype string) ([]dns.RR, bool) { records, ok := y.Zone.LookupType(qname, qtype) if !ok { return nil, false } rrs := []dns.RR{} for _, record := range records { ttl := record.Ttl if ttl == 0 { ttl = y.Config.DefaultTtl } rr, err := dns.NewRR(fmt.Sprintf("%s %d %s %s", qname, ttl, record.Type, record.Value)) if err != nil { return nil, false } rrs = append(rrs, rr) } return rrs, true } func (y YamlPlugin) Name() string { return "yaml" } func (y YamlPlugin) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) { state := request.Request{W: w, Req: r} qname := state.Name() qtype := state.Type() reply := new(dns.Msg) reply.SetReply(r) reply.Authoritative = true rrs, ok := y.lookupRRs(qname, qtype) if !ok { return dns.RcodeNameError, nil } reply.Answer = rrs w.WriteMsg(reply) return dns.RcodeSuccess, nil } func setup(c *caddy.Controller) error { c.Next() // yaml filename := "zones.yaml" if c.NextArg() { filename = c.Val() } defaultTtl := uint64(60) if c.NextArg() { var err error defaultTtl, err = strconv.ParseUint(c.Val(), 10, 32) if err != nil { return plugin.Error("yaml", fmt.Errorf("failed to parse default TTL: %w", err)) } } zone, err := LoadZone(filename) if err != nil { return plugin.Error("yaml", fmt.Errorf("failed to load zone from %s: %w", filename, err)) } dnsserver.GetConfig(c).AddPlugin(func(next plugin.Handler) plugin.Handler { return &YamlPlugin{ Next: next, Zone: zone, Config: YamlPluginConfig{ DefaultTtl: defaultTtl, }, } }) return nil } func init() { plugin.Register("yaml", setup) }