Endpoint.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  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: 2024-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. namespace ZeroTier {
  15. Endpoint::Endpoint(const InetAddress &sa,const Protocol proto) noexcept
  16. {
  17. switch (sa.family()) {
  18. case AF_INET:
  19. _t = TYPE_INETADDR_V4;
  20. break;
  21. case AF_INET6:
  22. _t = TYPE_INETADDR_V6;
  23. default:
  24. _t = TYPE_NIL;
  25. return;
  26. }
  27. asInetAddress(_v.in.sa) = sa;
  28. _v.in.proto = (uint8_t)proto;
  29. }
  30. bool Endpoint::operator==(const Endpoint &ep) const noexcept
  31. {
  32. if (_t == ep._t) {
  33. switch(_t) {
  34. default: return true;
  35. case TYPE_ZEROTIER: return ((_v.zt.address == ep._v.zt.address)&&(memcmp(_v.zt.hash,ep._v.zt.hash,sizeof(_v.zt.hash)) == 0));
  36. case TYPE_DNSNAME: return ((_v.dns.port == ep._v.dns.port)&&(strcmp(_v.dns.name,ep._v.dns.name) == 0));
  37. case TYPE_URL: return (strcmp(_v.url,ep._v.url) == 0);
  38. case TYPE_ETHERNET: return (_v.eth == ep._v.eth);
  39. case TYPE_INETADDR_V4:
  40. case TYPE_INETADDR_V6: return ((asInetAddress(_v.in.sa) == asInetAddress(ep._v.in.sa))&&(_v.in.proto == ep._v.in.proto));
  41. }
  42. }
  43. return false;
  44. }
  45. bool Endpoint::operator<(const Endpoint &ep) const noexcept
  46. {
  47. if ((int)_t < (int)ep._t) {
  48. return true;
  49. } else if (_t == ep._t) {
  50. int ncmp;
  51. switch(_t) {
  52. case TYPE_ZEROTIER: return (_v.zt.address < ep._v.zt.address) ? true : ((_v.zt.address == ep._v.zt.address)&&(memcmp(_v.zt.hash,ep._v.zt.hash,sizeof(_v.zt.hash)) < 0));
  53. case TYPE_DNSNAME:
  54. ncmp = strcmp(_v.dns.name,ep._v.dns.name);
  55. return ((ncmp < 0) ? true : (ncmp == 0)&&(_v.dns.port < ep._v.dns.port));
  56. case TYPE_URL: return (strcmp(_v.url,ep._v.url) < 0);
  57. case TYPE_ETHERNET: return (_v.eth < ep._v.eth);
  58. case TYPE_INETADDR_V4:
  59. case TYPE_INETADDR_V6: return ((_v.in.proto < ep._v.in.proto)||((_v.in.proto == ep._v.in.proto)&&(asInetAddress(_v.in.sa) < asInetAddress(ep._v.in.sa))));
  60. default: return false;
  61. }
  62. }
  63. return false;
  64. }
  65. int Endpoint::marshal(uint8_t data[ZT_ENDPOINT_MARSHAL_SIZE_MAX]) const noexcept
  66. {
  67. int p;
  68. data[0] = (uint8_t)_t;
  69. Utils::storeBigEndian(data + 1,(uint16_t)_l[0]);
  70. Utils::storeBigEndian(data + 3,(uint16_t)_l[1]);
  71. Utils::storeBigEndian(data + 5,(uint16_t)_l[2]);
  72. switch(_t) {
  73. case TYPE_ZEROTIER:
  74. data[7] = (uint8_t)(_v.zt.address >> 32U);
  75. data[8] = (uint8_t)(_v.zt.address >> 24U);
  76. data[9] = (uint8_t)(_v.zt.address >> 16U);
  77. data[10] = (uint8_t)(_v.zt.address >> 8U);
  78. data[11] = (uint8_t)_v.zt.address;
  79. memcpy(data + 12,_v.zt.hash,ZT_IDENTITY_HASH_SIZE);
  80. return ZT_IDENTITY_HASH_SIZE + 12;
  81. case TYPE_DNSNAME:
  82. p = 7;
  83. for (;;) {
  84. if ((data[p] = (uint8_t)_v.dns.name[p-1]) == 0)
  85. break;
  86. ++p;
  87. if (p == (ZT_ENDPOINT_MAX_NAME_SIZE+1))
  88. return -1;
  89. }
  90. data[p++] = (uint8_t)(_v.dns.port >> 8U);
  91. data[p++] = (uint8_t)_v.dns.port;
  92. return p;
  93. case TYPE_URL:
  94. p = 7;
  95. for (;;) {
  96. if ((data[p] = (uint8_t)_v.url[p-1]) == 0)
  97. break;
  98. ++p;
  99. if (p == (ZT_ENDPOINT_MAX_NAME_SIZE+1))
  100. return -1;
  101. }
  102. return p;
  103. case TYPE_ETHERNET:
  104. data[7] = (uint8_t)(_v.eth >> 40U);
  105. data[8] = (uint8_t)(_v.eth >> 32U);
  106. data[9] = (uint8_t)(_v.eth >> 24U);
  107. data[10] = (uint8_t)(_v.eth >> 16U);
  108. data[11] = (uint8_t)(_v.eth >> 8U);
  109. data[12] = (uint8_t)_v.eth;
  110. return 13;
  111. case TYPE_INETADDR_V4:
  112. case TYPE_INETADDR_V6:
  113. p = 7 + asInetAddress(_v.in.sa).marshal(data + 7);
  114. if (p <= 7)
  115. return -1;
  116. data[p++] = _v.in.proto;
  117. return p;
  118. default:
  119. data[0] = (uint8_t)TYPE_NIL;
  120. return 7;
  121. }
  122. }
  123. int Endpoint::unmarshal(const uint8_t *restrict data,const int len) noexcept
  124. {
  125. if (len < 7)
  126. return -1;
  127. int p;
  128. _t = (Type)data[0];
  129. _l[0] = (int)Utils::loadBigEndian<uint16_t>(data + 1);
  130. _l[1] = (int)Utils::loadBigEndian<uint16_t>(data + 3);
  131. _l[2] = (int)Utils::loadBigEndian<uint16_t>(data + 5);
  132. switch(_t) {
  133. case TYPE_NIL:
  134. return 7;
  135. case TYPE_ZEROTIER:
  136. if (len < (12 + ZT_IDENTITY_HASH_SIZE))
  137. return -1;
  138. _v.zt.address = ((uint64_t)data[7]) << 32U;
  139. _v.zt.address |= ((uint64_t)data[8]) << 24U;
  140. _v.zt.address |= ((uint64_t)data[9]) << 16U;
  141. _v.zt.address |= ((uint64_t)data[10]) << 8U;
  142. _v.zt.address |= (uint64_t)data[11];
  143. memcpy(_v.zt.hash,data + 12,ZT_IDENTITY_HASH_SIZE);
  144. return 60;
  145. case TYPE_DNSNAME:
  146. if (len < 10)
  147. return -1;
  148. p = 7;
  149. for (;;) {
  150. if ((_v.dns.name[p-1] = (char)data[p]) == 0) {
  151. ++p;
  152. break;
  153. }
  154. ++p;
  155. if ((p >= (ZT_ENDPOINT_MARSHAL_SIZE_MAX-2))||(p >= (len-2)))
  156. return -1;
  157. }
  158. _v.dns.port = (uint16_t)(((unsigned int)data[p++]) << 8U);
  159. _v.dns.port |= (uint16_t)data[p++];
  160. return p;
  161. case TYPE_URL:
  162. if (len < 8)
  163. return -1;
  164. p = 7;
  165. for (;;) {
  166. if ((_v.url[p-1] = (char)data[p]) == 0) {
  167. ++p;
  168. break;
  169. }
  170. ++p;
  171. if ((p >= (ZT_ENDPOINT_MAX_NAME_SIZE+1))||(p >= len))
  172. return -1;
  173. }
  174. return p;
  175. case TYPE_ETHERNET:
  176. if (len < 13)
  177. return -1;
  178. _v.eth = ((uint64_t)data[7]) << 40U;
  179. _v.eth |= ((uint64_t)data[8]) << 32U;
  180. _v.eth |= ((uint64_t)data[9]) << 24U;
  181. _v.eth |= ((uint64_t)data[10]) << 16U;
  182. _v.eth |= ((uint64_t)data[11]) << 8U;
  183. _v.eth |= (uint64_t)data[12];
  184. return 13;
  185. case TYPE_INETADDR_V4:
  186. case TYPE_INETADDR_V6:
  187. p = 7 + asInetAddress(_v.in.sa).unmarshal(data + 7,len - 7);
  188. if ((p <= 7)||(p >= len))
  189. return -1;
  190. _v.in.proto = data[p++];
  191. return p;
  192. default:
  193. // Unrecognized endpoint types not yet specified must start with a 16-bit
  194. // length so that older versions of ZeroTier can skip them.
  195. if (len < 9)
  196. return -1;
  197. p = 9 + (int)Utils::loadBigEndian<uint16_t>(data + 7);
  198. return (p > len) ? -1 : p;
  199. }
  200. }
  201. } // namespace ZeroTier