/
type_ip_address.go
137 lines (110 loc) · 2.88 KB
/
type_ip_address.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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package strategies
import (
"fmt"
"net"
"strings"
)
// TypeIPAddress is for ip-address values (eg "1.2.3.4" or "10.0.0.0/16"):
const TypeIPAddress = "IP_ADDRESS"
// parseIP get ip address from CIDR or simple ip (eg "1.2.3.4" or "10.0.0.0/16"):
func parseIP(value string) (net.IP, error) {
// Check for ip contain CIDR
isCIDR := strings.Contains(value, "/")
if isCIDR {
ip, _, err := net.ParseCIDR(value)
return ip, err
}
// Try to parse simple ip address
ip := net.ParseIP(value)
if len(ip) == 0 {
return net.IP{}, fmt.Errorf("unknown ip: %s", value)
}
return ip, nil
}
// IPAddress asserts the given parameters then passes on for evaluation:
func IPAddress(conditional string, options []interface{}, value interface{}) (bool, error) {
// Type assert the value:
assertedValue, ok := value.(string)
if !ok {
return false, fmt.Errorf("Unable to assert value (%v) as string", value)
}
ip, err := parseIP(assertedValue)
if err != nil {
return false, err
}
assertedValue = ip.String()
// Type assert all of the options:
var assertedOptions []string
for _, option := range options {
assertedOption, ok := option.(string)
if !ok {
return false, fmt.Errorf("Unable to assert value (%v) as string", option)
}
assertedOptions = append(assertedOptions, assertedOption)
}
// The string evaluations are fine for TypeIPAddress:
return evaluateIPAddress(conditional, assertedOptions, assertedValue), nil
}
// evaluateIPAddress makes evaluations for TypeIPAddress values:
func evaluateIPAddress(conditional string, options []string, value string) bool {
// Make sure we have a value:
if len(value) == 0 {
return false
}
switch conditional {
case ConditionalEquals:
// Return true if the value is equal to any of the options:
for _, option := range options {
if value == option {
return true
}
}
return false
case ConditionalNotEquals:
// Return false if the value is equal to any of the options:
for _, option := range options {
if value == option {
return false
}
}
return true
case ConditionalExcludes:
// Parse the value IP:
valueIP, err := parseIP(value)
if err != nil {
return false
}
// Return false if the value is included by any of the options:
for _, option := range options {
// Parse each option address:
_, optionNet, err := net.ParseCIDR(option)
if err != nil {
return false
}
if optionNet.Contains(valueIP) {
return false
}
}
return true
case ConditionalIncludes:
// Parse the value IP:
valueIP, err := parseIP(value)
if err != nil {
return false
}
// Return true if the value is included by any of the options:
for _, option := range options {
// Parse each option address:
_, optionNet, err := net.ParseCIDR(option)
if err != nil {
return false
}
if optionNet.Contains(valueIP) {
return true
}
}
return false
default:
return false
}
}