Add Scrub function

This function will make the message fit for the client's buffer, or
set the TC bit.
This commit is contained in:
Miek Gieben 2016-03-26 09:26:54 +00:00
parent a832ab696a
commit 90f73c50cf
3 changed files with 40 additions and 5 deletions

View file

@ -72,7 +72,7 @@ func (e Etcd) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (i
}
m = dedup(m)
m, _ = state.Scrub(m)
state.W.WriteMsg(m)
return 0, nil
}

View file

@ -3,6 +3,7 @@ package proxy
import (
"github.com/miekg/coredns/middleware"
"github.com/miekg/dns"
)
@ -18,7 +19,7 @@ func (p ReverseProxy) ServeDNS(w dns.ResponseWriter, r *dns.Msg, extra []dns.RR)
)
state := middleware.State{W: w, Req: r}
// tls+tcp ?
// We forward the original request, no need to fiddle with EDNS0 opt sizes.
if state.Proto() == "tcp" {
reply, err = middleware.Exchange(p.Client.TCP, r, p.Host)
} else {

View file

@ -102,9 +102,9 @@ func (s State) Size() int {
return dns.MinMsgSize
}
// SizeAndDo returns a ready made OPT record that the reflects the intent
// from the state. This can be added to upstream requests that will then
// hopefully return a message that is understandable by the original client.
// SizeAndDo returns a ready made OPT record that the reflects the intent from
// state. This can be added to upstream requests that will then hopefully
// return a message that is fits the buffer in the client.
func (s State) SizeAndDo() *dns.OPT {
size := s.Size()
Do := s.Do()
@ -119,6 +119,40 @@ func (s State) SizeAndDo() *dns.OPT {
return o
}
// Result is the result of Fit.
type Result int
const (
// ScrubIgnored is returned when Scrub did nothing to the message.
ScrubIgnored Result = iota
// ScrubDone is returned when the reply has been scrubbed.
ScrubDone
)
// Scrub scrubs the reply message so that it will fit the client's buffer. If even after dropping
// the additional section, it still does not fit the TC bit will be set on the message. Note,
// the TC bit will be set regardless of protocol, even TCP message will get the bit, the client
// should then retry with pigeons.
// TODO(referral).
func (s State) Scrub(reply *dns.Msg) (*dns.Msg, Result) {
size := s.Size()
l := reply.Len()
if size >= l {
return reply, ScrubIgnored
}
// If not delegation, drop additional section.
// TODO(miek): check for delegation
reply.Extra = nil
l = reply.Len()
if size >= l {
return reply, ScrubDone
}
// Still?!! does not fit.
reply.Truncated = true
return reply, ScrubDone
}
// Type returns the type of the question as a string.
func (s State) Type() string { return dns.Type(s.Req.Question[0].Qtype).String() }