1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
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]
}
|