forked from IBM/netaddr
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ipset.go
149 lines (131 loc) · 3.42 KB
/
ipset.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
package netaddr
import (
"net"
)
// IPSet is a set of IP addresses
type IPSet struct {
tree *ipTree
}
// InsertNet ensures this IPSet has the entire given IP network
func (s *IPSet) InsertNet(net *net.IPNet) {
if net == nil {
return
}
newNet := net
for {
newNode := &ipTree{net: newNet}
s.tree = s.tree.insert(newNode)
if s.tree != newNode && newNode.up == nil {
break
}
// The new node was inserted. See if it can be combined with the previous and/or next ones
prev := newNode.prev()
if prev != nil {
if ok, n := canCombineNets(prev.net, newNet); ok {
newNet = n
}
}
next := newNode.next()
if next != nil {
if ok, n := canCombineNets(newNet, next.net); ok {
newNet = n
}
}
if newNet == newNode.net {
break
}
}
}
// RemoveNet ensures that all of the IPs in the given network are removed from
// the set if present.
func (s *IPSet) RemoveNet(net *net.IPNet) {
if net == nil {
return
}
s.tree = s.tree.removeNet(net)
}
// ContainsNet returns true iff this IPSet contains all IPs in the given network
func (s *IPSet) ContainsNet(net *net.IPNet) bool {
if s == nil || net == nil {
return false
}
return s.tree.contains(&ipTree{net: net})
}
// Insert ensures this IPSet has the given IP
func (s *IPSet) Insert(ip net.IP) {
s.InsertNet(ipToNet(ip))
}
// Remove ensures this IPSet does not contain the given IP
func (s *IPSet) Remove(ip net.IP) {
s.RemoveNet(ipToNet(ip))
}
// Contains returns true iff this IPSet contains the the given IP address
func (s *IPSet) Contains(ip net.IP) bool {
return s.ContainsNet(ipToNet(ip))
}
// Union computes the union of this IPSet and another set. It returns the
// result as a new set.
func (s *IPSet) Union(other *IPSet) (newSet *IPSet) {
newSet = &IPSet{}
s.tree.walk(func(node *ipTree) {
newSet.InsertNet(node.net)
})
other.tree.walk(func(node *ipTree) {
newSet.InsertNet(node.net)
})
return
}
// Difference computes the set difference between this IPSet and another one
// It returns the result as a new set.
func (s *IPSet) Difference(other *IPSet) (newSet *IPSet) {
newSet = &IPSet{}
s.tree.walk(func(node *ipTree) {
newSet.InsertNet(node.net)
})
other.tree.walk(func(node *ipTree) {
newSet.RemoveNet(node.net)
})
return
}
// GetIPs retrieves a slice of the first IPs in the set ordered by address up
// to the given limit.
func (s *IPSet) GetIPs(limit int) (ips []net.IP) {
if limit == 0 {
limit = int(^uint(0) >> 1) // MaxInt
}
for node := s.tree.first(); node != nil; node = node.next() {
ips = append(ips, expandNet(node.net, limit-len(ips))...)
}
return
}
// GetNetworks retrieves a list of all networks included in the ipTree
func (s *IPSet) GetNetworks() []*net.IPNet {
networks := []*net.IPNet{}
s.tree.walk(func(node *ipTree) {
networks = append(networks, node.net)
})
return networks
}
// Intersection computes the set intersect between this IPSet and another one
// It returns a new set which is the intersection.
func (s *IPSet) Intersection(set1 *IPSet) (interSect *IPSet) {
interSect = &IPSet{}
s.tree.walk(func(node *ipTree) {
if set1.ContainsNet(node.net) {
interSect.InsertNet(node.net)
}
})
set1.tree.walk(func(node *ipTree) {
if s.ContainsNet(node.net) {
interSect.InsertNet(node.net)
}
})
return
}
// String returns a list of IP Networks
func (s *IPSet) String() (str []string) {
for node := s.tree.first(); node != nil; node = node.next() {
str = append(str, node.net.String())
}
return
}