-
Notifications
You must be signed in to change notification settings - Fork 0
/
host.go
102 lines (90 loc) · 2.32 KB
/
host.go
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// Copyright 2016 Giulio Iotti. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package kuradns
import (
"strings"
"github.com/miekg/dns"
)
// A host is a FQDN or common representation of a DNS address.
type host string
// browser returns the FQDN without the trailing dot.
func (h host) browser() string {
return strings.TrimSuffix(string(h), ".")
}
// dns returns the FQDN.
func (h host) dns() string {
return dns.Fqdn(string(h))
}
// hasSuffix returns true if h has suffix h2.
func (h host) hasSuffix(h2 host) bool {
return strings.HasSuffix(h.browser(), h2.browser())
}
// hasWildcard returns true if h is a wildcard host.
func (h host) hasWildcard() bool {
return countByte(string(h), '*') > 0
}
// matchWildcard matches a wildcard host h with non-wildcard host h2.
func (h host) matchWildcard(h2 host) bool {
// TODO: Rewrite this without using splitting to save on allocations.
hs := strings.Split(h.browser(), ".")
h2s := strings.Split(h2.browser(), ".")
if len(hs) != len(h2s) {
return false
}
for i := 0; i < len(hs); i++ {
if !matchWildcard(hs[i], h2s[i]) {
return false
}
}
return true
}
// match matches host h with host h2. Either can be a wildcard host.
// If both hosts are wildcard, match will return true if they are the
// exact same string.
func (h host) match(h2 host) bool {
if h.hasWildcard() {
if h2.hasWildcard() {
return h == h2
}
return h.matchWildcard(h2)
}
if h2.hasWildcard() {
return h2.matchWildcard(h)
}
return h == h2
}
// countByte returns the number of occurrences of b in s.
func countByte(s string, b byte) int {
n := 0
for i := 0; i < len(s); i++ {
if s[i] == b {
n++
}
}
return n
}
// matchWildcard matches wildcard string w against normal string s.
// Wilcard string w can only contain one star but can contain suffix
// or prefix.
func matchWildcard(w, s string) bool {
hasWildcard := countByte(w, '*')
if hasWildcard == 0 {
return w == s
}
// XXX: We do not support matching against multiple wildcards.
if hasWildcard > 1 {
return false
}
if w == "*" {
return true
}
ws := strings.Split(w, "*")
if ws[0] == "" {
return strings.HasSuffix(s, ws[1])
}
if ws[1] == "" {
return strings.HasPrefix(s, ws[0])
}
return strings.HasPrefix(s, ws[0]) && strings.HasSuffix(s, ws[1])
}