aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--plugin/template/README.md4
-rw-r--r--plugin/template/setup.go8
-rw-r--r--plugin/template/setup_test.go14
-rw-r--r--plugin/template/template.go8
4 files changed, 33 insertions, 1 deletions
diff --git a/plugin/template/README.md b/plugin/template/README.md
index 34a429cbb..1ec699511 100644
--- a/plugin/template/README.md
+++ b/plugin/template/README.md
@@ -18,6 +18,7 @@ template CLASS TYPE [ZONE...] {
[authority RR]
[...]
[rcode CODE]
+ [upstream [ADDRESS...]]
[fallthrough [ZONE...]]
}
~~~
@@ -29,6 +30,9 @@ template CLASS TYPE [ZONE...] {
* `answer|additional|authority` **RR** A [RFC 1035](https://tools.ietf.org/html/rfc1035#section-5) style resource record fragment
built by a [Go template](https://golang.org/pkg/text/template/) that contains the reply.
* `rcode` **CODE** A response code (`NXDOMAIN, SERVFAIL, ...`). The default is `SUCCESS`.
+* `upstream` [**ADDRESS**...] defines the upstream resolvers used for resolving CNAME.
+ If no **ADDRESS** is given, CoreDNS will resolve CNAMEs against itself. **ADDRESS**
+ can be an IP, an IP:port, or a path to a file structured like resolv.conf.
* `fallthrough` Continue with the next plugin if the zone matched but no regex matched.
If specific zones are listed (for example `in-addr.arpa` and `ip6.arpa`), then only queries for
those zones will be subject to fallthrough.
diff --git a/plugin/template/setup.go b/plugin/template/setup.go
index 616531e49..a1190d481 100644
--- a/plugin/template/setup.go
+++ b/plugin/template/setup.go
@@ -6,6 +6,7 @@ import (
"github.com/coredns/coredns/core/dnsserver"
"github.com/coredns/coredns/plugin"
+ "github.com/coredns/coredns/plugin/pkg/upstream"
"github.com/mholt/caddy"
"github.com/miekg/dns"
@@ -142,6 +143,13 @@ func templateParse(c *caddy.Controller) (handler Handler, err error) {
case "fallthrough":
t.fall.SetZonesFromArgs(c.RemainingArgs())
+ case "upstream":
+ args := c.RemainingArgs()
+ u, err := upstream.NewUpstream(args)
+ if err != nil {
+ return handler, err
+ }
+ t.upstream = u
default:
return handler, c.ArgErr()
}
diff --git a/plugin/template/setup_test.go b/plugin/template/setup_test.go
index 8233aed66..e4d4ff804 100644
--- a/plugin/template/setup_test.go
+++ b/plugin/template/setup_test.go
@@ -133,6 +133,20 @@ func TestSetupParse(t *testing.T) {
}`,
false,
},
+ {
+ `template ANY ANY up.stream.local {
+ answer "up.stream.local 5 IN CNAME up.river.local"
+ upstream
+ }`,
+ false,
+ },
+ {
+ `template ANY ANY up.stream.local {
+ answer "up.stream.local 5 IN CNAME up.river.local"
+ upstream invalid-upstream-argument
+ }`,
+ true,
+ },
}
for i, test := range tests {
c := caddy.NewTestController("dns", test.inputFileRules)
diff --git a/plugin/template/template.go b/plugin/template/template.go
index 0d1d0c251..0320d4c60 100644
--- a/plugin/template/template.go
+++ b/plugin/template/template.go
@@ -8,6 +8,7 @@ import (
"github.com/coredns/coredns/plugin"
"github.com/coredns/coredns/plugin/pkg/fall"
+ "github.com/coredns/coredns/plugin/pkg/upstream"
"github.com/coredns/coredns/request"
"github.com/miekg/dns"
@@ -32,6 +33,7 @@ type template struct {
qclass uint16
qtype uint16
fall fall.F
+ upstream upstream.Upstream
}
type templateData struct {
@@ -48,7 +50,7 @@ type templateData struct {
// ServeDNS implements the plugin.Handler interface.
func (h Handler) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
- state := request.Request{W: w, Req: r}
+ state := request.Request{W: w, Req: r, Context: ctx}
zone := plugin.Zones(h.Zones).Matches(state.Name())
if zone == "" {
@@ -81,6 +83,10 @@ func (h Handler) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg)
return dns.RcodeServerFailure, err
}
msg.Answer = append(msg.Answer, rr)
+ if rr.Header().Rrtype == dns.TypeCNAME {
+ up, _ := template.upstream.Lookup(state, rr.(*dns.CNAME).Target, dns.TypeA)
+ msg.Answer = append(msg.Answer, up.Answer...)
+ }
}
for _, additional := range template.additional {
rr, err := executeRRTemplate("additional", additional, data)