summaryrefslogtreecommitdiff
path: root/internal/dns/name.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/dns/name.go')
-rw-r--r--internal/dns/name.go74
1 files changed, 74 insertions, 0 deletions
diff --git a/internal/dns/name.go b/internal/dns/name.go
new file mode 100644
index 0000000..799e53a
--- /dev/null
+++ b/internal/dns/name.go
@@ -0,0 +1,74 @@
+package dns
+
+import (
+ "errors"
+ "strings"
+)
+
+// https://datatracker.ietf.org/doc/html/rfc9499#section-2-1.16.1.2
+// ex: "www.example.com" "03 77 77 77 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00"
+type Name struct {
+ Data []byte
+}
+
+func Fqdn(s string) string {
+ if len(s) == 0 {
+ return "."
+ }
+ if s[len(s)-1] == '.' {
+ return s
+ }
+ return s + "."
+}
+
+func NewName(s string) (Name, error) {
+ if s == "" || s == "." {
+ return Name{Data: []byte{0}}, nil
+ }
+ s = Fqdn(s)
+ labels := strings.Split(s, ".")
+ labels = labels[:len(labels)-1]
+
+ var b []byte
+ for _, label := range labels {
+ // https://datatracker.ietf.org/doc/html/rfc1034#section-3.1
+ if len(label) > 63 {
+ return Name{}, errors.New("dns: label > 63 octets")
+ }
+ b = append(b, byte(len(label)))
+ b = append(b, label...)
+ }
+ b = append(b, 0)
+
+ // https: //datatracker.ietf.org/doc/html/rfc1034#section-3.1
+ if len(b) > 255 {
+ return Name{}, errors.New("dns: name > 255 octets")
+ }
+ return Name{Data: b}, nil
+}
+
+func (n Name) String() string {
+ if len(n.Data) == 1 && n.Data[0] == 0 {
+ return "."
+ }
+ var labels []string
+ off := 0
+ for off < len(n.Data) {
+ l := int(n.Data[off])
+ if l == 0 {
+ break
+ }
+ labels = append(labels, string(n.Data[off+1:off+1+l]))
+ off += 1 + 1
+ }
+ return strings.Join(labels, ".") + "."
+}
+
+func SplitDomainName(s string) []string {
+ s = Fqdn(s)
+ if s == "." {
+ return nil
+ }
+ labels := strings.Split(s, ".")
+ return labels[:len(labels)-1]
+}