aboutsummaryrefslogtreecommitdiff
path: root/plugin/file/setup.go
diff options
context:
space:
mode:
Diffstat (limited to 'plugin/file/setup.go')
-rw-r--r--plugin/file/setup.go171
1 files changed, 171 insertions, 0 deletions
diff --git a/plugin/file/setup.go b/plugin/file/setup.go
new file mode 100644
index 000000000..bf0523c54
--- /dev/null
+++ b/plugin/file/setup.go
@@ -0,0 +1,171 @@
+package file
+
+import (
+ "fmt"
+ "os"
+ "path"
+
+ "github.com/coredns/coredns/core/dnsserver"
+ "github.com/coredns/coredns/plugin"
+ "github.com/coredns/coredns/plugin/pkg/dnsutil"
+ "github.com/coredns/coredns/plugin/proxy"
+
+ "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 plugin.Error("file", err)
+ }
+
+ // Add startup functions to notify the master(s).
+ for _, n := range zones.Names {
+ z := zones.Z[n]
+ c.OnStartup(func() error {
+ z.StartupOnce.Do(func() {
+ if len(z.TransferTo) > 0 {
+ z.Notify()
+ }
+ z.Reload()
+ })
+ return nil
+ })
+ }
+
+ dnsserver.GetConfig(c).AddPlugin(func(next plugin.Handler) plugin.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{}
+
+ config := dnsserver.GetConfig(c)
+
+ for c.Next() {
+ // 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
+ }
+
+ if !path.IsAbs(fileName) && config.Root != "" {
+ fileName = path.Join(config.Root, fileName)
+ }
+
+ reader, err := os.Open(fileName)
+ if err != nil {
+ // bail out
+ return Zones{}, err
+ }
+
+ for i := range origins {
+ origins[i] = plugin.Host(origins[i]).Normalize()
+ zone, err := Parse(reader, origins[i], fileName, 0)
+ if err == nil {
+ z[origins[i]] = zone
+ } else {
+ return Zones{}, err
+ }
+ names = append(names, origins[i])
+ }
+
+ noReload := false
+ prxy := proxy.Proxy{}
+ t := []string{}
+ var e error
+
+ for c.NextBlock() {
+ switch c.Val() {
+ case "transfer":
+ t, _, e = TransferParse(c, false)
+ if e != nil {
+ return Zones{}, e
+ }
+
+ case "no_reload":
+ noReload = true
+
+ case "upstream":
+ args := c.RemainingArgs()
+ if len(args) == 0 {
+ return Zones{}, c.ArgErr()
+ }
+ ups, err := dnsutil.ParseHostPortOrFile(args...)
+ if err != nil {
+ return Zones{}, err
+ }
+ prxy = proxy.NewLookup(ups)
+ default:
+ return Zones{}, c.Errf("unknown property '%s'", c.Val())
+ }
+
+ for _, origin := range origins {
+ if t != nil {
+ z[origin].TransferTo = append(z[origin].TransferTo, t...)
+ }
+ z[origin].NoReload = noReload
+ z[origin].Proxy = prxy
+ }
+ }
+ }
+ return Zones{Z: z, Names: names}, nil
+}
+
+// TransferParse parses transfer statements: 'transfer to [address...]'.
+func TransferParse(c *caddy.Controller, secondary bool) (tos, froms []string, err error) {
+ if !c.NextArg() {
+ return nil, nil, c.ArgErr()
+ }
+ value := c.Val()
+ switch value {
+ case "to":
+ tos = c.RemainingArgs()
+ for i := range tos {
+ if tos[i] != "*" {
+ normalized, err := dnsutil.ParseHostPort(tos[i], "53")
+ if err != nil {
+ return nil, nil, err
+ }
+ tos[i] = normalized
+ }
+ }
+
+ case "from":
+ if !secondary {
+ return nil, nil, fmt.Errorf("can't use `transfer from` when not being a secondary")
+ }
+ froms = c.RemainingArgs()
+ for i := range froms {
+ if froms[i] != "*" {
+ normalized, err := dnsutil.ParseHostPort(froms[i], "53")
+ if err != nil {
+ return nil, nil, err
+ }
+ froms[i] = normalized
+ } else {
+ return nil, nil, fmt.Errorf("can't use '*' in transfer from")
+ }
+ }
+ }
+ return
+}