aboutsummaryrefslogtreecommitdiff
path: root/core/setup/file.go
blob: 0b85d84f3db1df6c15f6b466282497a99e3c8293 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package setup

import (
	"log"
	"os"

	"github.com/miekg/coredns/middleware"
	"github.com/miekg/coredns/middleware/file"

	"github.com/miekg/dns"
)

// File sets up the file middleware.
func File(c *Controller) (middleware.Middleware, error) {
	zones, err := fileParse(c)
	if err != nil {
		return nil, err
	}
	return func(next middleware.Handler) middleware.Handler {
		return file.File{Next: next, Zones: zones}
	}, nil

}

func fileParse(c *Controller) (file.Zones, error) {
	// Maybe multiple, each for each zone.
	z := make(map[string]file.Zone)
	names := []string{}
	for c.Next() {
		if c.Val() == "file" {
			// file db.file [origin]
			if !c.NextArg() {
				return file.Zones{}, c.ArgErr()
			}
			fileName := c.Val()

			origin := c.ServerBlockHosts[c.ServerBlockHostIndex]
			if c.NextArg() {
				c.Next()
				origin = c.Val()
			}
			// normalize this origin
			origin = middleware.Host(origin).StandardHost()

			zone, err := parseZone(origin, fileName)
			if err == nil {
				z[origin] = zone
			}
			names = append(names, origin)
		}
	}
	return file.Zones{Z: z, Names: names}, nil
}

//
// parsrZone parses the zone in filename and returns a []RR or an error.
func parseZone(origin, fileName string) (file.Zone, error) {
	f, err := os.Open(fileName)
	if err != nil {
		return nil, err
	}
	tokens := dns.ParseZone(f, origin, fileName)
	zone := make([]dns.RR, 0, defaultZoneSize)
	for x := range tokens {
		if x.Error != nil {
			log.Printf("[ERROR] failed to parse %s: %v", origin, x.Error)
			return nil, x.Error
		}
		zone = append(zone, x.RR)
	}
	return file.Zone(zone), nil
}

const defaultZoneSize = 20 // A made up number.