Topology.hpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569
  1. /*
  2. * Copyright (c)2019 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: 2023-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 <stdio.h>
  16. #include <string.h>
  17. #include <vector>
  18. #include <stdexcept>
  19. #include <algorithm>
  20. #include <utility>
  21. #include <set>
  22. #include "Constants.hpp"
  23. #include "../include/ZeroTierOne.h"
  24. #include "Address.hpp"
  25. #include "Identity.hpp"
  26. #include "Peer.hpp"
  27. #include "Path.hpp"
  28. #include "Mutex.hpp"
  29. #include "InetAddress.hpp"
  30. #include "Hashtable.hpp"
  31. #include "Locator.hpp"
  32. #include "SharedPtr.hpp"
  33. #include "ScopedPtr.hpp"
  34. namespace ZeroTier {
  35. class RuntimeEnvironment;
  36. /**
  37. * Database of network topology
  38. */
  39. class Topology
  40. {
  41. private:
  42. struct _RootRankingFunction
  43. {
  44. ZT_ALWAYS_INLINE _RootRankingFunction() : bestRoot(),bestRootLatency(0xffff) {}
  45. ZT_ALWAYS_INLINE bool operator()(const SharedPtr<Peer> &peer,const std::vector<InetAddress> &phy)
  46. {
  47. const unsigned int lat = peer->latency(now);
  48. if ((!bestRoot)||((lat <= bestRootLatency)&&(peer->getAppropriatePath(now,false)))) {
  49. bestRoot = peer;
  50. bestRootLatency = lat;
  51. }
  52. return true;
  53. }
  54. int64_t now;
  55. SharedPtr<Peer> bestRoot;
  56. unsigned int bestRootLatency;
  57. };
  58. public:
  59. ZT_ALWAYS_INLINE Topology(const RuntimeEnvironment *renv,const Identity &myId) :
  60. RR(renv),
  61. _myIdentity(myId),
  62. _numConfiguredPhysicalPaths(0),
  63. _lastUpdatedBestRoot(0) {}
  64. ZT_ALWAYS_INLINE ~Topology() {}
  65. /**
  66. * Add a peer to database
  67. *
  68. * This will not replace existing peers. In that case the existing peer
  69. * record is returned.
  70. *
  71. * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
  72. * @param peer Peer to add
  73. * @return New or existing peer (should replace 'peer')
  74. */
  75. ZT_ALWAYS_INLINE SharedPtr<Peer> add(const SharedPtr<Peer> &peer)
  76. {
  77. SharedPtr<Peer> np;
  78. {
  79. Mutex::Lock _l(_peers_l);
  80. SharedPtr<Peer> &hp = _peers[peer->address()];
  81. if (!hp)
  82. hp = peer;
  83. np = hp;
  84. }
  85. return np;
  86. }
  87. /**
  88. * Get a peer from its address
  89. *
  90. * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
  91. * @param zta ZeroTier address of peer
  92. * @return Peer or NULL if not found
  93. */
  94. ZT_ALWAYS_INLINE SharedPtr<Peer> get(const Address &zta)
  95. {
  96. if (zta == _myIdentity.address())
  97. return SharedPtr<Peer>();
  98. Mutex::Lock l1(_peers_l);
  99. const SharedPtr<Peer> *const ap = _peers.get(zta);
  100. if (ap)
  101. return *ap;
  102. return SharedPtr<Peer>();
  103. }
  104. /**
  105. * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
  106. * @param zta ZeroTier address of peer
  107. * @return Identity or NULL identity if not found
  108. */
  109. ZT_ALWAYS_INLINE Identity getIdentity(void *tPtr,const Address &zta)
  110. {
  111. if (zta == _myIdentity.address()) {
  112. return _myIdentity;
  113. } else {
  114. Mutex::Lock _l(_peers_l);
  115. const SharedPtr<Peer> *const ap = _peers.get(zta);
  116. if (ap)
  117. return (*ap)->identity();
  118. }
  119. return Identity();
  120. }
  121. /**
  122. * Get a Path object for a given local and remote physical address, creating if needed
  123. *
  124. * @param l Local socket
  125. * @param r Remote address
  126. * @return Pointer to canonicalized Path object
  127. */
  128. ZT_ALWAYS_INLINE SharedPtr<Path> getPath(const int64_t l,const InetAddress &r)
  129. {
  130. Mutex::Lock _l(_paths_l);
  131. SharedPtr<Path> &p = _paths[Path::HashKey(l,r)];
  132. if (!p)
  133. p.set(new Path(l,r));
  134. return p;
  135. }
  136. /**
  137. * @param id Identity to check
  138. * @return True if this identity corresponds to a root
  139. */
  140. ZT_ALWAYS_INLINE bool isRoot(const Identity &id) const
  141. {
  142. {
  143. Mutex::Lock l(_dynamicRoots_l);
  144. if (_dynamicRootIdentities.contains(id))
  145. return true;
  146. }
  147. {
  148. Mutex::Lock l(_staticRoots_l);
  149. if (_staticRoots.contains(id))
  150. return true;
  151. }
  152. return false;
  153. }
  154. /**
  155. * Do periodic tasks such as database cleanup
  156. */
  157. ZT_ALWAYS_INLINE void doPeriodicTasks(int64_t now)
  158. {
  159. {
  160. Mutex::Lock _l1(_peers_l);
  161. Hashtable< Address,SharedPtr<Peer> >::Iterator i(_peers);
  162. Address *a = (Address *)0;
  163. SharedPtr<Peer> *p = (SharedPtr<Peer> *)0;
  164. while (i.next(a,p)) {
  165. if (!(*p)->alive(now)) {
  166. _peers.erase(*a);
  167. }
  168. }
  169. }
  170. {
  171. Mutex::Lock _l(_paths_l);
  172. Hashtable< Path::HashKey,SharedPtr<Path> >::Iterator i(_paths);
  173. Path::HashKey *k = (Path::HashKey *)0;
  174. SharedPtr<Path> *p = (SharedPtr<Path> *)0;
  175. while (i.next(k,p)) {
  176. if (p->references() <= 1)
  177. _paths.erase(*k);
  178. }
  179. }
  180. }
  181. /**
  182. * @param now Current time
  183. * @return Number of peers with active direct paths
  184. */
  185. ZT_ALWAYS_INLINE unsigned long countActive(int64_t now) const
  186. {
  187. unsigned long cnt = 0;
  188. Mutex::Lock _l(_peers_l);
  189. Hashtable< Address,SharedPtr<Peer> >::Iterator i(const_cast<Topology *>(this)->_peers);
  190. Address *a = (Address *)0;
  191. SharedPtr<Peer> *p = (SharedPtr<Peer> *)0;
  192. while (i.next(a,p)) {
  193. const SharedPtr<Path> pp((*p)->getAppropriatePath(now,false));
  194. if (pp)
  195. ++cnt;
  196. }
  197. return cnt;
  198. }
  199. /**
  200. * Apply a function or function object to all peers
  201. *
  202. * This locks the peer map during execution, so calls to get() etc. during
  203. * eachPeer() will deadlock.
  204. *
  205. * @param f Function to apply
  206. * @tparam F Function or function object type
  207. */
  208. template<typename F>
  209. ZT_ALWAYS_INLINE void eachPeer(F f)
  210. {
  211. Mutex::Lock l(_peers_l);
  212. Hashtable< Address,SharedPtr<Peer> >::Iterator i(_peers);
  213. Address *a = (Address *)0;
  214. SharedPtr<Peer> *p = (SharedPtr<Peer> *)0;
  215. while (i.next(a,p)) {
  216. f(*((const SharedPtr<Peer> *)p));
  217. }
  218. }
  219. /**
  220. * Apply a function or function object to all roots
  221. *
  222. * This locks the root list during execution but other operations
  223. * are fine.
  224. *
  225. * @param f Function to apply f(peer,IPs)
  226. * @tparam F function or function object type
  227. */
  228. template<typename F>
  229. inline void eachRoot(F f)
  230. {
  231. {
  232. Mutex::Lock l(_dynamicRoots_l);
  233. Hashtable< Str,Locator >::Iterator i(_dynamicRoots);
  234. Str *k = (Str *)0;
  235. Locator *v = (Locator *)0;
  236. while (i.next(k,v)) {
  237. if (*v) {
  238. for(std::vector<Identity>::const_iterator id(v->virt().begin());id!=v->virt().end();++id) {
  239. const SharedPtr<Peer> *ap;
  240. {
  241. Mutex::Lock l2(_peers_l);
  242. ap = _peers.get(id->address());
  243. }
  244. if (ap) {
  245. if (!f(*ap,v->phy()))
  246. return;
  247. } else {
  248. SharedPtr<Peer> p(new Peer(RR,_myIdentity,*id));
  249. {
  250. Mutex::Lock l2(_peers_l);
  251. _peers.set(id->address(),p);
  252. }
  253. if (!f(p,v->phy()))
  254. return;
  255. }
  256. }
  257. }
  258. }
  259. }
  260. {
  261. Mutex::Lock l(_staticRoots_l);
  262. Hashtable< Identity,std::vector<InetAddress> >::Iterator i(_staticRoots);
  263. Identity *k = (Identity *)0;
  264. std::vector<InetAddress> *v = (std::vector<InetAddress> *)0;
  265. while (i.next(k,v)) {
  266. if (!v->empty()) {
  267. const SharedPtr<Peer> *ap;
  268. {
  269. Mutex::Lock l2(_peers_l);
  270. ap = _peers.get(k->address());
  271. }
  272. if (ap) {
  273. if (!f(*ap,*v))
  274. return;
  275. } else {
  276. SharedPtr<Peer> p(new Peer(RR,_myIdentity,*k));
  277. {
  278. Mutex::Lock l2(_peers_l);
  279. _peers.set(k->address(),p);
  280. }
  281. if (!f(p,*v))
  282. return;
  283. }
  284. }
  285. }
  286. }
  287. }
  288. /**
  289. * @return Current best root (updated automatically each second)
  290. */
  291. inline SharedPtr<Peer> root(const int64_t now)
  292. {
  293. Mutex::Lock l(_bestRoot_l);
  294. if ((!_bestRoot)||((now - _lastUpdatedBestRoot) > 1000)) {
  295. _lastUpdatedBestRoot = now;
  296. _RootRankingFunction rrf;
  297. rrf.now = now;
  298. eachRoot(rrf);
  299. _bestRoot = rrf.bestRoot;
  300. }
  301. return _bestRoot;
  302. }
  303. /**
  304. * Set or update a static root entry
  305. *
  306. * @param id Static root's identity
  307. * @param addrs Static root's IP address(es)
  308. */
  309. ZT_ALWAYS_INLINE void setStaticRoot(const Identity &id,const std::vector<InetAddress> &addrs)
  310. {
  311. Mutex::Lock l(_staticRoots_l);
  312. _staticRoots[id] = addrs;
  313. }
  314. /**
  315. * Remove a static root
  316. *
  317. * @param id Identity to remove
  318. */
  319. ZT_ALWAYS_INLINE void removeStaticRoot(const Identity &id)
  320. {
  321. Mutex::Lock l(_staticRoots_l);
  322. _staticRoots.erase(id);
  323. }
  324. /**
  325. * @return Names of dynamic roots currently known by the system
  326. */
  327. ZT_ALWAYS_INLINE std::vector<Str> dynamicRootNames() const
  328. {
  329. Mutex::Lock l(_dynamicRoots_l);
  330. return _dynamicRoots.keys();
  331. }
  332. /**
  333. * Set or update dynamic root if new locator is newer and valid
  334. *
  335. * This checks internal validity of the new locator including its internal self-signature.
  336. * It does not check any DNS signatures.
  337. *
  338. * @param dnsName DNS name used to retrive root
  339. * @param latestLocator Latest locator
  340. * @return True if latest locator is internally valid and newer
  341. */
  342. ZT_ALWAYS_INLINE bool setDynamicRoot(const Str &dnsName,const Locator &latestLocator)
  343. {
  344. Mutex::Lock l(_dynamicRoots_l);
  345. Locator &ll = _dynamicRoots[dnsName];
  346. if (ll.timestamp() < latestLocator.timestamp()) {
  347. ll = latestLocator;
  348. _updateDynamicRootIdentities();
  349. return true;
  350. }
  351. return false;
  352. }
  353. /**
  354. * Remove a dynamic root entry
  355. *
  356. * @param dnsName DNS name to remove
  357. */
  358. ZT_ALWAYS_INLINE bool removeDynamicRoot(const Str &dnsName)
  359. {
  360. Mutex::Lock l(_dynamicRoots_l);
  361. _dynamicRoots.erase(dnsName);
  362. _updateDynamicRootIdentities();
  363. }
  364. /**
  365. * Remove all dynamic roots
  366. */
  367. ZT_ALWAYS_INLINE bool clearDynamicRoots(const Str &dnsName)
  368. {
  369. Mutex::Lock l(_dynamicRoots_l);
  370. _dynamicRoots.clear();
  371. _dynamicRootIdentities.clear();
  372. }
  373. /**
  374. * Get the best relay to a given address, which may or may not be a root
  375. *
  376. * @param now Current time
  377. * @param toAddr Destination address
  378. * @return Best current relay or NULL if none
  379. */
  380. ZT_ALWAYS_INLINE SharedPtr<Peer> findRelayTo(const int64_t now,const Address &toAddr)
  381. {
  382. // TODO: in the future this will check 'mesh-like' relays and if enabled consult LF for other roots (for if this is a root)
  383. //return root(now);
  384. }
  385. /**
  386. * @param allPeers vector to fill with all current peers
  387. */
  388. inline void getAllPeers(std::vector< SharedPtr<Peer> > &allPeers) const
  389. {
  390. Mutex::Lock l(_peers_l);
  391. allPeers.clear();
  392. allPeers.reserve(_peers.size());
  393. Hashtable< Address,SharedPtr<Peer> >::Iterator i(*(const_cast<Hashtable< Address,SharedPtr<Peer> > *>(&_peers)));
  394. Address *a = (Address *)0;
  395. SharedPtr<Peer> *p = (SharedPtr<Peer> *)0;
  396. while (i.next(a,p)) {
  397. allPeers.push_back(*p);
  398. }
  399. }
  400. /**
  401. * Get info about a path
  402. *
  403. * The supplied result variables are not modified if no special config info is found.
  404. *
  405. * @param physicalAddress Physical endpoint address
  406. * @param mtu Variable set to MTU
  407. * @param trustedPathId Variable set to trusted path ID
  408. */
  409. ZT_ALWAYS_INLINE void getOutboundPathInfo(const InetAddress &physicalAddress,unsigned int &mtu,uint64_t &trustedPathId)
  410. {
  411. for(unsigned int i=0,j=_numConfiguredPhysicalPaths;i<j;++i) {
  412. if (_physicalPathConfig[i].first.containsAddress(physicalAddress)) {
  413. trustedPathId = _physicalPathConfig[i].second.trustedPathId;
  414. mtu = _physicalPathConfig[i].second.mtu;
  415. return;
  416. }
  417. }
  418. }
  419. /**
  420. * Get the payload MTU for an outbound physical path (returns default if not configured)
  421. *
  422. * @param physicalAddress Physical endpoint address
  423. * @return MTU
  424. */
  425. ZT_ALWAYS_INLINE unsigned int getOutboundPathMtu(const InetAddress &physicalAddress)
  426. {
  427. for(unsigned int i=0,j=_numConfiguredPhysicalPaths;i<j;++i) {
  428. if (_physicalPathConfig[i].first.containsAddress(physicalAddress))
  429. return _physicalPathConfig[i].second.mtu;
  430. }
  431. return ZT_DEFAULT_PHYSMTU;
  432. }
  433. /**
  434. * Get the outbound trusted path ID for a physical address, or 0 if none
  435. *
  436. * @param physicalAddress Physical address to which we are sending the packet
  437. * @return Trusted path ID or 0 if none (0 is not a valid trusted path ID)
  438. */
  439. ZT_ALWAYS_INLINE uint64_t getOutboundPathTrust(const InetAddress &physicalAddress)
  440. {
  441. for(unsigned int i=0,j=_numConfiguredPhysicalPaths;i<j;++i) {
  442. if (_physicalPathConfig[i].first.containsAddress(physicalAddress))
  443. return _physicalPathConfig[i].second.trustedPathId;
  444. }
  445. return 0;
  446. }
  447. /**
  448. * Check whether in incoming trusted path marked packet is valid
  449. *
  450. * @param physicalAddress Originating physical address
  451. * @param trustedPathId Trusted path ID from packet (from MAC field)
  452. */
  453. ZT_ALWAYS_INLINE bool shouldInboundPathBeTrusted(const InetAddress &physicalAddress,const uint64_t trustedPathId)
  454. {
  455. for(unsigned int i=0,j=_numConfiguredPhysicalPaths;i<j;++i) {
  456. if ((_physicalPathConfig[i].second.trustedPathId == trustedPathId)&&(_physicalPathConfig[i].first.containsAddress(physicalAddress)))
  457. return true;
  458. }
  459. return false;
  460. }
  461. /**
  462. * Set or clear physical path configuration (called via Node::setPhysicalPathConfiguration)
  463. */
  464. inline void setPhysicalPathConfiguration(const struct sockaddr_storage *pathNetwork,const ZT_PhysicalPathConfiguration *pathConfig)
  465. {
  466. if (!pathNetwork) {
  467. _numConfiguredPhysicalPaths = 0;
  468. } else {
  469. std::map<InetAddress,ZT_PhysicalPathConfiguration> cpaths;
  470. for(unsigned int i=0,j=_numConfiguredPhysicalPaths;i<j;++i)
  471. cpaths[_physicalPathConfig[i].first] = _physicalPathConfig[i].second;
  472. if (pathConfig) {
  473. ZT_PhysicalPathConfiguration pc(*pathConfig);
  474. if (pc.mtu <= 0)
  475. pc.mtu = ZT_DEFAULT_PHYSMTU;
  476. else if (pc.mtu < ZT_MIN_PHYSMTU)
  477. pc.mtu = ZT_MIN_PHYSMTU;
  478. else if (pc.mtu > ZT_MAX_PHYSMTU)
  479. pc.mtu = ZT_MAX_PHYSMTU;
  480. cpaths[*(reinterpret_cast<const InetAddress *>(pathNetwork))] = pc;
  481. } else {
  482. cpaths.erase(*(reinterpret_cast<const InetAddress *>(pathNetwork)));
  483. }
  484. unsigned int cnt = 0;
  485. for(std::map<InetAddress,ZT_PhysicalPathConfiguration>::const_iterator i(cpaths.begin());((i!=cpaths.end())&&(cnt<ZT_MAX_CONFIGURABLE_PATHS));++i) {
  486. _physicalPathConfig[cnt].first = i->first;
  487. _physicalPathConfig[cnt].second = i->second;
  488. ++cnt;
  489. }
  490. _numConfiguredPhysicalPaths = cnt;
  491. }
  492. }
  493. private:
  494. inline void _updateDynamicRootIdentities()
  495. {
  496. // assumes _dynamicRoots_l is locked
  497. _dynamicRootIdentities.clear();
  498. Hashtable< Str,Locator >::Iterator i(_dynamicRoots);
  499. Str *k = (Str *)0;
  500. Locator *v = (Locator *)0;
  501. while (i.next(k,v)) {
  502. if (v->id())
  503. _dynamicRootIdentities.set(v->id(),true);
  504. }
  505. }
  506. const RuntimeEnvironment *const RR;
  507. const Identity _myIdentity;
  508. std::pair<InetAddress,ZT_PhysicalPathConfiguration> _physicalPathConfig[ZT_MAX_CONFIGURABLE_PATHS];
  509. unsigned int _numConfiguredPhysicalPaths;
  510. Hashtable< Address,SharedPtr<Peer> > _peers;
  511. Hashtable< Path::HashKey,SharedPtr<Path> > _paths;
  512. Hashtable< Str,Locator > _dynamicRoots;
  513. Hashtable< Identity,bool > _dynamicRootIdentities;
  514. Hashtable< Identity,std::vector<InetAddress> > _staticRoots;
  515. int64_t _lastUpdatedBestRoot;
  516. SharedPtr<Peer> _bestRoot;
  517. Mutex _peers_l;
  518. Mutex _paths_l;
  519. Mutex _dynamicRoots_l;
  520. Mutex _staticRoots_l;
  521. Mutex _bestRoot_l;
  522. };
  523. } // namespace ZeroTier
  524. #endif