mirror of
https://github.com/ZeroTier/ZeroTierOne
synced 2025-08-20 13:24:09 -07:00
Implement relay policy, and setting multicast limit to 0 now disables multicast on the network as would be expected.
This commit is contained in:
parent
ced8dfc639
commit
5b6d27e659
12 changed files with 159 additions and 83 deletions
|
@ -350,6 +350,11 @@
|
|||
*/
|
||||
#define ZT_PUSH_DIRECT_PATHS_CUTOFF_LIMIT 5
|
||||
|
||||
/**
|
||||
* Maximum number of paths per IP scope (e.g. global, link-local) and family (e.g. v4/v6)
|
||||
*/
|
||||
#define ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY 4
|
||||
|
||||
/**
|
||||
* Time horizon for VERB_NETWORK_CREDENTIALS cutoff
|
||||
*/
|
||||
|
@ -366,9 +371,9 @@
|
|||
#define ZT_PEER_GENERAL_RATE_LIMIT 1000
|
||||
|
||||
/**
|
||||
* Maximum number of paths per IP scope (e.g. global, link-local) and family (e.g. v4/v6)
|
||||
* How long is a path or peer considered to have a trust relationship with us (for e.g. relay policy) since last trusted established packet?
|
||||
*/
|
||||
#define ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY 4
|
||||
#define ZT_TRUST_EXPIRATION 600000
|
||||
|
||||
/**
|
||||
* Enable support for older network configurations from older (pre-1.1.6) controllers
|
||||
|
|
|
@ -670,8 +670,14 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,const SharedPtr<P
|
|||
peer->received(_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay
|
||||
return true;
|
||||
}
|
||||
} else if ( (to != network->mac()) && (!to.isMulticast()) ) {
|
||||
if (!network->config().permitsBridging(RR->identity.address())) {
|
||||
} else if (to != network->mac()) {
|
||||
if (to.isMulticast()) {
|
||||
if (network->config().multicastLimit == 0) {
|
||||
TRACE("dropped EXT_FRAME from %s@%s(%s) to %s: network %.16llx does not allow multicast",from.toString().c_str(),peer->address().toString().c_str(),_path->address().toString().c_str(),to.toString().c_str(),network->id());
|
||||
peer->received(_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay
|
||||
return true;
|
||||
}
|
||||
} else if (!network->config().permitsBridging(RR->identity.address())) {
|
||||
TRACE("dropped EXT_FRAME from %s@%s(%s) to %s: I cannot bridge to %.16llx or bridging disabled on network",from.toString().c_str(),peer->address().toString().c_str(),_path->address().toString().c_str(),to.toString().c_str(),network->id());
|
||||
peer->received(_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay
|
||||
return true;
|
||||
|
@ -1038,6 +1044,12 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,const Share
|
|||
return true;
|
||||
}
|
||||
|
||||
if (network->config().multicastLimit == 0) {
|
||||
TRACE("dropped MULTICAST_FRAME from %s(%s): network %.16llx does not allow multicast",peer->address().toString().c_str(),_path->address().toString().c_str(),(unsigned long long)network->id());
|
||||
peer->received(_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,false);
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned int gatherLimit = 0;
|
||||
if ((flags & 0x02) != 0) {
|
||||
gatherLimit = at<uint32_t>(offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_GATHER_LIMIT);
|
||||
|
|
|
@ -71,7 +71,8 @@ Node::Node(
|
|||
_prngStreamPtr(0),
|
||||
_now(now),
|
||||
_lastPingCheck(0),
|
||||
_lastHousekeepingRun(0)
|
||||
_lastHousekeepingRun(0),
|
||||
_relayPolicy(ZT_RELAY_POLICY_TRUSTED)
|
||||
{
|
||||
_online = false;
|
||||
|
||||
|
@ -118,6 +119,9 @@ Node::Node(
|
|||
throw;
|
||||
}
|
||||
|
||||
if (RR->topology->amRoot())
|
||||
_relayPolicy = ZT_RELAY_POLICY_ALWAYS;
|
||||
|
||||
postEvent(ZT_EVENT_UP);
|
||||
}
|
||||
|
||||
|
@ -131,6 +135,7 @@ Node::~Node()
|
|||
delete RR->topology;
|
||||
delete RR->mc;
|
||||
delete RR->sw;
|
||||
|
||||
#ifdef ZT_ENABLE_CLUSTER
|
||||
delete RR->cluster;
|
||||
#endif
|
||||
|
@ -319,6 +324,12 @@ ZT_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *nextB
|
|||
return ZT_RESULT_OK;
|
||||
}
|
||||
|
||||
ZT_ResultCode Node::setRelayPolicy(enum ZT_RelayPolicy rp)
|
||||
{
|
||||
_relayPolicy = rp;
|
||||
return ZT_RESULT_OK;
|
||||
}
|
||||
|
||||
ZT_ResultCode Node::join(uint64_t nwid,void *uptr)
|
||||
{
|
||||
Mutex::Lock _l(_networks_m);
|
||||
|
@ -824,6 +835,15 @@ enum ZT_ResultCode ZT_Node_processBackgroundTasks(ZT_Node *node,uint64_t now,vol
|
|||
}
|
||||
}
|
||||
|
||||
enum ZT_ResultCode ZT_Node_setRelayPolicy(ZT_Node *node,enum ZT_RelayPolicy rp)
|
||||
{
|
||||
try {
|
||||
return reinterpret_cast<ZeroTier::Node *>(node)->setRelayPolicy(rp);
|
||||
} catch ( ... ) {
|
||||
return ZT_RESULT_FATAL_ERROR_INTERNAL;
|
||||
}
|
||||
}
|
||||
|
||||
enum ZT_ResultCode ZT_Node_join(ZT_Node *node,uint64_t nwid,void *uptr)
|
||||
{
|
||||
try {
|
||||
|
|
|
@ -91,6 +91,7 @@ public:
|
|||
unsigned int frameLength,
|
||||
volatile uint64_t *nextBackgroundTaskDeadline);
|
||||
ZT_ResultCode processBackgroundTasks(uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline);
|
||||
ZT_ResultCode setRelayPolicy(enum ZT_RelayPolicy rp);
|
||||
ZT_ResultCode join(uint64_t nwid,void *uptr);
|
||||
ZT_ResultCode leave(uint64_t nwid,void **uptr);
|
||||
ZT_ResultCode multicastSubscribe(uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi);
|
||||
|
@ -245,6 +246,7 @@ public:
|
|||
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 bool online() const throw() { return _online; }
|
||||
inline ZT_RelayPolicy relayPolicy() const { return _relayPolicy; }
|
||||
|
||||
#ifdef ZT_TRACE
|
||||
void postTrace(const char *module,unsigned int line,const char *fmt,...);
|
||||
|
@ -326,6 +328,7 @@ private:
|
|||
uint64_t _now;
|
||||
uint64_t _lastPingCheck;
|
||||
uint64_t _lastHousekeepingRun;
|
||||
ZT_RelayPolicy _relayPolicy;
|
||||
bool _online;
|
||||
};
|
||||
|
||||
|
|
|
@ -104,6 +104,7 @@ public:
|
|||
Path() :
|
||||
_lastOut(0),
|
||||
_lastIn(0),
|
||||
_lastTrustEstablishedPacketReceived(0),
|
||||
_addr(),
|
||||
_localAddress(),
|
||||
_ipScope(InetAddress::IP_SCOPE_NONE)
|
||||
|
@ -113,6 +114,7 @@ public:
|
|||
Path(const InetAddress &localAddress,const InetAddress &addr) :
|
||||
_lastOut(0),
|
||||
_lastIn(0),
|
||||
_lastTrustEstablishedPacketReceived(0),
|
||||
_addr(addr),
|
||||
_localAddress(localAddress),
|
||||
_ipScope(addr.ipScope())
|
||||
|
@ -126,6 +128,11 @@ public:
|
|||
*/
|
||||
inline void received(const uint64_t t) { _lastIn = t; }
|
||||
|
||||
/**
|
||||
* Set time last trusted packet was received (done in Peer::received())
|
||||
*/
|
||||
inline void trustedPacketReceived(const uint64_t t) { _lastTrustEstablishedPacketReceived = t; }
|
||||
|
||||
/**
|
||||
* Send a packet via this path (last out time is also updated)
|
||||
*
|
||||
|
@ -159,6 +166,11 @@ public:
|
|||
*/
|
||||
inline InetAddress::IpScope ipScope() const { return _ipScope; }
|
||||
|
||||
/**
|
||||
* @return True if path has received a trust established packet (e.g. common network membership) in the past ZT_TRUST_EXPIRATION ms
|
||||
*/
|
||||
inline bool trustEstablished(const uint64_t now) const { return ((now - _lastTrustEstablishedPacketReceived) < ZT_TRUST_EXPIRATION); }
|
||||
|
||||
/**
|
||||
* @return Preference rank, higher == better
|
||||
*/
|
||||
|
@ -232,6 +244,7 @@ public:
|
|||
private:
|
||||
uint64_t _lastOut;
|
||||
uint64_t _lastIn;
|
||||
uint64_t _lastTrustEstablishedPacketReceived;
|
||||
InetAddress _addr;
|
||||
InetAddress _localAddress;
|
||||
InetAddress::IpScope _ipScope; // memoize this since it's a computed value checked often
|
||||
|
|
|
@ -52,6 +52,7 @@ Peer::Peer(const RuntimeEnvironment *renv,const Identity &myIdentity,const Ident
|
|||
_lastEchoRequestReceived(0),
|
||||
_lastComRequestReceived(0),
|
||||
_lastCredentialsReceived(0),
|
||||
_lastTrustEstablishedPacketReceived(0),
|
||||
RR(renv),
|
||||
_remoteClusterOptimal4(0),
|
||||
_vProto(0),
|
||||
|
@ -132,6 +133,11 @@ void Peer::received(
|
|||
else if (verb == Packet::VERB_MULTICAST_FRAME)
|
||||
_lastMulticastFrame = now;
|
||||
|
||||
if (trustEstablished) {
|
||||
_lastTrustEstablishedPacketReceived = now;
|
||||
path->trustedPacketReceived(now);
|
||||
}
|
||||
|
||||
if (hops == 0) {
|
||||
bool pathIsConfirmed = false;
|
||||
{
|
||||
|
|
|
@ -312,7 +312,7 @@ public:
|
|||
/**
|
||||
* @return 256-bit secret symmetric encryption key
|
||||
*/
|
||||
inline const unsigned char *key() const throw() { return _key; }
|
||||
inline const unsigned char *key() const { return _key; }
|
||||
|
||||
/**
|
||||
* Set the currently known remote version of this peer's client
|
||||
|
@ -330,12 +330,17 @@ public:
|
|||
_vRevision = (uint16_t)vrev;
|
||||
}
|
||||
|
||||
inline unsigned int remoteVersionProtocol() const throw() { return _vProto; }
|
||||
inline unsigned int remoteVersionMajor() const throw() { return _vMajor; }
|
||||
inline unsigned int remoteVersionMinor() const throw() { return _vMinor; }
|
||||
inline unsigned int remoteVersionRevision() const throw() { return _vRevision; }
|
||||
inline unsigned int remoteVersionProtocol() const { return _vProto; }
|
||||
inline unsigned int remoteVersionMajor() const { return _vMajor; }
|
||||
inline unsigned int remoteVersionMinor() const { return _vMinor; }
|
||||
inline unsigned int remoteVersionRevision() const { return _vRevision; }
|
||||
|
||||
inline bool remoteVersionKnown() const throw() { return ((_vMajor > 0)||(_vMinor > 0)||(_vRevision > 0)); }
|
||||
inline bool remoteVersionKnown() const { return ((_vMajor > 0)||(_vMinor > 0)||(_vRevision > 0)); }
|
||||
|
||||
/**
|
||||
* @return True if peer has received a trust established packet (e.g. common network membership) in the past ZT_TRUST_EXPIRATION ms
|
||||
*/
|
||||
inline bool trustEstablished(const uint64_t now) const { return ((now - _lastTrustEstablishedPacketReceived) < ZT_TRUST_EXPIRATION); }
|
||||
|
||||
/**
|
||||
* Rate limit gate for VERB_PUSH_DIRECT_PATHS
|
||||
|
@ -470,6 +475,7 @@ private:
|
|||
uint64_t _lastEchoRequestReceived;
|
||||
uint64_t _lastComRequestReceived;
|
||||
uint64_t _lastCredentialsReceived;
|
||||
uint64_t _lastTrustEstablishedPacketReceived;
|
||||
const RuntimeEnvironment *RR;
|
||||
uint32_t _remoteClusterOptimal4;
|
||||
uint16_t _vProto;
|
||||
|
|
|
@ -105,7 +105,18 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from
|
|||
const Address destination(fragment.destination());
|
||||
|
||||
if (destination != RR->identity.address()) {
|
||||
// Fragment is not for us, so try to relay it
|
||||
switch(RR->node->relayPolicy()) {
|
||||
case ZT_RELAY_POLICY_ALWAYS:
|
||||
break;
|
||||
case ZT_RELAY_POLICY_TRUSTED:
|
||||
if (!path->trustEstablished(now))
|
||||
return;
|
||||
break;
|
||||
// case ZT_RELAY_POLICY_NEVER:
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (fragment.hops() < ZT_RELAY_MAX_HOPS) {
|
||||
fragment.incrementHops();
|
||||
|
||||
|
@ -203,9 +214,20 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from
|
|||
//TRACE("<< %.16llx %s -> %s (size: %u)",(unsigned long long)packet->packetId(),source.toString().c_str(),destination.toString().c_str(),packet->size());
|
||||
|
||||
if (destination != RR->identity.address()) {
|
||||
switch(RR->node->relayPolicy()) {
|
||||
case ZT_RELAY_POLICY_ALWAYS:
|
||||
break;
|
||||
case ZT_RELAY_POLICY_TRUSTED:
|
||||
if (!path->trustEstablished(now))
|
||||
return;
|
||||
break;
|
||||
// case ZT_RELAY_POLICY_NEVER:
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
Packet packet(data,len);
|
||||
|
||||
// Packet is not for us, so try to relay it
|
||||
if (packet.hops() < ZT_RELAY_MAX_HOPS) {
|
||||
packet.incrementHops();
|
||||
|
||||
|
@ -327,6 +349,11 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
|
|||
}
|
||||
|
||||
if (to.isMulticast()) {
|
||||
if (network->config().multicastLimit == 0) {
|
||||
TRACE("%.16llx: dropped multicast: not allowed on network",network->id());
|
||||
return;
|
||||
}
|
||||
|
||||
// Destination is a multicast address (including broadcast)
|
||||
MulticastGroup mg(to,0);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue