v0.5.159: fix aggregateCIDRs — баг с 1<<31, склеивание /32
This commit is contained in:
+22
-10
@@ -100,23 +100,35 @@ function cidrToRange(cidr) {
|
||||
// Схлопывание списка CIDR в минимальный набор (для экспорта).
|
||||
// Пример: 10.0.0.0/24 + 10.0.1.0/24 → 10.0.0.0/23
|
||||
function aggregateCIDRs(cidrs) {
|
||||
// 1. Сортируем по start, мержим смежные
|
||||
const ranges = cidrs.map(c => cidrToRange(c)).sort((a, b) => a.start - b.start);
|
||||
const merged = [];
|
||||
for (const r of ranges) {
|
||||
const last = merged[merged.length - 1];
|
||||
if (last && r.start <= last.end + 1) last.end = Math.max(last.end, r.end);
|
||||
else merged.push({ ...r });
|
||||
else merged.push({ start: r.start, end: r.end });
|
||||
}
|
||||
return merged.map(r => {
|
||||
let start = r.start, end = r.end, cidrs = [];
|
||||
while (start <= end) {
|
||||
let maxMask = 32;
|
||||
while (maxMask > 0 && ((start & ((1 << (32 - maxMask)) - 1)) !== 0 || (start + (1 << (32 - maxMask)) - 1) > end)) maxMask--;
|
||||
cidrs.push(numToIP(start) + '/' + maxMask);
|
||||
start += (1 << (32 - maxMask));
|
||||
// 2. Каждый merged range → минимальный набор CIDR
|
||||
const result = [];
|
||||
for (const r of merged) {
|
||||
let start = r.start;
|
||||
while (start <= r.end) {
|
||||
// Ищем минимальную маску (самый широкий блок), подходящую под start и end.
|
||||
// Идём от 1 до 32, запоминаем минимальную (самую широкую) подходящую.
|
||||
let bestM = 32;
|
||||
for (let m = 1; m <= 32; m++) {
|
||||
if ((1 << (32 - m)) <= 0) continue;
|
||||
const size = 1 << (32 - m);
|
||||
if ((start & (size - 1)) !== 0) continue; // не выровнен
|
||||
if (start + size - 1 > r.end) continue; // выходит за range
|
||||
bestM = m;
|
||||
break; // нашли самую широкую
|
||||
}
|
||||
result.push(numToIP(start) + '/' + bestM);
|
||||
start += (1 << (32 - bestM));
|
||||
}
|
||||
return cidrs;
|
||||
}).flat();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function numToIP(n) {
|
||||
|
||||
Reference in New Issue
Block a user