-
Notifications
You must be signed in to change notification settings - Fork 2.8k
/
cidr.go
160 lines (142 loc) · 3.5 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
153
154
155
156
157
158
159
160
// SPDX-License-Identifier: Apache-2.0
// Copyright Authors of Cilium
package cidr
import (
"bytes"
"fmt"
"net"
)
// NewCIDR returns a new CIDR using a net.IPNet
func NewCIDR(ipnet *net.IPNet) *CIDR {
if ipnet == nil {
return nil
}
return &CIDR{ipnet}
}
// CIDR is a network CIDR representation based on net.IPNet
type CIDR struct {
*net.IPNet
}
// DeepEqual is an deepequal function, deeply comparing the receiver with other.
// in must be non-nil.
func (in *CIDR) DeepEqual(other *CIDR) bool {
if other == nil {
return false
}
if (in.IPNet == nil) != (other.IPNet == nil) {
return false
} else if in.IPNet != nil {
if !in.IPNet.IP.Equal(other.IPNet.IP) {
return false
}
inOnes, inBits := in.IPNet.Mask.Size()
otherOnes, otherBits := other.IPNet.Mask.Size()
return inOnes == otherOnes && inBits == otherBits
}
return true
}
// DeepCopy creates a deep copy of a CIDR
func (n *CIDR) DeepCopy() *CIDR {
if n == nil {
return nil
}
out := new(CIDR)
n.DeepCopyInto(out)
return out
}
// DeepCopyInto is a deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CIDR) DeepCopyInto(out *CIDR) {
*out = *in
if in.IPNet == nil {
return
}
out.IPNet = new(net.IPNet)
*out.IPNet = *in.IPNet
if in.IPNet.IP != nil {
in, out := &in.IPNet.IP, &out.IPNet.IP
*out = make(net.IP, len(*in))
copy(*out, *in)
}
if in.IPNet.Mask != nil {
in, out := &in.IPNet.Mask, &out.IPNet.Mask
*out = make(net.IPMask, len(*in))
copy(*out, *in)
}
return
}
// AvailableIPs returns the number of IPs available in a CIDR
func (n *CIDR) AvailableIPs() int {
ones, bits := n.Mask.Size()
return 1 << (bits - ones)
}
// Equal returns true if the receiver's CIDR equals the other CIDR.
func (n *CIDR) Equal(o *CIDR) bool {
if n == nil || o == nil {
return n == o
}
return Equal(n.IPNet, o.IPNet)
}
// Equal returns true if the n and o net.IPNet CIDRs arr Equal.
func Equal(n, o *net.IPNet) bool {
if n == nil || o == nil {
return n == o
}
if n == o {
return true
}
return n.IP.Equal(o.IP) &&
bytes.Equal(n.Mask, o.Mask)
}
// ContainsAll returns true if 'ipNets1' contains all net.IPNet of 'ipNets2'
func ContainsAll(ipNets1, ipNets2 []*net.IPNet) bool {
for _, n := range ipNets2 {
if !Contains(ipNets1, n) {
return false
}
}
return true
}
// Contains returns true if 'ipNets' contains ipNet.
func Contains(ipNets []*net.IPNet, ipNet *net.IPNet) bool {
for _, n := range ipNets {
if Equal(n, ipNet) {
return true
}
}
return false
}
// RemoveAll removes all cidrs specified in 'toRemove' from 'ipNets'. ipNets
// is clobbered (to ensure removed CIDRs can be garbage collected) and
// must not be used after this function has been called.
// Example usage:
//
// cidrs = cidr.RemoveAll(cidrs, toRemove)
func RemoveAll(ipNets, toRemove []*net.IPNet) []*net.IPNet {
newIPNets := ipNets[:0]
for _, n := range ipNets {
if !Contains(toRemove, n) {
newIPNets = append(newIPNets, n)
}
}
for i := len(newIPNets); i < len(ipNets); i++ {
ipNets[i] = nil // or the zero value of T
}
return newIPNets
}
// ParseCIDR parses the CIDR string using net.ParseCIDR
func ParseCIDR(str string) (*CIDR, error) {
_, ipnet, err := net.ParseCIDR(str)
if err != nil {
return nil, err
}
return NewCIDR(ipnet), nil
}
// MustParseCIDR parses the CIDR string using net.ParseCIDR and panics if the
// CIDR cannot be parsed
func MustParseCIDR(str string) *CIDR {
c, err := ParseCIDR(str)
if err != nil {
panic(fmt.Sprintf("Unable to parse CIDR '%s': %s", str, err))
}
return c
}