mirror of
https://github.com/ZeroTier/ZeroTierOne
synced 2025-08-14 10:37:33 -07:00
Replace long callback arg list with struct, and implement path whitelisting, path blacklisting, and local.conf support for roles.
This commit is contained in:
parent
cbaef66e82
commit
42ba70e79e
7 changed files with 302 additions and 217 deletions
|
@ -552,7 +552,7 @@ bool IncomingPacket::_doRENDEZVOUS(const RuntimeEnvironment *RR,const SharedPtr<
|
|||
const unsigned int addrlen = (*this)[ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRLEN];
|
||||
if ((port > 0)&&((addrlen == 4)||(addrlen == 16))) {
|
||||
const InetAddress atAddr(field(ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRESS,addrlen),addrlen,port);
|
||||
if (RR->node->shouldUsePathForZeroTierTraffic(_path->localAddress(),atAddr)) {
|
||||
if (RR->node->shouldUsePathForZeroTierTraffic(with,_path->localAddress(),atAddr)) {
|
||||
RR->node->putPacket(_path->localAddress(),atAddr,"ABRE",4,2); // send low-TTL junk packet to 'open' local NAT(s) and stateful firewalls
|
||||
rendezvousWith->attemptToContactAt(_path->localAddress(),atAddr,RR->node->now());
|
||||
TRACE("RENDEZVOUS from %s says %s might be at %s, sent verification attempt",peer->address().toString().c_str(),with.toString().c_str(),atAddr.toString().c_str());
|
||||
|
@ -1120,7 +1120,7 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,const Sha
|
|||
redundant = peer->hasActivePathTo(now,a);
|
||||
}
|
||||
|
||||
if ( ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_FORGET_PATH) == 0) && (!redundant) && (RR->node->shouldUsePathForZeroTierTraffic(_path->localAddress(),a)) ) {
|
||||
if ( ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_FORGET_PATH) == 0) && (!redundant) && (RR->node->shouldUsePathForZeroTierTraffic(peer->address(),_path->localAddress(),a)) ) {
|
||||
if (++countPerScope[(int)a.ipScope()][0] <= ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY) {
|
||||
TRACE("attempting to contact %s at pushed direct path %s",peer->address().toString().c_str(),a.toString().c_str());
|
||||
peer->attemptToContactAt(InetAddress(),a,now);
|
||||
|
@ -1139,7 +1139,7 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,const Sha
|
|||
redundant = peer->hasActivePathTo(now,a);
|
||||
}
|
||||
|
||||
if ( ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_FORGET_PATH) == 0) && (!redundant) && (RR->node->shouldUsePathForZeroTierTraffic(_path->localAddress(),a)) ) {
|
||||
if ( ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_FORGET_PATH) == 0) && (!redundant) && (RR->node->shouldUsePathForZeroTierTraffic(peer->address(),_path->localAddress(),a)) ) {
|
||||
if (++countPerScope[(int)a.ipScope()][1] <= ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY) {
|
||||
TRACE("attempting to contact %s at pushed direct path %s",peer->address().toString().c_str(),a.toString().c_str());
|
||||
peer->attemptToContactAt(InetAddress(),a,now);
|
||||
|
|
|
@ -46,34 +46,20 @@ namespace ZeroTier {
|
|||
/* Public Node interface (C++, exposed via CAPI bindings) */
|
||||
/****************************************************************************/
|
||||
|
||||
Node::Node(
|
||||
uint64_t now,
|
||||
void *uptr,
|
||||
ZT_DataStoreGetFunction dataStoreGetFunction,
|
||||
ZT_DataStorePutFunction dataStorePutFunction,
|
||||
ZT_WirePacketSendFunction wirePacketSendFunction,
|
||||
ZT_VirtualNetworkFrameFunction virtualNetworkFrameFunction,
|
||||
ZT_VirtualNetworkConfigFunction virtualNetworkConfigFunction,
|
||||
ZT_PathCheckFunction pathCheckFunction,
|
||||
ZT_EventCallback eventCallback) :
|
||||
Node::Node(void *uptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now) :
|
||||
_RR(this),
|
||||
RR(&_RR),
|
||||
_uPtr(uptr),
|
||||
_dataStoreGetFunction(dataStoreGetFunction),
|
||||
_dataStorePutFunction(dataStorePutFunction),
|
||||
_wirePacketSendFunction(wirePacketSendFunction),
|
||||
_virtualNetworkFrameFunction(virtualNetworkFrameFunction),
|
||||
_virtualNetworkConfigFunction(virtualNetworkConfigFunction),
|
||||
_pathCheckFunction(pathCheckFunction),
|
||||
_eventCallback(eventCallback),
|
||||
_networks(),
|
||||
_networks_m(),
|
||||
_prngStreamPtr(0),
|
||||
_now(now),
|
||||
_lastPingCheck(0),
|
||||
_lastHousekeepingRun(0),
|
||||
_relayPolicy(ZT_RELAY_POLICY_TRUSTED)
|
||||
{
|
||||
if (callbacks->version != 0)
|
||||
throw std::runtime_error("callbacks struct version mismatch");
|
||||
memcpy(&_cb,callbacks,sizeof(ZT_Node_Callbacks));
|
||||
|
||||
_online = false;
|
||||
|
||||
memset(_expectingRepliesToBucketPtr,0,sizeof(_expectingRepliesToBucketPtr));
|
||||
|
@ -81,30 +67,26 @@ Node::Node(
|
|||
memset(_lastIdentityVerification,0,sizeof(_lastIdentityVerification));
|
||||
|
||||
// Use Salsa20 alone as a high-quality non-crypto PRNG
|
||||
{
|
||||
char foo[32];
|
||||
Utils::getSecureRandom(foo,32);
|
||||
_prng.init(foo,256,foo);
|
||||
memset(_prngStream,0,sizeof(_prngStream));
|
||||
_prng.encrypt12(_prngStream,_prngStream,sizeof(_prngStream));
|
||||
}
|
||||
char foo[32];
|
||||
Utils::getSecureRandom(foo,32);
|
||||
_prng.init(foo,256,foo);
|
||||
memset(_prngStream,0,sizeof(_prngStream));
|
||||
_prng.encrypt12(_prngStream,_prngStream,sizeof(_prngStream));
|
||||
|
||||
{
|
||||
std::string idtmp(dataStoreGet("identity.secret"));
|
||||
if ((!idtmp.length())||(!RR->identity.fromString(idtmp))||(!RR->identity.hasPrivate())) {
|
||||
TRACE("identity.secret not found, generating...");
|
||||
RR->identity.generate();
|
||||
idtmp = RR->identity.toString(true);
|
||||
if (!dataStorePut("identity.secret",idtmp,true))
|
||||
throw std::runtime_error("unable to write identity.secret");
|
||||
}
|
||||
RR->publicIdentityStr = RR->identity.toString(false);
|
||||
RR->secretIdentityStr = RR->identity.toString(true);
|
||||
idtmp = dataStoreGet("identity.public");
|
||||
if (idtmp != RR->publicIdentityStr) {
|
||||
if (!dataStorePut("identity.public",RR->publicIdentityStr,false))
|
||||
throw std::runtime_error("unable to write identity.public");
|
||||
}
|
||||
std::string idtmp(dataStoreGet("identity.secret"));
|
||||
if ((!idtmp.length())||(!RR->identity.fromString(idtmp))||(!RR->identity.hasPrivate())) {
|
||||
TRACE("identity.secret not found, generating...");
|
||||
RR->identity.generate();
|
||||
idtmp = RR->identity.toString(true);
|
||||
if (!dataStorePut("identity.secret",idtmp,true))
|
||||
throw std::runtime_error("unable to write identity.secret");
|
||||
}
|
||||
RR->publicIdentityStr = RR->identity.toString(false);
|
||||
RR->secretIdentityStr = RR->identity.toString(true);
|
||||
idtmp = dataStoreGet("identity.public");
|
||||
if (idtmp != RR->publicIdentityStr) {
|
||||
if (!dataStorePut("identity.public",RR->publicIdentityStr,false))
|
||||
throw std::runtime_error("unable to write identity.public");
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -638,7 +620,7 @@ std::string Node::dataStoreGet(const char *name)
|
|||
std::string r;
|
||||
unsigned long olen = 0;
|
||||
do {
|
||||
long n = _dataStoreGetFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,name,buf,sizeof(buf),(unsigned long)r.length(),&olen);
|
||||
long n = _cb.dataStoreGetFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,name,buf,sizeof(buf),(unsigned long)r.length(),&olen);
|
||||
if (n <= 0)
|
||||
return std::string();
|
||||
r.append(buf,n);
|
||||
|
@ -646,7 +628,7 @@ std::string Node::dataStoreGet(const char *name)
|
|||
return r;
|
||||
}
|
||||
|
||||
bool Node::shouldUsePathForZeroTierTraffic(const InetAddress &localAddress,const InetAddress &remoteAddress)
|
||||
bool Node::shouldUsePathForZeroTierTraffic(const Address &ztaddr,const InetAddress &localAddress,const InetAddress &remoteAddress)
|
||||
{
|
||||
if (!Path::isAddressValidForPath(remoteAddress))
|
||||
return false;
|
||||
|
@ -663,9 +645,7 @@ bool Node::shouldUsePathForZeroTierTraffic(const InetAddress &localAddress,const
|
|||
}
|
||||
}
|
||||
|
||||
if (_pathCheckFunction)
|
||||
return (_pathCheckFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,reinterpret_cast<const struct sockaddr_storage *>(&localAddress),reinterpret_cast<const struct sockaddr_storage *>(&remoteAddress)) != 0);
|
||||
else return true;
|
||||
return ( (_cb.pathCheckFunction) ? (_cb.pathCheckFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,ztaddr.toInt(),reinterpret_cast<const struct sockaddr_storage *>(&localAddress),reinterpret_cast<const struct sockaddr_storage *>(&remoteAddress)) != 0) : true);
|
||||
}
|
||||
|
||||
#ifdef ZT_TRACE
|
||||
|
@ -822,21 +802,11 @@ void Node::ncSendError(uint64_t nwid,uint64_t requestPacketId,const Address &des
|
|||
|
||||
extern "C" {
|
||||
|
||||
enum ZT_ResultCode ZT_Node_new(
|
||||
ZT_Node **node,
|
||||
void *uptr,
|
||||
uint64_t now,
|
||||
ZT_DataStoreGetFunction dataStoreGetFunction,
|
||||
ZT_DataStorePutFunction dataStorePutFunction,
|
||||
ZT_WirePacketSendFunction wirePacketSendFunction,
|
||||
ZT_VirtualNetworkFrameFunction virtualNetworkFrameFunction,
|
||||
ZT_VirtualNetworkConfigFunction virtualNetworkConfigFunction,
|
||||
ZT_PathCheckFunction pathCheckFunction,
|
||||
ZT_EventCallback eventCallback)
|
||||
enum ZT_ResultCode ZT_Node_new(ZT_Node **node,void *uptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now)
|
||||
{
|
||||
*node = (ZT_Node *)0;
|
||||
try {
|
||||
*node = reinterpret_cast<ZT_Node *>(new ZeroTier::Node(now,uptr,dataStoreGetFunction,dataStorePutFunction,wirePacketSendFunction,virtualNetworkFrameFunction,virtualNetworkConfigFunction,pathCheckFunction,eventCallback));
|
||||
*node = reinterpret_cast<ZT_Node *>(new ZeroTier::Node(uptr,callbacks,now));
|
||||
return ZT_RESULT_OK;
|
||||
} catch (std::bad_alloc &exc) {
|
||||
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
|
||||
|
|
|
@ -59,17 +59,7 @@ namespace ZeroTier {
|
|||
class Node : public NetworkController::Sender
|
||||
{
|
||||
public:
|
||||
Node(
|
||||
uint64_t now,
|
||||
void *uptr,
|
||||
ZT_DataStoreGetFunction dataStoreGetFunction,
|
||||
ZT_DataStorePutFunction dataStorePutFunction,
|
||||
ZT_WirePacketSendFunction wirePacketSendFunction,
|
||||
ZT_VirtualNetworkFrameFunction virtualNetworkFrameFunction,
|
||||
ZT_VirtualNetworkConfigFunction virtualNetworkConfigFunction,
|
||||
ZT_PathCheckFunction pathCheckFunction,
|
||||
ZT_EventCallback eventCallback);
|
||||
|
||||
Node(void *uptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now);
|
||||
virtual ~Node();
|
||||
|
||||
// Public API Functions ----------------------------------------------------
|
||||
|
@ -127,24 +117,11 @@ public:
|
|||
|
||||
// Internal functions ------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @return Time as of last call to run()
|
||||
*/
|
||||
inline uint64_t now() const throw() { return _now; }
|
||||
|
||||
/**
|
||||
* Enqueue a ZeroTier message to be sent
|
||||
*
|
||||
* @param localAddress Local address
|
||||
* @param addr Destination address
|
||||
* @param data Packet data
|
||||
* @param len Packet length
|
||||
* @param ttl Desired TTL (default: 0 for unchanged/default TTL)
|
||||
* @return True if packet appears to have been sent
|
||||
*/
|
||||
inline bool putPacket(const InetAddress &localAddress,const InetAddress &addr,const void *data,unsigned int len,unsigned int ttl = 0)
|
||||
{
|
||||
return (_wirePacketSendFunction(
|
||||
return (_cb.wirePacketSendFunction(
|
||||
reinterpret_cast<ZT_Node *>(this),
|
||||
_uPtr,
|
||||
reinterpret_cast<const struct sockaddr_storage *>(&localAddress),
|
||||
|
@ -154,21 +131,9 @@ public:
|
|||
ttl) == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue a frame to be injected into a tap device (port)
|
||||
*
|
||||
* @param nwid Network ID
|
||||
* @param nuptr Network user ptr
|
||||
* @param source Source MAC
|
||||
* @param dest Destination MAC
|
||||
* @param etherType 16-bit ethernet type
|
||||
* @param vlanId VLAN ID or 0 if none
|
||||
* @param data Frame data
|
||||
* @param len Frame length
|
||||
*/
|
||||
inline void putFrame(uint64_t nwid,void **nuptr,const MAC &source,const MAC &dest,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len)
|
||||
{
|
||||
_virtualNetworkFrameFunction(
|
||||
_cb.virtualNetworkFrameFunction(
|
||||
reinterpret_cast<ZT_Node *>(this),
|
||||
_uPtr,
|
||||
nwid,
|
||||
|
@ -181,13 +146,6 @@ public:
|
|||
len);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param localAddress Local address
|
||||
* @param remoteAddress Remote address
|
||||
* @return True if path should be used
|
||||
*/
|
||||
bool shouldUsePathForZeroTierTraffic(const InetAddress &localAddress,const InetAddress &remoteAddress);
|
||||
|
||||
inline SharedPtr<Network> network(uint64_t nwid) const
|
||||
{
|
||||
Mutex::Lock _l(_networks_m);
|
||||
|
@ -214,37 +172,20 @@ public:
|
|||
return nw;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Potential direct paths to me a.k.a. local interface addresses
|
||||
*/
|
||||
inline std::vector<InetAddress> directPaths() const
|
||||
{
|
||||
Mutex::Lock _l(_directPaths_m);
|
||||
return _directPaths;
|
||||
}
|
||||
|
||||
inline bool dataStorePut(const char *name,const void *data,unsigned int len,bool secure) { return (_dataStorePutFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,name,data,len,(int)secure) == 0); }
|
||||
inline bool dataStorePut(const char *name,const void *data,unsigned int len,bool secure) { return (_cb.dataStorePutFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,name,data,len,(int)secure) == 0); }
|
||||
inline bool dataStorePut(const char *name,const std::string &data,bool secure) { return dataStorePut(name,(const void *)data.data(),(unsigned int)data.length(),secure); }
|
||||
inline void dataStoreDelete(const char *name) { _dataStorePutFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,name,(const void *)0,0,0); }
|
||||
inline void dataStoreDelete(const char *name) { _cb.dataStorePutFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,name,(const void *)0,0,0); }
|
||||
std::string dataStoreGet(const char *name);
|
||||
|
||||
/**
|
||||
* Post an event to the external user
|
||||
*
|
||||
* @param ev Event type
|
||||
* @param md Meta-data (default: NULL/none)
|
||||
*/
|
||||
inline void postEvent(ZT_Event ev,const void *md = (const void *)0) { _eventCallback(reinterpret_cast<ZT_Node *>(this),_uPtr,ev,md); }
|
||||
inline void postEvent(ZT_Event ev,const void *md = (const void *)0) { _cb.eventCallback(reinterpret_cast<ZT_Node *>(this),_uPtr,ev,md); }
|
||||
|
||||
/**
|
||||
* Update virtual network port configuration
|
||||
*
|
||||
* @param nwid Network ID
|
||||
* @param nuptr Network user ptr
|
||||
* @param op Configuration operation
|
||||
* @param nc Network configuration
|
||||
*/
|
||||
inline int configureVirtualNetworkPort(uint64_t nwid,void **nuptr,ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nc) { return _virtualNetworkConfigFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,nwid,nuptr,op,nc); }
|
||||
inline int configureVirtualNetworkPort(uint64_t nwid,void **nuptr,ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nc) { return _cb.virtualNetworkConfigFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,nwid,nuptr,op,nc); }
|
||||
|
||||
inline bool online() const throw() { return _online; }
|
||||
inline ZT_RelayPolicy relayPolicy() const { return _relayPolicy; }
|
||||
|
@ -253,6 +194,9 @@ public:
|
|||
void postTrace(const char *module,unsigned int line,const char *fmt,...);
|
||||
#endif
|
||||
|
||||
bool shouldUsePathForZeroTierTraffic(const Address &ztaddr,const InetAddress &localAddress,const InetAddress &remoteAddress);
|
||||
inline bool getPathHint(const Address &ztaddr,int family,InetAddress &addr) { return ( (_cb.pathLookupFunction) ? (_cb.pathLookupFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,ztaddr.toInt(),family,reinterpret_cast<struct sockaddr_storage *>(&addr)) != 0) : false ); }
|
||||
|
||||
uint64_t prng();
|
||||
void postCircuitTestReport(const ZT_CircuitTestReport *report);
|
||||
void setTrustedPaths(const struct sockaddr_storage *networks,const uint64_t *ids,unsigned int count);
|
||||
|
@ -317,8 +261,8 @@ private:
|
|||
|
||||
RuntimeEnvironment _RR;
|
||||
RuntimeEnvironment *RR;
|
||||
|
||||
void *_uPtr; // _uptr (lower case) is reserved in Visual Studio :P
|
||||
ZT_Node_Callbacks _cb;
|
||||
|
||||
// For tracking packet IDs to filter out OK/ERROR replies to packets we did not send
|
||||
uint8_t _expectingRepliesToBucketPtr[ZT_EXPECTING_REPLIES_BUCKET_MASK1 + 1];
|
||||
|
@ -327,14 +271,6 @@ private:
|
|||
// Time of last identity verification indexed by InetAddress.rateGateHash()
|
||||
uint64_t _lastIdentityVerification[16384];
|
||||
|
||||
ZT_DataStoreGetFunction _dataStoreGetFunction;
|
||||
ZT_DataStorePutFunction _dataStorePutFunction;
|
||||
ZT_WirePacketSendFunction _wirePacketSendFunction;
|
||||
ZT_VirtualNetworkFrameFunction _virtualNetworkFrameFunction;
|
||||
ZT_VirtualNetworkConfigFunction _virtualNetworkConfigFunction;
|
||||
ZT_PathCheckFunction _pathCheckFunction;
|
||||
ZT_EventCallback _eventCallback;
|
||||
|
||||
std::vector< std::pair< uint64_t, SharedPtr<Network> > > _networks;
|
||||
Mutex _networks_m;
|
||||
|
||||
|
|
|
@ -160,7 +160,7 @@ void Peer::received(
|
|||
}
|
||||
}
|
||||
|
||||
if ( (!pathIsConfirmed) && (RR->node->shouldUsePathForZeroTierTraffic(path->localAddress(),path->address())) ) {
|
||||
if ( (!pathIsConfirmed) && (RR->node->shouldUsePathForZeroTierTraffic(_id.address(),path->localAddress(),path->address())) ) {
|
||||
if (verb == Packet::VERB_OK) {
|
||||
Mutex::Lock _l(_paths_m);
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from
|
|||
Address beaconAddr(reinterpret_cast<const char *>(data) + 8,5);
|
||||
if (beaconAddr == RR->identity.address())
|
||||
return;
|
||||
if (!RR->node->shouldUsePathForZeroTierTraffic(localAddr,fromAddr))
|
||||
if (!RR->node->shouldUsePathForZeroTierTraffic(beaconAddr,localAddr,fromAddr))
|
||||
return;
|
||||
SharedPtr<Peer> peer(RR->topology->getPeer(beaconAddr));
|
||||
if (peer) { // we'll only respond to beacons from known peers
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue