ip.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. package cidr
  2. import (
  3. "encoding/hex"
  4. "fmt"
  5. "math"
  6. "math/big"
  7. "net"
  8. )
  9. // 裂解子网的方式
  10. const (
  11. MethodSubnetNum = 0 // 基于子网数量
  12. MethodHostNum = 1 // 基于主机数量
  13. )
  14. var _ CIDR = (*cidr)(nil)
  15. type CIDR interface {
  16. CIDR() string
  17. IP() string
  18. Network() string
  19. Broadcast() string
  20. Mask() string
  21. MaskSize() (int, int)
  22. IPRange() (string, string)
  23. IPCount() *big.Int
  24. IsIPv4() bool
  25. IsIPv6() bool
  26. Equal(string) bool
  27. Contains(string) bool
  28. ForEachIP(func(string) error) error
  29. ForEachIPBeginWith(string, func(string) error) error
  30. SubNetting(method, num int) ([]*cidr, error)
  31. }
  32. type cidr struct {
  33. ip net.IP
  34. ipNet *net.IPNet
  35. }
  36. // ParseCIDR 解析CIDR网段
  37. func ParseCIDR(s string) (*cidr, error) {
  38. i, n, err := net.ParseCIDR(s)
  39. if err != nil {
  40. return nil, err
  41. }
  42. return &cidr{ip: i, ipNet: n}, nil
  43. }
  44. // Equal 判断网段是否相等
  45. func (c *cidr) Equal(ns string) bool {
  46. c2, err := ParseCIDR(ns)
  47. if err != nil {
  48. return false
  49. }
  50. return c.ipNet.IP.Equal(c2.ipNet.IP) /* && c.ipNet.IP.Equal(c2.ip) */
  51. }
  52. // IsIPv4 判断是否IPv4
  53. func (c *cidr) IsIPv4() bool {
  54. _, bits := c.ipNet.Mask.Size()
  55. return bits/8 == net.IPv4len
  56. }
  57. // IsIPv6 判断是否IPv6
  58. func (c *cidr) IsIPv6() bool {
  59. _, bits := c.ipNet.Mask.Size()
  60. return bits/8 == net.IPv6len
  61. }
  62. // Contains 判断IP是否包含在网段中
  63. func (c *cidr) Contains(ip string) bool {
  64. return c.ipNet.Contains(net.ParseIP(ip))
  65. }
  66. // CIDR 根据子网掩码长度校准后的CIDR
  67. func (c *cidr) CIDR() string {
  68. return c.ipNet.String()
  69. }
  70. // IP CIDR字符串中的IP部分
  71. func (c *cidr) IP() string {
  72. return c.ip.String()
  73. }
  74. // Network 网络号
  75. func (c *cidr) Network() string {
  76. return c.ipNet.IP.String()
  77. }
  78. // MaskSize 子网掩码位数
  79. func (c *cidr) MaskSize() (ones, bits int) {
  80. ones, bits = c.ipNet.Mask.Size()
  81. return
  82. }
  83. // Mask 子网掩码
  84. func (c *cidr) Mask() string {
  85. mask, _ := hex.DecodeString(c.ipNet.Mask.String())
  86. return net.IP([]byte(mask)).String()
  87. }
  88. // Broadcast 广播地址(网段最后一个IP)
  89. func (c *cidr) Broadcast() string {
  90. mask := c.ipNet.Mask
  91. bcst := make(net.IP, len(c.ipNet.IP))
  92. copy(bcst, c.ipNet.IP)
  93. for i := 0; i < len(mask); i++ {
  94. ipIdx := len(bcst) - i - 1
  95. bcst[ipIdx] = c.ipNet.IP[ipIdx] | ^mask[len(mask)-i-1]
  96. }
  97. return bcst.String()
  98. }
  99. // IPRange 起始IP、结束IP
  100. func (c *cidr) IPRange() (start, end string) {
  101. return c.Network(), c.Broadcast()
  102. }
  103. // IPCount IP数量
  104. func (c *cidr) IPCount() *big.Int {
  105. ones, bits := c.ipNet.Mask.Size()
  106. return big.NewInt(0).Lsh(big.NewInt(1), uint(bits-ones))
  107. }
  108. // ForEachIP 遍历网段下所有IP
  109. func (c *cidr) ForEachIP(iterator func(ip string) error) error {
  110. next := make(net.IP, len(c.ipNet.IP))
  111. copy(next, c.ipNet.IP)
  112. for c.ipNet.Contains(next) {
  113. if err := iterator(next.String()); err != nil {
  114. return err
  115. }
  116. IncrIP(next)
  117. }
  118. return nil
  119. }
  120. // ForEachIPBeginWith 从指定IP开始遍历网段下后续的IP
  121. func (c *cidr) ForEachIPBeginWith(beginIP string, iterator func(ip string) error) error {
  122. next := net.ParseIP(beginIP)
  123. for c.ipNet.Contains(next) {
  124. if err := iterator(next.String()); err != nil {
  125. return err
  126. }
  127. IncrIP(next)
  128. }
  129. return nil
  130. }
  131. // SubNetting 裂解网段
  132. func (c *cidr) SubNetting(method, num int) ([]*cidr, error) {
  133. if num < 1 || (num&(num-1)) != 0 {
  134. return nil, fmt.Errorf("裂解数量必须是2的次方")
  135. }
  136. newOnes := int(math.Log2(float64(num)))
  137. ones, bits := c.MaskSize()
  138. switch method {
  139. default:
  140. return nil, fmt.Errorf("不支持的裂解方式")
  141. case MethodSubnetNum:
  142. newOnes = ones + newOnes
  143. // 如果子网的掩码长度大于父网段的长度,则无法裂解
  144. if newOnes > bits {
  145. return nil, nil
  146. }
  147. case MethodHostNum:
  148. newOnes = bits - newOnes
  149. // 如果子网的掩码长度小于等于父网段的掩码长度,则无法裂解
  150. if newOnes <= ones {
  151. return nil, nil
  152. }
  153. // 主机数量转换为子网数量
  154. num = int(math.Pow(float64(2), float64(newOnes-ones)))
  155. }
  156. var cidrs []*cidr
  157. network := make(net.IP, len(c.ipNet.IP))
  158. copy(network, c.ipNet.IP)
  159. for i := 0; i < num; i++ {
  160. cidr, _ := ParseCIDR(fmt.Sprintf("%v/%v", network.String(), newOnes))
  161. cidrs = append(cidrs, cidr)
  162. // 广播地址的下一个IP即为下一段的网络号
  163. network = net.ParseIP(cidr.Broadcast())
  164. IncrIP(network)
  165. }
  166. return cidrs, nil
  167. }