Fixes: debug RR and header bits (#151)
Always set the auth and rd bits in the reply. And reverse the ownername of debug queries so that manual matching is much easier.
This commit is contained in:
parent
c30671f4c0
commit
446eaa957d
9 changed files with 31 additions and 31 deletions
|
@ -113,8 +113,8 @@ var dnsTestCasesDebug = []test.Case{
|
||||||
test.A("dom.skydns.test. 300 IN A 127.0.0.2"),
|
test.A("dom.skydns.test. 300 IN A 127.0.0.2"),
|
||||||
},
|
},
|
||||||
Extra: []dns.RR{
|
Extra: []dns.RR{
|
||||||
test.TXT(`skydns.test.skydns.dom.a. 300 CH TXT "127.0.0.1:0(10,0,,false)[0,]"`),
|
test.TXT(`a.dom.skydns.test. 300 CH TXT "127.0.0.1:0(10,0,,false)[0,]"`),
|
||||||
test.TXT(`skydns.test.skydns.dom.sub.b. 300 CH TXT "127.0.0.2:0(10,0,,false)[0,]"`),
|
test.TXT(`b.sub.dom.skydns.test. 300 CH TXT "127.0.0.2:0(10,0,,false)[0,]"`),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -123,8 +123,8 @@ var dnsTestCasesDebug = []test.Case{
|
||||||
test.SOA("skydns.test. 300 IN SOA ns.dns.skydns.test. hostmaster.skydns.test. 1463943291 7200 1800 86400 60"),
|
test.SOA("skydns.test. 300 IN SOA ns.dns.skydns.test. hostmaster.skydns.test. 1463943291 7200 1800 86400 60"),
|
||||||
},
|
},
|
||||||
Extra: []dns.RR{
|
Extra: []dns.RR{
|
||||||
test.TXT(`skydns.test.skydns.dom.a. 300 CH TXT "127.0.0.1:0(10,0,,false)[0,]"`),
|
test.TXT(`a.dom.skydns.test. 300 CH TXT "127.0.0.1:0(10,0,,false)[0,]"`),
|
||||||
test.TXT(`skydns.test.skydns.dom.sub.b. 300 CH TXT "127.0.0.2:0(10,0,,false)[0,]"`),
|
test.TXT(`b.sub.dom.skydns.test. 300 CH TXT "127.0.0.2:0(10,0,,false)[0,]"`),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,12 +32,12 @@ type Etcd struct {
|
||||||
// this name. This is used when find matches when completing SRV lookups
|
// this name. This is used when find matches when completing SRV lookups
|
||||||
// for instance.
|
// for instance.
|
||||||
func (g Etcd) Records(name string, exact bool) ([]msg.Service, error) {
|
func (g Etcd) Records(name string, exact bool) ([]msg.Service, error) {
|
||||||
path, star := g.PathWithWildcard(name)
|
path, star := msg.PathWithWildcard(name, g.PathPrefix)
|
||||||
r, err := g.Get(path, true)
|
r, err := g.Get(path, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
segments := strings.Split(g.Path(name), "/")
|
segments := strings.Split(msg.Path(name, g.PathPrefix), "/")
|
||||||
switch {
|
switch {
|
||||||
case exact && r.Node.Dir:
|
case exact && r.Node.Dir:
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
|
@ -76,7 +76,7 @@ func (e Etcd) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (i
|
||||||
}
|
}
|
||||||
|
|
||||||
if e.debug != "" {
|
if e.debug != "" {
|
||||||
// substitute this name with the original when we return the request.
|
// Substitute this name with the original when we return the request.
|
||||||
state.Clear()
|
state.Clear()
|
||||||
state.Req.Question[0].Name = e.debug
|
state.Req.Question[0].Name = e.debug
|
||||||
}
|
}
|
||||||
|
@ -112,6 +112,7 @@ func (e Etcd) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (i
|
||||||
func (e Etcd) Err(zone string, rcode int, state middleware.State, debug []msg.Service) (int, error) {
|
func (e Etcd) Err(zone string, rcode int, state middleware.State, debug []msg.Service) (int, error) {
|
||||||
m := new(dns.Msg)
|
m := new(dns.Msg)
|
||||||
m.SetRcode(state.Req, rcode)
|
m.SetRcode(state.Req, rcode)
|
||||||
|
m.Authoritative, m.RecursionAvailable, m.Compress = true, true, true
|
||||||
m.Ns, _, _ = e.SOA(zone, state)
|
m.Ns, _, _ = e.SOA(zone, state)
|
||||||
m.Extra = servicesToTxt(debug)
|
m.Extra = servicesToTxt(debug)
|
||||||
state.SizeAndDo(m)
|
state.SizeAndDo(m)
|
||||||
|
|
|
@ -213,13 +213,13 @@ func (e Etcd) SRV(zone string, state middleware.State) (records, extra []dns.RR,
|
||||||
}
|
}
|
||||||
// e.AAA(zone, state1, nil) as well...?
|
// e.AAA(zone, state1, nil) as well...?
|
||||||
case ip.To4() != nil:
|
case ip.To4() != nil:
|
||||||
serv.Host = e.Domain(serv.Key)
|
serv.Host = msg.Domain(serv.Key)
|
||||||
srv := serv.NewSRV(state.QName(), weight)
|
srv := serv.NewSRV(state.QName(), weight)
|
||||||
|
|
||||||
records = append(records, srv)
|
records = append(records, srv)
|
||||||
extra = append(extra, serv.NewA(srv.Target, ip.To4()))
|
extra = append(extra, serv.NewA(srv.Target, ip.To4()))
|
||||||
case ip.To4() == nil:
|
case ip.To4() == nil:
|
||||||
serv.Host = e.Domain(serv.Key)
|
serv.Host = msg.Domain(serv.Key)
|
||||||
srv := serv.NewSRV(state.QName(), weight)
|
srv := serv.NewSRV(state.QName(), weight)
|
||||||
|
|
||||||
records = append(records, srv)
|
records = append(records, srv)
|
||||||
|
@ -278,11 +278,11 @@ func (e Etcd) MX(zone string, state middleware.State) (records, extra []dns.RR,
|
||||||
}
|
}
|
||||||
// e.AAAA as well
|
// e.AAAA as well
|
||||||
case ip.To4() != nil:
|
case ip.To4() != nil:
|
||||||
serv.Host = e.Domain(serv.Key)
|
serv.Host = msg.Domain(serv.Key)
|
||||||
records = append(records, serv.NewMX(state.QName()))
|
records = append(records, serv.NewMX(state.QName()))
|
||||||
extra = append(extra, serv.NewA(serv.Host, ip.To4()))
|
extra = append(extra, serv.NewA(serv.Host, ip.To4()))
|
||||||
case ip.To4() == nil:
|
case ip.To4() == nil:
|
||||||
serv.Host = e.Domain(serv.Key)
|
serv.Host = msg.Domain(serv.Key)
|
||||||
records = append(records, serv.NewMX(state.QName()))
|
records = append(records, serv.NewMX(state.QName()))
|
||||||
extra = append(extra, serv.NewAAAA(serv.Host, ip.To16()))
|
extra = append(extra, serv.NewAAAA(serv.Host, ip.To16()))
|
||||||
}
|
}
|
||||||
|
@ -340,11 +340,11 @@ func (e Etcd) NS(zone string, state middleware.State) (records, extra []dns.RR,
|
||||||
case ip == nil:
|
case ip == nil:
|
||||||
return nil, nil, debug, fmt.Errorf("NS record must be an IP address: %s", serv.Host)
|
return nil, nil, debug, fmt.Errorf("NS record must be an IP address: %s", serv.Host)
|
||||||
case ip.To4() != nil:
|
case ip.To4() != nil:
|
||||||
serv.Host = e.Domain(serv.Key)
|
serv.Host = msg.Domain(serv.Key)
|
||||||
records = append(records, serv.NewNS(state.QName()))
|
records = append(records, serv.NewNS(state.QName()))
|
||||||
extra = append(extra, serv.NewA(serv.Host, ip.To4()))
|
extra = append(extra, serv.NewA(serv.Host, ip.To4()))
|
||||||
case ip.To4() == nil:
|
case ip.To4() == nil:
|
||||||
serv.Host = e.Domain(serv.Key)
|
serv.Host = msg.Domain(serv.Key)
|
||||||
records = append(records, serv.NewNS(state.QName()))
|
records = append(records, serv.NewNS(state.QName()))
|
||||||
extra = append(extra, serv.NewAAAA(serv.Host, ip.To16()))
|
extra = append(extra, serv.NewAAAA(serv.Host, ip.To16()))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package etcd
|
package msg
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"path"
|
"path"
|
||||||
|
@ -9,16 +9,16 @@ import (
|
||||||
|
|
||||||
// Path converts a domainname to an etcd path. If s looks like service.staging.skydns.local.,
|
// Path converts a domainname to an etcd path. If s looks like service.staging.skydns.local.,
|
||||||
// the resulting key will be /skydns/local/skydns/staging/service .
|
// the resulting key will be /skydns/local/skydns/staging/service .
|
||||||
func (e Etcd) Path(s string) string {
|
func Path(s, prefix string) string {
|
||||||
l := dns.SplitDomainName(s)
|
l := dns.SplitDomainName(s)
|
||||||
for i, j := 0, len(l)-1; i < j; i, j = i+1, j-1 {
|
for i, j := 0, len(l)-1; i < j; i, j = i+1, j-1 {
|
||||||
l[i], l[j] = l[j], l[i]
|
l[i], l[j] = l[j], l[i]
|
||||||
}
|
}
|
||||||
return path.Join(append([]string{"/" + e.PathPrefix + "/"}, l...)...)
|
return path.Join(append([]string{"/" + prefix + "/"}, l...)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Domain is the opposite of Path.
|
// Domain is the opposite of Path.
|
||||||
func (e Etcd) Domain(s string) string {
|
func Domain(s string) string {
|
||||||
l := strings.Split(s, "/")
|
l := strings.Split(s, "/")
|
||||||
// start with 1, to strip /skydns
|
// start with 1, to strip /skydns
|
||||||
for i, j := 1, len(l)-1; i < j; i, j = i+1, j-1 {
|
for i, j := 1, len(l)-1; i < j; i, j = i+1, j-1 {
|
||||||
|
@ -32,15 +32,15 @@ func (e Etcd) Domain(s string) string {
|
||||||
// later find the matching names. So service.*.skydns.local, will look for all
|
// later find the matching names. So service.*.skydns.local, will look for all
|
||||||
// services under skydns.local and will later check for names that match
|
// services under skydns.local and will later check for names that match
|
||||||
// service.*.skydns.local. If a wildcard is found the returned bool is true.
|
// service.*.skydns.local. If a wildcard is found the returned bool is true.
|
||||||
func (e Etcd) PathWithWildcard(s string) (string, bool) {
|
func PathWithWildcard(s, prefix string) (string, bool) {
|
||||||
l := dns.SplitDomainName(s)
|
l := dns.SplitDomainName(s)
|
||||||
for i, j := 0, len(l)-1; i < j; i, j = i+1, j-1 {
|
for i, j := 0, len(l)-1; i < j; i, j = i+1, j-1 {
|
||||||
l[i], l[j] = l[j], l[i]
|
l[i], l[j] = l[j], l[i]
|
||||||
}
|
}
|
||||||
for i, k := range l {
|
for i, k := range l {
|
||||||
if k == "*" || k == "any" {
|
if k == "*" || k == "any" {
|
||||||
return path.Join(append([]string{"/" + e.PathPrefix + "/"}, l[:i]...)...), true
|
return path.Join(append([]string{"/" + prefix + "/"}, l[:i]...)...), true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return path.Join(append([]string{"/" + e.PathPrefix + "/"}, l...)...), false
|
return path.Join(append([]string{"/" + prefix + "/"}, l...)...), false
|
||||||
}
|
}
|
|
@ -1,11 +1,10 @@
|
||||||
package etcd
|
package msg
|
||||||
|
|
||||||
import "testing"
|
import "testing"
|
||||||
|
|
||||||
func TestPath(t *testing.T) {
|
func TestPath(t *testing.T) {
|
||||||
for _, path := range []string{"mydns", "skydns"} {
|
for _, path := range []string{"mydns", "skydns"} {
|
||||||
e := Etcd{PathPrefix: path}
|
result := Path("service.staging.skydns.local.", path)
|
||||||
result := e.Path("service.staging.skydns.local.")
|
|
||||||
if result != "/"+path+"/local/skydns/staging/service" {
|
if result != "/"+path+"/local/skydns/staging/service" {
|
||||||
t.Errorf("Failure to get domain's path with prefix: %s", result)
|
t.Errorf("Failure to get domain's path with prefix: %s", result)
|
||||||
}
|
}
|
|
@ -39,13 +39,13 @@ type Service struct {
|
||||||
// RR returns an RR representation of s. It is in a condensed form to minimize space
|
// RR returns an RR representation of s. It is in a condensed form to minimize space
|
||||||
// when this is returned in a DNS message.
|
// when this is returned in a DNS message.
|
||||||
// The RR will look like:
|
// The RR will look like:
|
||||||
// skydns.local.skydns.east.production.rails.1. 300 CH TXT "service1.example.com:8080(10,0,,false)[0,]"
|
// 1.rails.production.east.skydns.local. 300 CH TXT "service1.example.com:8080(10,0,,false)[0,]"
|
||||||
// etcd Key Ttl Host:Port < see below >
|
// etcd Key Ttl Host:Port < see below >
|
||||||
// between parens: (Priority, Weight, Text (only first 200 bytes!), Mail)
|
// between parens: (Priority, Weight, Text (only first 200 bytes!), Mail)
|
||||||
// between blockquotes: [TargetStrip,Group]
|
// between blockquotes: [TargetStrip,Group]
|
||||||
// If the record is synthesised by CoreDNS (i.e. no lookup in etcd happened):
|
// If the record is synthesised by CoreDNS (i.e. no lookup in etcd happened):
|
||||||
//
|
//
|
||||||
// skydns.local.skydns.east.production.rails.1. 300 CH TXT "service1.example.com:8080(10,0,,false)[0,]"
|
// TODO(miek): what to put here?
|
||||||
//
|
//
|
||||||
func (s *Service) RR() *dns.TXT {
|
func (s *Service) RR() *dns.TXT {
|
||||||
l := len(s.Text)
|
l := len(s.Text)
|
||||||
|
@ -56,8 +56,7 @@ func (s *Service) RR() *dns.TXT {
|
||||||
t.Hdr.Class = dns.ClassCHAOS
|
t.Hdr.Class = dns.ClassCHAOS
|
||||||
t.Hdr.Ttl = s.Ttl
|
t.Hdr.Ttl = s.Ttl
|
||||||
t.Hdr.Rrtype = dns.TypeTXT
|
t.Hdr.Rrtype = dns.TypeTXT
|
||||||
// TODO(miek): key guaranteerd to be > 1?
|
t.Hdr.Name = Domain(s.Key)
|
||||||
t.Hdr.Name = strings.Replace(s.Key[1:], "/", ".", -1) + "." // TODO(miek): slightly more like etcd.Domain()
|
|
||||||
|
|
||||||
t.Txt = make([]string, 1)
|
t.Txt = make([]string, 1)
|
||||||
t.Txt[0] = fmt.Sprintf("%s:%d(%d,%d,%s,%t)[%d,%s]",
|
t.Txt[0] = fmt.Sprintf("%s:%d(%d,%d,%s,%t)[%d,%s]",
|
||||||
|
|
|
@ -47,12 +47,12 @@ func set(t *testing.T, e Etcd, k string, ttl time.Duration, m *msg.Service) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
path, _ := e.PathWithWildcard(k)
|
path, _ := msg.PathWithWildcard(k, e.PathPrefix)
|
||||||
e.Client.Set(ctx, path, string(b), &etcdc.SetOptions{TTL: ttl})
|
e.Client.Set(ctx, path, string(b), &etcdc.SetOptions{TTL: ttl})
|
||||||
}
|
}
|
||||||
|
|
||||||
func delete(t *testing.T, e Etcd, k string) {
|
func delete(t *testing.T, e Etcd, k string) {
|
||||||
path, _ := e.PathWithWildcard(k)
|
path, _ := msg.PathWithWildcard(k, e.PathPrefix)
|
||||||
e.Client.Delete(ctx, path, &etcdc.DeleteOptions{Recursive: false})
|
e.Client.Delete(ctx, path, &etcdc.DeleteOptions{Recursive: false})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/miekg/coredns/middleware/etcd/msg"
|
||||||
"github.com/miekg/coredns/middleware/proxy"
|
"github.com/miekg/coredns/middleware/proxy"
|
||||||
|
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
|
@ -46,7 +47,7 @@ func (e *Etcd) updateStubZones() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
domain := e.Domain(serv.Key)
|
domain := msg.Domain(serv.Key)
|
||||||
labels := dns.SplitDomainName(domain)
|
labels := dns.SplitDomainName(domain)
|
||||||
|
|
||||||
// If the remaining name equals any of the zones we have, we ignore it.
|
// If the remaining name equals any of the zones we have, we ignore it.
|
||||||
|
|
Loading…
Add table
Reference in a new issue