plugin/cache: Fix filtering (#4148)

The filtering of DNSSEC records in the cache plugin was not done
correctly. Also the change to introduced this bug didn't take into
account that the cache - by virtue of differentiating between DNSSEC and
no-DNSSEC - relied on not copying the data from the cache.

This change copies and then filters the data and factors the filtering
into a function that is used in two places (albeit with on ugly boolean
parameters to prevent copying things twice).

Add tests, do_test.go is moved to test/cache_test.go because the OPT
handing is done outside of the cache plugin. The core server re-attaches
the correct OPT when replying, so that makes for a better e2e test.

Added small unit test for filterRRslice and an explicit test that asks
for DNSSEC first and then plain, and vice versa to test cache behavior.

Fixes: #4146

Signed-off-by: Miek Gieben <miek@miek.nl>
This commit is contained in:
Miek Gieben 2020-09-28 16:53:00 +02:00 committed by GitHub
parent 1a1ce9a9c8
commit 35b40a84f2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 220 additions and 163 deletions

View file

@ -46,6 +46,13 @@ func TestLookupCache(t *testing.T) {
testCase(t, "short.example.org.", udp, 1, 5)
})
t.Run("DNSSEC OPT", func(t *testing.T) {
testCaseDNSSEC(t, "example.org.", udp, 4096)
})
t.Run("DNSSEC OPT", func(t *testing.T) {
testCaseDNSSEC(t, "example.org.", udp, 0)
})
}
func testCase(t *testing.T, name, addr string, expectAnsLen int, expectTTL uint32) {
@ -53,7 +60,7 @@ func testCase(t *testing.T, name, addr string, expectAnsLen int, expectTTL uint3
m.SetQuestion(name, dns.TypeA)
resp, err := dns.Exchange(m, addr)
if err != nil {
t.Fatal("Expected to receive reply, but didn't")
t.Fatalf("Expected to receive reply, but didn't: %s", err)
}
if len(resp.Answer) != expectAnsLen {
@ -65,3 +72,41 @@ func testCase(t *testing.T, name, addr string, expectAnsLen int, expectTTL uint3
t.Errorf("Expected TTL to be %d, got %d", expectTTL, ttl)
}
}
func testCaseDNSSEC(t *testing.T, name, addr string, bufsize int) {
m := new(dns.Msg)
m.SetQuestion(name, dns.TypeA)
if bufsize > 0 {
o := &dns.OPT{Hdr: dns.RR_Header{Name: ".", Rrtype: dns.TypeOPT}}
o.SetDo()
o.SetUDPSize(uint16(bufsize))
m.Extra = append(m.Extra, o)
}
resp, err := dns.Exchange(m, addr)
if err != nil {
t.Fatalf("Expected to receive reply, but didn't: %s", err)
}
if len(resp.Extra) == 0 && bufsize == 0 {
// no OPT, this is OK
return
}
opt := resp.Extra[len(resp.Extra)-1]
if x, ok := opt.(*dns.OPT); !ok && bufsize > 0 {
t.Fatalf("Expected OPT RR, got %T", x)
}
if bufsize > 0 {
if !opt.(*dns.OPT).Do() {
t.Errorf("Expected DO bit to be set, got false")
}
if x := opt.(*dns.OPT).UDPSize(); int(x) != bufsize {
t.Errorf("Expected %d bufsize, got %d", bufsize, x)
}
} else {
if opt.Header().Rrtype == dns.TypeOPT {
t.Errorf("Expected no OPT RR, but got one: %s", opt)
}
}
}