Topology.hpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  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. #ifndef ZT_TOPOLOGY_HPP
  14. #define ZT_TOPOLOGY_HPP
  15. #include "Constants.hpp"
  16. #include "Address.hpp"
  17. #include "Identity.hpp"
  18. #include "Peer.hpp"
  19. #include "Path.hpp"
  20. #include "Mutex.hpp"
  21. #include "InetAddress.hpp"
  22. #include "SharedPtr.hpp"
  23. #include "ScopedPtr.hpp"
  24. #include "Fingerprint.hpp"
  25. #include "Blob.hpp"
  26. #include "FCV.hpp"
  27. #include "Certificate.hpp"
  28. #include "Containers.hpp"
  29. namespace ZeroTier {
  30. class RuntimeEnvironment;
  31. /**
  32. * Database of network topology
  33. */
  34. class Topology
  35. {
  36. public:
  37. Topology(const RuntimeEnvironment *renv, void *tPtr, int64_t now);
  38. /**
  39. * Add peer to database
  40. *
  41. * This will not replace existing peers. In that case the existing peer
  42. * record is returned.
  43. *
  44. * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
  45. * @param peer Peer to add
  46. * @return New or existing peer (should replace 'peer')
  47. */
  48. SharedPtr< Peer > add(void *tPtr, const SharedPtr< Peer > &peer);
  49. /**
  50. * Get a peer from its address
  51. *
  52. * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
  53. * @param zta ZeroTier address of peer
  54. * @param loadFromCached If false do not load from cache if not in memory (default: true)
  55. * @return Peer or NULL if not found
  56. */
  57. ZT_INLINE SharedPtr< Peer > peer(void *tPtr, const Address &zta, const bool loadFromCached = true)
  58. {
  59. {
  60. RWMutex::RLock l(m_peers_l);
  61. const SharedPtr< Peer > *const ap = m_peers.get(zta);
  62. if (likely(ap != nullptr))
  63. return *ap;
  64. }
  65. {
  66. SharedPtr< Peer > p;
  67. if (loadFromCached) {
  68. m_loadCached(tPtr, zta, p);
  69. if (p) {
  70. RWMutex::Lock l(m_peers_l);
  71. SharedPtr< Peer > &hp = m_peers[zta];
  72. if (hp)
  73. return hp;
  74. hp = p;
  75. }
  76. }
  77. return p;
  78. }
  79. }
  80. /**
  81. * Get a Path object for a given local and remote physical address, creating if needed
  82. *
  83. * @param l Local socket
  84. * @param r Remote address
  85. * @return Pointer to canonicalized Path object or NULL on error
  86. */
  87. ZT_INLINE SharedPtr< Path > path(const int64_t l, const InetAddress &r)
  88. {
  89. const uint64_t k = s_getPathKey(l, r);
  90. {
  91. RWMutex::RLock lck(m_paths_l);
  92. SharedPtr< Path > *const p = m_paths.get(k);
  93. if (likely(p != nullptr))
  94. return *p;
  95. }
  96. {
  97. SharedPtr< Path > p(new Path(l, r));
  98. RWMutex::Lock lck(m_paths_l);
  99. SharedPtr< Path > &p2 = m_paths[k];
  100. if (p2)
  101. return p2;
  102. p2 = p;
  103. return p;
  104. }
  105. }
  106. /**
  107. * @return Current best root server
  108. */
  109. ZT_INLINE SharedPtr< Peer > root() const
  110. {
  111. RWMutex::RLock l(m_roots_l);
  112. if (unlikely(m_rootPeers.empty()))
  113. return SharedPtr< Peer >();
  114. return m_rootPeers.front();
  115. }
  116. /**
  117. * @param id Identity to check
  118. * @return True if this identity corresponds to a root
  119. */
  120. ZT_INLINE bool isRoot(const Identity &id) const
  121. {
  122. RWMutex::RLock l(m_roots_l);
  123. return (m_roots.find(id) != m_roots.end());
  124. }
  125. /**
  126. * Apply a function or function object to all peers
  127. *
  128. * This locks the peer map during execution, so calls to get() etc. during
  129. * eachPeer() will deadlock.
  130. *
  131. * @param f Function to apply
  132. * @tparam F Function or function object type
  133. */
  134. template< typename F >
  135. ZT_INLINE void eachPeer(F f) const
  136. {
  137. RWMutex::RLock l(m_peers_l);
  138. for (Map< Address, SharedPtr< Peer > >::const_iterator i(m_peers.begin()); i != m_peers.end(); ++i)
  139. f(i->second);
  140. }
  141. /**
  142. * @param allPeers vector to fill with all current peers
  143. */
  144. ZT_INLINE void getAllPeers(Vector< SharedPtr< Peer > > &allPeers) const
  145. {
  146. allPeers.clear();
  147. RWMutex::RLock l(m_peers_l);
  148. allPeers.reserve(m_peers.size());
  149. for (Map< Address, SharedPtr< Peer > >::const_iterator i(m_peers.begin()); i != m_peers.end(); ++i)
  150. allPeers.push_back(i->second);
  151. }
  152. /**
  153. * @param allPeers vector to fill with all current peers
  154. */
  155. ZT_INLINE void getAllPeers(Vector< SharedPtr< Peer > > &allPeers, Vector< SharedPtr< Peer > > &rootPeers) const
  156. {
  157. allPeers.clear();
  158. RWMutex::RLock l(m_peers_l);
  159. allPeers.reserve(m_peers.size());
  160. for (Map< Address, SharedPtr< Peer > >::const_iterator i(m_peers.begin()); i != m_peers.end(); ++i)
  161. allPeers.push_back(i->second);
  162. rootPeers = m_rootPeers;
  163. }
  164. /**
  165. * Flag a peer as a root, adding the peer if it is not known
  166. *
  167. * @param tPtr Thread pointer
  168. * @param id Root identity (will be locally validated)
  169. * @return Root peer or NULL if some problem occurred
  170. */
  171. SharedPtr< Peer > addRoot(void *tPtr, const Identity &id);
  172. /**
  173. * Remove a root server's identity from the root server set
  174. *
  175. * @param tPtr Thread pointer
  176. * @param address Root address
  177. * @return True if root found and removed, false if not found
  178. */
  179. bool removeRoot(void *tPtr, Address address);
  180. /**
  181. * Sort roots in ascending order of apparent latency
  182. *
  183. * @param now Current time
  184. */
  185. void rankRoots();
  186. /**
  187. * Do periodic tasks such as database cleanup
  188. *
  189. * @param tPtr Thread pointer
  190. * @param now Current time
  191. */
  192. void doPeriodicTasks(void *tPtr, int64_t now);
  193. /**
  194. * Save all currently known peers to data store
  195. *
  196. * @param tPtr Thread pointer
  197. */
  198. void saveAll(void *tPtr);
  199. /**
  200. * Add a certificate to the local certificate store
  201. *
  202. * @param tPtr Thread pointer
  203. * @param cert Certificate to add (a copy will be made if added)
  204. * @param now Current time
  205. * @param localTrust Local trust bit flags
  206. * @param writeToLocalStore If true, write to local object store (via API callbacks)
  207. * @param refreshRootSets If true, refresh root sets in case a root set changed (default: true)
  208. * @param verify If true, verify certificate and certificate chain (default: true)
  209. * @return Error or 0 on success
  210. */
  211. ZT_CertificateError addCertificate(void *tPtr, const Certificate &cert, const int64_t now, unsigned int localTrust, bool writeToLocalStore, bool refreshRootSets = true, bool verify = true);
  212. private:
  213. void m_eraseCertificate_l_certs(const SharedPtr< const Certificate > &cert);
  214. bool m_cleanCertificates_l_certs(int64_t now);
  215. bool m_verifyCertificateChain_l_certs(const Certificate *current, const int64_t now) const;
  216. ZT_CertificateError m_verifyCertificate_l_certs(const Certificate &cert, const int64_t now, unsigned int localTrust, bool skipSignatureCheck) const;
  217. void m_loadCached(void *tPtr, const Address &zta, SharedPtr< Peer > &peer);
  218. void m_updateRootPeers_l_roots_certs(void *tPtr);
  219. void m_writeTrustStore_l_roots_certs(void *tPtr) const;
  220. // This gets an integer key from an InetAddress for looking up paths.
  221. static ZT_INLINE uint64_t s_getPathKey(const int64_t l, const InetAddress &r) noexcept
  222. {
  223. // SECURITY: these will be used as keys in a Map<> which uses its own hasher that
  224. // mixes in a per-invocation secret to work against hash collision attacks. See the
  225. // map hasher in Containers.hpp. Otherwise the point here is really really fast
  226. // path lookup by address. The number of paths is never likely to be high enough
  227. // for a collision to be something we worry about. That would require a minimum of
  228. // millions and millions of paths on a single node.
  229. if (r.family() == AF_INET) {
  230. return ((uint64_t)(r.as.sa_in.sin_addr.s_addr) << 32U) ^ ((uint64_t)r.as.sa_in.sin_port << 16U) ^ (uint64_t)l;
  231. } else if (r.family() == AF_INET6) {
  232. return Utils::loadAsIsEndian< uint64_t >(r.as.sa_in6.sin6_addr.s6_addr) + Utils::loadAsIsEndian< uint64_t >(r.as.sa_in6.sin6_addr.s6_addr + 8) + (uint64_t)r.as.sa_in6.sin6_port + (uint64_t)l;
  233. } else {
  234. // This should never really be used but it's here just in case.
  235. return (uint64_t)Utils::fnv1a32(reinterpret_cast<const void *>(&r), sizeof(InetAddress)) + (uint64_t)l;
  236. }
  237. }
  238. const RuntimeEnvironment *const RR;
  239. RWMutex m_paths_l; // m_paths
  240. RWMutex m_peers_l; // m_peers
  241. RWMutex m_roots_l; // m_roots, m_rootPeers
  242. Mutex m_certs_l; // m_certs, m_certsBySubjectIdentity
  243. Map< uint64_t, SharedPtr< Path > > m_paths;
  244. Map< Address, SharedPtr< Peer > > m_peers;
  245. Map< Identity, Set< SharedPtr< const Certificate > > > m_roots;
  246. Vector< SharedPtr< Peer > > m_rootPeers;
  247. Map< SHA384Hash, std::pair< SharedPtr< const Certificate >, unsigned int > > m_certs;
  248. Map< Fingerprint, Map< SharedPtr< const Certificate >, unsigned int > > m_certsBySubjectIdentity;
  249. SortedMap< Vector< uint8_t >, std::pair< SharedPtr< const Certificate >, unsigned int > > m_certsBySubjectUniqueId;
  250. };
  251. } // namespace ZeroTier
  252. #endif