-
Notifications
You must be signed in to change notification settings - Fork 2.7k
/
cidr.go
152 lines (133 loc) · 4.89 KB
/
cidr.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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
// Copyright 2016-2018 Authors of Cilium
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package api
import (
"net"
"github.com/cilium/cilium/pkg/ip"
"github.com/cilium/cilium/pkg/labels"
cidrpkg "github.com/cilium/cilium/pkg/labels/cidr"
)
// CIDR specifies a block of IP addresses.
// Example: 192.0.2.1/32
type CIDR string
// CIDRMatchAll is a []CIDR that matches everything
var CIDRMatchAll = []CIDR{CIDR("0.0.0.0/0"), CIDR("::/0")}
// MatchesAll determines whether the CIDR matches all traffic.
func (c *CIDR) MatchesAll() bool {
for _, wildcard := range CIDRMatchAll {
if *c == wildcard {
return true
}
}
return false
}
// CIDRRule is a rule that specifies a CIDR prefix to/from which outside
// communication is allowed, along with an optional list of subnets within that
// CIDR prefix to/from which outside communication is not allowed.
type CIDRRule struct {
// CIDR is a CIDR prefix / IP Block.
//
Cidr CIDR `json:"cidr"`
// ExceptCIDRs is a list of IP blocks which the endpoint subject to the rule
// is not allowed to initiate connections to. These CIDR prefixes should be
// contained within Cidr. These exceptions are only applied to the Cidr in
// this CIDRRule, and do not apply to any other CIDR prefixes in any other
// CIDRRules.
//
// +optional
ExceptCIDRs []CIDR `json:"except,omitempty"`
// Generated indicates whether the rule was generated based on other rules
// or provided by user
Generated bool `json:"-"`
}
// CIDRSlice is a slice of CIDRs. It allows receiver methods to be defined for
// transforming the slice into other convenient forms such as
// EndpointSelectorSlice.
type CIDRSlice []CIDR
// GetAsEndpointSelectors returns the provided CIDR slice as a slice of
// endpoint selectors
func (s CIDRSlice) GetAsEndpointSelectors() EndpointSelectorSlice {
// If multiple CIDRs representing reserved:world are in this CIDRSlice,
// we only have to add the EndpointSelector representing reserved:world
// once.
var hasWorldBeenAdded bool
slice := EndpointSelectorSlice{}
for _, cidr := range s {
if cidr.MatchesAll() && !hasWorldBeenAdded {
hasWorldBeenAdded = true
slice = append(slice, ReservedEndpointSelectors[labels.IDNameWorld])
}
lbl, err := cidrpkg.IPStringToLabel(string(cidr))
if err == nil {
slice = append(slice, NewESFromLabels(lbl))
}
// TODO: Log the error?
}
return slice
}
// StringSlice returns the CIDR slice as a slice of strings.
func (s CIDRSlice) StringSlice() []string {
result := make([]string, 0, len(s))
for _, c := range s {
result = append(result, string(c))
}
return result
}
// CIDRRuleSlice is a slice of CIDRRules. It allows receiver methods to be
// defined for transforming the slice into other convenient forms such as
// EndpointSelectorSlice.
type CIDRRuleSlice []CIDRRule
// GetAsEndpointSelectors returns the provided CIDRRule slice as a slice of
// endpoint selectors
func (s CIDRRuleSlice) GetAsEndpointSelectors() EndpointSelectorSlice {
cidrs := ComputeResultantCIDRSet(s)
return cidrs.GetAsEndpointSelectors()
}
// ComputeResultantCIDRSet converts a slice of CIDRRules into a slice of
// individual CIDRs. This expands the cidr defined by each CIDRRule, applies
// the CIDR exceptions defined in "ExceptCIDRs", and forms a minimal set of
// CIDRs that cover all of the CIDRRules.
//
// Assumes no error checking is necessary as CIDRRule.Sanitize already does this.
func ComputeResultantCIDRSet(cidrs CIDRRuleSlice) CIDRSlice {
var allResultantAllowedCIDRs CIDRSlice
for _, s := range cidrs {
_, allowNet, _ := net.ParseCIDR(string(s.Cidr))
var removeSubnets []*net.IPNet
for _, t := range s.ExceptCIDRs {
_, removeSubnet, _ := net.ParseCIDR(string(t))
removeSubnets = append(removeSubnets, removeSubnet)
}
resultantAllowedCIDRs, _ := ip.RemoveCIDRs([]*net.IPNet{allowNet}, removeSubnets)
for _, u := range resultantAllowedCIDRs {
allResultantAllowedCIDRs = append(allResultantAllowedCIDRs, CIDR(u.String()))
}
}
return allResultantAllowedCIDRs
}
// IPsToCIDRRules generates CIDRRules for the IPs passed in./
// This function will mark the rule to Generated true by default.
func IPsToCIDRRules(ips []net.IP) (cidrRules []CIDRRule) {
for _, ip := range ips {
rule := CIDRRule{ExceptCIDRs: make([]CIDR, 0)}
rule.Generated = true
if ip.To4() != nil {
rule.Cidr = CIDR(ip.String() + "/32")
} else {
rule.Cidr = CIDR(ip.String() + "/128")
}
cidrRules = append(cidrRules, rule)
}
return cidrRules
}