inetaddress.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. /*
  2. * Copyright (c)2019 ZeroTier, Inc.
  3. *
  4. * Use of this software is governed by the Business Source License included
  5. * in the LICENSE.TXT file in the project's root directory.
  6. *
  7. * Change Date: 2023-01-01
  8. *
  9. * On the date above, in accordance with the Business Source License, use
  10. * of this software will be governed by version 2.0 of the Apache License.
  11. */
  12. /****/
  13. package zerotier
  14. import (
  15. "bytes"
  16. "encoding/json"
  17. "net"
  18. "strconv"
  19. "strings"
  20. "unsafe"
  21. )
  22. // InetAddress implements net.Addr but has a ZeroTier-like string representation
  23. type InetAddress struct {
  24. IP net.IP
  25. Port int
  26. }
  27. // Less returns true if this IP/port is lexicographically less than another
  28. func (i *InetAddress) Less(i2 *InetAddress) bool {
  29. c := bytes.Compare(i.IP, i2.IP)
  30. if c < 0 {
  31. return true
  32. }
  33. if c == 0 {
  34. return i.Port < i2.Port
  35. }
  36. return false
  37. }
  38. // NewInetAddressFromString parses an IP[/port] format address
  39. func NewInetAddressFromString(s string) *InetAddress {
  40. i := new(InetAddress)
  41. ss := strings.Split(strings.TrimSpace(s), "/")
  42. if len(ss) > 0 {
  43. i.IP = net.ParseIP(ss[0])
  44. i4 := i.IP.To4()
  45. if len(i4) == 4 { // down-convert IPv4-in-6 IPs to native IPv4 as this is what all our code expects
  46. i.IP = i4
  47. }
  48. if len(ss) > 1 {
  49. p64, _ := strconv.ParseUint(ss[1], 10, 64)
  50. i.Port = int(p64 & 0xffff)
  51. }
  52. }
  53. return i
  54. }
  55. // NewInetAddressFromSockaddr parses a sockaddr_in or sockaddr_in6 C structure (may crash if given something other than these!)
  56. // This is a convenience wrapper around the CGO functions in node.go.
  57. func NewInetAddressFromSockaddr(sa unsafe.Pointer) *InetAddress {
  58. i := new(InetAddress)
  59. if uintptr(sa) != 0 {
  60. ua := sockaddrStorageToUDPAddr2(sa)
  61. if ua != nil {
  62. i.IP = ua.IP
  63. i.Port = ua.Port
  64. }
  65. }
  66. return i
  67. }
  68. // Network returns "udp" to implement net.Addr
  69. func (i *InetAddress) Network() string {
  70. return "udp"
  71. }
  72. // String returns this address in ZeroTier-canonical IP/port format
  73. func (i *InetAddress) String() string {
  74. return i.IP.String() + "/" + strconv.FormatInt(int64(i.Port), 10)
  75. }
  76. // Family returns the address family (AFInet etc.) or 0 if none
  77. func (i *InetAddress) Family() int {
  78. switch len(i.IP) {
  79. case 4:
  80. return AFInet
  81. case 16:
  82. return AFInet6
  83. }
  84. return 0
  85. }
  86. // Valid returns true if both the IP and port have valid values
  87. func (i *InetAddress) Valid() bool {
  88. return (len(i.IP) == 4 || len(i.IP) == 16) && (i.Port > 0 && i.Port < 65536)
  89. }
  90. // MarshalJSON marshals this MAC as a string
  91. func (i *InetAddress) MarshalJSON() ([]byte, error) {
  92. s := i.String()
  93. return json.Marshal(&s)
  94. }
  95. // UnmarshalJSON unmarshals this MAC from a string
  96. func (i *InetAddress) UnmarshalJSON(j []byte) error {
  97. var s string
  98. err := json.Unmarshal(j, &s)
  99. if err != nil {
  100. return err
  101. }
  102. *i = *NewInetAddressFromString(s)
  103. return nil
  104. }
  105. // key returns a short array suitable for use as a map[] key for this IP
  106. func (i *InetAddress) key() (k [3]uint64) {
  107. copy(((*[16]byte)(unsafe.Pointer(&k[0])))[:], i.IP)
  108. k[2] = uint64(i.Port)
  109. return
  110. }