Endpoint.cpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  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. #include "Endpoint.hpp"
  14. #include "Utils.hpp"
  15. namespace ZeroTier {
  16. char *Endpoint::toString(char s[ZT_ENDPOINT_STRING_SIZE_MAX]) const noexcept
  17. {
  18. static const char *const s_endpointTypeChars = "0123456789";
  19. static_assert(ZT_ENDPOINT_STRING_SIZE_MAX > (ZT_INETADDRESS_STRING_SIZE_MAX + 4), "overflow");
  20. static_assert(ZT_ENDPOINT_STRING_SIZE_MAX > (ZT_FINGERPRINT_STRING_SIZE_MAX + 4), "overflow");
  21. switch (this->type) {
  22. default: // ZT_ENDPOINT_TYPE_NIL
  23. s[0] = s_endpointTypeChars[ZT_ENDPOINT_TYPE_NIL];
  24. s[1] = 0;
  25. break;
  26. case ZT_ENDPOINT_TYPE_ZEROTIER:
  27. s[0] = s_endpointTypeChars[ZT_ENDPOINT_TYPE_ZEROTIER];
  28. s[1] = '/';
  29. zt().toString(s + 2);
  30. break;
  31. case ZT_ENDPOINT_TYPE_ETHERNET:
  32. case ZT_ENDPOINT_TYPE_WIFI_DIRECT:
  33. case ZT_ENDPOINT_TYPE_BLUETOOTH:
  34. s[0] = s_endpointTypeChars[this->type];
  35. s[1] = '/';
  36. eth().toString(s + 2);
  37. break;
  38. case ZT_ENDPOINT_TYPE_IP:
  39. case ZT_ENDPOINT_TYPE_IP_UDP:
  40. case ZT_ENDPOINT_TYPE_IP_TCP:
  41. case ZT_ENDPOINT_TYPE_IP_HTTP:
  42. s[0] = s_endpointTypeChars[this->type];
  43. s[1] = '/';
  44. ip().toString(s + 2);
  45. break;
  46. }
  47. return s;
  48. }
  49. bool Endpoint::fromString(const char *s) noexcept
  50. {
  51. memoryZero(this);
  52. if ((!s) || (!*s))
  53. return true;
  54. // Locate first slash, colon, and dot to help classify input.
  55. const char *slash = nullptr, *colon = nullptr, *dot = nullptr;
  56. for(const char *p=s;;++p) {
  57. const char c = *p;
  58. if (c != 0) {
  59. switch (c) {
  60. case '/':
  61. slash = p;
  62. break;
  63. case ':':
  64. colon = p;
  65. break;
  66. case '.':
  67. dot = p;
  68. break;
  69. }
  70. } else break;
  71. }
  72. if ((slash != nullptr) && (((colon == nullptr) && (dot == nullptr)) || (colon > slash) || (dot > slash))) {
  73. // Detect a fully specified endpoint of the form type/ip/port or type/other,
  74. // but don't detect ip/port as a fully specified endpoint.
  75. char tmp[16];
  76. for (unsigned int i=0;i<16;++i) {
  77. const char ss = s[i];
  78. if (ss == '/') {
  79. tmp[i] = 0;
  80. break;
  81. }
  82. tmp[i] = ss;
  83. }
  84. tmp[15] = 0;
  85. this->type = (ZT_EndpointType)Utils::strToUInt(tmp);
  86. ++slash;
  87. switch (this->type) {
  88. case ZT_ENDPOINT_TYPE_NIL:
  89. break;
  90. case ZT_ENDPOINT_TYPE_ZEROTIER: {
  91. Fingerprint tmpfp;
  92. if (!tmpfp.fromString(slash))
  93. return false;
  94. this->value.fp = tmpfp;
  95. } break;
  96. case ZT_ENDPOINT_TYPE_ETHERNET:
  97. case ZT_ENDPOINT_TYPE_WIFI_DIRECT:
  98. case ZT_ENDPOINT_TYPE_BLUETOOTH: {
  99. MAC tmpmac;
  100. tmpmac.fromString(slash);
  101. this->value.mac = tmpmac.toInt();
  102. } break;
  103. case ZT_ENDPOINT_TYPE_IP:
  104. case ZT_ENDPOINT_TYPE_IP_UDP:
  105. case ZT_ENDPOINT_TYPE_IP_TCP:
  106. case ZT_ENDPOINT_TYPE_IP_HTTP:
  107. if (!asInetAddress(this->value.ss).fromString(slash))
  108. return false;
  109. default:
  110. return false;
  111. }
  112. } else if (((colon != nullptr) || (dot != nullptr)) && (slash != nullptr)) {
  113. // Parse raw IP/port strings as IP_UDP endpoints.
  114. this->type = ZT_ENDPOINT_TYPE_IP_UDP;
  115. if (!asInetAddress(this->value.ss).fromString(s))
  116. return false;
  117. } else {
  118. // A naked '0' can be a NIL endpoint.
  119. if (Utils::strToUInt(s) != (unsigned int)ZT_ENDPOINT_TYPE_NIL)
  120. return false;
  121. }
  122. return true;
  123. }
  124. int Endpoint::marshal(uint8_t data[ZT_ENDPOINT_MARSHAL_SIZE_MAX]) const noexcept
  125. {
  126. switch (this->type) {
  127. default: // ZT_ENDPOINT_TYPE_NIL
  128. // NIL endpoints get serialized like NIL InetAddress instances.
  129. data[0] = ZT_ENDPOINT_TYPE_NIL;
  130. return 1;
  131. case ZT_ENDPOINT_TYPE_ZEROTIER:
  132. data[0] = 16 + ZT_ENDPOINT_TYPE_ZEROTIER;
  133. Address(this->value.fp.address).copyTo(data + 1);
  134. Utils::copy<ZT_FINGERPRINT_HASH_SIZE>(data + 1 + ZT_ADDRESS_LENGTH, this->value.fp.hash);
  135. return 1 + ZT_ADDRESS_LENGTH + ZT_FINGERPRINT_HASH_SIZE;
  136. case ZT_ENDPOINT_TYPE_ETHERNET:
  137. case ZT_ENDPOINT_TYPE_WIFI_DIRECT:
  138. case ZT_ENDPOINT_TYPE_BLUETOOTH:
  139. data[0] = 16 + (uint8_t)this->type;
  140. MAC(this->value.mac).copyTo(data + 1);
  141. return 7;
  142. case ZT_ENDPOINT_TYPE_IP_UDP:
  143. // Default UDP mode gets serialized to look exactly like an InetAddress.
  144. return asInetAddress(this->value.ss).marshal(data);
  145. case ZT_ENDPOINT_TYPE_IP:
  146. case ZT_ENDPOINT_TYPE_IP_TCP:
  147. case ZT_ENDPOINT_TYPE_IP_HTTP:
  148. // Other IP types get serialized as new version Endpoint instances with type.
  149. data[0] = 16 + (uint8_t)this->type;
  150. return 1 + asInetAddress(this->value.ss).marshal(data + 1);
  151. }
  152. }
  153. int Endpoint::unmarshal(const uint8_t *restrict data, int len) noexcept
  154. {
  155. memoryZero(this);
  156. if (unlikely(len <= 0))
  157. return -1;
  158. // Serialized endpoints with type bytes less than 16 are passed through
  159. // to the unmarshal method of InetAddress and considered UDP endpoints.
  160. // This allows backward compatibility with old endpoint fields in the
  161. // protocol that were serialized InetAddress instances.
  162. if (data[0] < 16) {
  163. switch (data[0]) {
  164. case 0:
  165. return 1;
  166. case 4:
  167. case 6:
  168. this->type = ZT_ENDPOINT_TYPE_IP_UDP;
  169. return asInetAddress(this->value.ss).unmarshal(data, len);
  170. }
  171. return -1;
  172. }
  173. switch ((this->type = (ZT_EndpointType)(data[0] - 16))) {
  174. case ZT_ENDPOINT_TYPE_NIL:
  175. return 1;
  176. case ZT_ENDPOINT_TYPE_ZEROTIER:
  177. if (len >= (1 + ZT_ADDRESS_LENGTH + ZT_FINGERPRINT_HASH_SIZE)) {
  178. this->value.fp.address = Address(data + 1).toInt();
  179. Utils::copy<ZT_FINGERPRINT_HASH_SIZE>(this->value.fp.hash, data + 1 + ZT_ADDRESS_LENGTH);
  180. return 1 + ZT_ADDRESS_LENGTH + ZT_FINGERPRINT_HASH_SIZE;
  181. }
  182. return -1;
  183. case ZT_ENDPOINT_TYPE_ETHERNET:
  184. case ZT_ENDPOINT_TYPE_WIFI_DIRECT:
  185. case ZT_ENDPOINT_TYPE_BLUETOOTH:
  186. if (len >= 7) {
  187. MAC tmp;
  188. tmp.setTo(data + 1);
  189. this->value.mac = tmp.toInt();
  190. return 7;
  191. }
  192. return -1;
  193. case ZT_ENDPOINT_TYPE_IP:
  194. case ZT_ENDPOINT_TYPE_IP_UDP:
  195. case ZT_ENDPOINT_TYPE_IP_TCP:
  196. case ZT_ENDPOINT_TYPE_IP_HTTP:
  197. return asInetAddress(this->value.ss).unmarshal(data + 1, len - 1);
  198. default:
  199. break;
  200. }
  201. // Unrecognized types can still be passed over in a valid stream if they are
  202. // prefixed by a 16-bit size. This allows forward compatibility with future
  203. // endpoint types.
  204. this->type = ZT_ENDPOINT_TYPE_NIL;
  205. if (len < 3)
  206. return -1;
  207. const int unrecLen = 1 + (int) Utils::loadBigEndian<uint16_t>(data + 1);
  208. return (unrecLen > len) ? -1 : unrecLen;
  209. }
  210. bool Endpoint::operator==(const Endpoint &ep) const noexcept
  211. {
  212. if (this->type == ep.type) {
  213. switch(this->type) {
  214. case ZT_ENDPOINT_TYPE_ZEROTIER:
  215. return zt() == ep.zt();
  216. case ZT_ENDPOINT_TYPE_ETHERNET:
  217. case ZT_ENDPOINT_TYPE_WIFI_DIRECT:
  218. case ZT_ENDPOINT_TYPE_BLUETOOTH:
  219. return this->value.mac == ep.value.mac;
  220. case ZT_ENDPOINT_TYPE_IP:
  221. case ZT_ENDPOINT_TYPE_IP_UDP:
  222. case ZT_ENDPOINT_TYPE_IP_TCP:
  223. case ZT_ENDPOINT_TYPE_IP_HTTP:
  224. return ip() == ep.ip();
  225. default:
  226. return true;
  227. }
  228. }
  229. return false;
  230. }
  231. bool Endpoint::operator<(const Endpoint &ep) const noexcept
  232. {
  233. if (this->type == ep.type) {
  234. switch(this->type) {
  235. case ZT_ENDPOINT_TYPE_ZEROTIER:
  236. return zt() < ep.zt();
  237. case ZT_ENDPOINT_TYPE_ETHERNET:
  238. case ZT_ENDPOINT_TYPE_WIFI_DIRECT:
  239. case ZT_ENDPOINT_TYPE_BLUETOOTH:
  240. return this->value.mac < ep.value.mac;
  241. case ZT_ENDPOINT_TYPE_IP:
  242. case ZT_ENDPOINT_TYPE_IP_UDP:
  243. case ZT_ENDPOINT_TYPE_IP_TCP:
  244. case ZT_ENDPOINT_TYPE_IP_HTTP:
  245. return ip() < ep.ip();
  246. default:
  247. return true;
  248. }
  249. }
  250. return (int)this->type < (int)ep.type;
  251. }
  252. } // namespace ZeroTier