-
Notifications
You must be signed in to change notification settings - Fork 4
/
exclude.go
57 lines (51 loc) · 1.18 KB
/
exclude.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
package ipx
import "net"
// Exclude returns a list of networks representing the address block when `b` is removed from `a`.
func Exclude(a, b *net.IPNet) []*net.IPNet {
four := a.IP.To4() != nil
if four != (b.IP.To4() != nil) || !IsSubnet(a, b) {
return []*net.IPNet{a}
}
if four {
return exclude4(newIP4Net(a), newIP4Net(b))
}
return exclude6(newIP6Net(a), newIP6Net(b))
}
func exclude4(a, b ip4Net) []*net.IPNet {
subs := make([]*net.IPNet, 0, a.prefix-b.prefix)
s1, s2 := a.subnets()
for s1 != b && s2 != b {
if b.subnetOf(s1) {
subs = append(subs, s2.asNet())
s1, s2 = s1.subnets()
continue
}
subs = append(subs, s1.asNet())
s1, s2 = s2.subnets()
}
if s1 == b {
subs = append(subs, s2.asNet())
} else {
subs = append(subs, s1.asNet())
}
return subs
}
func exclude6(a, b ip6Net) []*net.IPNet {
subs := make([]*net.IPNet, 0, a.prefix-b.prefix)
s1, s2 := a.subnets()
for s1 != b && s2 != b {
if b.subnetOf(s1) {
subs = append(subs, s2.asNet())
s1, s2 = s1.subnets()
continue
}
subs = append(subs, s1.asNet())
s1, s2 = s2.subnets()
}
if s1 == b {
subs = append(subs, s2.asNet())
} else {
subs = append(subs, s1.asNet())
}
return subs
}