Skip to content

Commit

Permalink
plugin/file: Use NXDOMAIN response if CNAME target is NXDOMAIN (cored…
Browse files Browse the repository at this point in the history
…ns#4303)

* pass through nxdomain results

Signed-off-by: Chris O'Haver <cohaver@infoblox.com>

* return srvfail and nodata results

Signed-off-by: Chris O'Haver <cohaver@infoblox.com>

* add test

Signed-off-by: Chris O'Haver <cohaver@infoblox.com>

* cover more response cases

Signed-off-by: Chris O'Haver <cohaver@infoblox.com>
  • Loading branch information
chrisohaver authored Dec 9, 2020
1 parent 5ecf23a commit 6bbb48d
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 8 deletions.
27 changes: 19 additions & 8 deletions plugin/file/lookup.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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++
Expand All @@ -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
Expand Down
107 changes: 107 additions & 0 deletions test/file_upstream_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
19 changes: 19 additions & 0 deletions test/go-test-tmpfile565156097
Original file line number Diff line number Diff line change
@@ -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.

0 comments on commit 6bbb48d

Please sign in to comment.