aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--plugin/file/lookup.go27
-rw-r--r--test/file_upstream_test.go107
-rw-r--r--test/go-test-tmpfile56515609719
3 files changed, 145 insertions, 8 deletions
diff --git a/plugin/file/lookup.go b/plugin/file/lookup.go
index 28da3d4d0..e036d809a 100644
--- a/plugin/file/lookup.go
+++ b/plugin/file/lookup.go
@@ -307,8 +307,9 @@ func (z *Zone) externalLookup(ctx context.Context, state request.Request, elem *
targetName := rrs[0].(*dns.CNAME).Target
elem, _ = z.Tree.Search(targetName)
if elem == nil {
- rrs = append(rrs, z.doLookup(ctx, state, targetName, qtype)...)
- return rrs, z.Apex.ns(do), nil, Success
+ lookupRRs, result := z.doLookup(ctx, state, targetName, qtype)
+ rrs = append(rrs, lookupRRs...)
+ return rrs, z.Apex.ns(do), nil, result
}
i := 0
@@ -326,8 +327,9 @@ Redo:
targetName := cname[0].(*dns.CNAME).Target
elem, _ = z.Tree.Search(targetName)
if elem == nil {
- rrs = append(rrs, z.doLookup(ctx, state, targetName, qtype)...)
- return rrs, z.Apex.ns(do), nil, Success
+ lookupRRs, result := z.doLookup(ctx, state, targetName, qtype)
+ rrs = append(rrs, lookupRRs...)
+ return rrs, z.Apex.ns(do), nil, result
}
i++
@@ -352,15 +354,24 @@ Redo:
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)
if e != nil {
- return nil
+ return nil, Success
}
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
diff --git a/test/file_upstream_test.go b/test/file_upstream_test.go
index 4d13a2ca0..6b796f90d 100644
--- a/test/file_upstream_test.go
+++ b/test/file_upstream_test.go
@@ -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.
// example.org contains a cname to foo.example.org; this should be resolved via upstream.Self.
func TestFileUpstreamAdditional(t *testing.T) {
diff --git a/test/go-test-tmpfile565156097 b/test/go-test-tmpfile565156097
new file mode 100644
index 000000000..752ec30cf
--- /dev/null
+++ b/test/go-test-tmpfile565156097
@@ -0,0 +1,19 @@
+$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.
+