github.com/TeaOSLab/EdgeNode@v1.3.8/internal/iplibrary/action_utils.go (about)

     1  package iplibrary
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"math"
     7  	"strconv"
     8  	"strings"
     9  )
    10  
    11  // Convert IPv4 range into CIDR
    12  // 来自:https://gist.github.com/P-A-R-U-S/a090dd90c5104ce85a29c32669dac107
    13  func iPv4RangeToCIDRRange(ipStart string, ipEnd string) (cidrs []string, err error) {
    14  
    15  	cidr2mask := []uint32{
    16  		0x00000000, 0x80000000, 0xC0000000,
    17  		0xE0000000, 0xF0000000, 0xF8000000,
    18  		0xFC000000, 0xFE000000, 0xFF000000,
    19  		0xFF800000, 0xFFC00000, 0xFFE00000,
    20  		0xFFF00000, 0xFFF80000, 0xFFFC0000,
    21  		0xFFFE0000, 0xFFFF0000, 0xFFFF8000,
    22  		0xFFFFC000, 0xFFFFE000, 0xFFFFF000,
    23  		0xFFFFF800, 0xFFFFFC00, 0xFFFFFE00,
    24  		0xFFFFFF00, 0xFFFFFF80, 0xFFFFFFC0,
    25  		0xFFFFFFE0, 0xFFFFFFF0, 0xFFFFFFF8,
    26  		0xFFFFFFFC, 0xFFFFFFFE, 0xFFFFFFFF,
    27  	}
    28  
    29  	ipStartUint32 := iPv4ToUint32(ipStart)
    30  	ipEndUint32 := iPv4ToUint32(ipEnd)
    31  
    32  	if ipStartUint32 > ipEndUint32 {
    33  		log.Fatalf("start IP:%s must be less than end IP:%s", ipStart, ipEnd)
    34  	}
    35  
    36  	for ipEndUint32 >= ipStartUint32 {
    37  		maxSize := 32
    38  		for maxSize > 0 {
    39  
    40  			maskedBase := ipStartUint32 & cidr2mask[maxSize-1]
    41  
    42  			if maskedBase != ipStartUint32 {
    43  				break
    44  			}
    45  			maxSize--
    46  
    47  		}
    48  
    49  		x := math.Log(float64(ipEndUint32-ipStartUint32+1)) / math.Log(2)
    50  		maxDiff := 32 - int(math.Floor(x))
    51  		if maxSize < maxDiff {
    52  			maxSize = maxDiff
    53  		}
    54  
    55  		cidrs = append(cidrs, uInt32ToIPv4(ipStartUint32)+"/"+strconv.Itoa(maxSize))
    56  
    57  		ipStartUint32 += uint32(math.Exp2(float64(32 - maxSize)))
    58  	}
    59  
    60  	return cidrs, err
    61  }
    62  
    63  //Convert IPv4 to uint32
    64  func iPv4ToUint32(iPv4 string) uint32 {
    65  
    66  	ipOctets := [4]uint64{}
    67  
    68  	for i, v := range strings.SplitN(iPv4, ".", 4) {
    69  		ipOctets[i], _ = strconv.ParseUint(v, 10, 32)
    70  	}
    71  
    72  	result := (ipOctets[0] << 24) | (ipOctets[1] << 16) | (ipOctets[2] << 8) | ipOctets[3]
    73  
    74  	return uint32(result)
    75  }
    76  
    77  //Convert uint32 to IP
    78  func uInt32ToIPv4(iPuInt32 uint32) (iP string) {
    79  	iP = fmt.Sprintf("%d.%d.%d.%d",
    80  		iPuInt32>>24,
    81  		(iPuInt32&0x00FFFFFF)>>16,
    82  		(iPuInt32&0x0000FFFF)>>8,
    83  		iPuInt32&0x000000FF)
    84  	return iP
    85  }