120 lines
2.3 KiB
Go
120 lines
2.3 KiB
Go
|
package cidr
|
|||
|
|
|||
|
import (
|
|||
|
"bytes"
|
|||
|
"fmt"
|
|||
|
"math"
|
|||
|
"net"
|
|||
|
"sort"
|
|||
|
)
|
|||
|
|
|||
|
// SuperNetting 合并网段
|
|||
|
func SuperNetting(ns []string) (*cidr, error) {
|
|||
|
num := len(ns)
|
|||
|
if num < 1 || (num&(num-1)) != 0 {
|
|||
|
return nil, fmt.Errorf("子网数量必须是2的次方")
|
|||
|
}
|
|||
|
|
|||
|
mask := ""
|
|||
|
var cidrs []*cidr
|
|||
|
for _, n := range ns {
|
|||
|
// 检查子网CIDR有效性
|
|||
|
c, err := ParseCIDR(n)
|
|||
|
if err != nil {
|
|||
|
return nil, fmt.Errorf("网段%v格式错误", n)
|
|||
|
}
|
|||
|
cidrs = append(cidrs, c)
|
|||
|
|
|||
|
// TODO 暂只考虑相同子网掩码的网段合并
|
|||
|
if len(mask) == 0 {
|
|||
|
mask = c.Mask()
|
|||
|
} else if c.Mask() != mask {
|
|||
|
return nil, fmt.Errorf("子网掩码不一致")
|
|||
|
}
|
|||
|
}
|
|||
|
AscSortCIDRs(cidrs)
|
|||
|
|
|||
|
// 检查网段是否连续
|
|||
|
var network net.IP
|
|||
|
for _, c := range cidrs {
|
|||
|
if len(network) > 0 {
|
|||
|
if !network.Equal(c.ipNet.IP) {
|
|||
|
return nil, fmt.Errorf("必须是连续的网段")
|
|||
|
}
|
|||
|
}
|
|||
|
network = net.ParseIP(c.Broadcast())
|
|||
|
IncrIP(network)
|
|||
|
}
|
|||
|
|
|||
|
// 子网掩码左移,得到共同的父网段
|
|||
|
c := cidrs[0]
|
|||
|
ones, bits := c.MaskSize()
|
|||
|
ones = ones - int(math.Log2(float64(num)))
|
|||
|
c.ipNet.Mask = net.CIDRMask(ones, bits)
|
|||
|
c.ipNet.IP.Mask(c.ipNet.Mask)
|
|||
|
|
|||
|
return c, nil
|
|||
|
}
|
|||
|
|
|||
|
// IncrIP IP地址自增
|
|||
|
func IncrIP(ip net.IP) {
|
|||
|
for i := len(ip) - 1; i >= 0; i-- {
|
|||
|
ip[i]++
|
|||
|
if ip[i] > 0 {
|
|||
|
break
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// DecrIP IP地址自减
|
|||
|
func DecrIP(ip net.IP) {
|
|||
|
length := len(ip)
|
|||
|
for i := length - 1; i >= 0; i-- {
|
|||
|
ip[length-1]--
|
|||
|
if ip[length-1] < 0xFF {
|
|||
|
break
|
|||
|
}
|
|||
|
for j := 1; j < length; j++ {
|
|||
|
ip[length-j-1]--
|
|||
|
if ip[length-j-1] < 0xFF {
|
|||
|
return
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Compare 比较IP大小 a等于b,返回0; a大于b,返回+1; a小于b,返回-1
|
|||
|
func Compare(a, b net.IP) int {
|
|||
|
return bytes.Compare(a, b)
|
|||
|
}
|
|||
|
|
|||
|
// AscSortCIDRs 升序
|
|||
|
func AscSortCIDRs(cs []*cidr) {
|
|||
|
sort.Slice(cs, func(i, j int) bool {
|
|||
|
if n := bytes.Compare(cs[i].ipNet.IP, cs[j].ipNet.IP); n != 0 {
|
|||
|
return n < 0
|
|||
|
}
|
|||
|
|
|||
|
if n := bytes.Compare(cs[i].ipNet.Mask, cs[j].ipNet.Mask); n != 0 {
|
|||
|
return n < 0
|
|||
|
}
|
|||
|
|
|||
|
return false
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
// DescSortCIDRs 降序
|
|||
|
func DescSortCIDRs(cs []*cidr) {
|
|||
|
sort.Slice(cs, func(i, j int) bool {
|
|||
|
if n := bytes.Compare(cs[i].ipNet.IP, cs[j].ipNet.IP); n != 0 {
|
|||
|
return n >= 0
|
|||
|
}
|
|||
|
|
|||
|
if n := bytes.Compare(cs[i].ipNet.Mask, cs[j].ipNet.Mask); n != 0 {
|
|||
|
return n >= 0
|
|||
|
}
|
|||
|
|
|||
|
return false
|
|||
|
})
|
|||
|
}
|