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
 | ||
| 	})
 | ||
| }
 |