aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--plugin/backend_lookup.go60
-rw-r--r--plugin/etcd/cname_test.go12
-rw-r--r--plugin/etcd/etcd.go10
-rw-r--r--plugin/etcd/handler.go2
-rw-r--r--plugin/etcd/msg/type.go6
-rw-r--r--plugin/kubernetes/handler.go2
6 files changed, 80 insertions, 12 deletions
diff --git a/plugin/backend_lookup.go b/plugin/backend_lookup.go
index 9e5c9eeec..c563295d6 100644
--- a/plugin/backend_lookup.go
+++ b/plugin/backend_lookup.go
@@ -325,15 +325,69 @@ func CNAME(ctx context.Context, b ServiceBackend, zone string, state request.Req
}
// TXT returns TXT records from Backend or an error.
-func TXT(ctx context.Context, b ServiceBackend, zone string, state request.Request, opt Options) (records []dns.RR, err error) {
- services, err := b.Services(ctx, state, false, opt)
+func TXT(ctx context.Context, b ServiceBackend, zone string, state request.Request, previousRecords []dns.RR, opt Options) (records []dns.RR, err error) {
+
+ services, err := b.Services(ctx, state, true, opt)
if err != nil {
return nil, err
}
+ dup := make(map[string]struct{})
+
for _, serv := range services {
- records = append(records, serv.NewTXT(state.QName()))
+
+ what, _ := serv.HostType()
+
+ switch what {
+ case dns.TypeCNAME:
+ if Name(state.Name()).Matches(dns.Fqdn(serv.Host)) {
+ // x CNAME x is a direct loop, don't add those
+ continue
+ }
+
+ newRecord := serv.NewCNAME(state.QName(), serv.Host)
+ if len(previousRecords) > 7 {
+ // don't add it, and just continue
+ continue
+ }
+ if dnsutil.DuplicateCNAME(newRecord, previousRecords) {
+ continue
+ }
+ if dns.IsSubDomain(zone, dns.Fqdn(serv.Host)) {
+ state1 := state.NewWithQuestion(serv.Host, state.QType())
+ state1.Zone = zone
+ nextRecords, err := TXT(ctx, b, zone, state1, append(previousRecords, newRecord), opt)
+
+ if err == nil {
+ // Not only have we found something we should add the CNAME and the IP addresses.
+ if len(nextRecords) > 0 {
+ records = append(records, newRecord)
+ records = append(records, nextRecords...)
+ }
+ }
+ continue
+ }
+ // This means we can not complete the CNAME, try to look else where.
+ target := newRecord.Target
+ // Lookup
+ m1, e1 := b.Lookup(ctx, state, target, state.QType())
+ if e1 != nil {
+ continue
+ }
+ // Len(m1.Answer) > 0 here is well?
+ records = append(records, newRecord)
+ records = append(records, m1.Answer...)
+ continue
+
+ case dns.TypeTXT:
+ if _, ok := dup[serv.Host]; !ok {
+ dup[serv.Host] = struct{}{}
+ return append(records, serv.NewTXT(state.QName())), nil
+ }
+
+ }
}
+
return records, nil
}
diff --git a/plugin/etcd/cname_test.go b/plugin/etcd/cname_test.go
index 3d571077f..a7d45d510 100644
--- a/plugin/etcd/cname_test.go
+++ b/plugin/etcd/cname_test.go
@@ -58,6 +58,9 @@ var servicesCname = []*msg.Service{
{Host: "cname6.region2.skydns.test", Key: "cname5.region2.skydns.test."},
{Host: "endpoint.region2.skydns.test", Key: "cname6.region2.skydns.test."},
{Host: "mainendpoint.region2.skydns.test", Key: "region2.skydns.test."},
+ {Host: "cname2.region3.skydns.test", Key: "cname3.region3.skydns.test."},
+ {Host: "cname1.region3.skydns.test", Key: "cname2.region3.skydns.test."},
+ {Host: "region3.skydns.test", Key: "cname1.region3.skydns.test."},
{Host: "", Key: "region3.skydns.test.", Text: "SOME-RECORD-TEXT"},
{Host: "10.240.0.1", Key: "endpoint.region2.skydns.test."},
}
@@ -91,4 +94,13 @@ var dnsTestCasesCname = []test.Case{
test.SOA("skydns.test. 303 IN SOA ns.dns.skydns.test. hostmaster.skydns.test. 1546424605 7200 1800 86400 30"),
},
},
+ {
+ Qname: "cname3.region3.skydns.test.", Qtype: dns.TypeTXT,
+ Answer: []dns.RR{
+ test.CNAME("cname3.region3.skydns.test. 300 IN CNAME cname2.region3.skydns.test."),
+ test.CNAME("cname2.region3.skydns.test. 300 IN CNAME cname1.region3.skydns.test."),
+ test.CNAME("cname1.region3.skydns.test. 300 IN CNAME region3.skydns.test."),
+ test.TXT("region3.skydns.test. 300 IN TXT \"SOME-RECORD-TEXT\""),
+ },
+ },
}
diff --git a/plugin/etcd/etcd.go b/plugin/etcd/etcd.go
index 305e8e492..d8e9e054e 100644
--- a/plugin/etcd/etcd.go
+++ b/plugin/etcd/etcd.go
@@ -177,11 +177,9 @@ func (e *Etcd) TTL(kv *mvccpb.KeyValue, serv *msg.Service) uint32 {
}
// shouldInclude returns true if the service should be included in a list of records, given the qType. For all the
-// currently supported lookup types, the only one to allow for an empty Host field in the service are TXT records.
-// Similarly, the TXT record in turn requires the Text field to be set.
+// currently supported lookup types, the only one to allow for an empty Host field in the service are TXT records
+// which resolve directly. If a TXT record is being resolved by CNAME, then we expect the Host field to have a
+// value while the TXT field will be empty.
func shouldInclude(serv *msg.Service, qType uint16) bool {
- if qType == dns.TypeTXT {
- return serv.Text != ""
- }
- return serv.Host != ""
+ return (qType == dns.TypeTXT && serv.Text != "") || serv.Host != ""
}
diff --git a/plugin/etcd/handler.go b/plugin/etcd/handler.go
index c62956736..395199bd0 100644
--- a/plugin/etcd/handler.go
+++ b/plugin/etcd/handler.go
@@ -30,7 +30,7 @@ func (e *Etcd) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (
case dns.TypeAAAA:
records, err = plugin.AAAA(ctx, e, zone, state, nil, opt)
case dns.TypeTXT:
- records, err = plugin.TXT(ctx, e, zone, state, opt)
+ records, err = plugin.TXT(ctx, e, zone, state, nil, opt)
case dns.TypeCNAME:
records, err = plugin.CNAME(ctx, e, zone, state, opt)
case dns.TypePTR:
diff --git a/plugin/etcd/msg/type.go b/plugin/etcd/msg/type.go
index 7f3bfdbb9..ad09e74fb 100644
--- a/plugin/etcd/msg/type.go
+++ b/plugin/etcd/msg/type.go
@@ -19,8 +19,12 @@ func (s *Service) HostType() (what uint16, normalized net.IP) {
ip := net.ParseIP(s.Host)
switch {
+
case ip == nil:
- return dns.TypeCNAME, nil
+ if len(s.Text) == 0 {
+ return dns.TypeCNAME, nil
+ }
+ return dns.TypeTXT, nil
case ip.To4() != nil:
return dns.TypeA, ip.To4()
diff --git a/plugin/kubernetes/handler.go b/plugin/kubernetes/handler.go
index 6ff8040a4..78761d303 100644
--- a/plugin/kubernetes/handler.go
+++ b/plugin/kubernetes/handler.go
@@ -35,7 +35,7 @@ func (k Kubernetes) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.M
case dns.TypeAAAA:
records, err = plugin.AAAA(ctx, &k, zone, state, nil, plugin.Options{})
case dns.TypeTXT:
- records, err = plugin.TXT(ctx, &k, zone, state, plugin.Options{})
+ records, err = plugin.TXT(ctx, &k, zone, state, nil, plugin.Options{})
case dns.TypeCNAME:
records, err = plugin.CNAME(ctx, &k, zone, state, plugin.Options{})
case dns.TypePTR: