summaryrefslogtreecommitdiffhomepage
path: root/rfc1035label/label.go
diff options
context:
space:
mode:
authorAndrea Barberio <insomniac@slackware.it>2018-11-19 20:52:08 +0000
committerinsomniac <insomniacslk@users.noreply.github.com>2018-11-20 14:03:33 +0000
commitdc5e468a3d26dafd71e6c16ee5a839a1da9a6afb (patch)
treec29c221a572ec6038befa89b9e085550dd597e83 /rfc1035label/label.go
parentea6c3e1bdb7e29e3c0653bfcb50f6ba88a822031 (diff)
rfc1035label: support compression pointers
Diffstat (limited to 'rfc1035label/label.go')
-rw-r--r--rfc1035label/label.go54
1 files changed, 38 insertions, 16 deletions
diff --git a/rfc1035label/label.go b/rfc1035label/label.go
index c63b4af..26d8a49 100644
--- a/rfc1035label/label.go
+++ b/rfc1035label/label.go
@@ -1,39 +1,61 @@
package rfc1035label
import (
- "fmt"
+ "errors"
"strings"
)
-// This implements the compression from RFC 1035, section 4.1.4
-// https://tools.ietf.org/html/rfc1035
+// This implements RFC 1035 labels, including compression.
+// https://tools.ietf.org/html/rfc1035#section-4.1.4
// LabelsFromBytes decodes a serialized stream and returns a list of labels
func LabelsFromBytes(buf []byte) ([]string, error) {
var (
- pos = 0
- domains = make([]string, 0)
- label = ""
+ pos, oldPos int
+ labels = make([]string, 0)
+ label string
+ handlingPointer bool
)
+
for {
if pos >= len(buf) {
- return domains, nil
+ break
}
length := int(buf[pos])
pos++
+ var chunk string
if length == 0 {
- domains = append(domains, label)
+ labels = append(labels, label)
label = ""
+ if handlingPointer {
+ pos = oldPos
+ handlingPointer = false
+ }
+ } else if length&0xc0 == 0xc0 {
+ // compression pointer
+ if handlingPointer {
+ return nil, errors.New("rfc1035label: cannot handle nested pointers")
+ }
+ handlingPointer = true
+ if pos+1 > len(buf) {
+ return nil, errors.New("rfc1035label: pointer buffer too short")
+ }
+ off := int(buf[pos-1]&^0xc0)<<8 + int(buf[pos])
+ oldPos = pos + 1
+ pos = off
+ } else {
+ if pos+length > len(buf) {
+ return nil, errors.New("rfc1035label: buffer too short")
+ }
+ chunk = string(buf[pos : pos+length])
+ if label != "" {
+ label += "."
+ }
+ label += chunk
+ pos += length
}
- if len(buf)-pos < length {
- return nil, fmt.Errorf("DomainNamesFromBytes: invalid short label length")
- }
- if label != "" {
- label += "."
- }
- label += string(buf[pos : pos+length])
- pos += length
}
+ return labels, nil
}
// LabelToBytes encodes a label and returns a serialized stream of bytes