aboutsummaryrefslogtreecommitdiff
path: root/middleware/file/setup.go
diff options
context:
space:
mode:
Diffstat (limited to 'middleware/file/setup.go')
-rw-r--r--middleware/file/setup.go143
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
+}