-
Notifications
You must be signed in to change notification settings - Fork 2
/
route.go
105 lines (90 loc) · 1.89 KB
/
route.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
package nkngomobile
import (
"errors"
"fmt"
"log"
"net"
"sort"
)
var ErrInvalidIP = errors.New("invalid IP address")
func IpToUint32(s string) (uint32, error) {
ip := net.ParseIP(s)
if ip == nil {
return 0, ErrInvalidIP
}
ip = ip.To4()
if ip == nil {
return 0, ErrInvalidIP
}
return uint32(ip[3]) | uint32(ip[2])<<8 | uint32(ip[1])<<16 | uint32(ip[0])<<24, nil
}
func Uint32ToIP(n uint32) net.IP {
return net.IPv4(byte(n>>24), byte(n>>16&0xFF), byte(n>>8)&0xFF, byte(n&0xFF))
}
// IpRangeToCIDR both side inclusive
func IpRangeToCIDR(start, end uint32) []string {
if start > end {
return nil
}
// use uint64 to prevent overflow
ip := int64(start)
tail := int64(0)
cidr := make([]string, 0)
// decrease mask bit
for {
// count number of tailing zero bits
for ; tail < 32; tail++ {
if (ip>>(tail+1))<<(tail+1) != ip {
break
}
}
if ip+(1<<tail)-1 > int64(end) {
break
}
cidr = append(cidr, fmt.Sprintf("%s/%d", Uint32ToIP(uint32(ip)).String(), 32-tail))
ip += 1 << tail
}
// increase mask bit
for {
for ; tail >= 0; tail-- {
if ip+(1<<tail)-1 <= int64(end) {
break
}
}
if tail < 0 {
break
}
cidr = append(cidr, fmt.Sprintf("%s/%d", Uint32ToIP(uint32(ip)).String(), 32-tail))
ip += 1 << tail
if ip-1 == int64(end) {
break
}
}
return cidr
}
func ExcludeRoute(ipArray *StringArray) *StringArray {
ips := make([]uint32, 0, ipArray.Len())
for _, ip := range ipArray.Elems() {
ipnum, err := IpToUint32(ip)
if err != nil {
log.Fatal(err)
}
ips = append(ips, ipnum)
}
sort.Slice(ips, func(i, j int) bool { return ips[i] < ips[j] })
min := uint32(0)
max := uint32(4294967295)
res := NewStringArray()
for _, ip := range ips {
cidr := IpRangeToCIDR(min, ip-1)
for _, s := range cidr {
res.Append(s)
}
min = ip + 1
}
cidr := IpRangeToCIDR(min, max)
for _, s := range cidr {
res.Append(s)
}
return res
}