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: 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 14 #ifndef ZT_TOPOLOGY_HPP 15 #define ZT_TOPOLOGY_HPP 16 17 #include <stdio.h> 18 #include <string.h> 19 20 #include <vector> 21 #include <stdexcept> 22 #include <algorithm> 23 #include <utility> 24 25 #include "Constants.hpp" 26 #include "../include/ZeroTierOne.h" 27 28 #include "Address.hpp" 29 #include "Identity.hpp" 30 #include "Peer.hpp" 31 #include "Path.hpp" 32 #include "Mutex.hpp" 33 #include "InetAddress.hpp" 34 #include "Hashtable.hpp" 35 #include "World.hpp" 36 37 namespace ZeroTier { 38 39 class RuntimeEnvironment; 40 41 /** 42 * Database of network topology 43 */ 44 class Topology 45 { 46 public: 47 Topology(const RuntimeEnvironment *renv,void *tPtr); 48 ~Topology(); 49 50 /** 51 * Add a peer to database 52 * 53 * This will not replace existing peers. In that case the existing peer 54 * record is returned. 55 * 56 * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call 57 * @param peer Peer to add 58 * @return New or existing peer (should replace 'peer') 59 */ 60 SharedPtr<Peer> addPeer(void *tPtr,const SharedPtr<Peer> &peer); 61 62 /** 63 * Get a peer from its address 64 * 65 * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call 66 * @param zta ZeroTier address of peer 67 * @return Peer or NULL if not found 68 */ 69 SharedPtr<Peer> getPeer(void *tPtr,const Address &zta); 70 71 /** 72 * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call 73 * @param zta ZeroTier address of peer 74 * @return Identity or NULL identity if not found 75 */ 76 Identity getIdentity(void *tPtr,const Address &zta); 77 78 /** 79 * Get a peer only if it is presently in memory (no disk cache) 80 * 81 * This also does not update the lastUsed() time for peers, which means 82 * that it won't prevent them from falling out of RAM. This is currently 83 * used in the Cluster code to update peer info without forcing all peers 84 * across the entire cluster to remain in memory cache. 85 * 86 * @param zta ZeroTier address 87 */ getPeerNoCache(const Address & zta)88 inline SharedPtr<Peer> getPeerNoCache(const Address &zta) 89 { 90 Mutex::Lock _l(_peers_m); 91 const SharedPtr<Peer> *const ap = _peers.get(zta); 92 if (ap) 93 return *ap; 94 return SharedPtr<Peer>(); 95 } 96 97 /** 98 * Get a Path object for a given local and remote physical address, creating if needed 99 * 100 * @param l Local socket 101 * @param r Remote address 102 * @return Pointer to canonicalized Path object 103 */ getPath(const int64_t l,const InetAddress & r)104 inline SharedPtr<Path> getPath(const int64_t l,const InetAddress &r) 105 { 106 Mutex::Lock _l(_paths_m); 107 SharedPtr<Path> &p = _paths[Path::HashKey(l,r)]; 108 if (!p) 109 p.set(new Path(l,r)); 110 return p; 111 } 112 113 /** 114 * Get the current best upstream peer 115 * 116 * @return Upstream or NULL if none available 117 */ 118 SharedPtr<Peer> getUpstreamPeer(); 119 120 /** 121 * @param id Identity to check 122 * @return True if this is a root server or a network preferred relay from one of our networks 123 */ 124 bool isUpstream(const Identity &id) const; 125 126 /** 127 * @param addr Address to check 128 * @return True if we should accept a world update from this address 129 */ 130 bool shouldAcceptWorldUpdateFrom(const Address &addr) const; 131 132 /** 133 * @param ztaddr ZeroTier address 134 * @return Peer role for this device 135 */ 136 ZT_PeerRole role(const Address &ztaddr) const; 137 138 /** 139 * Check for prohibited endpoints 140 * 141 * Right now this returns true if the designated ZT address is a root and if 142 * the IP (IP only, not port) does not equal any of the IPs defined in the 143 * current World. This is an extra little security feature in case root keys 144 * get appropriated or something. 145 * 146 * Otherwise it returns false. 147 * 148 * @param ztaddr ZeroTier address 149 * @param ipaddr IP address 150 * @return True if this ZT/IP pair should not be allowed to be used 151 */ 152 bool isProhibitedEndpoint(const Address &ztaddr,const InetAddress &ipaddr) const; 153 154 /** 155 * Gets upstreams to contact and their stable endpoints (if known) 156 * 157 * @param eps Hash table to fill with addresses and their stable endpoints 158 */ getUpstreamsToContact(Hashtable<Address,std::vector<InetAddress>> & eps) const159 inline void getUpstreamsToContact(Hashtable< Address,std::vector<InetAddress> > &eps) const 160 { 161 Mutex::Lock _l(_upstreams_m); 162 for(std::vector<World::Root>::const_iterator i(_planet.roots().begin());i!=_planet.roots().end();++i) { 163 if (i->identity != RR->identity) { 164 std::vector<InetAddress> &ips = eps[i->identity.address()]; 165 for(std::vector<InetAddress>::const_iterator j(i->stableEndpoints.begin());j!=i->stableEndpoints.end();++j) { 166 if (std::find(ips.begin(),ips.end(),*j) == ips.end()) 167 ips.push_back(*j); 168 } 169 } 170 } 171 for(std::vector<World>::const_iterator m(_moons.begin());m!=_moons.end();++m) { 172 for(std::vector<World::Root>::const_iterator i(m->roots().begin());i!=m->roots().end();++i) { 173 if (i->identity != RR->identity) { 174 std::vector<InetAddress> &ips = eps[i->identity.address()]; 175 for(std::vector<InetAddress>::const_iterator j(i->stableEndpoints.begin());j!=i->stableEndpoints.end();++j) { 176 if (std::find(ips.begin(),ips.end(),*j) == ips.end()) 177 ips.push_back(*j); 178 } 179 } 180 } 181 } 182 for(std::vector< std::pair<uint64_t,Address> >::const_iterator m(_moonSeeds.begin());m!=_moonSeeds.end();++m) 183 eps[m->second]; 184 } 185 186 /** 187 * @return Vector of active upstream addresses (including roots) 188 */ upstreamAddresses() const189 inline std::vector<Address> upstreamAddresses() const 190 { 191 Mutex::Lock _l(_upstreams_m); 192 return _upstreamAddresses; 193 } 194 195 /** 196 * @return Current moons 197 */ moons() const198 inline std::vector<World> moons() const 199 { 200 Mutex::Lock _l(_upstreams_m); 201 return _moons; 202 } 203 204 /** 205 * @return Moon IDs we are waiting for from seeds 206 */ moonsWanted() const207 inline std::vector<uint64_t> moonsWanted() const 208 { 209 Mutex::Lock _l(_upstreams_m); 210 std::vector<uint64_t> mw; 211 for(std::vector< std::pair<uint64_t,Address> >::const_iterator s(_moonSeeds.begin());s!=_moonSeeds.end();++s) { 212 if (std::find(mw.begin(),mw.end(),s->first) == mw.end()) 213 mw.push_back(s->first); 214 } 215 return mw; 216 } 217 218 /** 219 * @return Current planet 220 */ planet() const221 inline World planet() const 222 { 223 Mutex::Lock _l(_upstreams_m); 224 return _planet; 225 } 226 227 /** 228 * @return Current planet's world ID 229 */ planetWorldId() const230 inline uint64_t planetWorldId() const 231 { 232 return _planet.id(); // safe to read without lock, and used from within eachPeer() so don't lock 233 } 234 235 /** 236 * @return Current planet's world timestamp 237 */ planetWorldTimestamp() const238 inline uint64_t planetWorldTimestamp() const 239 { 240 return _planet.timestamp(); // safe to read without lock, and used from within eachPeer() so don't lock 241 } 242 243 /** 244 * Validate new world and update if newer and signature is okay 245 * 246 * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call 247 * @param newWorld A new or updated planet or moon to learn 248 * @param alwaysAcceptNew If true, always accept new moons even if we're not waiting for one 249 * @return True if it was valid and newer than current (or totally new for moons) 250 */ 251 bool addWorld(void *tPtr,const World &newWorld,bool alwaysAcceptNew); 252 253 /** 254 * Add a moon 255 * 256 * This loads it from moons.d if present, and if not adds it to 257 * a list of moons that we want to contact. 258 * 259 * @param id Moon ID 260 * @param seed If non-NULL, an address of any member of the moon to contact 261 */ 262 void addMoon(void *tPtr,const uint64_t id,const Address &seed); 263 264 /** 265 * Remove a moon 266 * 267 * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call 268 * @param id Moon's world ID 269 */ 270 void removeMoon(void *tPtr,const uint64_t id); 271 272 /** 273 * Clean and flush database 274 */ 275 void doPeriodicTasks(void *tPtr,int64_t now); 276 277 /** 278 * @param now Current time 279 * @return Number of peers with active direct paths 280 */ countActive(int64_t now) const281 inline unsigned long countActive(int64_t now) const 282 { 283 unsigned long cnt = 0; 284 Mutex::Lock _l(_peers_m); 285 Hashtable< Address,SharedPtr<Peer> >::Iterator i(const_cast<Topology *>(this)->_peers); 286 Address *a = (Address *)0; 287 SharedPtr<Peer> *p = (SharedPtr<Peer> *)0; 288 while (i.next(a,p)) { 289 const SharedPtr<Path> pp((*p)->getAppropriatePath(now,false)); 290 if (pp) 291 ++cnt; 292 } 293 return cnt; 294 } 295 296 /** 297 * Apply a function or function object to all peers 298 * 299 * @param f Function to apply 300 * @tparam F Function or function object type 301 */ 302 template<typename F> eachPeer(F f)303 inline void eachPeer(F f) 304 { 305 Mutex::Lock _l(_peers_m); 306 Hashtable< Address,SharedPtr<Peer> >::Iterator i(_peers); 307 Address *a = (Address *)0; 308 SharedPtr<Peer> *p = (SharedPtr<Peer> *)0; 309 while (i.next(a,p)) { 310 f(*this,*((const SharedPtr<Peer> *)p)); 311 } 312 } 313 314 /** 315 * @return All currently active peers by address (unsorted) 316 */ allPeers() const317 inline std::vector< std::pair< Address,SharedPtr<Peer> > > allPeers() const 318 { 319 Mutex::Lock _l(_peers_m); 320 return _peers.entries(); 321 } 322 323 /** 324 * @return True if I am a root server in a planet or moon 325 */ amUpstream() const326 inline bool amUpstream() const { return _amUpstream; } 327 328 /** 329 * Get info about a path 330 * 331 * The supplied result variables are not modified if no special config info is found. 332 * 333 * @param physicalAddress Physical endpoint address 334 * @param mtu Variable set to MTU 335 * @param trustedPathId Variable set to trusted path ID 336 */ getOutboundPathInfo(const InetAddress & physicalAddress,unsigned int & mtu,uint64_t & trustedPathId)337 inline void getOutboundPathInfo(const InetAddress &physicalAddress,unsigned int &mtu,uint64_t &trustedPathId) 338 { 339 for(unsigned int i=0,j=_numConfiguredPhysicalPaths;i<j;++i) { 340 if (_physicalPathConfig[i].first.containsAddress(physicalAddress)) { 341 trustedPathId = _physicalPathConfig[i].second.trustedPathId; 342 mtu = _physicalPathConfig[i].second.mtu; 343 return; 344 } 345 } 346 } 347 348 /** 349 * Get the payload MTU for an outbound physical path (returns default if not configured) 350 * 351 * @param physicalAddress Physical endpoint address 352 * @return MTU 353 */ getOutboundPathMtu(const InetAddress & physicalAddress)354 inline unsigned int getOutboundPathMtu(const InetAddress &physicalAddress) 355 { 356 for(unsigned int i=0,j=_numConfiguredPhysicalPaths;i<j;++i) { 357 if (_physicalPathConfig[i].first.containsAddress(physicalAddress)) 358 return _physicalPathConfig[i].second.mtu; 359 } 360 return ZT_DEFAULT_PHYSMTU; 361 } 362 363 /** 364 * Get the outbound trusted path ID for a physical address, or 0 if none 365 * 366 * @param physicalAddress Physical address to which we are sending the packet 367 * @return Trusted path ID or 0 if none (0 is not a valid trusted path ID) 368 */ getOutboundPathTrust(const InetAddress & physicalAddress)369 inline uint64_t getOutboundPathTrust(const InetAddress &physicalAddress) 370 { 371 for(unsigned int i=0,j=_numConfiguredPhysicalPaths;i<j;++i) { 372 if (_physicalPathConfig[i].first.containsAddress(physicalAddress)) 373 return _physicalPathConfig[i].second.trustedPathId; 374 } 375 return 0; 376 } 377 378 /** 379 * Check whether in incoming trusted path marked packet is valid 380 * 381 * @param physicalAddress Originating physical address 382 * @param trustedPathId Trusted path ID from packet (from MAC field) 383 */ shouldInboundPathBeTrusted(const InetAddress & physicalAddress,const uint64_t trustedPathId)384 inline bool shouldInboundPathBeTrusted(const InetAddress &physicalAddress,const uint64_t trustedPathId) 385 { 386 for(unsigned int i=0,j=_numConfiguredPhysicalPaths;i<j;++i) { 387 if ((_physicalPathConfig[i].second.trustedPathId == trustedPathId)&&(_physicalPathConfig[i].first.containsAddress(physicalAddress))) 388 return true; 389 } 390 return false; 391 } 392 393 /** 394 * Set or clear physical path configuration (called via Node::setPhysicalPathConfiguration) 395 */ setPhysicalPathConfiguration(const struct sockaddr_storage * pathNetwork,const ZT_PhysicalPathConfiguration * pathConfig)396 inline void setPhysicalPathConfiguration(const struct sockaddr_storage *pathNetwork,const ZT_PhysicalPathConfiguration *pathConfig) 397 { 398 if (!pathNetwork) { 399 _numConfiguredPhysicalPaths = 0; 400 } else { 401 std::map<InetAddress,ZT_PhysicalPathConfiguration> cpaths; 402 for(unsigned int i=0,j=_numConfiguredPhysicalPaths;i<j;++i) 403 cpaths[_physicalPathConfig[i].first] = _physicalPathConfig[i].second; 404 405 if (pathConfig) { 406 ZT_PhysicalPathConfiguration pc(*pathConfig); 407 408 if (pc.mtu <= 0) 409 pc.mtu = ZT_DEFAULT_PHYSMTU; 410 else if (pc.mtu < ZT_MIN_PHYSMTU) 411 pc.mtu = ZT_MIN_PHYSMTU; 412 else if (pc.mtu > ZT_MAX_PHYSMTU) 413 pc.mtu = ZT_MAX_PHYSMTU; 414 415 cpaths[*(reinterpret_cast<const InetAddress *>(pathNetwork))] = pc; 416 } else { 417 cpaths.erase(*(reinterpret_cast<const InetAddress *>(pathNetwork))); 418 } 419 420 unsigned int cnt = 0; 421 for(std::map<InetAddress,ZT_PhysicalPathConfiguration>::const_iterator i(cpaths.begin());((i!=cpaths.end())&&(cnt<ZT_MAX_CONFIGURABLE_PATHS));++i) { 422 _physicalPathConfig[cnt].first = i->first; 423 _physicalPathConfig[cnt].second = i->second; 424 ++cnt; 425 } 426 _numConfiguredPhysicalPaths = cnt; 427 } 428 } 429 430 private: 431 Identity _getIdentity(void *tPtr,const Address &zta); 432 void _memoizeUpstreams(void *tPtr); 433 void _savePeer(void *tPtr,const SharedPtr<Peer> &peer); 434 435 const RuntimeEnvironment *const RR; 436 437 std::pair<InetAddress,ZT_PhysicalPathConfiguration> _physicalPathConfig[ZT_MAX_CONFIGURABLE_PATHS]; 438 volatile unsigned int _numConfiguredPhysicalPaths; 439 440 Hashtable< Address,SharedPtr<Peer> > _peers; 441 Mutex _peers_m; 442 443 Hashtable< Path::HashKey,SharedPtr<Path> > _paths; 444 Mutex _paths_m; 445 446 World _planet; 447 std::vector<World> _moons; 448 std::vector< std::pair<uint64_t,Address> > _moonSeeds; 449 std::vector<Address> _upstreamAddresses; 450 bool _amUpstream; 451 Mutex _upstreams_m; // locks worlds, upstream info, moon info, etc. 452 }; 453 454 } // namespace ZeroTier 455 456 #endif 457