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:
Miek Gieben 2016-05-23 09:16:57 +01:00
parent c30671f4c0
commit 446eaa957d
9 changed files with 31 additions and 31 deletions

View file

@ -113,8 +113,8 @@ var dnsTestCasesDebug = []test.Case{
test.A("dom.skydns.test. 300 IN A 127.0.0.2"),
},
Extra: []dns.RR{
test.TXT(`skydns.test.skydns.dom.a. 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(`a.dom.skydns.test. 300 CH TXT "127.0.0.1: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"),
},
Extra: []dns.RR{
test.TXT(`skydns.test.skydns.dom.a. 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(`a.dom.skydns.test. 300 CH TXT "127.0.0.1:0(10,0,,false)[0,]"`),
test.TXT(`b.sub.dom.skydns.test. 300 CH TXT "127.0.0.2:0(10,0,,false)[0,]"`),
},
},
}

View file

@ -32,12 +32,12 @@ type Etcd struct {
// this name. This is used when find matches when completing SRV lookups
// for instance.
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)
if err != nil {
return nil, err
}
segments := strings.Split(g.Path(name), "/")
segments := strings.Split(msg.Path(name, g.PathPrefix), "/")
switch {
case exact && r.Node.Dir:
return nil, nil

View file

@ -76,7 +76,7 @@ func (e Etcd) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (i
}
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.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) {
m := new(dns.Msg)
m.SetRcode(state.Req, rcode)
m.Authoritative, m.RecursionAvailable, m.Compress = true, true, true
m.Ns, _, _ = e.SOA(zone, state)
m.Extra = servicesToTxt(debug)
state.SizeAndDo(m)

View file

@ -213,13 +213,13 @@ func (e Etcd) SRV(zone string, state middleware.State) (records, extra []dns.RR,
}
// e.AAA(zone, state1, nil) as well...?
case ip.To4() != nil:
serv.Host = e.Domain(serv.Key)
serv.Host = msg.Domain(serv.Key)
srv := serv.NewSRV(state.QName(), weight)
records = append(records, srv)
extra = append(extra, serv.NewA(srv.Target, ip.To4()))
case ip.To4() == nil:
serv.Host = e.Domain(serv.Key)
serv.Host = msg.Domain(serv.Key)
srv := serv.NewSRV(state.QName(), weight)
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
case ip.To4() != nil:
serv.Host = e.Domain(serv.Key)
serv.Host = msg.Domain(serv.Key)
records = append(records, serv.NewMX(state.QName()))
extra = append(extra, serv.NewA(serv.Host, ip.To4()))
case ip.To4() == nil:
serv.Host = e.Domain(serv.Key)
serv.Host = msg.Domain(serv.Key)
records = append(records, serv.NewMX(state.QName()))
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:
return nil, nil, debug, fmt.Errorf("NS record must be an IP address: %s", serv.Host)
case ip.To4() != nil:
serv.Host = e.Domain(serv.Key)
serv.Host = msg.Domain(serv.Key)
records = append(records, serv.NewNS(state.QName()))
extra = append(extra, serv.NewA(serv.Host, ip.To4()))
case ip.To4() == nil:
serv.Host = e.Domain(serv.Key)
serv.Host = msg.Domain(serv.Key)
records = append(records, serv.NewNS(state.QName()))
extra = append(extra, serv.NewAAAA(serv.Host, ip.To16()))
}

View file

@ -1,4 +1,4 @@
package etcd
package msg
import (
"path"
@ -9,16 +9,16 @@ import (
// 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 .
func (e Etcd) Path(s string) string {
func Path(s, prefix string) string {
l := dns.SplitDomainName(s)
for i, j := 0, len(l)-1; i < j; i, j = i+1, j-1 {
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.
func (e Etcd) Domain(s string) string {
func Domain(s string) string {
l := strings.Split(s, "/")
// start with 1, to strip /skydns
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
// 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.
func (e Etcd) PathWithWildcard(s string) (string, bool) {
func PathWithWildcard(s, prefix string) (string, bool) {
l := dns.SplitDomainName(s)
for i, j := 0, len(l)-1; i < j; i, j = i+1, j-1 {
l[i], l[j] = l[j], l[i]
}
for i, k := range l {
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
}

View file

@ -1,11 +1,10 @@
package etcd
package msg
import "testing"
func TestPath(t *testing.T) {
for _, path := range []string{"mydns", "skydns"} {
e := Etcd{PathPrefix: path}
result := e.Path("service.staging.skydns.local.")
result := Path("service.staging.skydns.local.", path)
if result != "/"+path+"/local/skydns/staging/service" {
t.Errorf("Failure to get domain's path with prefix: %s", result)
}

View file

@ -39,13 +39,13 @@ type Service struct {
// RR returns an RR representation of s. It is in a condensed form to minimize space
// when this is returned in a DNS message.
// The RR will look like:
// skydns.local.skydns.east.production.rails.1. 300 CH TXT "service1.example.com:8080(10,0,,false)[0,]"
// etcd Key Ttl Host:Port < see below >
// 1.rails.production.east.skydns.local. 300 CH TXT "service1.example.com:8080(10,0,,false)[0,]"
// etcd Key Ttl Host:Port < see below >
// between parens: (Priority, Weight, Text (only first 200 bytes!), Mail)
// between blockquotes: [TargetStrip,Group]
// 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 {
l := len(s.Text)
@ -56,8 +56,7 @@ func (s *Service) RR() *dns.TXT {
t.Hdr.Class = dns.ClassCHAOS
t.Hdr.Ttl = s.Ttl
t.Hdr.Rrtype = dns.TypeTXT
// TODO(miek): key guaranteerd to be > 1?
t.Hdr.Name = strings.Replace(s.Key[1:], "/", ".", -1) + "." // TODO(miek): slightly more like etcd.Domain()
t.Hdr.Name = Domain(s.Key)
t.Txt = make([]string, 1)
t.Txt[0] = fmt.Sprintf("%s:%d(%d,%d,%s,%t)[%d,%s]",

View file

@ -47,12 +47,12 @@ func set(t *testing.T, e Etcd, k string, ttl time.Duration, m *msg.Service) {
if err != nil {
t.Fatal(err)
}
path, _ := e.PathWithWildcard(k)
path, _ := msg.PathWithWildcard(k, e.PathPrefix)
e.Client.Set(ctx, path, string(b), &etcdc.SetOptions{TTL: ttl})
}
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})
}

View file

@ -7,6 +7,7 @@ import (
"strings"
"time"
"github.com/miekg/coredns/middleware/etcd/msg"
"github.com/miekg/coredns/middleware/proxy"
"github.com/miekg/dns"
@ -46,7 +47,7 @@ func (e *Etcd) updateStubZones() {
continue
}
domain := e.Domain(serv.Key)
domain := msg.Domain(serv.Key)
labels := dns.SplitDomainName(domain)
// If the remaining name equals any of the zones we have, we ignore it.