Commit 6bbb48d4 authored by Chris O'Haver's avatar Chris O'Haver Committed by GitHub

plugin/file: Use NXDOMAIN response if CNAME target is NXDOMAIN (#4303)

* pass through nxdomain results
Signed-off-by: default avatarChris O'Haver <cohaver@infoblox.com>

* return srvfail and nodata results
Signed-off-by: default avatarChris O'Haver <cohaver@infoblox.com>

* add test
Signed-off-by: default avatarChris O'Haver <cohaver@infoblox.com>

* cover more response cases
Signed-off-by: default avatarChris O'Haver <cohaver@infoblox.com>
parent 5ecf23ae
...@@ -307,8 +307,9 @@ func (z *Zone) externalLookup(ctx context.Context, state request.Request, elem * ...@@ -307,8 +307,9 @@ func (z *Zone) externalLookup(ctx context.Context, state request.Request, elem *
targetName := rrs[0].(*dns.CNAME).Target targetName := rrs[0].(*dns.CNAME).Target
elem, _ = z.Tree.Search(targetName) elem, _ = z.Tree.Search(targetName)
if elem == nil { if elem == nil {
rrs = append(rrs, z.doLookup(ctx, state, targetName, qtype)...) lookupRRs, result := z.doLookup(ctx, state, targetName, qtype)
return rrs, z.Apex.ns(do), nil, Success rrs = append(rrs, lookupRRs...)
return rrs, z.Apex.ns(do), nil, result
} }
i := 0 i := 0
...@@ -326,8 +327,9 @@ Redo: ...@@ -326,8 +327,9 @@ Redo:
targetName := cname[0].(*dns.CNAME).Target targetName := cname[0].(*dns.CNAME).Target
elem, _ = z.Tree.Search(targetName) elem, _ = z.Tree.Search(targetName)
if elem == nil { if elem == nil {
rrs = append(rrs, z.doLookup(ctx, state, targetName, qtype)...) lookupRRs, result := z.doLookup(ctx, state, targetName, qtype)
return rrs, z.Apex.ns(do), nil, Success rrs = append(rrs, lookupRRs...)
return rrs, z.Apex.ns(do), nil, result
} }
i++ i++
...@@ -352,15 +354,24 @@ Redo: ...@@ -352,15 +354,24 @@ Redo:
return rrs, z.Apex.ns(do), nil, Success return rrs, z.Apex.ns(do), nil, Success
} }
func (z *Zone) doLookup(ctx context.Context, state request.Request, target string, qtype uint16) []dns.RR { func (z *Zone) doLookup(ctx context.Context, state request.Request, target string, qtype uint16) ([]dns.RR, Result) {
m, e := z.Upstream.Lookup(ctx, state, target, qtype) m, e := z.Upstream.Lookup(ctx, state, target, qtype)
if e != nil { if e != nil {
return nil return nil, Success
} }
if m == nil { if m == nil {
return nil return nil, Success
}
if m.Rcode == dns.RcodeNameError {
return m.Answer, NameError
}
if m.Rcode == dns.RcodeServerFailure {
return m.Answer, ServerFailure
}
if m.Rcode == dns.RcodeSuccess && len(m.Answer) == 0 {
return m.Answer, NoData
} }
return m.Answer return m.Answer, Success
} }
// additionalProcessing checks the current answer section and retrieves A or AAAA records // additionalProcessing checks the current answer section and retrieves A or AAAA records
......
...@@ -58,6 +58,113 @@ www 3600 IN CNAME www.example.net. ...@@ -58,6 +58,113 @@ www 3600 IN CNAME www.example.net.
} }
} }
func TestFileUpstreamError(t *testing.T) {
cases := map[string]test.Case{
"nxdomain": {
Qname: "nxdomain.example.org.", Qtype: dns.TypeA,
Answer: []dns.RR{
test.CNAME("nxdomain.example.org. 3600 IN CNAME nxdomain.example.net"),
},
Rcode: dns.RcodeNameError,
},
"nxdomain-chain": {
Qname: "chain1.example.org.", Qtype: dns.TypeA,
Answer: []dns.RR{
test.CNAME("chain1.example.org. 3600 IN CNAME nxdomain.example.org"),
test.CNAME("nxdomain.example.org. 3600 IN CNAME nxdomain.example.net"),
},
Rcode: dns.RcodeNameError,
},
"srvfail": {
Qname: "srvfail.example.org.", Qtype: dns.TypeA,
Rcode: dns.RcodeServerFailure,
},
"srvfail-chain": {
Qname: "chain2.example.org.", Qtype: dns.TypeA,
Rcode: dns.RcodeServerFailure,
},
"nodata": {
Qname: "nodata.example.org.", Qtype: dns.TypeA,
Answer: []dns.RR{
test.CNAME("nodata.example.org. 3600 IN CNAME nodata.example.net"),
},
Rcode: dns.RcodeSuccess,
},
"nodata-chain": {
Qname: "chain3.example.org.", Qtype: dns.TypeA,
Answer: []dns.RR{
test.CNAME("chain3.example.org. 3600 IN CNAME nodata.example.org"),
test.CNAME("nodata.example.org. 3600 IN CNAME nodata.example.net"),
},
Rcode: dns.RcodeSuccess,
},
}
name, rm, err := test.TempFile(".", `$ORIGIN example.org.
@ 3600 IN SOA sns.dns.icann.org. noc.dns.icann.org. (
2017042745 ; serial
7200 ; refresh (2 hours)
3600 ; retry (1 hour)
1209600 ; expire (2 weeks)
3600 ; minimum (1 hour)
)
3600 IN NS a.iana-servers.net.
3600 IN NS b.iana-servers.net.
chain1 3600 IN CNAME nxdomain
nxdomain 3600 IN CNAME nxdomain.example.net.
chain2 3600 IN CNAME srvfail
srvfail 3600 IN CNAME srvfail.example.net.
chain3 3600 IN CNAME nodata
nodata 3600 IN CNAME nodata.example.net.
`)
if err != nil {
t.Fatalf("Failed to create zone: %s", err)
}
defer rm()
corefile := `.:0 {
template ANY A nxdomain.example.net. {
rcode NXDOMAIN
}
template ANY A srvfail.example.net. {
rcode SERVFAIL
}
template ANY A nodata.example.net. {
}
file ` + name + ` example.org
}`
i, udp, _, err := CoreDNSServerAndPorts(corefile)
if err != nil {
t.Fatalf("Could not get CoreDNS serving instance: %s", err)
}
defer i.Stop()
for n, tc := range cases {
t.Run(n, func(t *testing.T) {
m := new(dns.Msg)
m.SetQuestion(tc.Qname, tc.Qtype)
m.SetEdns0(4096, true)
r, err := dns.Exchange(m, udp)
if err != nil {
t.Fatalf("Could not exchange msg: %s", err)
}
if r.Rcode != tc.Rcode {
t.Fatalf("expected rcode %v, got %v", tc.Rcode, r.Rcode)
}
if n := len(r.Answer); n != len(tc.Answer) {
t.Fatalf("Expected %v answers, got %v", len(tc.Answer), n)
}
if err := test.Section(tc, test.Answer, r.Answer); err != nil {
t.Error(err)
}
})
}
}
// TestFileUpstreamAdditional runs two CoreDNS servers that serve example.org and foo.example.org. // TestFileUpstreamAdditional runs two CoreDNS servers that serve example.org and foo.example.org.
// example.org contains a cname to foo.example.org; this should be resolved via upstream.Self. // example.org contains a cname to foo.example.org; this should be resolved via upstream.Self.
func TestFileUpstreamAdditional(t *testing.T) { func TestFileUpstreamAdditional(t *testing.T) {
......
$ORIGIN example.org.
@ 3600 IN SOA sns.dns.icann.org. noc.dns.icann.org. (
2017042745 ; serial
7200 ; refresh (2 hours)
3600 ; retry (1 hour)
1209600 ; expire (2 weeks)
3600 ; minimum (1 hour)
)
3600 IN NS a.iana-servers.net.
3600 IN NS b.iana-servers.net.
chain1 3600 IN CNAME nxdomain
nxdomain 3600 IN CNAME nxdomain.example.net.
chain2 3600 IN CNAME srvfail
srvfail 3600 IN CNAME srvfail.example.net.
chain3 3600 IN CNAME nodata
nodata 3600 IN CNAME nodata.example.net.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment