diff options
author | Pablo Mazzini <pmazzini@gmail.com> | 2018-08-01 19:12:37 +0200 |
---|---|---|
committer | Pablo Mazzini <pmazzini@gmail.com> | 2018-08-01 19:12:37 +0200 |
commit | a606ffc4c7a61ae981450b9dcc5605f78bba7e07 (patch) | |
tree | f273798ada3b32da3f1e26887d8c3f3a3b141a7e /rfc1035label | |
parent | 833497ba74dfdd0188176ae38a19de7a03a7858a (diff) |
rename dnscompress to rfc1035label
Diffstat (limited to 'rfc1035label')
-rw-r--r-- | rfc1035label/label.go | 60 | ||||
-rw-r--r-- | rfc1035label/label_test.go | 66 |
2 files changed, 126 insertions, 0 deletions
diff --git a/rfc1035label/label.go b/rfc1035label/label.go new file mode 100644 index 0000000..c63b4af --- /dev/null +++ b/rfc1035label/label.go @@ -0,0 +1,60 @@ +package rfc1035label + +import ( + "fmt" + "strings" +) + +// This implements the compression from RFC 1035, section 4.1.4 +// https://tools.ietf.org/html/rfc1035 + +// 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 = "" + ) + for { + if pos >= len(buf) { + return domains, nil + } + length := int(buf[pos]) + pos++ + if length == 0 { + domains = append(domains, label) + label = "" + } + 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 + } +} + +// LabelToBytes encodes a label and returns a serialized stream of bytes +func LabelToBytes(label string) []byte { + var encodedLabel []byte + if len(label) == 0 { + return []byte{0} + } + for _, part := range strings.Split(label, ".") { + encodedLabel = append(encodedLabel, byte(len(part))) + encodedLabel = append(encodedLabel, []byte(part)...) + } + return append(encodedLabel, 0) +} + +// LabelsToBytes encodes a list of labels and returns a serialized stream of +// bytes +func LabelsToBytes(labels []string) []byte { + var encodedLabels []byte + for _, label := range labels { + encodedLabels = append(encodedLabels, LabelToBytes(label)...) + } + return encodedLabels +} diff --git a/rfc1035label/label_test.go b/rfc1035label/label_test.go new file mode 100644 index 0000000..f91110b --- /dev/null +++ b/rfc1035label/label_test.go @@ -0,0 +1,66 @@ +package rfc1035label + +import ( + "bytes" + "testing" +) + +func TestLabelsFromBytes(t *testing.T) { + labels, err := LabelsFromBytes([]byte{ + 0x9, 's', 'l', 'a', 'c', 'k', 'w', 'a', 'r', 'e', + 0x2, 'i', 't', + 0x0, + }) + if err != nil { + t.Fatal(err) + } + if len(labels) != 1 { + t.Fatalf("Invalid labels length. Expected: 1, got: %v", len(labels)) + } + if labels[0] != "slackware.it" { + t.Fatalf("Invalid label. Expected: %v, got: %v'", "slackware.it", labels[0]) + } +} + +func TestLabelsFromBytesZeroLength(t *testing.T) { + labels, err := LabelsFromBytes([]byte{}) + if err != nil { + t.Fatal(err) + } + if len(labels) != 0 { + t.Fatalf("Invalid labels length. Expected: 0, got: %v", len(labels)) + } +} + +func TestLabelsFromBytesInvalidLength(t *testing.T) { + labels, err := LabelsFromBytes([]byte{0x3, 0xaa, 0xbb}) // short length + if err == nil { + t.Fatal("Expected error, got nil") + } + if len(labels) != 0 { + t.Fatalf("Invalid labels length. Expected: 0, got: %v", len(labels)) + } + if labels != nil { + t.Fatalf("Invalid label. Expected nil, got %v", labels) + } +} + +func TestLabelToBytes(t *testing.T) { + encodedLabel := LabelToBytes("slackware.it") + expected := []byte{ + 0x9, 's', 'l', 'a', 'c', 'k', 'w', 'a', 'r', 'e', + 0x2, 'i', 't', + 0x0, + } + if !bytes.Equal(encodedLabel, expected) { + t.Fatalf("Invalid label. Expected: %v, got: %v", expected, encodedLabel) + } +} + +func TestLabelToBytesZeroLength(t *testing.T) { + encodedLabel := LabelToBytes("") + expected := []byte{0} + if !bytes.Equal(encodedLabel, expected) { + t.Fatalf("Invalid label. Expected: %v, got: %v", expected, encodedLabel) + } +} |