cidr-tools 5.0.8 → 5.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/index.js +58 -73
- package/package.json +3 -5
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ exclude(['::1/127'], ['::1/128']) //=> ['::/128']
|
|
|
18
18
|
expand(['2001:db8::/126']) //=> ['2001:db8::', '2001:db8::1', '2001:db8::2', '2001:db8::3']
|
|
19
19
|
overlap('1.0.0.0/24', '1.0.0.128/25') //=> true
|
|
20
20
|
contains(["1.0.0.0/24", "2.0.0.0/24"], "1.0.0.1") //=> true
|
|
21
|
-
normalize('
|
|
21
|
+
normalize('::ffff/64') //=> '::/64'
|
|
22
22
|
```
|
|
23
23
|
|
|
24
24
|
## API
|
package/index.js
CHANGED
|
@@ -1,23 +1,17 @@
|
|
|
1
1
|
import IPCIDR from "ip-cidr";
|
|
2
2
|
import ipRegex from "ip-regex";
|
|
3
3
|
import isCidr from "is-cidr";
|
|
4
|
-
import ipv6Normalize from "ipv6-normalize";
|
|
5
4
|
import naturalCompare from "string-natural-compare";
|
|
6
|
-
import {stringifyIp} from "ip-bigint";
|
|
7
|
-
import {BigInteger} from "jsbn";
|
|
5
|
+
import {parseIp, stringifyIp} from "ip-bigint";
|
|
8
6
|
|
|
9
7
|
const bits = {
|
|
10
8
|
"v4": 32,
|
|
11
9
|
"v6": 128,
|
|
12
10
|
};
|
|
13
11
|
|
|
14
|
-
const
|
|
12
|
+
const normalizeIp = str => stringifyIp(parseIp(str));
|
|
15
13
|
const uniq = arr => [...new Set(arr)];
|
|
16
14
|
|
|
17
|
-
const zero = bigint("0");
|
|
18
|
-
const one = bigint("1");
|
|
19
|
-
const two = bigint("2");
|
|
20
|
-
|
|
21
15
|
function isIP(ip) {
|
|
22
16
|
if (ipRegex.v4({exact: true}).test(ip)) return 4;
|
|
23
17
|
if (ipRegex.v6({exact: true}).test(ip)) return 6;
|
|
@@ -31,7 +25,7 @@ function doNormalize(cidr) {
|
|
|
31
25
|
if (cidrVersion) {
|
|
32
26
|
// set network address to first address
|
|
33
27
|
let start = (new IPCIDR(cidr)).start();
|
|
34
|
-
if (cidrVersion === 6) start =
|
|
28
|
+
if (cidrVersion === 6) start = normalizeIp(start);
|
|
35
29
|
if (start) {
|
|
36
30
|
return `${start}${cidr.match(/\/.+/)}`.toLowerCase();
|
|
37
31
|
}
|
|
@@ -39,10 +33,10 @@ function doNormalize(cidr) {
|
|
|
39
33
|
|
|
40
34
|
// single ip
|
|
41
35
|
const parsed = parse(cidr);
|
|
42
|
-
if (parsed
|
|
36
|
+
if (parsed?.address?.v4) {
|
|
43
37
|
return cidr;
|
|
44
|
-
} else if (parsed
|
|
45
|
-
return
|
|
38
|
+
} else if (parsed?.address?.v4 === false) {
|
|
39
|
+
return normalizeIp(cidr);
|
|
46
40
|
}
|
|
47
41
|
|
|
48
42
|
throw new Error(`Invalid network: ${cidr}`);
|
|
@@ -65,21 +59,12 @@ function parse(str) {
|
|
|
65
59
|
}
|
|
66
60
|
}
|
|
67
61
|
|
|
68
|
-
function format(number, version) {
|
|
69
|
-
if (!(number instanceof BigInteger)) number = bigint(number);
|
|
70
|
-
|
|
71
|
-
return normalize(stringifyIp({
|
|
72
|
-
number: BigInt(number.toString()),
|
|
73
|
-
version: Number(version.substring(1)),
|
|
74
|
-
}));
|
|
75
|
-
}
|
|
76
|
-
|
|
77
62
|
// utility function that returns boundaries of two networks
|
|
78
63
|
function getBoundaries(a, b) {
|
|
79
|
-
const aStart = a.start({type: "bigInteger"});
|
|
80
|
-
const bStart = b.start({type: "bigInteger"});
|
|
81
|
-
const aEnd = a.end({type: "bigInteger"});
|
|
82
|
-
const bEnd = b.end({type: "bigInteger"});
|
|
64
|
+
const aStart = BigInt(a.start({type: "bigInteger"}).toString());
|
|
65
|
+
const bStart = BigInt(b.start({type: "bigInteger"}).toString());
|
|
66
|
+
const aEnd = BigInt(a.end({type: "bigInteger"}).toString());
|
|
67
|
+
const bEnd = BigInt(b.end({type: "bigInteger"}).toString());
|
|
83
68
|
return {aStart, bStart, aEnd, bEnd};
|
|
84
69
|
}
|
|
85
70
|
|
|
@@ -89,11 +74,11 @@ function doNetsOverlap(a, b) {
|
|
|
89
74
|
|
|
90
75
|
// aaa
|
|
91
76
|
// bbb
|
|
92
|
-
if (aStart
|
|
77
|
+
if (aStart > bEnd) return false; // a starts after b
|
|
93
78
|
|
|
94
79
|
// aaa
|
|
95
80
|
// bbb
|
|
96
|
-
if (bStart
|
|
81
|
+
if (bStart > aEnd) return false; // b starts after a
|
|
97
82
|
|
|
98
83
|
return true;
|
|
99
84
|
}
|
|
@@ -104,11 +89,11 @@ function netContains(a, b) {
|
|
|
104
89
|
|
|
105
90
|
// aaa
|
|
106
91
|
// bbbb
|
|
107
|
-
if (bStart
|
|
92
|
+
if (bStart < aStart) return false; // a starts after b
|
|
108
93
|
|
|
109
94
|
// aaa
|
|
110
95
|
// bbbb
|
|
111
|
-
if (bEnd
|
|
96
|
+
if (bEnd > aEnd) return false; // b starts after a
|
|
112
97
|
|
|
113
98
|
return true;
|
|
114
99
|
}
|
|
@@ -124,19 +109,19 @@ function excludeNets(a, b, v) {
|
|
|
124
109
|
// bbb
|
|
125
110
|
// aaa
|
|
126
111
|
// bbb
|
|
127
|
-
if (aStart
|
|
112
|
+
if (aStart > bEnd || aEnd < bStart) {
|
|
128
113
|
return [a.cidr];
|
|
129
114
|
}
|
|
130
115
|
|
|
131
116
|
// aaa
|
|
132
117
|
// bbb
|
|
133
|
-
if (aStart
|
|
118
|
+
if (aStart === bStart && aEnd === bEnd) {
|
|
134
119
|
return [];
|
|
135
120
|
}
|
|
136
121
|
|
|
137
122
|
// aa
|
|
138
123
|
// bbbb
|
|
139
|
-
if (aStart
|
|
124
|
+
if (aStart > bStart && aEnd < bEnd) {
|
|
140
125
|
return [];
|
|
141
126
|
}
|
|
142
127
|
|
|
@@ -144,24 +129,24 @@ function excludeNets(a, b, v) {
|
|
|
144
129
|
// bbbb
|
|
145
130
|
// aaaa
|
|
146
131
|
// bb
|
|
147
|
-
if (aStart
|
|
148
|
-
parts.push({start: aStart, end: bStart
|
|
132
|
+
if (aStart < bStart && aEnd <= bEnd) {
|
|
133
|
+
parts.push({start: aStart, end: bStart - 1n});
|
|
149
134
|
}
|
|
150
135
|
|
|
151
136
|
// aaa
|
|
152
137
|
// bbb
|
|
153
138
|
// aaaa
|
|
154
139
|
// bbb
|
|
155
|
-
if (aStart
|
|
156
|
-
parts.push({start: bEnd
|
|
140
|
+
if (aStart >= bStart && aEnd > bEnd) {
|
|
141
|
+
parts.push({start: bEnd + 1n, end: aEnd});
|
|
157
142
|
}
|
|
158
143
|
|
|
159
144
|
// aaaa
|
|
160
145
|
// bb
|
|
161
|
-
if (aStart
|
|
146
|
+
if (aStart < bStart && aEnd > bEnd) {
|
|
162
147
|
parts.push(
|
|
163
|
-
{start: aStart, end: bStart
|
|
164
|
-
{start: bEnd
|
|
148
|
+
{start: aStart, end: bStart - 1n},
|
|
149
|
+
{start: bEnd + 1n, end: aEnd},
|
|
165
150
|
);
|
|
166
151
|
}
|
|
167
152
|
|
|
@@ -176,15 +161,14 @@ function excludeNets(a, b, v) {
|
|
|
176
161
|
}
|
|
177
162
|
|
|
178
163
|
function biggestPowerOfTwo(num) {
|
|
179
|
-
if (num
|
|
180
|
-
|
|
181
|
-
return two.pow(power);
|
|
164
|
+
if (num === 0n) return 0n;
|
|
165
|
+
return 2n ** BigInt(String(num.toString(2).length - 1));
|
|
182
166
|
}
|
|
183
167
|
|
|
184
168
|
function subparts(part) {
|
|
185
169
|
// special case for when part is length 1
|
|
186
|
-
if (part.end
|
|
187
|
-
if (part.end
|
|
170
|
+
if ((part.end - part.start) === 1n) {
|
|
171
|
+
if (part.end % 2n === 0n) {
|
|
188
172
|
return [{start: part.start, end: part.start}, {start: part.end, end: part.end}];
|
|
189
173
|
} else {
|
|
190
174
|
return [{start: part.start, end: part.end}];
|
|
@@ -195,56 +179,59 @@ function subparts(part) {
|
|
|
195
179
|
let biggest = biggestPowerOfTwo(size);
|
|
196
180
|
|
|
197
181
|
let start, end;
|
|
198
|
-
if (size
|
|
182
|
+
if (size === biggest && part.start + size === part.end) {
|
|
199
183
|
return [part];
|
|
200
|
-
} else if (part.start
|
|
184
|
+
} else if (part.start % biggest === 0n) {
|
|
201
185
|
// start is matching on the size-defined boundary - ex: 0-12, use 0-8
|
|
202
186
|
start = part.start;
|
|
203
|
-
end = start
|
|
187
|
+
end = start + biggest - 1n;
|
|
204
188
|
} else {
|
|
205
|
-
start = part.end
|
|
189
|
+
start = (part.end / biggest) * biggest;
|
|
206
190
|
|
|
207
191
|
// start is not matching on the size-defined boundary - 4-16, use 8-16
|
|
208
|
-
if (start
|
|
192
|
+
if ((start + biggest - 1n) > part.end) {
|
|
209
193
|
// divide will floor to nearest integer
|
|
210
|
-
start = part.end
|
|
194
|
+
start = ((part.end / biggest) - 1n) * biggest;
|
|
211
195
|
|
|
212
|
-
while (start
|
|
213
|
-
biggest
|
|
214
|
-
start = part.end
|
|
196
|
+
while (start < part.start) {
|
|
197
|
+
biggest /= 2n;
|
|
198
|
+
start = ((part.end / biggest) - 1n) * biggest;
|
|
215
199
|
}
|
|
216
200
|
|
|
217
|
-
end = start
|
|
201
|
+
end = start + biggest - 1n;
|
|
218
202
|
} else {
|
|
219
|
-
start = part.end
|
|
220
|
-
end = start
|
|
203
|
+
start = (part.end / biggest) * biggest;
|
|
204
|
+
end = start + biggest - 1n;
|
|
221
205
|
}
|
|
222
206
|
}
|
|
223
207
|
|
|
224
208
|
let parts = [{start, end}];
|
|
225
209
|
|
|
226
210
|
// additional subnets on left side
|
|
227
|
-
if (
|
|
228
|
-
parts = parts.concat(subparts({start: part.start, end: start
|
|
211
|
+
if (start !== part.start) {
|
|
212
|
+
parts = parts.concat(subparts({start: part.start, end: start - 1n}));
|
|
229
213
|
}
|
|
230
214
|
|
|
231
215
|
// additional subnets on right side
|
|
232
|
-
if (
|
|
233
|
-
parts = parts.concat(subparts({start: end
|
|
216
|
+
if (end !== part.end) {
|
|
217
|
+
parts = parts.concat(subparts({start: end + 1n, end: part.end}));
|
|
234
218
|
}
|
|
235
219
|
|
|
236
220
|
return parts;
|
|
237
221
|
}
|
|
238
222
|
|
|
239
223
|
function diff(a, b) {
|
|
240
|
-
if (
|
|
241
|
-
if (
|
|
242
|
-
a
|
|
243
|
-
return a
|
|
224
|
+
if (typeof a !== "bigint") a = BigInt(a);
|
|
225
|
+
if (typeof b !== "bigint") b = BigInt(b);
|
|
226
|
+
a += 1n;
|
|
227
|
+
return a - b;
|
|
244
228
|
}
|
|
245
229
|
|
|
246
230
|
function formatPart(part, v) {
|
|
247
|
-
const ip =
|
|
231
|
+
const ip = normalize(stringifyIp({
|
|
232
|
+
number: BigInt(part.start.toString()),
|
|
233
|
+
version: Number(v.substring(1)),
|
|
234
|
+
}));
|
|
248
235
|
const zeroes = diff(part.end, part.start).toString(2);
|
|
249
236
|
const prefix = bits[v] - (zeroes.match(/0/g) || []).length;
|
|
250
237
|
return `${ip}/${prefix}`;
|
|
@@ -253,8 +240,8 @@ function formatPart(part, v) {
|
|
|
253
240
|
function mapNets(nets) {
|
|
254
241
|
const maps = {v4: {}, v6: {}};
|
|
255
242
|
for (const net of nets) {
|
|
256
|
-
const start = net.start({type: "bigInteger"}).toString();
|
|
257
|
-
const end = net.end({type: "bigInteger"}).toString();
|
|
243
|
+
const start = BigInt(net.start({type: "bigInteger"}).toString());
|
|
244
|
+
const end = BigInt(net.end({type: "bigInteger"}).toString());
|
|
258
245
|
const v = `v${isCidr(net)}`;
|
|
259
246
|
|
|
260
247
|
if (!maps[v][start]) maps[v][start] = {};
|
|
@@ -290,11 +277,11 @@ export function merge(nets) {
|
|
|
290
277
|
for (const [index, number] of numbers.entries()) {
|
|
291
278
|
const marker = maps[v][number];
|
|
292
279
|
|
|
293
|
-
if (
|
|
294
|
-
start[v] =
|
|
280
|
+
if (start[v] === null && marker.start) {
|
|
281
|
+
start[v] = BigInt(number);
|
|
295
282
|
}
|
|
296
283
|
if (marker.end) {
|
|
297
|
-
end[v] =
|
|
284
|
+
end[v] = BigInt(number);
|
|
298
285
|
}
|
|
299
286
|
|
|
300
287
|
if (marker.start) depth += marker.start;
|
|
@@ -314,9 +301,7 @@ export function merge(nets) {
|
|
|
314
301
|
}
|
|
315
302
|
}
|
|
316
303
|
|
|
317
|
-
merged.v4
|
|
318
|
-
merged.v6 = merged.v6.sort(naturalCompare);
|
|
319
|
-
return merged.v4.concat(merged.v6);
|
|
304
|
+
return [...merged.v4.sort(naturalCompare), ...merged.v6.sort(naturalCompare)];
|
|
320
305
|
}
|
|
321
306
|
|
|
322
307
|
export function exclude(basenets, exclnets) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cidr-tools",
|
|
3
|
-
"version": "5.0.
|
|
3
|
+
"version": "5.0.10",
|
|
4
4
|
"author": "silverwind <me@silverwind.io>",
|
|
5
5
|
"description": "Tools to work with IPv4 and IPv6 CIDR network lists",
|
|
6
6
|
"repository": "silverwind/cidr-tools",
|
|
@@ -32,16 +32,14 @@
|
|
|
32
32
|
"ip-bigint": "5.0.3",
|
|
33
33
|
"ip-cidr": "3.0.10",
|
|
34
34
|
"ip-regex": "5.0.0",
|
|
35
|
-
"ipv6-normalize": "1.0.1",
|
|
36
35
|
"is-cidr": "5.0.2",
|
|
37
|
-
"jsbn": "^1.1.0",
|
|
38
36
|
"string-natural-compare": "3.0.1"
|
|
39
37
|
},
|
|
40
38
|
"devDependencies": {
|
|
41
39
|
"eslint": "8.23.1",
|
|
42
40
|
"eslint-config-silverwind": "54.0.2",
|
|
43
41
|
"jest": "29.0.3",
|
|
44
|
-
"updates": "13.1.
|
|
45
|
-
"versions": "9.3.
|
|
42
|
+
"updates": "13.1.7",
|
|
43
|
+
"versions": "9.3.2"
|
|
46
44
|
}
|
|
47
45
|
}
|