aboutsummaryrefslogtreecommitdiff
path: root/plugin/pkg/upstream/upstream.go
diff options
context:
space:
mode:
Diffstat (limited to 'plugin/pkg/upstream/upstream.go')
-rw-r--r--plugin/pkg/upstream/upstream.go55
1 files changed, 55 insertions, 0 deletions
diff --git a/plugin/pkg/upstream/upstream.go b/plugin/pkg/upstream/upstream.go
new file mode 100644
index 000000000..fc85d3f5c
--- /dev/null
+++ b/plugin/pkg/upstream/upstream.go
@@ -0,0 +1,55 @@
+// Package upstream abstracts a upstream lookups so that plugins
+// can handle them in an unified way.
+package upstream
+
+import (
+ "github.com/miekg/dns"
+
+ "github.com/coredns/coredns/core/dnsserver"
+ "github.com/coredns/coredns/plugin/pkg/dnsutil"
+ "github.com/coredns/coredns/plugin/pkg/nonwriter"
+ "github.com/coredns/coredns/plugin/proxy"
+ "github.com/coredns/coredns/request"
+)
+
+// Upstream is used to resolve CNAME targets
+type Upstream struct {
+ self bool
+ Forward *proxy.Proxy
+}
+
+// NewUpstream creates a new Upstream for given destination(s)
+func NewUpstream(dests []string) (Upstream, error) {
+ u := Upstream{}
+ if len(dests) == 0 {
+ u.self = true
+ return u, nil
+ }
+ u.self = false
+ ups, err := dnsutil.ParseHostPortOrFile(dests...)
+ if err != nil {
+ return u, err
+ }
+ p := proxy.NewLookup(ups)
+ u.Forward = &p
+ return u, nil
+}
+
+// Lookup routes lookups to Self or Forward
+func (u Upstream) Lookup(state request.Request, name string, typ uint16) (*dns.Msg, error) {
+ if u.self {
+ // lookup via self
+ req := new(dns.Msg)
+ req.SetQuestion(name, typ)
+ state.SizeAndDo(req)
+ nw := nonwriter.New(state.W)
+ state2 := request.Request{W: nw, Req: req}
+ server := state.Context.Value(dnsserver.Key{}).(*dnsserver.Server)
+ server.ServeDNS(state.Context, state2.W, req)
+ return nw.Msg, nil
+ }
+ if u.Forward != nil {
+ return u.Forward.Lookup(state, name, typ)
+ }
+ return &dns.Msg{}, nil
+}