diff options
Diffstat (limited to 'middleware/file/setup.go')
-rw-r--r-- | middleware/file/setup.go | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/middleware/file/setup.go b/middleware/file/setup.go new file mode 100644 index 000000000..8b44650ee --- /dev/null +++ b/middleware/file/setup.go @@ -0,0 +1,143 @@ +package file + +import ( + "fmt" + "net" + "os" + + "github.com/miekg/coredns/core/dnsserver" + "github.com/miekg/coredns/middleware" + + "github.com/mholt/caddy" +) + +func init() { + caddy.RegisterPlugin("file", caddy.Plugin{ + ServerType: "dns", + Action: setup, + }) +} + +func setup(c *caddy.Controller) error { + zones, err := fileParse(c) + if err != nil { + return err + } + + // Add startup functions to notify the master(s). + for _, n := range zones.Names { + c.OnStartup(func() error { + zones.Z[n].StartupOnce.Do(func() { + if len(zones.Z[n].TransferTo) > 0 { + zones.Z[n].Notify() + } + zones.Z[n].Reload(nil) + }) + return nil + }) + } + + dnsserver.GetConfig(c).AddMiddleware(func(next dnsserver.Handler) dnsserver.Handler { + return File{Next: next, Zones: zones} + }) + + return nil +} + +func fileParse(c *caddy.Controller) (Zones, error) { + z := make(map[string]*Zone) + names := []string{} + origins := []string{} + + for c.Next() { + if c.Val() == "file" { + // file db.file [zones...] + if !c.NextArg() { + return Zones{}, c.ArgErr() + } + fileName := c.Val() + + origins = make([]string, len(c.ServerBlockKeys)) + copy(origins, c.ServerBlockKeys) + args := c.RemainingArgs() + if len(args) > 0 { + origins = args + } + + reader, err := os.Open(fileName) + if err != nil { + // bail out + return Zones{}, err + } + + for i, _ := range origins { + origins[i] = middleware.Host(origins[i]).Normalize() + zone, err := Parse(reader, origins[i], fileName) + if err == nil { + z[origins[i]] = zone + } else { + return Zones{}, err + } + names = append(names, origins[i]) + } + + noReload := false + for c.NextBlock() { + t, _, e := TransferParse(c) + if e != nil { + return Zones{}, e + } + switch c.Val() { + case "no_reload": + noReload = true + } + // discard from, here, maybe check and show log when we do? + for _, origin := range origins { + if t != nil { + z[origin].TransferTo = append(z[origin].TransferTo, t...) + } + z[origin].NoReload = noReload + } + } + } + } + return Zones{Z: z, Names: names}, nil +} + +// TransferParse parses transfer statements: 'transfer to [address...]'. +// Exported so secondary can use this as well. +func TransferParse(c *caddy.Controller) (tos, froms []string, err error) { + what := c.Val() + if !c.NextArg() { + return nil, nil, c.ArgErr() + } + value := c.Val() + switch what { + case "transfer": + if value == "to" { + tos = c.RemainingArgs() + for i, _ := range tos { + if tos[i] != "*" { + if x := net.ParseIP(tos[i]); x == nil { + return nil, nil, fmt.Errorf("must specify an IP addres: `%s'", tos[i]) + } + tos[i] = middleware.Addr(tos[i]).Normalize() + } + } + } + if value == "from" { + froms = c.RemainingArgs() + for i, _ := range froms { + if froms[i] != "*" { + if x := net.ParseIP(froms[i]); x == nil { + return nil, nil, fmt.Errorf("must specify an IP addres: `%s'", froms[i]) + } + froms[i] = middleware.Addr(froms[i]).Normalize() + } else { + return nil, nil, fmt.Errorf("can't use '*' in transfer from") + } + } + } + } + return +} |