inetaddress.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /*
  2. * Copyright (C)2013-2020 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: 2025-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. // #include "../../serviceiocore/GoGlue.h"
  15. import "C"
  16. import (
  17. "bytes"
  18. "encoding/binary"
  19. "encoding/json"
  20. "net"
  21. "strconv"
  22. "strings"
  23. "syscall"
  24. "unsafe"
  25. )
  26. func sockaddrStorageToIPNet(ss *C.struct_sockaddr_storage) *net.IPNet {
  27. var a net.IPNet
  28. switch ss.ss_family {
  29. case syscall.AF_INET:
  30. sa4 := (*C.struct_sockaddr_in)(unsafe.Pointer(ss))
  31. var ip4 [4]byte
  32. copy(ip4[:], (*[4]byte)(unsafe.Pointer(&sa4.sin_addr))[:])
  33. a.IP = ip4[:]
  34. a.Mask = net.CIDRMask(int(binary.BigEndian.Uint16(((*[2]byte)(unsafe.Pointer(&sa4.sin_port)))[:])), 32)
  35. return &a
  36. case syscall.AF_INET6:
  37. sa6 := (*C.struct_sockaddr_in6)(unsafe.Pointer(ss))
  38. var ip6 [16]byte
  39. copy(ip6[:], (*[16]byte)(unsafe.Pointer(&sa6.sin6_addr))[:])
  40. a.IP = ip6[:]
  41. a.Mask = net.CIDRMask(int(binary.BigEndian.Uint16(((*[2]byte)(unsafe.Pointer(&sa6.sin6_port)))[:])), 128)
  42. return &a
  43. }
  44. return nil
  45. }
  46. func sockaddrStorageToUDPAddr(ss *C.struct_sockaddr_storage) *net.UDPAddr {
  47. var a net.UDPAddr
  48. switch ss.ss_family {
  49. case syscall.AF_INET:
  50. sa4 := (*C.struct_sockaddr_in)(unsafe.Pointer(ss))
  51. var ip4 [4]byte
  52. copy(ip4[:], (*[4]byte)(unsafe.Pointer(&sa4.sin_addr))[:])
  53. a.IP = ip4[:]
  54. a.Port = int(binary.BigEndian.Uint16(((*[2]byte)(unsafe.Pointer(&sa4.sin_port)))[:]))
  55. return &a
  56. case syscall.AF_INET6:
  57. sa6 := (*C.struct_sockaddr_in6)(unsafe.Pointer(ss))
  58. var ip6 [16]byte
  59. copy(ip6[:], (*[16]byte)(unsafe.Pointer(&sa6.sin6_addr))[:])
  60. a.IP = ip6[:]
  61. a.Port = int(binary.BigEndian.Uint16(((*[2]byte)(unsafe.Pointer(&sa6.sin6_port)))[:]))
  62. return &a
  63. }
  64. return nil
  65. }
  66. func sockaddrStorageToUDPAddr2(ss unsafe.Pointer) *net.UDPAddr {
  67. return sockaddrStorageToUDPAddr((*C.struct_sockaddr_storage)(ss))
  68. }
  69. func zeroSockaddrStorage(ss *C.struct_sockaddr_storage) {
  70. C.memset(unsafe.Pointer(ss), 0, C.sizeof_struct_sockaddr_storage)
  71. }
  72. func makeSockaddrStorage(ip net.IP, port int, ss *C.struct_sockaddr_storage) bool {
  73. zeroSockaddrStorage(ss)
  74. if len(ip) == 4 {
  75. sa4 := (*C.struct_sockaddr_in)(unsafe.Pointer(ss))
  76. sa4.sin_family = syscall.AF_INET
  77. copy(((*[4]byte)(unsafe.Pointer(&sa4.sin_addr)))[:], ip)
  78. binary.BigEndian.PutUint16(((*[2]byte)(unsafe.Pointer(&sa4.sin_port)))[:], uint16(port))
  79. return true
  80. }
  81. if len(ip) == 16 {
  82. sa6 := (*C.struct_sockaddr_in6)(unsafe.Pointer(ss))
  83. sa6.sin6_family = syscall.AF_INET6
  84. copy(((*[16]byte)(unsafe.Pointer(&sa6.sin6_addr)))[:], ip)
  85. binary.BigEndian.PutUint16(((*[2]byte)(unsafe.Pointer(&sa6.sin6_port)))[:], uint16(port))
  86. return true
  87. }
  88. return false
  89. }
  90. // InetAddress implements net.Addr but has a ZeroTier-like string representation
  91. type InetAddress struct {
  92. IP net.IP
  93. Port int
  94. }
  95. // Nil returns true if this InetAddress is empty.
  96. func (ina *InetAddress) Nil() bool {
  97. return len(ina.IP) == 0
  98. }
  99. // Less returns true if this IP/port is lexicographically less than another
  100. func (ina *InetAddress) Less(i2 *InetAddress) bool {
  101. c := bytes.Compare(ina.IP, i2.IP)
  102. if c < 0 {
  103. return true
  104. }
  105. if c == 0 {
  106. return ina.Port < i2.Port
  107. }
  108. return false
  109. }
  110. // NewInetAddressFromString parses an IP[/port] format address
  111. func NewInetAddressFromString(s string) *InetAddress {
  112. i := new(InetAddress)
  113. ss := strings.Split(strings.TrimSpace(s), "/")
  114. if len(ss) > 0 {
  115. i.IP = net.ParseIP(ss[0])
  116. i4 := i.IP.To4()
  117. if len(i4) == 4 { // down-convert IPv4-in-6 IPs to native IPv4 as this is what all our code expects
  118. i.IP = i4
  119. }
  120. if len(ss) > 1 {
  121. p64, _ := strconv.ParseUint(ss[1], 10, 64)
  122. i.Port = int(p64 & 0xffff)
  123. }
  124. }
  125. return i
  126. }
  127. // NewInetAddressFromSockaddr parses a sockaddr_in or sockaddr_in6 C structure (may crash if given something other than these!)
  128. // This is a convenience wrapper around the CGO functions in node.go.
  129. func NewInetAddressFromSockaddr(sa unsafe.Pointer) *InetAddress {
  130. i := new(InetAddress)
  131. if uintptr(sa) != 0 {
  132. ua := sockaddrStorageToUDPAddr2(sa)
  133. if ua != nil {
  134. i.IP = ua.IP
  135. i.Port = ua.Port
  136. }
  137. }
  138. return i
  139. }
  140. // Network returns "udp" to implement net.Addr
  141. func (ina *InetAddress) Network() string {
  142. return "udp"
  143. }
  144. // String returns this address in ZeroTier-canonical IP/port format
  145. func (ina *InetAddress) String() string {
  146. return ina.IP.String() + "/" + strconv.FormatInt(int64(ina.Port), 10)
  147. }
  148. // Family returns the address family (AFInet etc.) or 0 if none
  149. func (ina *InetAddress) Family() int {
  150. switch len(ina.IP) {
  151. case 4:
  152. return syscall.AF_INET
  153. case 16:
  154. return syscall.AF_INET6
  155. }
  156. return 0
  157. }
  158. // Valid returns true if both the IP and port have valid values
  159. func (ina *InetAddress) Valid() bool {
  160. return (len(ina.IP) == 4 || len(ina.IP) == 16) && (ina.Port > 0 && ina.Port < 65536)
  161. }
  162. // MarshalJSON marshals this MAC as a string
  163. func (ina *InetAddress) MarshalJSON() ([]byte, error) {
  164. s := ina.String()
  165. return json.Marshal(&s)
  166. }
  167. // UnmarshalJSON unmarshals this MAC from a string
  168. func (ina *InetAddress) UnmarshalJSON(j []byte) error {
  169. var s string
  170. err := json.Unmarshal(j, &s)
  171. if err != nil {
  172. return err
  173. }
  174. *ina = *NewInetAddressFromString(s)
  175. return nil
  176. }
  177. // key returns a short array suitable for use as a map[] key for this IP
  178. func (ina *InetAddress) key() (k [3]uint64) {
  179. copy(((*[16]byte)(unsafe.Pointer(&k[0])))[:], ina.IP)
  180. k[2] = uint64(ina.Port)
  181. return
  182. }