aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--request/request.go16
-rw-r--r--request/request_test.go55
2 files changed, 63 insertions, 8 deletions
diff --git a/request/request.go b/request/request.go
index 06f840f89..3ee4c2126 100644
--- a/request/request.go
+++ b/request/request.go
@@ -263,12 +263,16 @@ func (r *Request) Scrub(reply *dns.Msg) (*dns.Msg, Result) {
// Account for the OPT record that gets added in SizeAndDo(), subtract that length.
sub := 0
- if r.Do() {
+ if r.Req.IsEdns0() != nil {
sub = optLen
}
- origExtra := reply.Extra
+
+ // substract to make spaces for re-added EDNS0 OPT RR.
re := len(reply.Extra) - sub
+ size -= sub
+
l, m := 0, 0
+ origExtra := reply.Extra
for l < re {
m = (l + re) / 2
reply.Extra = origExtra[:m]
@@ -297,9 +301,9 @@ func (r *Request) Scrub(reply *dns.Msg) (*dns.Msg, Result) {
return reply, ScrubExtra
}
- origAnswer := reply.Answer
ra := len(reply.Answer)
l, m = 0, 0
+ origAnswer := reply.Answer
for l < ra {
m = (l + ra) / 2
reply.Answer = origAnswer[:m]
@@ -324,14 +328,12 @@ func (r *Request) Scrub(reply *dns.Msg) (*dns.Msg, Result) {
// this extra m-1 step does make it fit in the client's buffer however.
}
- // It now fits, but Truncated. We can't call sizeAndDo() because that adds a new record (OPT)
- // in the additional section.
+ r.SizeAndDo(reply)
reply.Truncated = true
return reply, ScrubAnswer
}
-// Type returns the type of the question as a string. If the request is malformed
-// the empty string is returned.
+// Type returns the type of the question as a string. If the request is malformed the empty string is returned.
func (r *Request) Type() string {
if r.Req == nil {
return ""
diff --git a/request/request_test.go b/request/request_test.go
index c58612605..cad2dce0d 100644
--- a/request/request_test.go
+++ b/request/request_test.go
@@ -138,6 +138,39 @@ func TestRequestScrubExtraEdns0(t *testing.T) {
}
}
+func TestRequestScrubExtraRegression(t *testing.T) {
+ m := new(dns.Msg)
+ m.SetQuestion("large.example.com.", dns.TypeSRV)
+ m.SetEdns0(2048, true)
+ req := Request{W: &test.ResponseWriter{}, Req: m}
+
+ reply := new(dns.Msg)
+ reply.SetReply(m)
+ for i := 1; i < 33; i++ {
+ reply.Answer = append(reply.Answer, test.SRV(
+ fmt.Sprintf("large.example.com. 10 IN SRV 0 0 80 10-0-0-%d.default.pod.k8s.example.com.", i)))
+ }
+ for i := 1; i < 33; i++ {
+ reply.Extra = append(reply.Extra, test.A(
+ fmt.Sprintf("10-0-0-%d.default.pod.k8s.example.com. 10 IN A 10.0.0.%d", i, i)))
+ }
+
+ _, got := req.Scrub(reply)
+ if want := ScrubExtra; want != got {
+ t.Errorf("Want scrub result %d, got %d", want, got)
+ }
+ if want, got := req.Size(), reply.Len(); want < got {
+ t.Errorf("Want scrub to reduce message length below %d bytes, got %d bytes", want, got)
+ }
+ if reply.Truncated {
+ t.Errorf("Want scrub to not set truncated bit")
+ }
+ opt := reply.Extra[len(reply.Extra)-1]
+ if opt.Header().Rrtype != dns.TypeOPT {
+ t.Errorf("Last RR must be OPT record")
+ }
+}
+
func TestRequestScrubAnswerExact(t *testing.T) {
m := new(dns.Msg)
m.SetQuestion("large.example.com.", dns.TypeSRV)
@@ -196,10 +229,30 @@ func BenchmarkRequestSize(b *testing.B) {
}
}
+func BenchmarkRequestScrub(b *testing.B) {
+ st := testRequest()
+
+ reply := new(dns.Msg)
+ reply.SetReply(st.Req)
+ for i := 1; i < 33; i++ {
+ reply.Answer = append(reply.Answer, test.SRV(
+ fmt.Sprintf("large.example.com. 10 IN SRV 0 0 80 10-0-0-%d.default.pod.k8s.example.com.", i)))
+ }
+ for i := 1; i < 33; i++ {
+ reply.Extra = append(reply.Extra, test.A(
+ fmt.Sprintf("10-0-0-%d.default.pod.k8s.example.com. 10 IN A 10.0.0.%d", i, i)))
+ }
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ st.Scrub(reply.Copy())
+ }
+}
+
func testRequest() Request {
m := new(dns.Msg)
m.SetQuestion("example.com.", dns.TypeA)
- m.SetEdns0(4097, true)
+ m.SetEdns0(4096, true)
return Request{W: &test.ResponseWriter{}, Req: m}
}