mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-04-20 17:00:49 +00:00
A bunch more refactoring to rip out obsolete stuff related to old root system and general cleanup.
This commit is contained in:
parent
b23d551d00
commit
521d371b5d
152
attic/MulticastGroup.hpp
Normal file
152
attic/MulticastGroup.hpp
Normal file
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* ZeroTier One - Network Virtualization Everywhere
|
||||
* Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* --
|
||||
*
|
||||
* You can be released from the requirements of the license by purchasing
|
||||
* a commercial license. Buying such a license is mandatory as soon as you
|
||||
* develop commercial closed-source software that incorporates or links
|
||||
* directly against ZeroTier software without disclosing the source code
|
||||
* of your own application.
|
||||
*/
|
||||
|
||||
#ifndef ZT_MULTICASTGROUP_HPP
|
||||
#define ZT_MULTICASTGROUP_HPP
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "MAC.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
/**
|
||||
* A multicast group composed of a multicast MAC and a 32-bit ADI field
|
||||
*
|
||||
* ADI stands for additional distinguishing information. ADI is primarily for
|
||||
* adding additional information to broadcast (ff:ff:ff:ff:ff:ff) memberships,
|
||||
* since straight-up broadcast won't scale. Right now it's zero except for
|
||||
* IPv4 ARP, where it holds the IPv4 address itself to make ARP into a
|
||||
* selective multicast query that can scale.
|
||||
*
|
||||
* In the future we might add some kind of plugin architecture that can add
|
||||
* ADI for things like mDNS (multicast DNS) to improve the selectivity of
|
||||
* those protocols.
|
||||
*
|
||||
* MulticastGroup behaves as an immutable value object.
|
||||
*/
|
||||
class MulticastGroup
|
||||
{
|
||||
public:
|
||||
inline MulticastGroup() :
|
||||
_mac(),
|
||||
_adi(0)
|
||||
{
|
||||
}
|
||||
|
||||
inline MulticastGroup(const MAC &m,uint32_t a) :
|
||||
_mac(m),
|
||||
_adi(a)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Derive the multicast group used for address resolution (ARP/NDP) for an IP
|
||||
*
|
||||
* @param ip IP address (port field is ignored)
|
||||
* @return Multicast group for ARP/NDP
|
||||
*/
|
||||
static inline MulticastGroup deriveMulticastGroupForAddressResolution(const InetAddress &ip)
|
||||
{
|
||||
if (ip.isV4()) {
|
||||
// IPv4 wants broadcast MACs, so we shove the V4 address itself into
|
||||
// the Multicast Group ADI field. Making V4 ARP work is basically why
|
||||
// ADI was added, as well as handling other things that want mindless
|
||||
// Ethernet broadcast to all.
|
||||
return MulticastGroup(MAC(0xffffffffffffULL),Utils::ntoh(*((const uint32_t *)ip.rawIpData())));
|
||||
} else if (ip.isV6()) {
|
||||
// IPv6 is better designed in this respect. We can compute the IPv6
|
||||
// multicast address directly from the IP address, and it gives us
|
||||
// 24 bits of uniqueness. Collisions aren't likely to be common enough
|
||||
// to care about.
|
||||
const unsigned char *a = (const unsigned char *)ip.rawIpData();
|
||||
return MulticastGroup(MAC(0x33,0x33,0xff,a[13],a[14],a[15]),0);
|
||||
}
|
||||
return MulticastGroup();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Multicast address
|
||||
*/
|
||||
inline const MAC &mac() const { return _mac; }
|
||||
|
||||
/**
|
||||
* @return Additional distinguishing information
|
||||
*/
|
||||
inline uint32_t adi() const { return _adi; }
|
||||
|
||||
/**
|
||||
* Compute a 32-bit randomized identifier for this group
|
||||
*
|
||||
* This is a 32-bit fnv1a hash of the MAC and ADI. It's part of the protocol as it's
|
||||
* used to generate unique identifiers for multicast groups for multicast lookup, so
|
||||
* don't change it lightly.
|
||||
*/
|
||||
inline uint32_t id32() const
|
||||
{
|
||||
uint32_t h = 0x811c9dc5;
|
||||
const uint64_t m = _mac.toInt();
|
||||
const uint32_t p = 0x1000193;
|
||||
h ^= (uint32_t)(m >> 40) & 0xff; h *= p;
|
||||
h ^= (uint32_t)(m >> 32) & 0xff; h *= p;
|
||||
h ^= (uint32_t)(m >> 24) & 0xff; h *= p;
|
||||
h ^= (uint32_t)(m >> 16) & 0xff; h *= p;
|
||||
h ^= (uint32_t)(m >> 8) & 0xff; h *= p;
|
||||
h ^= (uint32_t)m & 0xff; h *= p;
|
||||
h ^= _adi >> 24; h *= p;
|
||||
h ^= (_adi >> 16) & 0xff; h *= p;
|
||||
h ^= (_adi >> 8) & 0xff; h *= p;
|
||||
h ^= _adi & 0xff; h *= p;
|
||||
return h;
|
||||
}
|
||||
|
||||
inline unsigned long hashCode() const { return (_mac.hashCode() + (unsigned long)_adi); }
|
||||
|
||||
inline bool operator==(const MulticastGroup &g) const { return ((_mac == g._mac)&&(_adi == g._adi)); }
|
||||
inline bool operator!=(const MulticastGroup &g) const { return ((_mac != g._mac)||(_adi != g._adi)); }
|
||||
inline bool operator<(const MulticastGroup &g) const
|
||||
{
|
||||
if (_mac < g._mac)
|
||||
return true;
|
||||
else if (_mac == g._mac)
|
||||
return (_adi < g._adi);
|
||||
return false;
|
||||
}
|
||||
inline bool operator>(const MulticastGroup &g) const { return (g < *this); }
|
||||
inline bool operator<=(const MulticastGroup &g) const { return !(g < *this); }
|
||||
inline bool operator>=(const MulticastGroup &g) const { return !(*this < g); }
|
||||
|
||||
private:
|
||||
MAC _mac;
|
||||
uint32_t _adi;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif
|
123
attic/MulticastSubscriptions.hpp
Normal file
123
attic/MulticastSubscriptions.hpp
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* ZeroTier One - Network Virtualization Everywhere
|
||||
* Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* --
|
||||
*
|
||||
* You can be released from the requirements of the license by purchasing
|
||||
* a commercial license. Buying such a license is mandatory as soon as you
|
||||
* develop commercial closed-source software that incorporates or links
|
||||
* directly against ZeroTier software without disclosing the source code
|
||||
* of your own application.
|
||||
*/
|
||||
|
||||
#ifndef ZT_MULTICASTSUBSCRIPTIONS_HPP
|
||||
#define ZT_MULTICASTSUBSCRIPTIONS_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "MulticastGroup.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "Buffer.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
/**
|
||||
* A compact collection of multicast subscriptions identified by 32-bit hash values
|
||||
*/
|
||||
class MulticastSubscriptions
|
||||
{
|
||||
public:
|
||||
inline MulticastSubscriptions() : _signatureLength(0) {}
|
||||
|
||||
inline void add(const MulticastGroup &mg)
|
||||
{
|
||||
if (_subscriptions.size() < ZT_MAX_MULTICAST_SUBSCRIPTIONS)
|
||||
_subscriptions.push_back(mg.id32());
|
||||
}
|
||||
|
||||
inline bool sign(const Identity &signer,const int64_t ts)
|
||||
{
|
||||
_ts = ts;
|
||||
std::sort(_subscriptions.begin(),_subscriptions.end());
|
||||
_subscriptions.erase(std::unique(_subscriptions.begin(),_subscriptions.end()),_subscriptions.end());
|
||||
|
||||
_SRec tmp;
|
||||
tmp.ts = Utils::hton((uint64_t)ts);
|
||||
for(unsigned long i=0,j=(unsigned long)_subscriptions.size();i<j;++i)
|
||||
tmp.g[i] = Utils::hton(_subscriptions[i]);
|
||||
|
||||
_signatureLength = signer.sign(&tmp,(unsigned int)((_subscriptions.size() * sizeof(uint32_t)) + sizeof(uint64_t)),_signature,sizeof(_signature));
|
||||
return (_signatureLength > 0);
|
||||
}
|
||||
|
||||
inline bool verify(const Identity &signer)
|
||||
{
|
||||
if ((_signatureLength == 0)||(_signatureLength > ZT_SIGNATURE_BUFFER_SIZE))
|
||||
return false;
|
||||
_SRec tmp;
|
||||
tmp.ts = Utils::hton((uint64_t)_ts);
|
||||
for(unsigned long i=0,j=(unsigned long)_subscriptions.size();i<j;++i)
|
||||
tmp.g[i] = Utils::hton(_subscriptions[i]);
|
||||
return signer.verify(&tmp,(unsigned int)((_subscriptions.size() * sizeof(uint32_t)) + sizeof(uint64_t)),_signature,_signatureLength);
|
||||
}
|
||||
|
||||
inline int64_t timestamp() const { return _ts; }
|
||||
inline unsigned int count() const { return (unsigned int)_subscriptions.size(); }
|
||||
inline bool contains(const MulticastGroup &mg) const { return std::binary_search(_subscriptions.begin(),_subscriptions.end(),mg.id32()); }
|
||||
|
||||
template<unsigned int C>
|
||||
inline void serialize(Buffer<C> &b) const
|
||||
{
|
||||
b.append((uint64_t)_ts);
|
||||
b.append((uint16_t)_subscriptions.size());
|
||||
for(std::vector<uint32_t>::const_iterator i(_subscriptions.begin());i!=_subscriptions.end();++i)
|
||||
b.append(*i);
|
||||
b.append((uint16_t)_signatureLength);
|
||||
b.append(_signature,_signatureLength);
|
||||
}
|
||||
|
||||
template<unsigned int C>
|
||||
inline unsigned int deserialize(const Buffer<C> &b,unsigned int startAt = 0)
|
||||
{
|
||||
unsigned int p = startAt;
|
||||
_ts = (int64_t)(b.template at<uint64_t>(p)); p += 8;
|
||||
_subscriptions.resize(b.template at<uint16_t>(p)); p += 2;
|
||||
for(std::vector<uint32_t>::iterator i(_subscriptions.begin());i!=_subscriptions.end();++i) {
|
||||
*i = b.template at<uint32_t>(p);
|
||||
p += 4;
|
||||
}
|
||||
_signatureLength = b.template at<uint16_t>(p); p += 2;
|
||||
if (_signatureLength > ZT_SIGNATURE_BUFFER_SIZE)
|
||||
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW;
|
||||
memcpy(_signature,b.field(p,_signatureLength),_signatureLength); p += _signatureLength;
|
||||
return (p - startAt);
|
||||
}
|
||||
|
||||
private:
|
||||
ZT_PACKED_STRUCT(struct _SRec {
|
||||
uint64_t ts;
|
||||
uint32_t g[ZT_MAX_MULTICAST_SUBSCRIPTIONS];
|
||||
});
|
||||
|
||||
int64_t _ts;
|
||||
std::vector<uint32_t> _subscriptions;
|
||||
unsigned int _signatureLength;
|
||||
uint8_t _signature[ZT_SIGNATURE_BUFFER_SIZE];
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif
|
@ -130,7 +130,7 @@ extern "C" {
|
||||
/**
|
||||
* Maximum number of multicast group subscriptions per network
|
||||
*/
|
||||
#define ZT_MAX_NETWORK_MULTICAST_SUBSCRIPTIONS 4096
|
||||
#define ZT_MAX_NETWORK_MULTICAST_SUBSCRIPTIONS 2048
|
||||
|
||||
/**
|
||||
* Rules engine revision ID, which specifies rules engine capabilities
|
||||
|
@ -383,26 +383,11 @@ public:
|
||||
|
||||
private:
|
||||
template<typename O>
|
||||
static inline unsigned long _hc(const O &obj)
|
||||
{
|
||||
return (unsigned long)obj.hashCode();
|
||||
}
|
||||
static inline unsigned long _hc(const uint64_t i)
|
||||
{
|
||||
return (unsigned long)(i ^ (i >> 32)); // good for network IDs and addresses
|
||||
}
|
||||
static inline unsigned long _hc(const uint32_t i)
|
||||
{
|
||||
return ((unsigned long)i * (unsigned long)0x9e3779b1);
|
||||
}
|
||||
static inline unsigned long _hc(const uint16_t i)
|
||||
{
|
||||
return ((unsigned long)i * (unsigned long)0x9e3779b1);
|
||||
}
|
||||
static inline unsigned long _hc(const int i)
|
||||
{
|
||||
return ((unsigned long)i * (unsigned long)0x9e3379b1);
|
||||
}
|
||||
static inline unsigned long _hc(const O &obj) { return (unsigned long)obj.hashCode(); }
|
||||
static inline unsigned long _hc(const uint64_t i) { return (unsigned long)(i ^ (i >> 32)); }
|
||||
static inline unsigned long _hc(const uint32_t i) { return ((unsigned long)i * (unsigned long)0x9e3779b1); }
|
||||
static inline unsigned long _hc(const uint16_t i) { return ((unsigned long)i * (unsigned long)0x9e3779b1); }
|
||||
static inline unsigned long _hc(const int i) { return ((unsigned long)i * (unsigned long)0x9e3379b1); }
|
||||
|
||||
inline void _grow()
|
||||
{
|
||||
|
@ -75,7 +75,7 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR,void *tPtr)
|
||||
return _doHELLO(RR,tPtr,false);
|
||||
}
|
||||
|
||||
const SharedPtr<Peer> peer(RR->topology->getPeer(tPtr,sourceAddress));
|
||||
const SharedPtr<Peer> peer(RR->topology->get(sourceAddress));
|
||||
if (peer) {
|
||||
if (!trusted) {
|
||||
if (!dearmor(peer->key())) {
|
||||
@ -170,7 +170,7 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,void *tPtr,const Shar
|
||||
case Packet::ERROR_IDENTITY_COLLISION:
|
||||
// This is a trusted upstream telling us our 5-digit ID is taken. This
|
||||
// causes the node to generate another.
|
||||
if (RR->topology->isUpstream(peer->identity()))
|
||||
if (RR->topology->isRoot(peer->identity()))
|
||||
RR->node->postEvent(tPtr,ZT_EVENT_FATAL_ERROR_IDENTITY_COLLISION);
|
||||
break;
|
||||
|
||||
@ -283,7 +283,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool
|
||||
return true;
|
||||
}
|
||||
|
||||
SharedPtr<Peer> peer(RR->topology->getPeer(tPtr,id.address()));
|
||||
SharedPtr<Peer> peer(RR->topology->get(id.address()));
|
||||
if (peer) {
|
||||
// We already have an identity with this address -- check for collisions
|
||||
if (!alreadyAuthenticated) {
|
||||
@ -351,7 +351,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool
|
||||
return true;
|
||||
}
|
||||
|
||||
peer = RR->topology->addPeer(tPtr,newPeer);
|
||||
peer = RR->topology->add(newPeer);
|
||||
|
||||
// Continue at // VALID
|
||||
}
|
||||
@ -363,7 +363,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool
|
||||
if (ptr < size()) {
|
||||
ptr += externalSurfaceAddress.deserialize(*this,ptr);
|
||||
if ((externalSurfaceAddress)&&(hops() == 0))
|
||||
RR->sa->iam(tPtr,id.address(),_path->localSocket(),_path->address(),externalSurfaceAddress,RR->topology->isUpstream(id),now);
|
||||
RR->sa->iam(tPtr,id.address(),_path->localSocket(),_path->address(),externalSurfaceAddress,RR->topology->isRoot(id),now);
|
||||
}
|
||||
|
||||
// Send OK(HELLO) with an echo of the packet's timestamp and some of the same
|
||||
@ -451,13 +451,13 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,void *tPtr,const SharedP
|
||||
peer->setRemoteVersion(vProto,vMajor,vMinor,vRevision);
|
||||
|
||||
if ((externalSurfaceAddress)&&(hops() == 0))
|
||||
RR->sa->iam(tPtr,peer->address(),_path->localSocket(),_path->address(),externalSurfaceAddress,RR->topology->isUpstream(peer->identity()),RR->node->now());
|
||||
RR->sa->iam(tPtr,peer->address(),_path->localSocket(),_path->address(),externalSurfaceAddress,RR->topology->isRoot(peer->identity()),RR->node->now());
|
||||
} break;
|
||||
|
||||
case Packet::VERB_WHOIS:
|
||||
if (RR->topology->isUpstream(peer->identity())) {
|
||||
if (RR->topology->isRoot(peer->identity())) {
|
||||
const Identity id(*this,ZT_PROTO_VERB_WHOIS__OK__IDX_IDENTITY);
|
||||
RR->sw->doAnythingWaitingForPeer(tPtr,RR->topology->addPeer(tPtr,SharedPtr<Peer>(new Peer(RR,RR->identity,id))));
|
||||
RR->sw->doAnythingWaitingForPeer(tPtr,RR->topology->add(SharedPtr<Peer>(new Peer(RR,RR->identity,id))));
|
||||
}
|
||||
break;
|
||||
|
||||
@ -550,9 +550,9 @@ bool IncomingPacket::_doWHOIS(const RuntimeEnvironment *RR,void *tPtr,const Shar
|
||||
|
||||
bool IncomingPacket::_doRENDEZVOUS(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer)
|
||||
{
|
||||
if (RR->topology->isUpstream(peer->identity())) {
|
||||
if (RR->topology->isRoot(peer->identity())) {
|
||||
const Address with(field(ZT_PROTO_VERB_RENDEZVOUS_IDX_ZTADDRESS,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH);
|
||||
const SharedPtr<Peer> rendezvousWith(RR->topology->getPeer(tPtr,with));
|
||||
const SharedPtr<Peer> rendezvousWith(RR->topology->get(with));
|
||||
if (rendezvousWith) {
|
||||
const unsigned int port = at<uint16_t>(ZT_PROTO_VERB_RENDEZVOUS_IDX_PORT);
|
||||
const unsigned int addrlen = (*this)[ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRLEN];
|
||||
@ -1021,7 +1021,7 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,void *tPtr,
|
||||
const bool amAnchor = (std::find(anchors.begin(),anchors.end(),RR->identity.address()) != anchors.end());
|
||||
|
||||
for(std::list<Address>::iterator ra(recipients.begin());ra!=recipients.end();) {
|
||||
SharedPtr<Peer> recipient(RR->topology->getPeer(tPtr,*ra));
|
||||
SharedPtr<Peer> recipient(RR->topology->get(*ra));
|
||||
if ((recipient)&&((recipient->remoteVersionProtocol() < 10)||(amAnchor))) {
|
||||
Packet outp(*ra,RR->identity.address(),Packet::VERB_MULTICAST_FRAME);
|
||||
outp.append(field(ZT_PACKET_IDX_PAYLOAD,recipientsOffset - ZT_PACKET_IDX_PAYLOAD),recipientsOffset - ZT_PACKET_IDX_PAYLOAD);
|
||||
|
@ -38,6 +38,7 @@ namespace ZeroTier {
|
||||
|
||||
const InetAddress InetAddress::LO4((const void *)("\x7f\x00\x00\x01"),4,0);
|
||||
const InetAddress InetAddress::LO6((const void *)("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"),16,0);
|
||||
const InetAddress InetAddress::NIL;
|
||||
|
||||
InetAddress::IpScope InetAddress::ipScope() const
|
||||
{
|
||||
|
@ -64,6 +64,11 @@ struct InetAddress : public sockaddr_storage
|
||||
*/
|
||||
static const InetAddress LO6;
|
||||
|
||||
/**
|
||||
* Null address
|
||||
*/
|
||||
static const InetAddress NIL;
|
||||
|
||||
/**
|
||||
* IP address scope
|
||||
*
|
||||
|
@ -58,10 +58,11 @@ namespace ZeroTier {
|
||||
class Locator
|
||||
{
|
||||
public:
|
||||
inline Locator() : _signatureLength(0) {}
|
||||
inline Locator() : _ts(0),_signatureLength(0) {}
|
||||
|
||||
inline const Identity &id() const { return _id; }
|
||||
inline const Identity &signer() const { return ((_signedBy) ? _signedBy : _id); }
|
||||
inline int64_t timestamp() const { return _ts; }
|
||||
|
||||
inline const std::vector<InetAddress> &phy() const { return _physical; }
|
||||
inline const std::vector<Identity> &virt() const { return _virtual; }
|
||||
@ -186,10 +187,9 @@ public:
|
||||
/**
|
||||
* Decode TXT records
|
||||
*
|
||||
* The supplied TXT records must be sorted in ascending natural sort order prior
|
||||
* to calling this method. The iterators supplied must be read iterators that
|
||||
* point to string objects supporting the c_str() method, which can be Str or
|
||||
* std::string.
|
||||
* TXT records can be provided as an iterator over std::string, Str, or char *
|
||||
* values, and TXT records can be provided in any order. Any oversize or empty
|
||||
* entries will be ignored.
|
||||
*
|
||||
* This method checks the decoded locator's signature using the supplied DNS TXT
|
||||
* record signing public key. False is returned if the TXT records are invalid,
|
||||
@ -202,11 +202,22 @@ public:
|
||||
uint8_t dec[256],s384[48];
|
||||
Buffer<65536> *tmp = nullptr;
|
||||
try {
|
||||
tmp = new Buffer<65536>();
|
||||
std::vector<Str> txtRecords;
|
||||
while (start != end) {
|
||||
tmp->append(dec,Utils::b64d(start->c_str(),dec,sizeof(dec)));
|
||||
try {
|
||||
Str ts(start);
|
||||
if (ts.length() > 2)
|
||||
txtRecords.push_back(ts);
|
||||
} catch ( ... ) {} // skip any records that trigger out of bounds exceptions
|
||||
++start;
|
||||
}
|
||||
if (txtRecords.empty())
|
||||
return false;
|
||||
std::sort(txtRecords.begin(),txtRecords.end());
|
||||
|
||||
tmp = new Buffer<65536>();
|
||||
for(std::vector<Str>::const_iterator i(txtRecords.begin());i!=txtRecords.end();++i)
|
||||
tmp->append(dec,Utils::b64d(i->c_str() + 2,dec,sizeof(dec)));
|
||||
|
||||
if (tmp->size() <= ZT_ECC384_SIGNATURE_SIZE) {
|
||||
delete tmp;
|
||||
@ -219,8 +230,8 @@ public:
|
||||
}
|
||||
|
||||
deserialize(*tmp,0);
|
||||
|
||||
delete tmp;
|
||||
|
||||
return verify();
|
||||
} catch ( ... ) {
|
||||
if (tmp) delete tmp;
|
||||
@ -235,10 +246,10 @@ public:
|
||||
|
||||
b.append((uint8_t)0); // version/flags, currently 0
|
||||
b.append((uint64_t)_ts);
|
||||
_id.serialise(b,false);
|
||||
_id.serialize(b,false);
|
||||
if (_signedBy) {
|
||||
b.append((uint8_t)1); // number of signers, current max is 1
|
||||
_signedBy.serialize(b,false);
|
||||
_signedBy.serialize(b,false); // be sure not to include private key!
|
||||
} else {
|
||||
b.append((uint8_t)0); // signer is _id
|
||||
}
|
||||
@ -282,7 +293,7 @@ public:
|
||||
_virtual.resize(virtualCount);
|
||||
for(unsigned int i=0;i<virtualCount;++i)
|
||||
p += _virtual[i].deserialize(b,p);
|
||||
_signatureLen = b.template at<uint16_t>(p); p += 2;
|
||||
_signatureLength = b.template at<uint16_t>(p); p += 2;
|
||||
if (_signatureLength > ZT_SIGNATURE_BUFFER_SIZE)
|
||||
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW;
|
||||
memcpy(_signature,b.field(p,_signatureLength),_signatureLength);
|
||||
|
@ -191,7 +191,7 @@ public:
|
||||
* @param i Value from 0 to 5 (inclusive)
|
||||
* @return Byte at said position (address interpreted in big-endian order)
|
||||
*/
|
||||
inline unsigned char operator[](unsigned int i) const { return (unsigned char)((_m >> (40 - (i * 8))) & 0xff); }
|
||||
inline uint8_t operator[](unsigned int i) const { return (uint8_t)(_m >> (40 - (i * 8))); }
|
||||
|
||||
/**
|
||||
* @return 6, which is the number of bytes in a MAC, for container compliance
|
||||
@ -230,7 +230,7 @@ public:
|
||||
}
|
||||
inline MAC &operator=(const uint64_t m)
|
||||
{
|
||||
_m = m;
|
||||
_m = m & 0xffffffffffffULL;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "MAC.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "Utils.hpp"
|
||||
@ -90,17 +91,10 @@ public:
|
||||
return MulticastGroup();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Multicast address
|
||||
*/
|
||||
inline const MAC &mac() const { return _mac; }
|
||||
|
||||
/**
|
||||
* @return Additional distinguishing information
|
||||
*/
|
||||
inline uint32_t adi() const { return _adi; }
|
||||
|
||||
inline unsigned long hashCode() const { return (_mac.hashCode() ^ (unsigned long)_adi); }
|
||||
inline unsigned long hashCode() const { return (_mac.hashCode() + (unsigned long)_adi); }
|
||||
|
||||
inline bool operator==(const MulticastGroup &g) const { return ((_mac == g._mac)&&(_adi == g._adi)); }
|
||||
inline bool operator!=(const MulticastGroup &g) const { return ((_mac != g._mac)||(_adi != g._adi)); }
|
||||
|
@ -243,10 +243,6 @@ void Multicaster::send(
|
||||
Address explicitGatherPeers[16];
|
||||
unsigned int numExplicitGatherPeers = 0;
|
||||
|
||||
SharedPtr<Peer> bestRoot(RR->topology->getUpstreamPeer());
|
||||
if (bestRoot)
|
||||
explicitGatherPeers[numExplicitGatherPeers++] = bestRoot->address();
|
||||
|
||||
explicitGatherPeers[numExplicitGatherPeers++] = network->controller();
|
||||
|
||||
Address ac[ZT_MAX_NETWORK_SPECIALISTS];
|
||||
|
@ -1246,15 +1246,12 @@ void Network::clean()
|
||||
_multicastGroupsBehindMe.erase(*mg);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
Address *a = (Address *)0;
|
||||
Membership *m = (Membership *)0;
|
||||
Hashtable<Address,Membership>::Iterator i(_memberships);
|
||||
while (i.next(a,m)) {
|
||||
if (!RR->topology->getPeerNoCache(*a))
|
||||
_memberships.erase(*a);
|
||||
else m->clean(now,_config);
|
||||
m->clean(now,_config);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1403,42 +1400,17 @@ void Network::_externalConfig(ZT_VirtualNetworkConfig *ec) const
|
||||
}
|
||||
}
|
||||
|
||||
void Network::_sendUpdatesToMembers(void *tPtr,const MulticastGroup *const newMulticastGroup)
|
||||
void Network::_sendUpdatesToMembers(void *tPtr)
|
||||
{
|
||||
// Assumes _lock is locked
|
||||
const int64_t now = RR->node->now();
|
||||
|
||||
std::vector<MulticastGroup> groups;
|
||||
if (newMulticastGroup)
|
||||
groups.push_back(*newMulticastGroup);
|
||||
else groups = _allMulticastGroups();
|
||||
|
||||
std::vector<Address> alwaysAnnounceTo;
|
||||
|
||||
if ((newMulticastGroup)||((now - _lastAnnouncedMulticastGroupsUpstream) >= ZT_MULTICAST_ANNOUNCE_PERIOD)) {
|
||||
if (!newMulticastGroup)
|
||||
_lastAnnouncedMulticastGroupsUpstream = now;
|
||||
|
||||
alwaysAnnounceTo = _config.alwaysContactAddresses();
|
||||
if (std::find(alwaysAnnounceTo.begin(),alwaysAnnounceTo.end(),controller()) == alwaysAnnounceTo.end())
|
||||
alwaysAnnounceTo.push_back(controller());
|
||||
const std::vector<Address> upstreams(RR->topology->upstreamAddresses());
|
||||
for(std::vector<Address>::const_iterator a(upstreams.begin());a!=upstreams.end();++a) {
|
||||
if (std::find(alwaysAnnounceTo.begin(),alwaysAnnounceTo.end(),*a) == alwaysAnnounceTo.end())
|
||||
alwaysAnnounceTo.push_back(*a);
|
||||
}
|
||||
std::sort(alwaysAnnounceTo.begin(),alwaysAnnounceTo.end());
|
||||
|
||||
for(std::vector<Address>::const_iterator a(alwaysAnnounceTo.begin());a!=alwaysAnnounceTo.end();++a)
|
||||
_announceMulticastGroupsTo(tPtr,*a,groups);
|
||||
}
|
||||
|
||||
const std::vector<MulticastGroup> groups(_allMulticastGroups());
|
||||
_announceMulticastGroupsTo(tPtr,controller(),groups);
|
||||
{
|
||||
Address *a = (Address *)0;
|
||||
Membership *m = (Membership *)0;
|
||||
Hashtable<Address,Membership>::Iterator i(_memberships);
|
||||
while (i.next(a,m)) {
|
||||
if ( ( m->multicastLikeGate(now) || (newMulticastGroup) ) && (m->isAllowedOnNetwork(_config)) && (!std::binary_search(alwaysAnnounceTo.begin(),alwaysAnnounceTo.end(),*a)) )
|
||||
if (m->isAllowedOnNetwork(_config))
|
||||
_announceMulticastGroupsTo(tPtr,*a,groups);
|
||||
}
|
||||
}
|
||||
|
@ -193,10 +193,10 @@ public:
|
||||
Mutex::Lock _l(_lock);
|
||||
if (!std::binary_search(_myMulticastGroups.begin(),_myMulticastGroups.end(),mg)) {
|
||||
_myMulticastGroups.insert(std::upper_bound(_myMulticastGroups.begin(),_myMulticastGroups.end(),mg),mg);
|
||||
_sendUpdatesToMembers(tPtr,&mg);
|
||||
_sendUpdatesToMembers(tPtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Unsubscribe from a multicast group
|
||||
*
|
||||
@ -295,7 +295,7 @@ public:
|
||||
inline void sendUpdatesToMembers(void *tPtr)
|
||||
{
|
||||
Mutex::Lock _l(_lock);
|
||||
_sendUpdatesToMembers(tPtr,(const MulticastGroup *)0);
|
||||
_sendUpdatesToMembers(tPtr);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -432,7 +432,7 @@ private:
|
||||
ZT_VirtualNetworkStatus _status() const;
|
||||
void _externalConfig(ZT_VirtualNetworkConfig *ec) const; // assumes _lock is locked
|
||||
bool _gate(const SharedPtr<Peer> &peer);
|
||||
void _sendUpdatesToMembers(void *tPtr,const MulticastGroup *const newMulticastGroup);
|
||||
void _sendUpdatesToMembers(void *tPtr);
|
||||
void _announceMulticastGroupsTo(void *tPtr,const Address &peer,const std::vector<MulticastGroup> &allMulticastGroups);
|
||||
std::vector<MulticastGroup> _allMulticastGroups() const;
|
||||
|
||||
|
@ -104,7 +104,7 @@ namespace ZeroTier {
|
||||
#define ZT_NETWORKCONFIG_DICT_CAPACITY (1024 + (sizeof(ZT_VirtualNetworkRule) * ZT_MAX_NETWORK_RULES) + (sizeof(Capability) * ZT_MAX_NETWORK_CAPABILITIES) + (sizeof(Tag) * ZT_MAX_NETWORK_TAGS) + (sizeof(CertificateOfOwnership) * ZT_MAX_CERTIFICATES_OF_OWNERSHIP))
|
||||
|
||||
// Dictionary capacity needed for max size network meta-data
|
||||
#define ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY 1024
|
||||
#define ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY 2048
|
||||
|
||||
// Network config version
|
||||
#define ZT_NETWORKCONFIG_VERSION 7
|
||||
|
@ -126,7 +126,7 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,int64
|
||||
m += sws;
|
||||
RR->mc = new (m) Multicaster(RR);
|
||||
m += mcs;
|
||||
RR->topology = new (m) Topology(RR,tptr);
|
||||
RR->topology = new (m) Topology(RR,RR->identity);
|
||||
m += topologys;
|
||||
RR->sa = new (m) SelfAwareness(RR);
|
||||
} catch ( ... ) {
|
||||
@ -190,6 +190,7 @@ ZT_ResultCode Node::processVirtualNetworkFrame(
|
||||
} else return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
|
||||
}
|
||||
|
||||
/*
|
||||
// Function object used to traverse the peer list, check peer status, and ping
|
||||
// those that need pinging.
|
||||
struct _PingPeersThatNeedPing
|
||||
@ -254,6 +255,7 @@ struct _PingPeersThatNeedPing
|
||||
|
||||
bool online;
|
||||
};
|
||||
*/
|
||||
|
||||
ZT_ResultCode Node::processBackgroundTasks(void *tptr,int64_t now,volatile int64_t *nextBackgroundTaskDeadline)
|
||||
{
|
||||
@ -282,6 +284,7 @@ ZT_ResultCode Node::processBackgroundTasks(void *tptr,int64_t now,volatile int64
|
||||
_localControllerAuthorizations_m.unlock();
|
||||
}
|
||||
|
||||
/*
|
||||
// (1) Get peers we should remain connected to and (2) get networks that need config.
|
||||
Hashtable< Address,std::vector<InetAddress> > alwaysContact;
|
||||
RR->topology->getAlwaysContact(alwaysContact);
|
||||
@ -322,6 +325,7 @@ ZT_ResultCode Node::processBackgroundTasks(void *tptr,int64_t now,volatile int64
|
||||
_online = pfunc.online;
|
||||
if (oldOnline != _online)
|
||||
postEvent(tptr,_online ? ZT_EVENT_ONLINE : ZT_EVENT_OFFLINE);
|
||||
*/
|
||||
} catch ( ... ) {
|
||||
return ZT_RESULT_FATAL_ERROR_INTERNAL;
|
||||
}
|
||||
@ -337,7 +341,7 @@ ZT_ResultCode Node::processBackgroundTasks(void *tptr,int64_t now,volatile int64
|
||||
if ((now - _lastHousekeepingRun) >= ZT_HOUSEKEEPING_PERIOD) {
|
||||
_lastHousekeepingRun = now;
|
||||
try {
|
||||
RR->topology->doPeriodicTasks(tptr,now);
|
||||
RR->topology->doPeriodicTasks(now);
|
||||
RR->sa->clean(now);
|
||||
RR->mc->clean(now);
|
||||
} catch ( ... ) {
|
||||
@ -454,7 +458,7 @@ ZT_PeerList *Node::peers() const
|
||||
p->latency = pi->second->latency(_now);
|
||||
if (p->latency >= 0xffff)
|
||||
p->latency = -1;
|
||||
p->role = RR->topology->role(pi->second->identity().address());
|
||||
p->role = RR->topology->isRoot(pi->second->identity()) ? ZT_PEER_ROLE_PLANET : ZT_PEER_ROLE_LEAF;
|
||||
|
||||
std::vector< SharedPtr<Path> > paths(pi->second->paths(_now));
|
||||
SharedPtr<Path> bestp(pi->second->getAppropriatePath(_now,false));
|
||||
|
223
node/Root.hpp
Normal file
223
node/Root.hpp
Normal file
@ -0,0 +1,223 @@
|
||||
/*
|
||||
* ZeroTier One - Network Virtualization Everywhere
|
||||
* Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* --
|
||||
*
|
||||
* You can be released from the requirements of the license by purchasing
|
||||
* a commercial license. Buying such a license is mandatory as soon as you
|
||||
* develop commercial closed-source software that incorporates or links
|
||||
* directly against ZeroTier software without disclosing the source code
|
||||
* of your own application.
|
||||
*/
|
||||
|
||||
#ifndef ZT_ROOT_HPP
|
||||
#define ZT_ROOT_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Str.hpp"
|
||||
#include "ECC384.hpp"
|
||||
#include "Locator.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "Mutex.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
/**
|
||||
* A root entry pointing to a node capable of global identity lookup and indirect transit
|
||||
*
|
||||
* Root entries point to DNS records that contain TXT entries that decode to Locator objects
|
||||
* pointing to actual root nodes. A default root identity and static addresses can also be
|
||||
* provided as fallback if DNS is not available.
|
||||
*
|
||||
* Note that root identities can change if DNS returns a different result, but that DNS entries
|
||||
* are authenticated using their own signature scheme. This allows a root DNS name to serve
|
||||
* up different roots based on factors like location or relative load of different roots.
|
||||
*
|
||||
* It's also possible to create a root with no DNS and no DNS validator public key. This root
|
||||
* will be a static entry pointing to a single root identity and set of physical addresses.
|
||||
*
|
||||
* This object is thread-safe and may be concurrently accessed and updated.
|
||||
*/
|
||||
class Root
|
||||
{
|
||||
public:
|
||||
inline Root() : _dnsPublicKeySize(0) {}
|
||||
inline Root(const Root &r) { *this = r; }
|
||||
|
||||
/**
|
||||
* Create a new root entry
|
||||
*
|
||||
* @param dn DNS name
|
||||
* @param dnspk DNS public key for record validation
|
||||
* @param dnspksize Size of DNS public key (currently always the size of a NIST P-384 point compressed public key)
|
||||
* @param dflId Default identity if DNS is not available
|
||||
* @param dflAddrs Default IP addresses if DNS is not available
|
||||
*/
|
||||
template<typename S>
|
||||
inline Root(S dn,const uint8_t *const dnspk,const unsigned int dnspksize,const Identity &dflId,const std::vector<InetAddress> &dflAddrs) :
|
||||
_defaultIdentity(dflId),
|
||||
_defaultAddresses(dflAddrs),
|
||||
_dnsName(dn),
|
||||
_dnsPublicKeySize(dnspksize)
|
||||
{
|
||||
if (dnspksize != 0) {
|
||||
if (dnspksize > sizeof(_dnsPublicKey))
|
||||
throw ZT_EXCEPTION_INVALID_ARGUMENT;
|
||||
memcpy(_dnsPublicKey,dnspk,dnspksize);
|
||||
}
|
||||
}
|
||||
|
||||
inline Root &operator=(const Root &r)
|
||||
{
|
||||
Mutex::Lock l(_lock);
|
||||
Mutex::Lock rl(r._lock);
|
||||
_defaultIdentity = r._defaultIdentity;
|
||||
_defaultAddresses = r._defaultAddresses;
|
||||
_dnsName = r._dnsName;
|
||||
_lastFetchedLocator = r._lastFetchedLocator;
|
||||
_dnsPublicKeySize = r._dnsPublicKeySize;
|
||||
memcpy(_dnsPublicKey,r._dnsPublicKey,_dnsPublicKeySize);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Current identity (either default or latest locator)
|
||||
*/
|
||||
inline const Identity id() const
|
||||
{
|
||||
Mutex::Lock l(_lock);
|
||||
if (_lastFetchedLocator.id())
|
||||
return _lastFetchedLocator.id();
|
||||
return _defaultIdentity;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param id Identity to check
|
||||
* @return True if identity equals this root's current identity
|
||||
*/
|
||||
inline bool is(const Identity &id) const
|
||||
{
|
||||
Mutex::Lock l(_lock);
|
||||
return ((_lastFetchedLocator.id()) ? (id == _lastFetchedLocator.id()) : (id == _defaultIdentity));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Current ZeroTier address (either default or latest locator)
|
||||
*/
|
||||
inline const Address address() const
|
||||
{
|
||||
Mutex::Lock l(_lock);
|
||||
if (_lastFetchedLocator.id())
|
||||
return _lastFetchedLocator.id().address();
|
||||
return _defaultIdentity.address();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return DNS name for this root (or empty string if none)
|
||||
*/
|
||||
inline const Str dnsName() const
|
||||
{
|
||||
Mutex::Lock l(_lock);
|
||||
return _dnsName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Latest locator
|
||||
*/
|
||||
inline Locator locator() const
|
||||
{
|
||||
Mutex::Lock l(_lock);
|
||||
return _lastFetchedLocator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Timestamp of latest retrieved locator
|
||||
*/
|
||||
inline int64_t locatorTimestamp() const
|
||||
{
|
||||
Mutex::Lock l(_lock);
|
||||
return _lastFetchedLocator.timestamp();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pick a random physical address
|
||||
*
|
||||
* @return Physical address or InetAddress::NIL if none are available
|
||||
*/
|
||||
inline const InetAddress randomPhysicalAddress() const
|
||||
{
|
||||
Mutex::Lock l(_lock);
|
||||
if (_lastFetchedLocator.phy().empty()) {
|
||||
if (_defaultAddresses.empty())
|
||||
return InetAddress::NIL;
|
||||
return _defaultAddresses[(unsigned long)Utils::random() % (unsigned long)_defaultAddresses.size()];
|
||||
}
|
||||
return _lastFetchedLocator.phy()[(unsigned long)Utils::random() % (unsigned long)_lastFetchedLocator.phy().size()];
|
||||
}
|
||||
|
||||
/**
|
||||
* Update locator, returning true if new locator is valid and newer than existing
|
||||
*/
|
||||
inline bool updateLocator(const Locator &loc)
|
||||
{
|
||||
if (!loc.verify())
|
||||
return false;
|
||||
Mutex::Lock l(_lock);
|
||||
if ((loc.phy().size() > 0)&&(loc.timestamp() > _lastFetchedLocator.timestamp())) {
|
||||
_lastFetchedLocator = loc;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update this root's locator from a series of TXT records
|
||||
*/
|
||||
template<typename I>
|
||||
inline bool updateLocatorFromTxt(I start,I end)
|
||||
{
|
||||
try {
|
||||
Mutex::Lock l(_lock);
|
||||
if (_dnsPublicKeySize != ZT_ECC384_PUBLIC_KEY_SIZE)
|
||||
return false;
|
||||
Locator loc;
|
||||
if (!loc.decodeTxtRecords(start,end,_dnsPublicKey))
|
||||
return false;
|
||||
if ((loc.phy().size() > 0)&&(loc.timestamp() > _lastFetchedLocator.timestamp())) {
|
||||
_lastFetchedLocator = loc;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} catch ( ... ) {}
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
Identity _defaultIdentity;
|
||||
std::vector<InetAddress> _defaultAddresses;
|
||||
Str _dnsName;
|
||||
Locator _lastFetchedLocator;
|
||||
unsigned int _dnsPublicKeySize;
|
||||
uint8_t _dnsPublicKey[ZT_ECC384_PUBLIC_KEY_SIZE];
|
||||
Mutex _lock;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif
|
23
node/Str.hpp
23
node/Str.hpp
@ -33,6 +33,8 @@
|
||||
#include "MAC.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
#define ZT_STR_CAPACITY 254
|
||||
|
||||
namespace ZeroTier {
|
||||
@ -58,6 +60,10 @@ public:
|
||||
_s[0] = 0;
|
||||
(*this) << s;
|
||||
}
|
||||
inline Str(const std::string &s)
|
||||
{
|
||||
*this = s;
|
||||
}
|
||||
|
||||
inline Str &operator=(const Str &s)
|
||||
{
|
||||
@ -71,6 +77,19 @@ public:
|
||||
_s[0] = 0;
|
||||
return ((*this) << s);
|
||||
}
|
||||
inline Str &operator=(const std::string &s)
|
||||
{
|
||||
if (s.length() > ZT_STR_CAPACITY) {
|
||||
_l = 0;
|
||||
_s[0] = 0;
|
||||
throw ZT_EXCEPTION_OUT_OF_BOUNDS;
|
||||
} else {
|
||||
_l = (uint8_t)s.length();
|
||||
memcpy(_s,s.data(),s.length());
|
||||
_s[s.length()] = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline char operator[](const unsigned int i) const
|
||||
{
|
||||
@ -82,6 +101,7 @@ public:
|
||||
inline void clear() { _l = 0; _s[0] = 0; }
|
||||
inline const char *c_str() const { return _s; }
|
||||
inline unsigned int length() const { return (unsigned int)_l; }
|
||||
inline bool empty() const { return (_l == 0); }
|
||||
inline iterator begin() { return (iterator)_s; }
|
||||
inline iterator end() { return (iterator)(_s + (unsigned long)_l); }
|
||||
inline const_iterator begin() const { return (const_iterator)_s; }
|
||||
@ -113,6 +133,7 @@ public:
|
||||
}
|
||||
_s[(unsigned long)(_l++)] = c;
|
||||
_s[(unsigned long)_l] = 0;
|
||||
return *this;
|
||||
}
|
||||
inline Str &operator<<(const unsigned long n)
|
||||
{
|
||||
@ -142,6 +163,8 @@ public:
|
||||
return ((*this) << a.toString(tmp));
|
||||
}
|
||||
|
||||
inline operator bool() const { return (_l != 0); }
|
||||
|
||||
inline bool operator==(const Str &s) const { return ((_l == s._l)&&(strcmp(_s,s._s) == 0)); }
|
||||
inline bool operator!=(const Str &s) const { return ((_l != s._l)||(strcmp(_s,s._s) != 0)); }
|
||||
inline bool operator<(const Str &s) const { return ((_l < s._l)&&(strcmp(_s,s._s) < 0)); }
|
||||
|
@ -73,7 +73,7 @@ void Switch::onRemotePacket(void *tPtr,const int64_t localSocket,const InetAddre
|
||||
return;
|
||||
if (!RR->node->shouldUsePathForZeroTierTraffic(tPtr,beaconAddr,localSocket,fromAddr))
|
||||
return;
|
||||
const SharedPtr<Peer> peer(RR->topology->getPeer(tPtr,beaconAddr));
|
||||
const SharedPtr<Peer> peer(RR->topology->get(beaconAddr));
|
||||
if (peer) { // we'll only respond to beacons from known peers
|
||||
if ((now - _lastBeaconResponse) >= 2500) { // limit rate of responses
|
||||
_lastBeaconResponse = now;
|
||||
@ -96,12 +96,13 @@ void Switch::onRemotePacket(void *tPtr,const int64_t localSocket,const InetAddre
|
||||
|
||||
// Note: we don't bother initiating NAT-t for fragments, since heads will set that off.
|
||||
// It wouldn't hurt anything, just redundant and unnecessary.
|
||||
SharedPtr<Peer> relayTo = RR->topology->getPeer(tPtr,destination);
|
||||
SharedPtr<Peer> relayTo = RR->topology->get(destination);
|
||||
if ((!relayTo)||(!relayTo->sendDirect(tPtr,fragment.data(),fragment.size(),now,false))) {
|
||||
// Don't know peer or no direct path -- so relay via someone upstream
|
||||
relayTo = RR->topology->getUpstreamPeer();
|
||||
if (relayTo)
|
||||
relayTo->sendDirect(tPtr,fragment.data(),fragment.size(),now,true);
|
||||
// TODO
|
||||
//relayTo = RR->topology->getUpstreamPeer();
|
||||
//if (relayTo)
|
||||
// relayTo->sendDirect(tPtr,fragment.data(),fragment.size(),now,true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -163,22 +164,25 @@ void Switch::onRemotePacket(void *tPtr,const int64_t localSocket,const InetAddre
|
||||
Packet packet(data,len);
|
||||
if (packet.hops() < ZT_RELAY_MAX_HOPS) {
|
||||
packet.incrementHops();
|
||||
SharedPtr<Peer> relayTo = RR->topology->getPeer(tPtr,destination);
|
||||
SharedPtr<Peer> relayTo = RR->topology->get(destination);
|
||||
if ((relayTo)&&(relayTo->sendDirect(tPtr,packet.data(),packet.size(),now,false))) {
|
||||
if ((source != RR->identity.address())&&(_shouldUnite(now,source,destination))) {
|
||||
const SharedPtr<Peer> sourcePeer(RR->topology->getPeer(tPtr,source));
|
||||
const SharedPtr<Peer> sourcePeer(RR->topology->get(source));
|
||||
if (sourcePeer)
|
||||
relayTo->introduce(tPtr,now,sourcePeer);
|
||||
}
|
||||
} else {
|
||||
// TODO
|
||||
/*
|
||||
relayTo = RR->topology->getUpstreamPeer();
|
||||
if ((relayTo)&&(relayTo->address() != source)) {
|
||||
if (relayTo->sendDirect(tPtr,packet.data(),packet.size(),now,true)) {
|
||||
const SharedPtr<Peer> sourcePeer(RR->topology->getPeer(tPtr,source));
|
||||
const SharedPtr<Peer> sourcePeer(RR->topology->get(source));
|
||||
if (sourcePeer)
|
||||
relayTo->introduce(tPtr,now,sourcePeer);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
} else if ((reinterpret_cast<const uint8_t *>(data)[ZT_PACKET_IDX_FLAGS] & ZT_PROTO_FLAG_FRAGMENTED) != 0) {
|
||||
@ -402,7 +406,7 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr<Network> &network,const
|
||||
// Destination is another ZeroTier peer on the same network
|
||||
|
||||
Address toZT(to.toAddress(network->id())); // since in-network MACs are derived from addresses and network IDs, we can reverse this
|
||||
SharedPtr<Peer> toPeer(RR->topology->getPeer(tPtr,toZT));
|
||||
SharedPtr<Peer> toPeer(RR->topology->get(toZT));
|
||||
|
||||
if (!network->filterOutgoingPacket(tPtr,false,RR->identity.address(),toZT,from,to,(const uint8_t *)data,len,etherType,vlanId,qosBucket)) {
|
||||
RR->t->outgoingNetworkFrameDropped(tPtr,network,from,to,etherType,vlanId,len,"filter blocked");
|
||||
@ -763,7 +767,7 @@ void Switch::send(void *tPtr,Packet &packet,bool encrypt)
|
||||
}
|
||||
_txQueue.push_back(TXQueueEntry(dest,RR->node->now(),packet,encrypt));
|
||||
}
|
||||
if (!RR->topology->getPeer(tPtr,dest))
|
||||
if (!RR->topology->get(dest))
|
||||
requestWhois(tPtr,RR->node->now(),dest);
|
||||
}
|
||||
}
|
||||
@ -781,6 +785,8 @@ void Switch::requestWhois(void *tPtr,const int64_t now,const Address &addr)
|
||||
else last = now;
|
||||
}
|
||||
|
||||
// TODO
|
||||
/*
|
||||
const SharedPtr<Peer> upstream(RR->topology->getUpstreamPeer());
|
||||
if (upstream) {
|
||||
Packet outp(upstream->address(),RR->identity.address(),Packet::VERB_WHOIS);
|
||||
@ -788,6 +794,7 @@ void Switch::requestWhois(void *tPtr,const int64_t now,const Address &addr)
|
||||
RR->node->expectReplyTo(outp.packetId());
|
||||
send(tPtr,outp,true);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void Switch::doAnythingWaitingForPeer(void *tPtr,const SharedPtr<Peer> &peer)
|
||||
@ -840,7 +847,7 @@ unsigned long Switch::doTimerTasks(void *tPtr,int64_t now)
|
||||
} else if ((now - txi->creationTime) > ZT_TRANSMIT_QUEUE_TIMEOUT) {
|
||||
_txQueue.erase(txi++);
|
||||
} else {
|
||||
if (!RR->topology->getPeer(tPtr,txi->dest))
|
||||
if (!RR->topology->get(txi->dest))
|
||||
needWhois.push_back(txi->dest);
|
||||
++txi;
|
||||
}
|
||||
@ -857,7 +864,7 @@ unsigned long Switch::doTimerTasks(void *tPtr,int64_t now)
|
||||
rq->timestamp = 0;
|
||||
} else {
|
||||
const Address src(rq->frag0.source());
|
||||
if (!RR->topology->getPeer(tPtr,src))
|
||||
if (!RR->topology->get(src))
|
||||
requestWhois(tPtr,now,src);
|
||||
}
|
||||
}
|
||||
@ -905,16 +912,19 @@ bool Switch::_trySend(void *tPtr,Packet &packet,bool encrypt)
|
||||
const int64_t now = RR->node->now();
|
||||
const Address destination(packet.destination());
|
||||
|
||||
const SharedPtr<Peer> peer(RR->topology->getPeer(tPtr,destination));
|
||||
const SharedPtr<Peer> peer(RR->topology->get(destination));
|
||||
if (peer) {
|
||||
viaPath = peer->getAppropriatePath(now,false);
|
||||
if (!viaPath) {
|
||||
// TODO
|
||||
/*
|
||||
peer->tryMemorizedPath(tPtr,now); // periodically attempt memorized or statically defined paths, if any are known
|
||||
const SharedPtr<Peer> relay(RR->topology->getUpstreamPeer());
|
||||
if ( (!relay) || (!(viaPath = relay->getAppropriatePath(now,false))) ) {
|
||||
if (!(viaPath = peer->getAppropriatePath(now,true)))
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "Mutex.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "Hashtable.hpp"
|
||||
#include "Root.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
@ -56,8 +57,9 @@ class RuntimeEnvironment;
|
||||
class Topology
|
||||
{
|
||||
public:
|
||||
inline Topology(const RuntimeEnvironment *renv,void *tPtr) :
|
||||
inline Topology(const RuntimeEnvironment *renv,const Identity &myId) :
|
||||
RR(renv),
|
||||
_myIdentity(myId),
|
||||
_numConfiguredPhysicalPaths(0) {}
|
||||
inline ~Topology() {}
|
||||
|
||||
@ -71,7 +73,7 @@ public:
|
||||
* @param peer Peer to add
|
||||
* @return New or existing peer (should replace 'peer')
|
||||
*/
|
||||
inline SharedPtr<Peer> addPeer(void *tPtr,const SharedPtr<Peer> &peer)
|
||||
inline SharedPtr<Peer> add(const SharedPtr<Peer> &peer)
|
||||
{
|
||||
SharedPtr<Peer> np;
|
||||
{
|
||||
@ -91,13 +93,28 @@ public:
|
||||
* @param zta ZeroTier address of peer
|
||||
* @return Peer or NULL if not found
|
||||
*/
|
||||
inline SharedPtr<Peer> getPeer(void *tPtr,const Address &zta) const
|
||||
inline SharedPtr<Peer> get(const Address &zta)
|
||||
{
|
||||
if (zta == RR->identity.address())
|
||||
if (zta == _myIdentity.address())
|
||||
return SharedPtr<Peer>();
|
||||
Mutex::Lock _l(_peers_m);
|
||||
|
||||
Mutex::Lock l1(_peers_m);
|
||||
const SharedPtr<Peer> *const ap = _peers.get(zta);
|
||||
return ((ap) ? *ap : SharedPtr<Peer>());
|
||||
if (ap)
|
||||
return *ap;
|
||||
|
||||
Mutex::Lock l2(_roots_m);
|
||||
for(std::vector<Root>::const_iterator r(_roots.begin());r!=_roots.end();++r) {
|
||||
if (r->address() == zta) {
|
||||
try {
|
||||
SharedPtr<Peer> rp(new Peer(RR,_myIdentity,r->id()));
|
||||
_peers[zta] = rp;
|
||||
return rp;
|
||||
} catch ( ... ) {}
|
||||
}
|
||||
}
|
||||
|
||||
return SharedPtr<Peer>();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -107,8 +124,8 @@ public:
|
||||
*/
|
||||
inline Identity getIdentity(void *tPtr,const Address &zta)
|
||||
{
|
||||
if (zta == RR->identity.address()) {
|
||||
return RR->identity;
|
||||
if (zta == _myIdentity.address()) {
|
||||
return _myIdentity;
|
||||
} else {
|
||||
Mutex::Lock _l(_peers_m);
|
||||
const SharedPtr<Peer> *const ap = _peers.get(zta);
|
||||
@ -118,25 +135,6 @@ public:
|
||||
return Identity();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a peer only if it is presently in memory (no disk cache)
|
||||
*
|
||||
* This also does not update the lastUsed() time for peers, which means
|
||||
* that it won't prevent them from falling out of RAM. This is currently
|
||||
* used in the Cluster code to update peer info without forcing all peers
|
||||
* across the entire cluster to remain in memory cache.
|
||||
*
|
||||
* @param zta ZeroTier address
|
||||
*/
|
||||
inline SharedPtr<Peer> getPeerNoCache(const Address &zta)
|
||||
{
|
||||
Mutex::Lock _l(_peers_m);
|
||||
const SharedPtr<Peer> *const ap = _peers.get(zta);
|
||||
if (ap)
|
||||
return *ap;
|
||||
return SharedPtr<Peer>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Path object for a given local and remote physical address, creating if needed
|
||||
*
|
||||
@ -153,36 +151,24 @@ public:
|
||||
return p;
|
||||
}
|
||||
|
||||
inline SharedPtr<Peer> getUpstreamPeer() const
|
||||
/**
|
||||
* @param id Identity to check
|
||||
* @return True if this identity corresponds to a root
|
||||
*/
|
||||
inline bool isRoot(const Identity &id) const
|
||||
{
|
||||
// TODO
|
||||
return SharedPtr<Peer>();
|
||||
}
|
||||
|
||||
inline bool isUpstream(const Identity &id) const
|
||||
{
|
||||
// TODO
|
||||
Mutex::Lock l(_roots_m);
|
||||
for(std::vector<Root>::const_iterator r(_roots.begin());r!=_roots.end();++r) {
|
||||
if (r->is(id))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline ZT_PeerRole role(const Address &ztaddr) const
|
||||
{
|
||||
// TODO
|
||||
return ZT_PEER_ROLE_LEAF;
|
||||
}
|
||||
|
||||
inline void getAlwaysContact(Hashtable< Address,std::vector<InetAddress> > &eps) const
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
inline std::vector<Address> upstreamAddresses() const
|
||||
{
|
||||
// TODO
|
||||
return std::vector<Address>();
|
||||
}
|
||||
|
||||
inline void doPeriodicTasks(void *tPtr,int64_t now)
|
||||
/**
|
||||
* Do periodic tasks such as database cleanup
|
||||
*/
|
||||
inline void doPeriodicTasks(int64_t now)
|
||||
{
|
||||
{
|
||||
Mutex::Lock _l1(_peers_m);
|
||||
@ -357,11 +343,14 @@ public:
|
||||
|
||||
private:
|
||||
const RuntimeEnvironment *const RR;
|
||||
const Identity _myIdentity;
|
||||
std::pair<InetAddress,ZT_PhysicalPathConfiguration> _physicalPathConfig[ZT_MAX_CONFIGURABLE_PATHS];
|
||||
unsigned int _numConfiguredPhysicalPaths;
|
||||
std::vector<Root> _roots;
|
||||
Hashtable< Address,SharedPtr<Peer> > _peers;
|
||||
Mutex _peers_m;
|
||||
Hashtable< Path::HashKey,SharedPtr<Path> > _paths;
|
||||
Mutex _roots_m;
|
||||
Mutex _peers_m;
|
||||
Mutex _paths_m;
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user