Simply network auth logic and always sent error on auth failure even for unknown networks to prevent forensics.

This commit is contained in:
Adam Ierymenko 2016-09-27 13:49:43 -07:00
parent 5ba7ca91c0
commit 9f550292fe
7 changed files with 64 additions and 61 deletions

View file

@ -169,7 +169,7 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,const SharedPtr<Peer>
// Peers can send this in response to frames if they do not have a recent enough COM from us // Peers can send this in response to frames if they do not have a recent enough COM from us
const SharedPtr<Network> network(RR->node->network(at<uint64_t>(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD))); const SharedPtr<Network> network(RR->node->network(at<uint64_t>(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD)));
const uint64_t now = RR->node->now(); const uint64_t now = RR->node->now();
if ( (network) && (network->config().com) && (peer->rateGateComRequest(now)) ) if ( (network) && (network->config().com) && (peer->rateGateIncomingComRequest(now)) )
network->pushCredentialsNow(peer->address(),now); network->pushCredentialsNow(peer->address(),now);
} break; } break;
@ -184,7 +184,7 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,const SharedPtr<Peer>
// Members of networks can use this error to indicate that they no longer // Members of networks can use this error to indicate that they no longer
// want to receive multicasts on a given channel. // want to receive multicasts on a given channel.
const SharedPtr<Network> network(RR->node->network(at<uint64_t>(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD))); const SharedPtr<Network> network(RR->node->network(at<uint64_t>(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD)));
if ((network)&&(network->gate(peer,verb(),packetId()))) { if ((network)&&(network->gate(peer))) {
const MulticastGroup mg(MAC(field(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD + 8,6),6),at<uint32_t>(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD + 14)); const MulticastGroup mg(MAC(field(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD + 8,6),6),at<uint32_t>(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD + 14));
TRACE("%.16llx: peer %s unsubscrubed from multicast group %s",network->id(),peer->address().toString().c_str(),mg.toString().c_str()); TRACE("%.16llx: peer %s unsubscrubed from multicast group %s",network->id(),peer->address().toString().c_str(),mg.toString().c_str());
RR->mc->remove(network->id(),mg,peer->address()); RR->mc->remove(network->id(),mg,peer->address());
@ -375,7 +375,6 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &p
try { try {
const Packet::Verb inReVerb = (Packet::Verb)(*this)[ZT_PROTO_VERB_OK_IDX_IN_RE_VERB]; const Packet::Verb inReVerb = (Packet::Verb)(*this)[ZT_PROTO_VERB_OK_IDX_IN_RE_VERB];
const uint64_t inRePacketId = at<uint64_t>(ZT_PROTO_VERB_OK_IDX_IN_RE_PACKET_ID); const uint64_t inRePacketId = at<uint64_t>(ZT_PROTO_VERB_OK_IDX_IN_RE_PACKET_ID);
bool trustEstablished = false;
if (!RR->node->expectingReplyTo(inRePacketId)) { if (!RR->node->expectingReplyTo(inRePacketId)) {
TRACE("%s(%s): OK(%s) DROPPED: not expecting reply to %.16llx",peer->address().toString().c_str(),_path->address().toString().c_str(),Packet::verbString(inReVerb),packetId()); TRACE("%s(%s): OK(%s) DROPPED: not expecting reply to %.16llx",peer->address().toString().c_str(),_path->address().toString().c_str(),Packet::verbString(inReVerb),packetId());
@ -441,8 +440,7 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &p
case Packet::VERB_MULTICAST_GATHER: { case Packet::VERB_MULTICAST_GATHER: {
const uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_NETWORK_ID); const uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_NETWORK_ID);
const SharedPtr<Network> network(RR->node->network(nwid)); const SharedPtr<Network> network(RR->node->network(nwid));
if ((network)&&(network->gateMulticastGatherReply(peer,verb(),packetId()))) { if (network) {
trustEstablished = true;
const MulticastGroup mg(MAC(field(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_MAC,6),6),at<uint32_t>(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_ADI)); const MulticastGroup mg(MAC(field(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_MAC,6),6),at<uint32_t>(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_ADI));
//TRACE("%s(%s): OK(MULTICAST_GATHER) %.16llx/%s length %u",source().toString().c_str(),_path->address().toString().c_str(),nwid,mg.toString().c_str(),size()); //TRACE("%s(%s): OK(MULTICAST_GATHER) %.16llx/%s length %u",source().toString().c_str(),_path->address().toString().c_str(),nwid,mg.toString().c_str(),size());
const unsigned int count = at<uint16_t>(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_GATHER_RESULTS + 4); const unsigned int count = at<uint16_t>(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_GATHER_RESULTS + 4);
@ -468,15 +466,12 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &p
network->addCredential(com); network->addCredential(com);
} }
if (network->gateMulticastGatherReply(peer,verb(),packetId())) { if ((flags & 0x02) != 0) {
trustEstablished = true; // OK(MULTICAST_FRAME) includes implicit gather results
if ((flags & 0x02) != 0) { offset += ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_COM_AND_GATHER_RESULTS;
// OK(MULTICAST_FRAME) includes implicit gather results unsigned int totalKnown = at<uint32_t>(offset); offset += 4;
offset += ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_COM_AND_GATHER_RESULTS; unsigned int count = at<uint16_t>(offset); offset += 2;
unsigned int totalKnown = at<uint32_t>(offset); offset += 4; RR->mc->addMultiple(RR->node->now(),nwid,mg,field(offset,count * 5),count,totalKnown);
unsigned int count = at<uint16_t>(offset); offset += 2;
RR->mc->addMultiple(RR->node->now(),nwid,mg,field(offset,count * 5),count,totalKnown);
}
} }
} }
} break; } break;
@ -484,7 +479,7 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &p
default: break; default: break;
} }
peer->received(_path,hops(),packetId(),Packet::VERB_OK,inRePacketId,inReVerb,trustEstablished); peer->received(_path,hops(),packetId(),Packet::VERB_OK,inRePacketId,inReVerb,false);
} catch ( ... ) { } catch ( ... ) {
TRACE("dropped OK from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str()); TRACE("dropped OK from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
} }
@ -581,9 +576,7 @@ bool IncomingPacket::_doFRAME(const RuntimeEnvironment *RR,const SharedPtr<Peer>
const SharedPtr<Network> network(RR->node->network(nwid)); const SharedPtr<Network> network(RR->node->network(nwid));
bool trustEstablished = false; bool trustEstablished = false;
if (network) { if (network) {
if (!network->gate(peer,verb(),packetId())) { if (network->gate(peer)) {
TRACE("dropped FRAME from %s(%s): not a member of private network %.16llx",peer->address().toString().c_str(),_path->address().toString().c_str(),(unsigned long long)network->id());
} else {
trustEstablished = true; trustEstablished = true;
if (size() > ZT_PROTO_VERB_FRAME_IDX_PAYLOAD) { if (size() > ZT_PROTO_VERB_FRAME_IDX_PAYLOAD) {
const unsigned int etherType = at<uint16_t>(ZT_PROTO_VERB_FRAME_IDX_ETHERTYPE); const unsigned int etherType = at<uint16_t>(ZT_PROTO_VERB_FRAME_IDX_ETHERTYPE);
@ -593,9 +586,13 @@ bool IncomingPacket::_doFRAME(const RuntimeEnvironment *RR,const SharedPtr<Peer>
if (network->filterIncomingPacket(peer,RR->identity.address(),sourceMac,network->mac(),frameData,frameLen,etherType,0) > 0) if (network->filterIncomingPacket(peer,RR->identity.address(),sourceMac,network->mac(),frameData,frameLen,etherType,0) > 0)
RR->node->putFrame(nwid,network->userPtr(),sourceMac,network->mac(),etherType,0,(const void *)frameData,frameLen); RR->node->putFrame(nwid,network->userPtr(),sourceMac,network->mac(),etherType,0,(const void *)frameData,frameLen);
} }
} else {
TRACE("dropped FRAME from %s(%s): not a member of private network %.16llx",peer->address().toString().c_str(),_path->address().toString().c_str(),(unsigned long long)network->id());
_sendErrorNeedCredentials(RR,peer,nwid);
} }
} else { } else {
TRACE("dropped FRAME from %s(%s): we are not a member of network %.16llx",source().toString().c_str(),_path->address().toString().c_str(),at<uint64_t>(ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID)); TRACE("dropped FRAME from %s(%s): we are not a member of network %.16llx",source().toString().c_str(),_path->address().toString().c_str(),at<uint64_t>(ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID));
_sendErrorNeedCredentials(RR,peer,nwid);
} }
peer->received(_path,hops(),packetId(),Packet::VERB_FRAME,0,Packet::VERB_NOP,trustEstablished); peer->received(_path,hops(),packetId(),Packet::VERB_FRAME,0,Packet::VERB_NOP,trustEstablished);
} catch ( ... ) { } catch ( ... ) {
@ -620,8 +617,9 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,const SharedPtr<P
network->addCredential(com); network->addCredential(com);
} }
if (!network->gate(peer,verb(),packetId())) { if (!network->gate(peer)) {
TRACE("dropped EXT_FRAME from %s(%s): not a member of private network %.16llx",peer->address().toString().c_str(),_path->address().toString().c_str(),network->id()); TRACE("dropped EXT_FRAME from %s(%s): not a member of private network %.16llx",peer->address().toString().c_str(),_path->address().toString().c_str(),network->id());
_sendErrorNeedCredentials(RR,peer,nwid);
peer->received(_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,false); peer->received(_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,false);
return true; return true;
} }
@ -681,6 +679,7 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,const SharedPtr<P
peer->received(_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,true); peer->received(_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,true);
} else { } else {
TRACE("dropped EXT_FRAME from %s(%s): we are not connected to network %.16llx",source().toString().c_str(),_path->address().toString().c_str(),at<uint64_t>(ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID)); TRACE("dropped EXT_FRAME from %s(%s): we are not connected to network %.16llx",source().toString().c_str(),_path->address().toString().c_str(),at<uint64_t>(ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID));
_sendErrorNeedCredentials(RR,peer,nwid);
peer->received(_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,false); peer->received(_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,false);
} }
} catch ( ... ) { } catch ( ... ) {
@ -737,7 +736,7 @@ bool IncomingPacket::_doMULTICAST_LIKE(const RuntimeEnvironment *RR,const Shared
if (!auth) { if (!auth) {
if ((!network)||(network->id() != nwid)) if ((!network)||(network->id() != nwid))
network = RR->node->network(nwid); network = RR->node->network(nwid);
const bool authOnNet = ((network)&&(network->gate(peer,verb(),packetId()))); const bool authOnNet = ((network)&&(network->gate(peer)));
trustEstablished |= authOnNet; trustEstablished |= authOnNet;
if (authOnNet||RR->mc->cacheAuthorized(peer->address(),nwid,now)) { if (authOnNet||RR->mc->cacheAuthorized(peer->address(),nwid,now)) {
auth = true; auth = true;
@ -986,7 +985,6 @@ bool IncomingPacket::_doNETWORK_CONFIG(const RuntimeEnvironment *RR,const Shared
_path->send(RR,outp.data(),outp.size(),RR->node->now()); _path->send(RR,outp.data(),outp.size(),RR->node->now());
} }
} }
peer->received(_path,hops(),packetId(),Packet::VERB_NETWORK_CONFIG,0,Packet::VERB_NOP,false); peer->received(_path,hops(),packetId(),Packet::VERB_NETWORK_CONFIG,0,Packet::VERB_NOP,false);
} catch ( ... ) { } catch ( ... ) {
TRACE("dropped NETWORK_CONFIG_REFRESH from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str()); TRACE("dropped NETWORK_CONFIG_REFRESH from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
@ -1020,7 +1018,7 @@ bool IncomingPacket::_doMULTICAST_GATHER(const RuntimeEnvironment *RR,const Shar
} }
} }
const bool trustEstablished = ((network)&&(network->gate(peer,verb(),packetId()))); const bool trustEstablished = ((network)&&(network->gate(peer)));
if ( ( trustEstablished || RR->mc->cacheAuthorized(peer->address(),nwid,RR->node->now()) ) && (gatherLimit > 0) ) { if ( ( trustEstablished || RR->mc->cacheAuthorized(peer->address(),nwid,RR->node->now()) ) && (gatherLimit > 0) ) {
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_OK); Packet outp(peer->address(),RR->identity.address(),Packet::VERB_OK);
outp.append((unsigned char)Packet::VERB_MULTICAST_GATHER); outp.append((unsigned char)Packet::VERB_MULTICAST_GATHER);
@ -1067,8 +1065,9 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,const Share
network->addCredential(com); network->addCredential(com);
} }
if (!network->gate(peer,verb(),packetId())) { if (!network->gate(peer)) {
TRACE("dropped MULTICAST_FRAME from %s(%s): not a member of private network %.16llx",peer->address().toString().c_str(),_path->address().toString().c_str(),(unsigned long long)network->id()); TRACE("dropped MULTICAST_FRAME from %s(%s): not a member of private network %.16llx",peer->address().toString().c_str(),_path->address().toString().c_str(),(unsigned long long)network->id());
_sendErrorNeedCredentials(RR,peer,nwid);
peer->received(_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,false); peer->received(_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,false);
return true; return true;
} }
@ -1143,6 +1142,7 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,const Share
peer->received(_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,true); peer->received(_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,true);
} else { } else {
_sendErrorNeedCredentials(RR,peer,nwid);
peer->received(_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,false); peer->received(_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,false);
} }
} catch ( ... ) { } catch ( ... ) {
@ -1288,7 +1288,7 @@ bool IncomingPacket::_doCIRCUIT_TEST(const RuntimeEnvironment *RR,const SharedPt
peer->received(_path,hops(),packetId(),Packet::VERB_CIRCUIT_TEST,0,Packet::VERB_NOP,false); peer->received(_path,hops(),packetId(),Packet::VERB_CIRCUIT_TEST,0,Packet::VERB_NOP,false);
return true; return true;
} }
if (network->gate(peer,verb(),packetId())) if (network->gate(peer))
reportFlags |= ZT_CIRCUIT_TEST_REPORT_FLAGS_UPSTREAM_AUTHORIZED_IN_PATH; reportFlags |= ZT_CIRCUIT_TEST_REPORT_FLAGS_UPSTREAM_AUTHORIZED_IN_PATH;
} else { } else {
TRACE("dropped CIRCUIT_TEST from %s(%s): originator %s did not specify a credential or credential type",source().toString().c_str(),_path->address().toString().c_str(),originatorAddress.toString().c_str()); TRACE("dropped CIRCUIT_TEST from %s(%s): originator %s did not specify a credential or credential type",source().toString().c_str(),_path->address().toString().c_str(),originatorAddress.toString().c_str());
@ -1479,6 +1479,19 @@ bool IncomingPacket::_doREQUEST_PROOF_OF_WORK(const RuntimeEnvironment *RR,const
return true; return true;
} }
void IncomingPacket::_sendErrorNeedCredentials(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer,const uint64_t nwid)
{
if (peer->rateGateOutgoingComRequest(RR->node->now())) {
Packet outp(source(),RR->identity.address(),Packet::VERB_ERROR);
outp.append((uint8_t)verb());
outp.append(packetId());
outp.append((uint8_t)Packet::ERROR_NEED_MEMBERSHIP_CERTIFICATE);
outp.append(nwid);
outp.armor(peer->key(),true);
_path->send(RR,outp.data(),outp.size(),RR->node->now());
}
}
void IncomingPacket::computeSalsa2012Sha512ProofOfWork(unsigned int difficulty,const void *challenge,unsigned int challengeLength,unsigned char result[16]) void IncomingPacket::computeSalsa2012Sha512ProofOfWork(unsigned int difficulty,const void *challenge,unsigned int challengeLength,unsigned char result[16])
{ {
unsigned char salsabuf[131072]; // 131072 == protocol constant, size of memory buffer for this proof of work function unsigned char salsabuf[131072]; // 131072 == protocol constant, size of memory buffer for this proof of work function

View file

@ -154,6 +154,8 @@ private:
bool _doCIRCUIT_TEST_REPORT(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer); bool _doCIRCUIT_TEST_REPORT(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
bool _doREQUEST_PROOF_OF_WORK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer); bool _doREQUEST_PROOF_OF_WORK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
void _sendErrorNeedCredentials(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer,const uint64_t nwid);
uint64_t _receiveTime; uint64_t _receiveTime;
SharedPtr<Path> _path; SharedPtr<Path> _path;
}; };

