util.go 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. package iputil
  2. import (
  3. "encoding/binary"
  4. "fmt"
  5. "net"
  6. "net/netip"
  7. )
  8. type VpnIp uint32
  9. const maxIPv4StringLen = len("255.255.255.255")
  10. func (ip VpnIp) String() string {
  11. b := make([]byte, maxIPv4StringLen)
  12. n := ubtoa(b, 0, byte(ip>>24))
  13. b[n] = '.'
  14. n++
  15. n += ubtoa(b, n, byte(ip>>16&255))
  16. b[n] = '.'
  17. n++
  18. n += ubtoa(b, n, byte(ip>>8&255))
  19. b[n] = '.'
  20. n++
  21. n += ubtoa(b, n, byte(ip&255))
  22. return string(b[:n])
  23. }
  24. func (ip VpnIp) MarshalJSON() ([]byte, error) {
  25. return []byte(fmt.Sprintf("\"%s\"", ip.String())), nil
  26. }
  27. func (ip VpnIp) ToIP() net.IP {
  28. nip := make(net.IP, 4)
  29. binary.BigEndian.PutUint32(nip, uint32(ip))
  30. return nip
  31. }
  32. func (ip VpnIp) ToNetIpAddr() netip.Addr {
  33. var nip [4]byte
  34. binary.BigEndian.PutUint32(nip[:], uint32(ip))
  35. return netip.AddrFrom4(nip)
  36. }
  37. func Ip2VpnIp(ip []byte) VpnIp {
  38. if len(ip) == 16 {
  39. return VpnIp(binary.BigEndian.Uint32(ip[12:16]))
  40. }
  41. return VpnIp(binary.BigEndian.Uint32(ip))
  42. }
  43. func ToNetIpAddr(ip net.IP) (netip.Addr, error) {
  44. addr, ok := netip.AddrFromSlice(ip)
  45. if !ok {
  46. return netip.Addr{}, fmt.Errorf("invalid net.IP: %v", ip)
  47. }
  48. return addr, nil
  49. }
  50. func ToNetIpPrefix(ipNet net.IPNet) (netip.Prefix, error) {
  51. addr, err := ToNetIpAddr(ipNet.IP)
  52. if err != nil {
  53. return netip.Prefix{}, err
  54. }
  55. ones, bits := ipNet.Mask.Size()
  56. if ones == 0 && bits == 0 {
  57. return netip.Prefix{}, fmt.Errorf("invalid net.IP: %v", ipNet)
  58. }
  59. return netip.PrefixFrom(addr, ones), nil
  60. }
  61. // ubtoa encodes the string form of the integer v to dst[start:] and
  62. // returns the number of bytes written to dst. The caller must ensure
  63. // that dst has sufficient length.
  64. func ubtoa(dst []byte, start int, v byte) int {
  65. if v < 10 {
  66. dst[start] = v + '0'
  67. return 1
  68. } else if v < 100 {
  69. dst[start+1] = v%10 + '0'
  70. dst[start] = v/10 + '0'
  71. return 2
  72. }
  73. dst[start+2] = v%10 + '0'
  74. dst[start+1] = (v/10)%10 + '0'
  75. dst[start] = v/100 + '0'
  76. return 3
  77. }