diff options
author | Martin Kraft <martinkraft@gmail.com> | 2018-05-22 12:54:00 -0400 |
---|---|---|
committer | Martin Kraft <martinkraft@gmail.com> | 2018-05-22 12:54:00 -0400 |
commit | 4c683aff7627040ff811f065848a820b2cb19d59 (patch) | |
tree | 668061e8acfd8827fd02bab18a998b7986944296 /vendor/github.com/miekg/dns/msg.go | |
parent | eb78d273f39202046fa71555a5a19b0ec8a95cb3 (diff) | |
parent | 1af1bce6199597bb2d41ddcdc00ef0f28a73c83e (diff) | |
download | chat-4c683aff7627040ff811f065848a820b2cb19d59.tar.gz chat-4c683aff7627040ff811f065848a820b2cb19d59.tar.bz2 chat-4c683aff7627040ff811f065848a820b2cb19d59.zip |
Merge remote-tracking branch 'origin/master' into advanced-permissions-phase-2
Diffstat (limited to 'vendor/github.com/miekg/dns/msg.go')
-rw-r--r-- | vendor/github.com/miekg/dns/msg.go | 127 |
1 files changed, 78 insertions, 49 deletions
diff --git a/vendor/github.com/miekg/dns/msg.go b/vendor/github.com/miekg/dns/msg.go index 276e6b027..dcd3b6a5e 100644 --- a/vendor/github.com/miekg/dns/msg.go +++ b/vendor/github.com/miekg/dns/msg.go @@ -691,18 +691,20 @@ func (dns *Msg) Pack() (msg []byte, err error) { return dns.PackBuffer(nil) } -// PackBuffer packs a Msg, using the given buffer buf. If buf is too small -// a new buffer is allocated. +// PackBuffer packs a Msg, using the given buffer buf. If buf is too small a new buffer is allocated. func (dns *Msg) PackBuffer(buf []byte) (msg []byte, err error) { - // We use a similar function in tsig.go's stripTsig. - var ( - dh Header - compression map[string]int - ) - + var compression map[string]int if dns.Compress { - compression = make(map[string]int) // Compression pointer mappings + compression = make(map[string]int) // Compression pointer mappings. } + return dns.packBufferWithCompressionMap(buf, compression) +} + +// packBufferWithCompressionMap packs a Msg, using the given buffer buf. +func (dns *Msg) packBufferWithCompressionMap(buf []byte, compression map[string]int) (msg []byte, err error) { + // We use a similar function in tsig.go's stripTsig. + + var dh Header if dns.Rcode < 0 || dns.Rcode > 0xFFF { return nil, ErrRcode @@ -714,12 +716,11 @@ func (dns *Msg) PackBuffer(buf []byte) (msg []byte, err error) { return nil, ErrExtendedRcode } opt.SetExtendedRcode(uint8(dns.Rcode >> 4)) - dns.Rcode &= 0xF } // Convert convenient Msg into wire-like Header. dh.Id = dns.Id - dh.Bits = uint16(dns.Opcode)<<11 | uint16(dns.Rcode) + dh.Bits = uint16(dns.Opcode)<<11 | uint16(dns.Rcode&0xF) if dns.Response { dh.Bits |= _QR } @@ -922,23 +923,27 @@ func (dns *Msg) String() string { // than packing it, measuring the size and discarding the buffer. func (dns *Msg) Len() int { return compressedLen(dns, dns.Compress) } +func compressedLenWithCompressionMap(dns *Msg, compression map[string]int) int { + l := 12 // Message header is always 12 bytes + for _, r := range dns.Question { + compressionLenHelper(compression, r.Name, l) + l += r.len() + } + l += compressionLenSlice(l, compression, dns.Answer) + l += compressionLenSlice(l, compression, dns.Ns) + l += compressionLenSlice(l, compression, dns.Extra) + return l +} + // compressedLen returns the message length when in compressed wire format // when compress is true, otherwise the uncompressed length is returned. func compressedLen(dns *Msg, compress bool) int { // We always return one more than needed. - l := 12 // Message header is always 12 bytes if compress { compression := map[string]int{} - for _, r := range dns.Question { - l += r.len() - compressionLenHelper(compression, r.Name) - } - l += compressionLenSlice(l, compression, dns.Answer) - l += compressionLenSlice(l, compression, dns.Ns) - l += compressionLenSlice(l, compression, dns.Extra) - - return l + return compressedLenWithCompressionMap(dns, compression) } + l := 12 // Message header is always 12 bytes for _, r := range dns.Question { l += r.len() @@ -962,70 +967,94 @@ func compressedLen(dns *Msg, compress bool) int { return l } -func compressionLenSlice(len int, c map[string]int, rs []RR) int { - var l int +func compressionLenSlice(lenp int, c map[string]int, rs []RR) int { + initLen := lenp for _, r := range rs { if r == nil { continue } - // track this length, and the global length in len, while taking compression into account for both. - x := r.len() - l += x - len += x + // TmpLen is to track len of record at 14bits boudaries + tmpLen := lenp - k, ok := compressionLenSearch(c, r.Header().Name) + x := r.len() + // track this length, and the global length in len, while taking compression into account for both. + k, ok, _ := compressionLenSearch(c, r.Header().Name) if ok { - l += 1 - k - len += 1 - k - } - - if len < maxCompressionOffset { - compressionLenHelper(c, r.Header().Name) + // Size of x is reduced by k, but we add 1 since k includes the '.' and label descriptor take 2 bytes + // so, basically x:= x - k - 1 + 2 + x += 1 - k } - k, ok = compressionLenSearchType(c, r) + tmpLen += compressionLenHelper(c, r.Header().Name, tmpLen) + k, ok, _ = compressionLenSearchType(c, r) if ok { - l += 1 - k - len += 1 - k + x += 1 - k } + lenp += x + tmpLen = lenp + tmpLen += compressionLenHelperType(c, r, tmpLen) - if len < maxCompressionOffset { - compressionLenHelperType(c, r) - } } - return l + return lenp - initLen } -// Put the parts of the name in the compression map. -func compressionLenHelper(c map[string]int, s string) { +// Put the parts of the name in the compression map, return the size in bytes added in payload +func compressionLenHelper(c map[string]int, s string, currentLen int) int { + if currentLen > maxCompressionOffset { + // We won't be able to add any label that could be re-used later anyway + return 0 + } + if _, ok := c[s]; ok { + return 0 + } + initLen := currentLen pref := "" + prev := s lbs := Split(s) - for j := len(lbs) - 1; j >= 0; j-- { + for j := 0; j < len(lbs); j++ { pref = s[lbs[j]:] + currentLen += len(prev) - len(pref) + prev = pref if _, ok := c[pref]; !ok { - c[pref] = len(pref) + // If first byte label is within the first 14bits, it might be re-used later + if currentLen < maxCompressionOffset { + c[pref] = currentLen + } + } else { + added := currentLen - initLen + if j > 0 { + // We added a new PTR + added += 2 + } + return added } } + return currentLen - initLen } // Look for each part in the compression map and returns its length, // keep on searching so we get the longest match. -func compressionLenSearch(c map[string]int, s string) (int, bool) { +// Will return the size of compression found, whether a match has been +// found and the size of record if added in payload +func compressionLenSearch(c map[string]int, s string) (int, bool, int) { off := 0 end := false if s == "" { // don't bork on bogus data - return 0, false + return 0, false, 0 } + fullSize := 0 for { if _, ok := c[s[off:]]; ok { - return len(s[off:]), true + return len(s[off:]), true, fullSize + off } if end { break } + // Each label descriptor takes 2 bytes, add it + fullSize += 2 off, end = NextLabel(s, off) } - return 0, false + return 0, false, fullSize + len(s) } // Copy returns a new RR which is a deep-copy of r. |