View file

@ -50,6 +50,7 @@ static const char *_rtn(const ZT_VirtualNetworkRuleType rt)
case ZT_NETWORK_RULE_ACTION_DROP: return "ACTION_DROP"; case ZT_NETWORK_RULE_ACTION_DROP: return "ACTION_DROP";
case ZT_NETWORK_RULE_ACTION_ACCEPT: return "ACTION_ACCEPT"; case ZT_NETWORK_RULE_ACTION_ACCEPT: return "ACTION_ACCEPT";
case ZT_NETWORK_RULE_ACTION_TEE: return "ACTION_TEE"; case ZT_NETWORK_RULE_ACTION_TEE: return "ACTION_TEE";
case ZT_NETWORK_RULE_ACTION_WATCH: return "ACTION_WATCH";
case ZT_NETWORK_RULE_ACTION_REDIRECT: return "ACTION_REDIRECT"; case ZT_NETWORK_RULE_ACTION_REDIRECT: return "ACTION_REDIRECT";
case ZT_NETWORK_RULE_ACTION_DEBUG_LOG: return "ACTION_DEBUG_LOG"; case ZT_NETWORK_RULE_ACTION_DEBUG_LOG: return "ACTION_DEBUG_LOG";
case ZT_NETWORK_RULE_MATCH_SOURCE_ZEROTIER_ADDRESS: return "MATCH_SOURCE_ZEROTIER_ADDRESS"; case ZT_NETWORK_RULE_MATCH_SOURCE_ZEROTIER_ADDRESS: return "MATCH_SOURCE_ZEROTIER_ADDRESS";
@ -882,7 +883,7 @@ uint64_t Network::handleConfigChunk(const Packet &chunk,unsigned int ptr)
const unsigned int start = ptr; const unsigned int start = ptr;
ptr += 8; // skip network ID, which is already obviously known ptr += 8; // skip network ID, which is already obviously known
const uint16_t chunkLen = chunk.at<uint16_t>(ptr); ptr += 2; const unsigned int chunkLen = chunk.at<uint16_t>(ptr); ptr += 2;
const void *chunkData = chunk.field(ptr,chunkLen); ptr += chunkLen; const void *chunkData = chunk.field(ptr,chunkLen); ptr += chunkLen;
Mutex::Lock _l(_lock); Mutex::Lock _l(_lock);
@ -975,8 +976,6 @@ uint64_t Network::handleConfigChunk(const Packet &chunk,unsigned int ptr)
if (c->updateId != configUpdateId) { if (c->updateId != configUpdateId) {
c->updateId = configUpdateId; c->updateId = configUpdateId;
for(int i=0;i<ZT_NETWORK_MAX_UPDATE_CHUNKS;++i)
c->haveChunkIds[i] = 0;
c->haveChunks = 0; c->haveChunks = 0;
c->haveBytes = 0; c->haveBytes = 0;
} }
@ -1065,7 +1064,7 @@ void Network::requestConfiguration()
RR->sw->send(outp,true); RR->sw->send(outp,true);
} }
bool Network::gate(const SharedPtr<Peer> &peer,const Packet::Verb verb,const uint64_t packetId) bool Network::gate(const SharedPtr<Peer> &peer)
{ {
const uint64_t now = RR->node->now(); const uint64_t now = RR->node->now();
Mutex::Lock _l(_lock); Mutex::Lock _l(_lock);
@ -1081,15 +1080,6 @@ bool Network::gate(const SharedPtr<Peer> &peer,const Packet::Verb verb,const uin
m->likingMulticasts(now); m->likingMulticasts(now);
} }
return true; return true;
} else {
if (peer->rateGateRequestCredentials(now)) {
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_ERROR);
outp.append((uint8_t)verb);
outp.append(packetId);
outp.append((uint8_t)Packet::ERROR_NEED_MEMBERSHIP_CERTIFICATE);
outp.append(_id);
RR->sw->send(outp,true);
}
} }
} }
} catch ( ... ) { } catch ( ... ) {
@ -1098,11 +1088,6 @@ bool Network::gate(const SharedPtr<Peer> &peer,const Packet::Verb verb,const uin
return false; return false;
} }
bool Network::gateMulticastGatherReply(const SharedPtr<Peer> &peer,const Packet::Verb verb,const uint64_t packetId)
{
return ( (peer->address() == controller()) || RR->topology->isUpstream(peer->identity()) || gate(peer,verb,packetId) || _config.isAnchor(peer->address()) );
}
void Network::clean() void Network::clean()
{ {
const uint64_t now = RR->node->now(); const uint64_t now = RR->node->now();

View file

@ -212,21 +212,8 @@ public:
/** /**
* Determine whether this peer is permitted to communicate on this network * Determine whether this peer is permitted to communicate on this network
*
* This also performs certain periodic actions such as pushing renewed
* credentials to peers, so like the filters it is not side-effect-free.
*
* @param peer Peer to check
* @param verb Packet verb
* @param packetId Packet ID
* @return True if peer is allowed to communicate on this network
*/ */
bool gate(const SharedPtr<Peer> &peer,const Packet::Verb verb,const uint64_t packetId); bool gate(const SharedPtr<Peer> &peer);
/**
* Check whether this peer is allowed to provide multicast info for this network
*/
bool gateMulticastGatherReply(const SharedPtr<Peer> &peer,const Packet::Verb verb,const uint64_t packetId);
/** /**
* Do periodic cleanup and housekeeping tasks * Do periodic cleanup and housekeeping tasks

View file

@ -267,17 +267,19 @@ public:
} }
/** /**
* Check whether a given packet ID is something we are expecting a reply to * Check whether a given packet ID is something we are expecting a reply to (and erase from list)
* *
* @param packetId Packet ID to check * @param packetId Packet ID to check
* @return True if we're expecting a reply * @return True if we're expecting a reply
*/ */
inline bool expectingReplyTo(const uint64_t packetId) const inline bool expectingReplyTo(const uint64_t packetId)
{ {
const unsigned long bucket = (unsigned long)(packetId & ZT_EXPECTING_REPLIES_BUCKET_MASK1); const unsigned long bucket = (unsigned long)(packetId & ZT_EXPECTING_REPLIES_BUCKET_MASK1);
for(unsigned long i=0;i<=ZT_EXPECTING_REPLIES_BUCKET_MASK2;++i) { for(unsigned long i=0;i<=ZT_EXPECTING_REPLIES_BUCKET_MASK2;++i) {
if (_expectingRepliesTo[bucket][i] == packetId) if (_expectingRepliesTo[bucket][i] == packetId) {
_expectingRepliesTo[bucket][i] = 0;
return true; return true;
}
} }
return false; return false;
} }

View file

@ -50,6 +50,7 @@ Peer::Peer(const RuntimeEnvironment *renv,const Identity &myIdentity,const Ident
_lastWhoisRequestReceived(0), _lastWhoisRequestReceived(0),
_lastEchoRequestReceived(0), _lastEchoRequestReceived(0),
_lastComRequestReceived(0), _lastComRequestReceived(0),
_lastComRequestSent(0),
_lastCredentialsReceived(0), _lastCredentialsReceived(0),
_lastTrustEstablishedPacketReceived(0), _lastTrustEstablishedPacketReceived(0),
RR(renv), RR(renv),

View file

@ -395,9 +395,9 @@ public:
} }
/** /**
* Rate gate requests for network COM * Rate gate incoming requests for network COM
*/ */
inline bool rateGateComRequest(const uint64_t now) inline bool rateGateIncomingComRequest(const uint64_t now)
{ {
if ((now - _lastComRequestReceived) >= ZT_PEER_GENERAL_RATE_LIMIT) { if ((now - _lastComRequestReceived) >= ZT_PEER_GENERAL_RATE_LIMIT) {
_lastComRequestReceived = now; _lastComRequestReceived = now;
@ -406,6 +406,18 @@ public:
return false; return false;
} }
/**
* Rate gate outgoing requests for network COM
*/
inline bool rateGateOutgoingComRequest(const uint64_t now)
{
if ((now - _lastComRequestSent) >= ZT_PEER_GENERAL_RATE_LIMIT) {
_lastComRequestSent = now;
return true;
}
return false;
}
/** /**
* Find a common set of addresses by which two peers can link, if any * Find a common set of addresses by which two peers can link, if any
* *
@ -465,6 +477,7 @@ private:
uint64_t _lastWhoisRequestReceived; uint64_t _lastWhoisRequestReceived;
uint64_t _lastEchoRequestReceived; uint64_t _lastEchoRequestReceived;
uint64_t _lastComRequestReceived; uint64_t _lastComRequestReceived;
uint64_t _lastComRequestSent;
uint64_t _lastCredentialsReceived; uint64_t _lastCredentialsReceived;
uint64_t _lastTrustEstablishedPacketReceived; uint64_t _lastTrustEstablishedPacketReceived;
const RuntimeEnvironment *RR; const RuntimeEnvironment *RR;