Files
EdgeNode/internal/iplibrary/action_utils.go
2021-02-06 17:34:33 +08:00

86 lines
1.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package iplibrary
import (
"fmt"
"log"
"math"
"strconv"
"strings"
)
// Convert IPv4 range into CIDR
// 来自https://gist.github.com/P-A-R-U-S/a090dd90c5104ce85a29c32669dac107
func iPv4RangeToCIDRRange(ipStart string, ipEnd string) (cidrs []string, err error) {
cidr2mask := []uint32{
0x00000000, 0x80000000, 0xC0000000,
0xE0000000, 0xF0000000, 0xF8000000,
0xFC000000, 0xFE000000, 0xFF000000,
0xFF800000, 0xFFC00000, 0xFFE00000,
0xFFF00000, 0xFFF80000, 0xFFFC0000,
0xFFFE0000, 0xFFFF0000, 0xFFFF8000,
0xFFFFC000, 0xFFFFE000, 0xFFFFF000,
0xFFFFF800, 0xFFFFFC00, 0xFFFFFE00,
0xFFFFFF00, 0xFFFFFF80, 0xFFFFFFC0,
0xFFFFFFE0, 0xFFFFFFF0, 0xFFFFFFF8,
0xFFFFFFFC, 0xFFFFFFFE, 0xFFFFFFFF,
}
ipStartUint32 := iPv4ToUint32(ipStart)
ipEndUint32 := iPv4ToUint32(ipEnd)
if ipStartUint32 > ipEndUint32 {
log.Fatalf("start IP:%s must be less than end IP:%s", ipStart, ipEnd)
}
for ipEndUint32 >= ipStartUint32 {
maxSize := 32
for maxSize > 0 {
maskedBase := ipStartUint32 & cidr2mask[maxSize-1]
if maskedBase != ipStartUint32 {
break
}
maxSize--
}
x := math.Log(float64(ipEndUint32-ipStartUint32+1)) / math.Log(2)
maxDiff := 32 - int(math.Floor(x))
if maxSize < maxDiff {
maxSize = maxDiff
}
cidrs = append(cidrs, uInt32ToIPv4(ipStartUint32)+"/"+strconv.Itoa(maxSize))
ipStartUint32 += uint32(math.Exp2(float64(32 - maxSize)))
}
return cidrs, err
}
//Convert IPv4 to uint32
func iPv4ToUint32(iPv4 string) uint32 {
ipOctets := [4]uint64{}
for i, v := range strings.SplitN(iPv4, ".", 4) {
ipOctets[i], _ = strconv.ParseUint(v, 10, 32)
}
result := (ipOctets[0] << 24) | (ipOctets[1] << 16) | (ipOctets[2] << 8) | ipOctets[3]
return uint32(result)
}
//Convert uint32 to IP
func uInt32ToIPv4(iPuInt32 uint32) (iP string) {
iP = fmt.Sprintf("%d.%d.%d.%d",
iPuInt32>>24,
(iPuInt32&0x00FFFFFF)>>16,
(iPuInt32&0x0000FFFF)>>8,
iPuInt32&0x000000FF)
return iP
}