misc.go 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  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. "encoding/base32"
  18. "encoding/binary"
  19. "math/rand"
  20. "net"
  21. "sync"
  22. "time"
  23. "unsafe"
  24. )
  25. // LogoChar is the unicode character that is ZeroTier's logo
  26. const LogoChar = "⏁"
  27. // pointerSize is the size of a pointer on this system
  28. const pointerSize = unsafe.Sizeof(uintptr(0))
  29. // Base32Alphabet is the Base32 alphabet used in ZeroTier.
  30. const Base32Alphabet = "abcdefghijklmnopqrstuvwxyz234567"
  31. // Base32 is an encoder using the ZeroTier base32 encoding and no padding (same as core).
  32. var Base32 = base32.NewEncoding(Base32Alphabet).WithPadding(base32.NoPadding)
  33. // unassignedPrivilegedPorts are ports below 1024 that do not appear to be assigned by IANA.
  34. // The new 2.0+ ZeroTier default is 793, which we will eventually seek to have assigned. These
  35. // are searched as backups if this port is already in use on a system.
  36. var unassignedPrivilegedPorts = []int{
  37. 4,
  38. 6,
  39. 8,
  40. 10,
  41. 12,
  42. 14,
  43. 15,
  44. 16,
  45. 26,
  46. 28,
  47. 30,
  48. 32,
  49. 34,
  50. 36,
  51. 40,
  52. 60,
  53. 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279,
  54. 285,
  55. 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307,
  56. 323, 324, 325, 326, 327, 328, 329, 330, 331, 332,
  57. 334, 335, 336, 337, 338, 339, 340, 341, 342, 343,
  58. 703,
  59. 708,
  60. 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728,
  61. 732, 733, 734, 735, 736, 737, 738, 739, 740,
  62. 743,
  63. 745, 746,
  64. 755, 756,
  65. 766,
  66. 768,
  67. 778, 779,
  68. 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799,
  69. 802, 803, 804, 805, 806, 807, 808, 809,
  70. 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827,
  71. 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846,
  72. 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859,
  73. 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872,
  74. 874, 875, 876, 877, 878, 879, 880, 881, 882, 883, 884, 885,
  75. 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899,
  76. 904, 905, 906, 907, 908, 909, 910, 911,
  77. 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, 988,
  78. 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009,
  79. 1023,
  80. }
  81. var prng = rand.NewSource(time.Now().UnixNano())
  82. var prngLock sync.Mutex
  83. func randomUInt() uint {
  84. prngLock.Lock()
  85. i := prng.Int63()
  86. prngLock.Unlock()
  87. return uint(i)
  88. }
  89. // TimeMs returns the time in milliseconds since epoch.
  90. func TimeMs() int64 { return int64(time.Now().UnixNano()) / int64(1000000) }
  91. // ipNetToKey creates a key that can be used in a map[] from a net.IPNet
  92. func ipNetToKey(ipn *InetAddress) (k [3]uint64) {
  93. copy(((*[16]byte)(unsafe.Pointer(&k[0])))[:], ipn.IP)
  94. k[2] = uint64(ipn.Port)
  95. return
  96. }
  97. func allZero(b []byte) bool {
  98. for _, bb := range b {
  99. if bb != 0 {
  100. return false
  101. }
  102. }
  103. return true
  104. }
  105. // checkPort does trial binding to a port using both UDP and TCP and returns false if any bindings fail.
  106. func checkPort(port int) bool {
  107. var ua net.UDPAddr
  108. ua.IP = net.IPv6zero
  109. ua.Port = port
  110. uc, err := net.ListenUDP("udp6", &ua)
  111. if uc != nil {
  112. _ = uc.Close()
  113. }
  114. if err != nil {
  115. return false
  116. }
  117. ua.IP = net.IPv4zero
  118. uc, err = net.ListenUDP("udp4", &ua)
  119. if uc != nil {
  120. _ = uc.Close()
  121. }
  122. if err != nil {
  123. return false
  124. }
  125. var ta net.TCPAddr
  126. ta.IP = net.IPv6zero
  127. ta.Port = port
  128. tc, err := net.ListenTCP("tcp6", &ta)
  129. if tc != nil {
  130. _ = tc.Close()
  131. }
  132. if err != nil {
  133. return false
  134. }
  135. ta.IP = net.IPv4zero
  136. tc, err = net.ListenTCP("tcp4", &ta)
  137. if tc != nil {
  138. _ = tc.Close()
  139. }
  140. if err != nil {
  141. return false
  142. }
  143. return true
  144. }
  145. // The ipClassify code below is based on and should produce identical results to
  146. // InetAddress::ipScope() in the C++ code.
  147. const (
  148. ipClassificationNone = -1
  149. ipClassificationLoopback = 0
  150. ipClassificationPseudoprivate = 1
  151. ipClassificationPrivate = 2
  152. ipClassificationLinkLocal = 3
  153. ipClassificationMulticast = 4
  154. ipClassificationGlobal = 5
  155. )
  156. var ipv4PseudoprivatePrefixes = []byte{
  157. 0x06, // 6.0.0.0/8 (US Army)
  158. 0x0b, // 11.0.0.0/8 (US DoD)
  159. 0x15, // 21.0.0.0/8 (US DDN-RVN)
  160. 0x16, // 22.0.0.0/8 (US DISA)
  161. 0x19, // 25.0.0.0/8 (UK Ministry of Defense)
  162. 0x1a, // 26.0.0.0/8 (US DISA)
  163. 0x1c, // 28.0.0.0/8 (US DSI-North)
  164. 0x1d, // 29.0.0.0/8 (US DISA)
  165. 0x1e, // 30.0.0.0/8 (US DISA)
  166. 0x33, // 51.0.0.0/8 (UK Department of Social Security)
  167. 0x37, // 55.0.0.0/8 (US DoD)
  168. 0x38, // 56.0.0.0/8 (US Postal Service)
  169. }
  170. // ipClassify determines the official or in a few cases unofficial role of an IP address
  171. func ipClassify(ip net.IP) int {
  172. if len(ip) == 16 {
  173. ip4 := ip.To4()
  174. if len(ip4) == 4 {
  175. ip = ip4
  176. }
  177. }
  178. if len(ip) == 4 {
  179. ip4FirstByte := ip[0]
  180. for _, b := range ipv4PseudoprivatePrefixes {
  181. if ip4FirstByte == b {
  182. return ipClassificationPseudoprivate
  183. }
  184. }
  185. ip4 := binary.BigEndian.Uint32(ip)
  186. switch ip4FirstByte {
  187. case 0x0a: // 10.0.0.0/8
  188. return ipClassificationPrivate
  189. case 0x64: // 100.64.0.0/10
  190. if (ip4 & 0xffc00000) == 0x64400000 {
  191. return ipClassificationPrivate
  192. }
  193. case 0x7f: // 127.0.0.1/8
  194. return ipClassificationLoopback
  195. case 0xa9: // 169.254.0.0/16
  196. if (ip4 & 0xffff0000) == 0xa9fe0000 {
  197. return ipClassificationLinkLocal
  198. }
  199. case 0xac: // 172.16.0.0/12
  200. if (ip4 & 0xfff00000) == 0xac100000 {
  201. return ipClassificationPrivate
  202. }
  203. case 0xc0: // 192.168.0.0/16
  204. if (ip4 & 0xffff0000) == 0xc0a80000 {
  205. return ipClassificationPrivate
  206. }
  207. }
  208. switch ip4 >> 28 {
  209. case 0xe: // 224.0.0.0/4
  210. return ipClassificationMulticast
  211. case 0xf: // 240.0.0.0/4 ("reserved," usually unusable)
  212. return ipClassificationNone
  213. }
  214. return ipClassificationGlobal
  215. }
  216. if len(ip) == 16 {
  217. if (ip[0] & 0xf0) == 0xf0 {
  218. if ip[0] == 0xff { // ff00::/8
  219. return ipClassificationMulticast
  220. }
  221. if ip[0] == 0xfe && (ip[1]&0xc0) == 0x80 {
  222. if allZero(ip[2:15]) {
  223. if ip[15] == 0x01 { // fe80::1/128
  224. return ipClassificationLoopback
  225. }
  226. return ipClassificationLinkLocal
  227. }
  228. }
  229. if (ip[0] & 0xfe) == 0xfc { // fc00::/7
  230. return ipClassificationPrivate
  231. }
  232. }
  233. if allZero(ip[0:15]) {
  234. if ip[15] == 0x01 { // ::1/128
  235. return ipClassificationLoopback
  236. }
  237. if ip[15] == 0x00 { // ::/128
  238. return ipClassificationNone
  239. }
  240. }
  241. return ipClassificationGlobal
  242. }
  243. return ipClassificationNone
  244. }
  245. // stringAsZeroTerminatedBytes creates a C string but as a Go []byte
  246. func stringAsZeroTerminatedBytes(s string) (b []byte) {
  247. if len(s) == 0 {
  248. b = []byte{0} // single zero
  249. return
  250. }
  251. sb := []byte(s)
  252. b = make([]byte, len(sb) + 1)
  253. copy(b, sb)
  254. // make() will zero memory, so b[len(sb)+1] will be 0
  255. return
  256. }
  257. // cStrCopy copies src into dest as a zero-terminated C string
  258. func cStrCopy(dest unsafe.Pointer, destSize int, src string) {
  259. sb := []byte(src)
  260. if len(sb) > (destSize - 1) {
  261. sb = sb[0:destSize - 1]
  262. }
  263. dp := dest
  264. for _, c := range sb {
  265. *((*byte)(dp)) = c
  266. dp = unsafe.Pointer(uintptr(dp) + 1)
  267. }
  268. *((*byte)(dp)) = 0
  269. }
  270. // cStr returns an always zero-terminated byte array.
  271. // It's like C.CString but doesn't do a malloc or need a free.
  272. func cStr(s string) []byte {
  273. sb := []byte(s)
  274. if len(sb) > 0 {
  275. return append(append(make([]byte, 0, len(sb)+1), sb...), byte(0))
  276. } else {
  277. return []byte{0}
  278. }
  279. }