ipnet.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. package pkg
  2. import (
  3. "bytes"
  4. "errors"
  5. "fmt"
  6. "net"
  7. )
  8. type IP4 uint32
  9. func FromBytes(ip []byte) IP4 {
  10. if NativelyLittle() {
  11. return IP4(uint32(ip[3]) |
  12. (uint32(ip[2]) << 8) |
  13. (uint32(ip[1]) << 16) |
  14. (uint32(ip[0]) << 24))
  15. } else {
  16. return IP4(uint32(ip[0]) |
  17. (uint32(ip[1]) << 8) |
  18. (uint32(ip[2]) << 16) |
  19. (uint32(ip[3]) << 24))
  20. }
  21. }
  22. func FromIP(ip net.IP) IP4 {
  23. return FromBytes(ip.To4())
  24. }
  25. func ParseIP4(s string) (IP4, error) {
  26. ip := net.ParseIP(s)
  27. if ip == nil {
  28. return IP4(0), errors.New("Invalid IP address format")
  29. }
  30. return FromIP(ip), nil
  31. }
  32. func (ip IP4) Octets() (a, b, c, d byte) {
  33. if NativelyLittle() {
  34. a, b, c, d = byte(ip>>24), byte(ip>>16), byte(ip>>8), byte(ip)
  35. } else {
  36. a, b, c, d = byte(ip), byte(ip>>8), byte(ip>>16), byte(ip>>24)
  37. }
  38. return
  39. }
  40. func (ip IP4) ToIP() net.IP {
  41. return net.IPv4(ip.Octets())
  42. }
  43. func (ip IP4) String() string {
  44. return ip.ToIP().String()
  45. }
  46. func (ip IP4) StringSep(sep string) string {
  47. a, b, c, d := ip.Octets()
  48. return fmt.Sprintf("%d%s%d%s%d%s%d", a, sep, b, sep, c, sep, d)
  49. }
  50. // json.Marshaler impl
  51. func (ip IP4) MarshalJSON() ([]byte, error) {
  52. return []byte(fmt.Sprintf(`"%s"`, ip)), nil
  53. }
  54. // json.Unmarshaler impl
  55. func (ip *IP4) UnmarshalJSON(j []byte) error {
  56. j = bytes.Trim(j, "\"")
  57. if val, err := ParseIP4(string(j)); err != nil {
  58. return err
  59. } else {
  60. *ip = val
  61. return nil
  62. }
  63. }
  64. // similar to net.IPNet but has uint based representation
  65. type IP4Net struct {
  66. IP IP4
  67. PrefixLen uint
  68. }
  69. func (n IP4Net) String() string {
  70. return fmt.Sprintf("%s/%d", n.IP.String(), n.PrefixLen)
  71. }
  72. func (n IP4Net) StringSep(octetSep, prefixSep string) string {
  73. return fmt.Sprintf("%s%s%d", n.IP.StringSep(octetSep), prefixSep, n.PrefixLen)
  74. }
  75. func (n IP4Net) Network() IP4Net {
  76. return IP4Net{
  77. n.IP & IP4(n.Mask()),
  78. n.PrefixLen,
  79. }
  80. }
  81. func (n IP4Net) Next() IP4Net {
  82. return IP4Net{
  83. n.IP + (1 << (32 - n.PrefixLen)),
  84. n.PrefixLen,
  85. }
  86. }
  87. func FromIPNet(n *net.IPNet) IP4Net {
  88. prefixLen, _ := n.Mask.Size()
  89. return IP4Net{
  90. FromIP(n.IP),
  91. uint(prefixLen),
  92. }
  93. }
  94. func (n IP4Net) ToIPNet() *net.IPNet {
  95. return &net.IPNet{
  96. IP: n.IP.ToIP(),
  97. Mask: net.CIDRMask(int(n.PrefixLen), 32),
  98. }
  99. }
  100. func (n IP4Net) Overlaps(other IP4Net) bool {
  101. var mask uint32
  102. if n.PrefixLen < other.PrefixLen {
  103. mask = n.Mask()
  104. } else {
  105. mask = other.Mask()
  106. }
  107. return (uint32(n.IP) & mask) == (uint32(other.IP) & mask)
  108. }
  109. func (n IP4Net) Equal(other IP4Net) bool {
  110. return n.IP == other.IP && n.PrefixLen == other.PrefixLen
  111. }
  112. func (n IP4Net) Mask() uint32 {
  113. var ones uint32 = 0xFFFFFFFF
  114. return ones << (32 - n.PrefixLen)
  115. }
  116. func (n IP4Net) Contains(ip IP4) bool {
  117. return (uint32(n.IP) & n.Mask()) == (uint32(ip) & n.Mask())
  118. }
  119. // json.Marshaler impl
  120. func (n IP4Net) MarshalJSON() ([]byte, error) {
  121. return []byte(fmt.Sprintf(`"%s"`, n)), nil
  122. }
  123. // json.Unmarshaler impl
  124. func (n *IP4Net) UnmarshalJSON(j []byte) error {
  125. j = bytes.Trim(j, "\"")
  126. if _, val, err := net.ParseCIDR(string(j)); err != nil {
  127. fmt.Println(err)
  128. return err
  129. } else {
  130. *n = FromIPNet(val)
  131. return nil
  132. }
  133. }