request: re-adjust size for edns0 RR (#2007)

* Add regression test for broken DNS truncation

With the latest changes to the implementation, request.Scrub() returns
invalid response messages which are larger than the advertised buffer
size. This commit adds a failing test for that.

* Add benchmark for response truncation

* request: re-adjust size for edns0 RR

Cherry-picked the test and benchmark commits from #1962 and make the
failing test not fail, by adding minimal fix in request.go.

This makes size 12 bytes smaller if we need to add back the OPT RR in
the message.

Closes: #1962

Signed-off-by: Miek Gieben <miek@miek.nl>

* Scrub: correctly check for EDNS0, not only Do

Make Scrub check for EDNS0, not only if the Do bit is set.

Signed-off-by: Miek Gieben <miek@miek.nl>
This commit is contained in:
Miek Gieben
2018-07-28 10:27:38 +01:00
committed by GitHub
parent 395be9adfc
commit 62df253371
2 changed files with 63 additions and 8 deletions

View File

@@ -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 ""