forked from cutethotw/ClashRule
-
Notifications
You must be signed in to change notification settings - Fork 0
/
cidr.js
98 lines (87 loc) · 2.15 KB
/
cidr.js
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
function getIpRange(ip, maskStr) {
if (typeof ip === 'string' && ip.includes('/')) {
const [ipStr, mask] = ip.split('/')
maskStr = mask
ip = ipStr
}
let ips = []
if (typeof ip === 'string' && ip.indexOf('.') > -1) {
ips = ip.split('.').map(x => parseInt(x, 10))
} else if (ip instanceof Buffer) {
ips = [...ip]
} else if (Array.isArray(ip)) {
ips = ip
} else {
throw new Error('Invalid ip address: ' + ip)
}
let bitmask = maskStr ? parseInt(maskStr, 10) : 32
if (!(bitmask <= 32)) {
throw new Error('Invalid mask for ip4: ' + maskStr)
}
const ipLong = (ips[0] << 24 | ips[1] << 16 | ips[2] << 8 | ips[3]) >>> 0
let maskLong = 0
if (bitmask > 0) {
maskLong = (0xffffffff << (32 - bitmask)) >>> 0
}
let netLong = 0
try {
netLong = (ipLong & maskLong) >>> 0
} catch (error1) {
throw new Error('Invalid net address: ' + ip + '/' + bitmask)
}
const size = Math.pow(2, 32 - bitmask)
return { start: netLong, end: netLong + size - 1, ip: Buffer.from(ips), mask: bitmask }
}
class Cidr {
list = []
add(ip, prefix) {
this.list.push(getIpRange(ip, prefix))
}
addCidr(cidr) {
this.list.push(cidr)
}
contains(ip) {
const { start, end } = getIpRange(ip)
for (const { start: s, end: e } of this.list) {
if (start >= s && end <= e) {
return true
}
}
return false
}
containsCidr(cidr) {
const { start, end } = cidr
for (const { start: s, end: e } of this.list) {
if (start >= s && end <= e) {
return true
}
}
return false
}
size() {
return this.list.length
}
static compare(ip1, ip2){
const range1 = getIpRange(ip1)
const range2 = getIpRange(ip2)
return range2.start >= range1.start && range2.end <= range1.end
}
removeCidr(cidr) {
const { start, end } = cidr
for (let i = 0; i < this.list.length; i++) {
const { start: s, end: e } = this.list[i]
if (start === s && end === e) {
this.list.splice(i, 1)
return
}
}
}
toList(){
const list = []
for (const item of this.list) {
list.push({ ip: item.ip, prefix: item.mask })
}
return list
}
}
module.exports = Cidr