123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194 |
- package cidr
- import (
- "encoding/hex"
- "fmt"
- "math"
- "math/big"
- "net"
- )
- // 裂解子网的方式
- const (
- MethodSubnetNum = 0 // 基于子网数量
- MethodHostNum = 1 // 基于主机数量
- )
- var _ CIDR = (*cidr)(nil)
- type CIDR interface {
- CIDR() string
- IP() string
- Network() string
- Broadcast() string
- Mask() string
- MaskSize() (int, int)
- IPRange() (string, string)
- IPCount() *big.Int
- IsIPv4() bool
- IsIPv6() bool
- Equal(string) bool
- Contains(string) bool
- ForEachIP(func(string) error) error
- ForEachIPBeginWith(string, func(string) error) error
- SubNetting(method, num int) ([]*cidr, error)
- }
- type cidr struct {
- ip net.IP
- ipNet *net.IPNet
- }
- // ParseCIDR 解析CIDR网段
- func ParseCIDR(s string) (*cidr, error) {
- i, n, err := net.ParseCIDR(s)
- if err != nil {
- return nil, err
- }
- return &cidr{ip: i, ipNet: n}, nil
- }
- // Equal 判断网段是否相等
- func (c *cidr) Equal(ns string) bool {
- c2, err := ParseCIDR(ns)
- if err != nil {
- return false
- }
- return c.ipNet.IP.Equal(c2.ipNet.IP) /* && c.ipNet.IP.Equal(c2.ip) */
- }
- // IsIPv4 判断是否IPv4
- func (c *cidr) IsIPv4() bool {
- _, bits := c.ipNet.Mask.Size()
- return bits/8 == net.IPv4len
- }
- // IsIPv6 判断是否IPv6
- func (c *cidr) IsIPv6() bool {
- _, bits := c.ipNet.Mask.Size()
- return bits/8 == net.IPv6len
- }
- // Contains 判断IP是否包含在网段中
- func (c *cidr) Contains(ip string) bool {
- return c.ipNet.Contains(net.ParseIP(ip))
- }
- // CIDR 根据子网掩码长度校准后的CIDR
- func (c *cidr) CIDR() string {
- return c.ipNet.String()
- }
- // IP CIDR字符串中的IP部分
- func (c *cidr) IP() string {
- return c.ip.String()
- }
- // Network 网络号
- func (c *cidr) Network() string {
- return c.ipNet.IP.String()
- }
- // MaskSize 子网掩码位数
- func (c *cidr) MaskSize() (ones, bits int) {
- ones, bits = c.ipNet.Mask.Size()
- return
- }
- // Mask 子网掩码
- func (c *cidr) Mask() string {
- mask, _ := hex.DecodeString(c.ipNet.Mask.String())
- return net.IP([]byte(mask)).String()
- }
- // Broadcast 广播地址(网段最后一个IP)
- func (c *cidr) Broadcast() string {
- mask := c.ipNet.Mask
- bcst := make(net.IP, len(c.ipNet.IP))
- copy(bcst, c.ipNet.IP)
- for i := 0; i < len(mask); i++ {
- ipIdx := len(bcst) - i - 1
- bcst[ipIdx] = c.ipNet.IP[ipIdx] | ^mask[len(mask)-i-1]
- }
- return bcst.String()
- }
- // IPRange 起始IP、结束IP
- func (c *cidr) IPRange() (start, end string) {
- return c.Network(), c.Broadcast()
- }
- // IPCount IP数量
- func (c *cidr) IPCount() *big.Int {
- ones, bits := c.ipNet.Mask.Size()
- return big.NewInt(0).Lsh(big.NewInt(1), uint(bits-ones))
- }
- // ForEachIP 遍历网段下所有IP
- func (c *cidr) ForEachIP(iterator func(ip string) error) error {
- next := make(net.IP, len(c.ipNet.IP))
- copy(next, c.ipNet.IP)
- for c.ipNet.Contains(next) {
- if err := iterator(next.String()); err != nil {
- return err
- }
- IncrIP(next)
- }
- return nil
- }
- // ForEachIPBeginWith 从指定IP开始遍历网段下后续的IP
- func (c *cidr) ForEachIPBeginWith(beginIP string, iterator func(ip string) error) error {
- next := net.ParseIP(beginIP)
- for c.ipNet.Contains(next) {
- if err := iterator(next.String()); err != nil {
- return err
- }
- IncrIP(next)
- }
- return nil
- }
- // SubNetting 裂解网段
- func (c *cidr) SubNetting(method, num int) ([]*cidr, error) {
- if num < 1 || (num&(num-1)) != 0 {
- return nil, fmt.Errorf("裂解数量必须是2的次方")
- }
- newOnes := int(math.Log2(float64(num)))
- ones, bits := c.MaskSize()
- switch method {
- default:
- return nil, fmt.Errorf("不支持的裂解方式")
- case MethodSubnetNum:
- newOnes = ones + newOnes
- // 如果子网的掩码长度大于父网段的长度,则无法裂解
- if newOnes > bits {
- return nil, nil
- }
- case MethodHostNum:
- newOnes = bits - newOnes
- // 如果子网的掩码长度小于等于父网段的掩码长度,则无法裂解
- if newOnes <= ones {
- return nil, nil
- }
- // 主机数量转换为子网数量
- num = int(math.Pow(float64(2), float64(newOnes-ones)))
- }
- var cidrs []*cidr
- network := make(net.IP, len(c.ipNet.IP))
- copy(network, c.ipNet.IP)
- for i := 0; i < num; i++ {
- cidr, _ := ParseCIDR(fmt.Sprintf("%v/%v", network.String(), newOnes))
- cidrs = append(cidrs, cidr)
- // 广播地址的下一个IP即为下一段的网络号
- network = net.ParseIP(cidr.Broadcast())
- IncrIP(network)
- }
- return cidrs, nil
- }
|