mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-25 11:05:45 +00:00
util/dnsname: make ToFQDN take exactly 0 or 1 allocs for everything.
name old time/op new time/op delta ToFQDN/www.tailscale.com.-32 9.55ns ± 2% 12.13ns ± 3% +27.03% (p=0.000 n=10+10) ToFQDN/www.tailscale.com-32 86.3ns ± 1% 40.7ns ± 1% -52.86% (p=0.000 n=10+9) ToFQDN/.www.tailscale.com-32 86.5ns ± 1% 40.4ns ± 1% -53.29% (p=0.000 n=10+9) ToFQDN/_ssh._tcp.www.tailscale.com.-32 12.8ns ± 2% 14.7ns ± 2% +14.24% (p=0.000 n=9+10) ToFQDN/_ssh._tcp.www.tailscale.com-32 104ns ± 1% 45ns ± 0% -57.16% (p=0.000 n=10+9) name old alloc/op new alloc/op delta ToFQDN/www.tailscale.com.-32 0.00B 0.00B ~ (all equal) ToFQDN/www.tailscale.com-32 72.0B ± 0% 24.0B ± 0% -66.67% (p=0.000 n=10+10) ToFQDN/.www.tailscale.com-32 72.0B ± 0% 24.0B ± 0% -66.67% (p=0.000 n=10+10) ToFQDN/_ssh._tcp.www.tailscale.com.-32 0.00B 0.00B ~ (all equal) ToFQDN/_ssh._tcp.www.tailscale.com-32 112B ± 0% 32B ± 0% -71.43% (p=0.000 n=10+10) name old allocs/op new allocs/op delta ToFQDN/www.tailscale.com.-32 0.00 0.00 ~ (all equal) ToFQDN/www.tailscale.com-32 2.00 ± 0% 1.00 ± 0% -50.00% (p=0.000 n=10+10) ToFQDN/.www.tailscale.com-32 2.00 ± 0% 1.00 ± 0% -50.00% (p=0.000 n=10+10) ToFQDN/_ssh._tcp.www.tailscale.com.-32 0.00 0.00 ~ (all equal) ToFQDN/_ssh._tcp.www.tailscale.com-32 2.00 ± 0% 1.00 ± 0% -50.00% (p=0.000 n=10+10) Signed-off-by: David Anderson <danderson@tailscale.com>
This commit is contained in:
parent
d7f6ef3a79
commit
c54cc24e87
@ -21,31 +21,48 @@
|
||||
type FQDN string
|
||||
|
||||
func ToFQDN(s string) (FQDN, error) {
|
||||
if isValidFQDN(s) {
|
||||
return FQDN(s), nil
|
||||
}
|
||||
if len(s) == 0 || s == "." {
|
||||
return FQDN("."), nil
|
||||
}
|
||||
|
||||
if s[len(s)-1] == '.' {
|
||||
s = s[:len(s)-1]
|
||||
}
|
||||
if s[0] == '.' {
|
||||
s = s[1:]
|
||||
}
|
||||
if len(s) > maxNameLength {
|
||||
raw := s
|
||||
totalLen := len(s)
|
||||
if s[len(s)-1] == '.' {
|
||||
s = s[:len(s)-1]
|
||||
} else {
|
||||
totalLen += 1 // account for missing dot
|
||||
}
|
||||
if totalLen > maxNameLength {
|
||||
return "", fmt.Errorf("%q is too long to be a DNS name", s)
|
||||
}
|
||||
|
||||
fs := strings.Split(s, ".")
|
||||
for _, f := range fs {
|
||||
if !validLabel(f) {
|
||||
return "", fmt.Errorf("%q is not a valid DNS label", f)
|
||||
st := 0
|
||||
for i := 0; i < len(s); i++ {
|
||||
if s[i] != '.' {
|
||||
continue
|
||||
}
|
||||
label := s[st:i]
|
||||
// You might be tempted to do further validation of the
|
||||
// contents of labels here, based on the hostname rules in RFC
|
||||
// 1123. However, DNS labels are not always subject to
|
||||
// hostname rules. In general, they can contain any non-zero
|
||||
// byte sequence, even though in practice a more restricted
|
||||
// set is used.
|
||||
//
|
||||
// See https://github.com/tailscale/tailscale/issues/2024 for more.
|
||||
if len(label) == 0 || len(label) > maxLabelLength {
|
||||
return "", fmt.Errorf("%q is not a valid DNS label", label)
|
||||
}
|
||||
st = i + 1
|
||||
}
|
||||
|
||||
return FQDN(s + "."), nil
|
||||
if raw[len(raw)-1] != '.' {
|
||||
raw = raw + "."
|
||||
}
|
||||
return FQDN(raw), nil
|
||||
}
|
||||
|
||||
// WithTrailingDot returns f as a string, with a trailing dot.
|
||||
@ -77,58 +94,6 @@ func (f FQDN) Contains(other FQDN) bool {
|
||||
return strings.HasSuffix(other.WithTrailingDot(), cmp)
|
||||
}
|
||||
|
||||
// isValidFQDN reports whether s is already a valid FQDN, without
|
||||
// allocating.
|
||||
func isValidFQDN(s string) bool {
|
||||
if len(s) == 0 {
|
||||
return false
|
||||
}
|
||||
if len(s) > maxNameLength {
|
||||
return false
|
||||
}
|
||||
// DNS root name.
|
||||
if s == "." {
|
||||
return true
|
||||
}
|
||||
// Missing trailing dot.
|
||||
if s[len(s)-1] != '.' {
|
||||
return false
|
||||
}
|
||||
// Leading dots not allowed.
|
||||
if s[0] == '.' {
|
||||
return false
|
||||
}
|
||||
|
||||
st := 0
|
||||
for i := 0; i < len(s); i++ {
|
||||
if s[i] != '.' {
|
||||
continue
|
||||
}
|
||||
label := s[st:i]
|
||||
if !validLabel(label) {
|
||||
return false
|
||||
}
|
||||
st = i + 1
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func validLabel(s string) bool {
|
||||
// You might be tempted to do further validation of the
|
||||
// contents of labels here, based on the hostname rules in RFC
|
||||
// 1123. However, DNS labels are not always subject to
|
||||
// hostname rules. In general, they can contain any non-zero
|
||||
// byte sequence, even though in practice a more restricted
|
||||
// set is used.
|
||||
//
|
||||
// See https://github.com/tailscale/tailscale/issues/2024 for more.
|
||||
if len(s) == 0 || len(s) > maxLabelLength {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// SanitizeLabel takes a string intended to be a DNS name label
|
||||
// and turns it into a valid name label according to RFC 1035.
|
||||
func SanitizeLabel(label string) string {
|
||||
|
Loading…
Reference in New Issue
Block a user