diff --git a/node/Dictionary.hpp b/node/Dictionary.hpp index 6cbbfc0ec..061dcac1b 100644 --- a/node/Dictionary.hpp +++ b/node/Dictionary.hpp @@ -288,6 +288,21 @@ public: return dfl; } + /** + * Get an unsigned int64 stored as hex in the dictionary + * + * @param key Key to look up + * @param dfl Default value or 0 if unspecified + * @return Decoded hex UInt value or 'dfl' if not found + */ + inline int64_t getI(const char *key,int64_t dfl = 0) const + { + char tmp[128]; + if (this->get(key,tmp,sizeof(tmp)) >= 1) + return Utils::hexStrTo64(tmp); + return dfl; + } + /** * Add a new key=value pair * @@ -394,6 +409,20 @@ public: return this->add(key,Utils::hex(value,tmp),-1); } + /** + * Add a 64-bit integer (unsigned) as a hex value + */ + inline bool add(const char *key,int64_t value) + { + char tmp[32]; + if (value >= 0) { + return this->add(key,Utils::hex((uint64_t)value,tmp),-1); + } else { + tmp[0] = '-'; + return this->add(key,Utils::hex((uint64_t)(value * -1),tmp+1),-1); + } + } + /** * Add a 64-bit integer (unsigned) as a hex value */ diff --git a/node/Identity.cpp b/node/Identity.cpp index 3b00b4c0c..dba27d1c6 100644 --- a/node/Identity.cpp +++ b/node/Identity.cpp @@ -151,7 +151,7 @@ char *Identity::toString(bool includePrivate,char buf[ZT_IDENTITY_STRING_BUFFER_ Utils::hex(_privateKey->data,ZT_C25519_PRIVATE_KEY_LEN,p); p += ZT_C25519_PRIVATE_KEY_LEN * 2; } - *(p++) = (char)0; + *p = (char)0; return buf; } diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index e1fb180cf..a5875d1ec 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -66,10 +66,10 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR,void *tPtr) // packets are dropped on the floor. const uint64_t tpid = trustedPathId(); if (RR->topology->shouldInboundPathBeTrusted(_path->address(),tpid)) { - RR->t->incomingPacketTrustedPath(_path,packetId(),sourceAddress,tpid,true); + RR->t->incomingPacketTrustedPath(tPtr,_path,packetId(),sourceAddress,tpid,true); trusted = true; } else { - RR->t->incomingPacketTrustedPath(_path,packetId(),sourceAddress,tpid,false); + RR->t->incomingPacketTrustedPath(tPtr,_path,packetId(),sourceAddress,tpid,false); return true; } } else if ((c == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_NONE)&&(verb() == Packet::VERB_HELLO)) { @@ -82,14 +82,14 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR,void *tPtr) if (!trusted) { if (!dearmor(peer->key())) { //fprintf(stderr,"dropped packet from %s(%s), MAC authentication failed (size: %u)" ZT_EOL_S,sourceAddress.toString().c_str(),_path->address().toString().c_str(),size()); - RR->t->incomingPacketMessageAuthenticationFailure(_path,packetId(),sourceAddress); + RR->t->incomingPacketMessageAuthenticationFailure(tPtr,_path,packetId(),sourceAddress,hops()); return true; } } if (!uncompress()) { //fprintf(stderr,"dropped packet from %s(%s), compressed data invalid (size %u, verb may be %u)" ZT_EOL_S,sourceAddress.toString().c_str(),_path->address().toString().c_str(),size(),(unsigned int)verb()); - RR->t->incomingPacketInvalid(_path,packetId(),sourceAddress,Packet::VERB_NOP,"LZ4 decompression failed"); + RR->t->incomingPacketInvalid(tPtr,_path,packetId(),sourceAddress,hops(),Packet::VERB_NOP,"LZ4 decompression failed"); return true; } @@ -97,7 +97,7 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR,void *tPtr) switch(v) { //case Packet::VERB_NOP: default: // ignore unknown verbs, but if they pass auth check they are "received" - peer->received(tPtr,_path,hops(),packetId(),v,0,Packet::VERB_NOP,false); + peer->received(tPtr,_path,hops(),packetId(),v,0,Packet::VERB_NOP,false,0); return true; case Packet::VERB_HELLO: return _doHELLO(RR,tPtr,true); @@ -122,7 +122,7 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR,void *tPtr) return false; } } catch ( ... ) { - RR->t->incomingPacketInvalid(_path,packetId(),sourceAddress,Packet::VERB_NOP,"unexpected exception in tryDecode() (outer)"); + RR->t->incomingPacketInvalid(tPtr,_path,packetId(),sourceAddress,hops(),verb(),"unexpected exception in tryDecode() (outer)"); return true; } } @@ -133,6 +133,7 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,void *tPtr,const Shar const Packet::Verb inReVerb = (Packet::Verb)(*this)[ZT_PROTO_VERB_ERROR_IDX_IN_RE_VERB]; const uint64_t inRePacketId = at(ZT_PROTO_VERB_ERROR_IDX_IN_RE_PACKET_ID); const Packet::ErrorCode errorCode = (Packet::ErrorCode)(*this)[ZT_PROTO_VERB_ERROR_IDX_ERROR_CODE]; + uint64_t networkId = 0; /* Security note: we do not gate doERROR() with expectingReplyTo() to * avoid having to log every outgoing packet ID. Instead we put the @@ -170,7 +171,8 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,void *tPtr,const Shar case Packet::ERROR_NEED_MEMBERSHIP_CERTIFICATE: { // Peers can send this in response to frames if they do not have a recent enough COM from us - const SharedPtr network(RR->node->network(at(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD))); + networkId = at(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD); + const SharedPtr network(RR->node->network(networkId)); const uint64_t now = RR->node->now(); if ( (network) && (network->config().com) && (peer->rateGateIncomingComRequest(now)) ) network->pushCredentialsNow(tPtr,peer->address(),now); @@ -186,7 +188,8 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,void *tPtr,const Shar case Packet::ERROR_UNWANTED_MULTICAST: { // Members of networks can use this error to indicate that they no longer // want to receive multicasts on a given channel. - const SharedPtr network(RR->node->network(at(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD))); + networkId = at(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD); + const SharedPtr network(RR->node->network(networkId)); if ((network)&&(network->gate(tPtr,peer))) { const MulticastGroup mg(MAC(field(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD + 8,6),6),at(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD + 14)); RR->mc->remove(network->id(),mg,peer->address()); @@ -196,9 +199,9 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,void *tPtr,const Shar default: break; } - peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_ERROR,inRePacketId,inReVerb,false); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_ERROR,inRePacketId,inReVerb,false,networkId); } catch ( ... ) { - RR->t->incomingPacketInvalid(_path,packetId(),source(),Packet::VERB_ERROR,"unexpected exception"); + RR->t->incomingPacketInvalid(tPtr,_path,packetId(),source(),hops(),Packet::VERB_ERROR,"unexpected exception"); } return true; } @@ -219,11 +222,11 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool unsigned int ptr = ZT_PROTO_VERB_HELLO_IDX_IDENTITY + id.deserialize(*this,ZT_PROTO_VERB_HELLO_IDX_IDENTITY); if (protoVersion < ZT_PROTO_VERSION_MIN) { - RR->t->incomingPacketDroppedHELLO(_path,pid,fromAddress,"protocol version too old"); + RR->t->incomingPacketDroppedHELLO(tPtr,_path,pid,fromAddress,"protocol version too old"); return true; } if (fromAddress != id.address()) { - RR->t->incomingPacketDroppedHELLO(_path,pid,fromAddress,"identity/address mismatch"); + RR->t->incomingPacketDroppedHELLO(tPtr,_path,pid,fromAddress,"identity/address mismatch"); return true; } @@ -241,7 +244,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool uint8_t key[ZT_PEER_SECRET_KEY_LENGTH]; if (RR->identity.agree(id,key,ZT_PEER_SECRET_KEY_LENGTH)) { if (dearmor(key)) { // ensure packet is authentic, otherwise drop - RR->t->incomingPacketDroppedHELLO(_path,pid,fromAddress,"address collision"); + RR->t->incomingPacketDroppedHELLO(tPtr,_path,pid,fromAddress,"address collision"); Packet outp(id.address(),RR->identity.address(),Packet::VERB_ERROR); outp.append((uint8_t)Packet::VERB_HELLO); outp.append((uint64_t)pid); @@ -249,10 +252,10 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool outp.armor(key,true,_path->nextOutgoingCounter()); _path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now()); } else { - RR->t->incomingPacketMessageAuthenticationFailure(_path,pid,fromAddress); + RR->t->incomingPacketMessageAuthenticationFailure(tPtr,_path,pid,fromAddress,hops()); } } else { - RR->t->incomingPacketMessageAuthenticationFailure(_path,pid,fromAddress); + RR->t->incomingPacketMessageAuthenticationFailure(tPtr,_path,pid,fromAddress,hops()); } return true; @@ -260,7 +263,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool // Identity is the same as the one we already have -- check packet integrity if (!dearmor(peer->key())) { - RR->t->incomingPacketMessageAuthenticationFailure(_path,pid,fromAddress); + RR->t->incomingPacketMessageAuthenticationFailure(tPtr,_path,pid,fromAddress,hops()); return true; } @@ -272,26 +275,26 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool // Sanity check: this basically can't happen if (alreadyAuthenticated) { - RR->t->incomingPacketDroppedHELLO(_path,pid,fromAddress,"illegal alreadyAuthenticated state"); + RR->t->incomingPacketDroppedHELLO(tPtr,_path,pid,fromAddress,"illegal alreadyAuthenticated state"); return true; } // Check rate limits if (!RR->node->rateGateIdentityVerification(now,_path->address())) { - RR->t->incomingPacketDroppedHELLO(_path,pid,fromAddress,"rate limit exceeded"); + RR->t->incomingPacketDroppedHELLO(tPtr,_path,pid,fromAddress,"rate limit exceeded"); return true; } // Check packet integrity and MAC (this is faster than locallyValidate() so do it first to filter out total crap) SharedPtr newPeer(new Peer(RR,RR->identity,id)); if (!dearmor(newPeer->key())) { - RR->t->incomingPacketMessageAuthenticationFailure(_path,pid,fromAddress); + RR->t->incomingPacketMessageAuthenticationFailure(tPtr,_path,pid,fromAddress,hops()); return true; } // Check that identity's address is valid as per the derivation function if (!id.locallyValidate()) { - RR->t->incomingPacketDroppedHELLO(_path,pid,fromAddress,"invalid identity"); + RR->t->incomingPacketDroppedHELLO(tPtr,_path,pid,fromAddress,"invalid identity"); return true; } @@ -414,9 +417,9 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool _path->send(RR,tPtr,outp.data(),outp.size(),now); peer->setRemoteVersion(protoVersion,vMajor,vMinor,vRevision); // important for this to go first so received() knows the version - peer->received(tPtr,_path,hops(),pid,Packet::VERB_HELLO,0,Packet::VERB_NOP,false); + peer->received(tPtr,_path,hops(),pid,Packet::VERB_HELLO,0,Packet::VERB_NOP,false,0); } catch ( ... ) { - RR->t->incomingPacketInvalid(_path,packetId(),source(),Packet::VERB_HELLO,"unexpected exception"); + RR->t->incomingPacketInvalid(tPtr,_path,packetId(),source(),hops(),Packet::VERB_HELLO,"unexpected exception"); } return true; } @@ -426,6 +429,7 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,void *tPtr,const SharedP try { const Packet::Verb inReVerb = (Packet::Verb)(*this)[ZT_PROTO_VERB_OK_IDX_IN_RE_VERB]; const uint64_t inRePacketId = at(ZT_PROTO_VERB_OK_IDX_IN_RE_PACKET_ID); + uint64_t networkId = 0; if (!RR->node->expectingReplyTo(inRePacketId)) return true; @@ -491,27 +495,28 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,void *tPtr,const SharedP break; case Packet::VERB_NETWORK_CONFIG_REQUEST: { - const SharedPtr network(RR->node->network(at(ZT_PROTO_VERB_OK_IDX_PAYLOAD))); + networkId = at(ZT_PROTO_VERB_OK_IDX_PAYLOAD); + const SharedPtr network(RR->node->network(networkId)); if (network) network->handleConfigChunk(tPtr,packetId(),source(),*this,ZT_PROTO_VERB_OK_IDX_PAYLOAD); } break; case Packet::VERB_MULTICAST_GATHER: { - const uint64_t nwid = at(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_NETWORK_ID); - const SharedPtr network(RR->node->network(nwid)); + networkId = at(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_NETWORK_ID); + const SharedPtr network(RR->node->network(networkId)); if (network) { const MulticastGroup mg(MAC(field(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_MAC,6),6),at(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_ADI)); const unsigned int count = at(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_GATHER_RESULTS + 4); - RR->mc->addMultiple(tPtr,RR->node->now(),nwid,mg,field(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_GATHER_RESULTS + 6,count * 5),count,at(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_GATHER_RESULTS)); + RR->mc->addMultiple(tPtr,RR->node->now(),networkId,mg,field(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_GATHER_RESULTS + 6,count * 5),count,at(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_GATHER_RESULTS)); } } break; case Packet::VERB_MULTICAST_FRAME: { const unsigned int flags = (*this)[ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_FLAGS]; - const uint64_t nwid = at(ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_NETWORK_ID); + networkId = at(ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_NETWORK_ID); const MulticastGroup mg(MAC(field(ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_MAC,6),6),at(ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_ADI)); - const SharedPtr network(RR->node->network(nwid)); + const SharedPtr network(RR->node->network(networkId)); if (network) { unsigned int offset = 0; @@ -527,7 +532,7 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,void *tPtr,const SharedP offset += ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_COM_AND_GATHER_RESULTS; unsigned int totalKnown = at(offset); offset += 4; unsigned int count = at(offset); offset += 2; - RR->mc->addMultiple(tPtr,RR->node->now(),nwid,mg,field(offset,count * 5),count,totalKnown); + RR->mc->addMultiple(tPtr,RR->node->now(),networkId,mg,field(offset,count * 5),count,totalKnown); } } } break; @@ -535,9 +540,9 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,void *tPtr,const SharedP default: break; } - peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_OK,inRePacketId,inReVerb,false); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_OK,inRePacketId,inReVerb,false,networkId); } catch ( ... ) { - RR->t->incomingPacketInvalid(_path,packetId(),source(),Packet::VERB_OK,"unexpected exception"); + RR->t->incomingPacketInvalid(tPtr,_path,packetId(),source(),hops(),Packet::VERB_OK,"unexpected exception"); } return true; } @@ -573,9 +578,9 @@ bool IncomingPacket::_doWHOIS(const RuntimeEnvironment *RR,void *tPtr,const Shar _path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now()); } - peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_WHOIS,0,Packet::VERB_NOP,false); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_WHOIS,0,Packet::VERB_NOP,false,0); } catch ( ... ) { - RR->t->incomingPacketInvalid(_path,packetId(),source(),Packet::VERB_WHOIS,"unexpected exception"); + RR->t->incomingPacketInvalid(tPtr,_path,packetId(),source(),hops(),Packet::VERB_WHOIS,"unexpected exception"); } return true; } @@ -599,9 +604,9 @@ bool IncomingPacket::_doRENDEZVOUS(const RuntimeEnvironment *RR,void *tPtr,const } } } - peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_RENDEZVOUS,0,Packet::VERB_NOP,false); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_RENDEZVOUS,0,Packet::VERB_NOP,false,0); } catch ( ... ) { - RR->t->incomingPacketInvalid(_path,packetId(),source(),Packet::VERB_RENDEZVOUS,"unexpected exception"); + RR->t->incomingPacketInvalid(tPtr,_path,packetId(),source(),hops(),Packet::VERB_RENDEZVOUS,"unexpected exception"); } return true; } @@ -625,14 +630,14 @@ bool IncomingPacket::_doFRAME(const RuntimeEnvironment *RR,void *tPtr,const Shar } } else { _sendErrorNeedCredentials(RR,tPtr,peer,nwid); - RR->t->networkAccessDenied(network,_path,packetId(),size(),peer->address(),Packet::VERB_FRAME,true); + RR->t->incomingNetworkAccessDenied(tPtr,network,_path,packetId(),size(),peer->address(),Packet::VERB_FRAME,true); } } else { _sendErrorNeedCredentials(RR,tPtr,peer,nwid); } - peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_FRAME,0,Packet::VERB_NOP,trustEstablished); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_FRAME,0,Packet::VERB_NOP,trustEstablished,nwid); } catch ( ... ) { - RR->t->incomingPacketInvalid(_path,packetId(),source(),Packet::VERB_FRAME,"unexpected exception"); + RR->t->incomingPacketInvalid(tPtr,_path,packetId(),source(),hops(),Packet::VERB_FRAME,"unexpected exception"); } return true; } @@ -654,9 +659,9 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,void *tPtr,const } if (!network->gate(tPtr,peer)) { - RR->t->networkAccessDenied(network,_path,packetId(),size(),peer->address(),Packet::VERB_EXT_FRAME,true); + RR->t->incomingNetworkAccessDenied(tPtr,network,_path,packetId(),size(),peer->address(),Packet::VERB_EXT_FRAME,true); _sendErrorNeedCredentials(RR,tPtr,peer,nwid); - peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,false); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,false,nwid); return true; } @@ -668,7 +673,7 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,void *tPtr,const const uint8_t *const frameData = (const uint8_t *)field(comLen + ZT_PROTO_VERB_EXT_FRAME_IDX_PAYLOAD,frameLen); if ((!from)||(from == network->mac())) { - peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,true,nwid); // trustEstablished because COM is okay return true; } @@ -678,20 +683,20 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,void *tPtr,const if (network->config().permitsBridging(peer->address())) { network->learnBridgeRoute(from,peer->address()); } else { - RR->t->networkFrameDropped(network,_path,packetId(),size(),peer->address(),Packet::VERB_EXT_FRAME,from,to); - peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay + RR->t->incomingNetworkFrameDropped(tPtr,network,_path,packetId(),size(),peer->address(),Packet::VERB_EXT_FRAME,from,to); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,true,nwid); // trustEstablished because COM is okay return true; } } else if (to != network->mac()) { if (to.isMulticast()) { if (network->config().multicastLimit == 0) { - RR->t->networkFrameDropped(network,_path,packetId(),size(),peer->address(),Packet::VERB_EXT_FRAME,from,to); - peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay + RR->t->incomingNetworkFrameDropped(tPtr,network,_path,packetId(),size(),peer->address(),Packet::VERB_EXT_FRAME,from,to); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,true,nwid); // trustEstablished because COM is okay return true; } } else if (!network->config().permitsBridging(RR->identity.address())) { - RR->t->networkFrameDropped(network,_path,packetId(),size(),peer->address(),Packet::VERB_EXT_FRAME,from,to); - peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay + RR->t->incomingNetworkFrameDropped(tPtr,network,_path,packetId(),size(),peer->address(),Packet::VERB_EXT_FRAME,from,to); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,true,nwid); // trustEstablished because COM is okay return true; } } @@ -711,12 +716,12 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,void *tPtr,const _path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now()); } - peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,true); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,true,nwid); } else { - peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,false); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,false,nwid); } } catch ( ... ) { - RR->t->incomingPacketInvalid(_path,packetId(),source(),Packet::VERB_EXT_FRAME,"unexpected exception"); + RR->t->incomingPacketInvalid(tPtr,_path,packetId(),source(),hops(),Packet::VERB_EXT_FRAME,"unexpected exception"); } return true; } @@ -736,9 +741,9 @@ bool IncomingPacket::_doECHO(const RuntimeEnvironment *RR,void *tPtr,const Share outp.armor(peer->key(),true,_path->nextOutgoingCounter()); _path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now()); - peer->received(tPtr,_path,hops(),pid,Packet::VERB_ECHO,0,Packet::VERB_NOP,false); + peer->received(tPtr,_path,hops(),pid,Packet::VERB_ECHO,0,Packet::VERB_NOP,false,0); } catch ( ... ) { - RR->t->incomingPacketInvalid(_path,packetId(),source(),Packet::VERB_ECHO,"unexpected exception"); + RR->t->incomingPacketInvalid(tPtr,_path,packetId(),source(),hops(),Packet::VERB_ECHO,"unexpected exception"); } return true; } @@ -784,9 +789,9 @@ bool IncomingPacket::_doMULTICAST_LIKE(const RuntimeEnvironment *RR,void *tPtr,c } } - peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_MULTICAST_LIKE,0,Packet::VERB_NOP,trustEstablished); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_MULTICAST_LIKE,0,Packet::VERB_NOP,trustEstablished,(network) ? network->id() : 0); } catch ( ... ) { - RR->t->incomingPacketInvalid(_path,packetId(),source(),Packet::VERB_MULTICAST_LIKE,"unexpected exception"); + RR->t->incomingPacketInvalid(tPtr,_path,packetId(),source(),hops(),Packet::VERB_MULTICAST_LIKE,"unexpected exception"); } return true; } @@ -803,12 +808,13 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,void *t Revocation revocation; CertificateOfOwnership coo; bool trustEstablished = false; + SharedPtr network; unsigned int p = ZT_PACKET_IDX_PAYLOAD; while ((p < size())&&((*this)[p] != 0)) { p += com.deserialize(*this,p); if (com) { - const SharedPtr network(RR->node->network(com.networkId())); + network = RR->node->network(com.networkId()); if (network) { switch (network->addCredential(tPtr,com)) { case Membership::ADD_REJECTED: @@ -829,7 +835,8 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,void *t const unsigned int numCapabilities = at(p); p += 2; for(unsigned int i=0;i network(RR->node->network(cap.networkId())); + if ((!network)||(network->id() != cap.networkId())) + network = RR->node->network(cap.networkId()); if (network) { switch (network->addCredential(tPtr,cap)) { case Membership::ADD_REJECTED: @@ -849,7 +856,8 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,void *t const unsigned int numTags = at(p); p += 2; for(unsigned int i=0;i network(RR->node->network(tag.networkId())); + if ((!network)||(network->id() != tag.networkId())) + network = RR->node->network(tag.networkId()); if (network) { switch (network->addCredential(tPtr,tag)) { case Membership::ADD_REJECTED: @@ -869,7 +877,8 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,void *t const unsigned int numRevocations = at(p); p += 2; for(unsigned int i=0;i network(RR->node->network(revocation.networkId())); + if ((!network)||(network->id() != revocation.networkId())) + network = RR->node->network(revocation.networkId()); if (network) { switch(network->addCredential(tPtr,peer->address(),revocation)) { case Membership::ADD_REJECTED: @@ -889,7 +898,8 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,void *t const unsigned int numCoos = at(p); p += 2; for(unsigned int i=0;i network(RR->node->network(coo.networkId())); + if ((!network)||(network->id() != coo.networkId())) + network = RR->node->network(coo.networkId()); if (network) { switch(network->addCredential(tPtr,coo)) { case Membership::ADD_REJECTED: @@ -905,9 +915,9 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,void *t } } - peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_NETWORK_CREDENTIALS,0,Packet::VERB_NOP,trustEstablished); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_NETWORK_CREDENTIALS,0,Packet::VERB_NOP,trustEstablished,(network) ? network->id() : 0); } catch ( ... ) { - RR->t->incomingPacketInvalid(_path,packetId(),source(),Packet::VERB_NETWORK_CREDENTIALS,"unexpected exception"); + RR->t->incomingPacketInvalid(tPtr,_path,packetId(),source(),hops(),Packet::VERB_NETWORK_CREDENTIALS,"unexpected exception"); } return true; } @@ -934,9 +944,9 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,void _path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now()); } - peer->received(tPtr,_path,hopCount,requestPacketId,Packet::VERB_NETWORK_CONFIG_REQUEST,0,Packet::VERB_NOP,false); + peer->received(tPtr,_path,hopCount,requestPacketId,Packet::VERB_NETWORK_CONFIG_REQUEST,0,Packet::VERB_NOP,false,nwid); } catch ( ... ) { - RR->t->incomingPacketInvalid(_path,packetId(),source(),Packet::VERB_NETWORK_CONFIG_REQUEST,"unexpected exception"); + RR->t->incomingPacketInvalid(tPtr,_path,packetId(),source(),hops(),Packet::VERB_NETWORK_CONFIG_REQUEST,"unexpected exception"); } return true; } @@ -957,9 +967,9 @@ bool IncomingPacket::_doNETWORK_CONFIG(const RuntimeEnvironment *RR,void *tPtr,c _path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now()); } } - peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_NETWORK_CONFIG,0,Packet::VERB_NOP,false); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_NETWORK_CONFIG,0,Packet::VERB_NOP,false,(network) ? network->id() : 0); } catch ( ... ) { - RR->t->incomingPacketInvalid(_path,packetId(),source(),Packet::VERB_NETWORK_CONFIG,"unexpected exception"); + RR->t->incomingPacketInvalid(tPtr,_path,packetId(),source(),hops(),Packet::VERB_NETWORK_CONFIG,"unexpected exception"); } return true; } @@ -1003,9 +1013,9 @@ bool IncomingPacket::_doMULTICAST_GATHER(const RuntimeEnvironment *RR,void *tPtr } } - peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_MULTICAST_GATHER,0,Packet::VERB_NOP,trustEstablished); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_MULTICAST_GATHER,0,Packet::VERB_NOP,trustEstablished,nwid); } catch ( ... ) { - RR->t->incomingPacketInvalid(_path,packetId(),source(),Packet::VERB_MULTICAST_GATHER,"unexpected exception"); + RR->t->incomingPacketInvalid(tPtr,_path,packetId(),source(),hops(),Packet::VERB_MULTICAST_GATHER,"unexpected exception"); } return true; } @@ -1030,9 +1040,9 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,void *tPtr, } if (!network->gate(tPtr,peer)) { - RR->t->networkAccessDenied(network,_path,packetId(),size(),peer->address(),Packet::VERB_MULTICAST_FRAME,true); + RR->t->incomingNetworkAccessDenied(tPtr,network,_path,packetId(),size(),peer->address(),Packet::VERB_MULTICAST_FRAME,true); _sendErrorNeedCredentials(RR,tPtr,peer,nwid); - peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,false); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,false,nwid); return true; } @@ -1055,20 +1065,20 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,void *tPtr, const unsigned int frameLen = size() - (offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME); if (network->config().multicastLimit == 0) { - RR->t->networkFrameDropped(network,_path,packetId(),size(),peer->address(),Packet::VERB_MULTICAST_FRAME,from,to.mac()); - peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,false); + RR->t->incomingNetworkFrameDropped(tPtr,network,_path,packetId(),size(),peer->address(),Packet::VERB_MULTICAST_FRAME,from,to.mac()); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,false,nwid); return true; } if ((frameLen > 0)&&(frameLen <= ZT_MAX_MTU)) { if (!to.mac().isMulticast()) { - RR->t->incomingPacketInvalid(_path,packetId(),source(),Packet::VERB_MULTICAST_FRAME,"destination not multicast"); - peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay + RR->t->incomingPacketInvalid(tPtr,_path,packetId(),source(),hops(),Packet::VERB_MULTICAST_FRAME,"destination not multicast"); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,true,nwid); // trustEstablished because COM is okay return true; } if ((!from)||(from.isMulticast())||(from == network->mac())) { - RR->t->incomingPacketInvalid(_path,packetId(),source(),Packet::VERB_MULTICAST_FRAME,"invalid source MAC"); - peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay + RR->t->incomingPacketInvalid(tPtr,_path,packetId(),source(),hops(),Packet::VERB_MULTICAST_FRAME,"invalid source MAC"); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,true,nwid); // trustEstablished because COM is okay return true; } @@ -1076,8 +1086,8 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,void *tPtr, if (network->config().permitsBridging(peer->address())) { network->learnBridgeRoute(from,peer->address()); } else { - RR->t->networkFrameDropped(network,_path,packetId(),size(),peer->address(),Packet::VERB_MULTICAST_FRAME,from,to.mac()); - peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay + RR->t->incomingNetworkFrameDropped(tPtr,network,_path,packetId(),size(),peer->address(),Packet::VERB_MULTICAST_FRAME,from,to.mac()); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,true,nwid); // trustEstablished because COM is okay return true; } } @@ -1101,13 +1111,13 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,void *tPtr, } } - peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,true); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,true,nwid); } else { _sendErrorNeedCredentials(RR,tPtr,peer,nwid); - peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,false); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,false,nwid); } } catch ( ... ) { - RR->t->incomingPacketInvalid(_path,packetId(),source(),Packet::VERB_MULTICAST_FRAME,"unexpected exception"); + RR->t->incomingPacketInvalid(tPtr,_path,packetId(),source(),hops(),Packet::VERB_MULTICAST_FRAME,"unexpected exception"); } return true; } @@ -1119,7 +1129,7 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,void *tPt // First, subject this to a rate limit if (!peer->rateGatePushDirectPaths(now)) { - peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_PUSH_DIRECT_PATHS,0,Packet::VERB_NOP,false); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_PUSH_DIRECT_PATHS,0,Packet::VERB_NOP,false,0); return true; } @@ -1172,9 +1182,9 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,void *tPt ptr += addrLen; } - peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_PUSH_DIRECT_PATHS,0,Packet::VERB_NOP,false); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_PUSH_DIRECT_PATHS,0,Packet::VERB_NOP,false,0); } catch ( ... ) { - RR->t->incomingPacketInvalid(_path,packetId(),source(),Packet::VERB_PUSH_DIRECT_PATHS,"unexpected exception"); + RR->t->incomingPacketInvalid(tPtr,_path,packetId(),source(),hops(),Packet::VERB_PUSH_DIRECT_PATHS,"unexpected exception"); } return true; } @@ -1190,9 +1200,9 @@ bool IncomingPacket::_doUSER_MESSAGE(const RuntimeEnvironment *RR,void *tPtr,con um.length = size() - (ZT_PACKET_IDX_PAYLOAD + 8); RR->node->postEvent(tPtr,ZT_EVENT_USER_MESSAGE,reinterpret_cast(&um)); } - peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_USER_MESSAGE,0,Packet::VERB_NOP,false); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_USER_MESSAGE,0,Packet::VERB_NOP,false,0); } catch ( ... ) { - RR->t->incomingPacketInvalid(_path,packetId(),source(),Packet::VERB_USER_MESSAGE,"unexpected exception"); + RR->t->incomingPacketInvalid(tPtr,_path,packetId(),source(),hops(),Packet::VERB_USER_MESSAGE,"unexpected exception"); } return true; } diff --git a/node/Membership.cpp b/node/Membership.cpp index be6ea6a58..a14533077 100644 --- a/node/Membership.cpp +++ b/node/Membership.cpp @@ -129,13 +129,13 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme { const uint64_t newts = com.timestamp(); if (newts <= _comRevocationThreshold) { - RR->t->credentialRejected(com,"revoked"); + RR->t->credentialRejected(tPtr,com,"revoked"); return ADD_REJECTED; } const uint64_t oldts = _com.timestamp(); if (newts < oldts) { - RR->t->credentialRejected(com,"old"); + RR->t->credentialRejected(tPtr,com,"old"); return ADD_REJECTED; } if ((newts == oldts)&&(_com == com)) @@ -143,11 +143,11 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme switch(com.verify(RR,tPtr)) { default: - RR->t->credentialRejected(com,"invalid"); + RR->t->credentialRejected(tPtr,com,"invalid"); return ADD_REJECTED; case 0: _com = com; - RR->t->credentialAccepted(com); + RR->t->credentialAccepted(tPtr,com); return ADD_ACCEPTED_NEW; case 1: return ADD_DEFERRED_FOR_WHOIS; @@ -161,7 +161,7 @@ static Membership::AddCredentialResult _addCredImpl(Hashtable &remot C *rc = remoteCreds.get(cred.id()); if (rc) { if (rc->timestamp() > cred.timestamp()) { - RR->t->credentialRejected(cred,"old"); + RR->t->credentialRejected(tPtr,cred,"old"); return Membership::ADD_REJECTED; } if (*rc == cred) @@ -170,16 +170,16 @@ static Membership::AddCredentialResult _addCredImpl(Hashtable &remot const uint64_t *const rt = revocations.get(Membership::credentialKey(C::credentialType(),cred.id())); if ((rt)&&(*rt >= cred.timestamp())) { - RR->t->credentialRejected(cred,"revoked"); + RR->t->credentialRejected(tPtr,cred,"revoked"); return Membership::ADD_REJECTED; } switch(cred.verify(RR,tPtr)) { default: - RR->t->credentialRejected(cred,"invalid"); + RR->t->credentialRejected(tPtr,cred,"invalid"); return Membership::ADD_REJECTED; case 0: - RR->t->credentialAccepted(cred); + RR->t->credentialAccepted(tPtr,cred); if (!rc) rc = &(remoteCreds[cred.id()]); *rc = cred; @@ -198,14 +198,14 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme uint64_t *rt; switch(rev.verify(RR,tPtr)) { default: - RR->t->credentialRejected(rev,"invalid"); + RR->t->credentialRejected(tPtr,rev,"invalid"); return ADD_REJECTED; case 0: { const Credential::Type ct = rev.type(); switch(ct) { case Credential::CREDENTIAL_TYPE_COM: if (rev.threshold() > _comRevocationThreshold) { - RR->t->credentialAccepted(rev); + RR->t->credentialAccepted(tPtr,rev); _comRevocationThreshold = rev.threshold(); return ADD_ACCEPTED_NEW; } @@ -221,7 +221,7 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme } return ADD_ACCEPTED_REDUNDANT; default: - RR->t->credentialRejected(rev,"invalid"); + RR->t->credentialRejected(tPtr,rev,"invalid"); return ADD_REJECTED; } } diff --git a/node/Membership.hpp b/node/Membership.hpp index 5e4475dad..c6e2b803a 100644 --- a/node/Membership.hpp +++ b/node/Membership.hpp @@ -110,6 +110,11 @@ public: return nconf.com.agreesWith(_com); } + inline bool recentlyAssociated(const uint64_t now) const + { + return ((_com)&&((now - _com.timestamp()) < ZT_PEER_ACTIVITY_TIMEOUT)); + } + /** * Check whether the peer represented by this Membership owns a given resource * diff --git a/node/Network.cpp b/node/Network.cpp index 575b0170b..f7b144e3a 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -648,7 +648,7 @@ bool Network::filterOutgoingPacket( case DOZTFILTER_DROP: if (_config.remoteTraceTarget) - RR->t->networkFilter(*this,rrl,(Trace::RuleResultLog *)0,(Capability *)0,ztSource,ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,noTee,false,0); + RR->t->networkFilter(tPtr,*this,rrl,(Trace::RuleResultLog *)0,(Capability *)0,ztSource,ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,noTee,false,0); return false; case DOZTFILTER_REDIRECT: // interpreted as ACCEPT but ztFinalDest will have been changed in _doZtFilter() @@ -695,16 +695,16 @@ bool Network::filterOutgoingPacket( RR->sw->send(tPtr,outp,true); if (_config.remoteTraceTarget) - RR->t->networkFilter(*this,rrl,(localCapabilityIndex >= 0) ? &crrl : (Trace::RuleResultLog *)0,(localCapabilityIndex >= 0) ? &(_config.capabilities[localCapabilityIndex]) : (Capability *)0,ztSource,ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,noTee,false,0); + RR->t->networkFilter(tPtr,*this,rrl,(localCapabilityIndex >= 0) ? &crrl : (Trace::RuleResultLog *)0,(localCapabilityIndex >= 0) ? &(_config.capabilities[localCapabilityIndex]) : (Capability *)0,ztSource,ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,noTee,false,0); return false; // DROP locally, since we redirected } else { if (_config.remoteTraceTarget) - RR->t->networkFilter(*this,rrl,(localCapabilityIndex >= 0) ? &crrl : (Trace::RuleResultLog *)0,(localCapabilityIndex >= 0) ? &(_config.capabilities[localCapabilityIndex]) : (Capability *)0,ztSource,ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,noTee,false,1); + RR->t->networkFilter(tPtr,*this,rrl,(localCapabilityIndex >= 0) ? &crrl : (Trace::RuleResultLog *)0,(localCapabilityIndex >= 0) ? &(_config.capabilities[localCapabilityIndex]) : (Capability *)0,ztSource,ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,noTee,false,1); return true; } } else { if (_config.remoteTraceTarget) - RR->t->networkFilter(*this,rrl,(localCapabilityIndex >= 0) ? &crrl : (Trace::RuleResultLog *)0,(localCapabilityIndex >= 0) ? &(_config.capabilities[localCapabilityIndex]) : (Capability *)0,ztSource,ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,noTee,false,0); + RR->t->networkFilter(tPtr,*this,rrl,(localCapabilityIndex >= 0) ? &crrl : (Trace::RuleResultLog *)0,(localCapabilityIndex >= 0) ? &(_config.capabilities[localCapabilityIndex]) : (Capability *)0,ztSource,ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,noTee,false,0); return false; } } @@ -775,7 +775,7 @@ int Network::filterIncomingPacket( case DOZTFILTER_DROP: if (_config.remoteTraceTarget) - RR->t->networkFilter(*this,rrl,(Trace::RuleResultLog *)0,(Capability *)0,sourcePeer->address(),ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,false,true,0); + RR->t->networkFilter(tPtr,*this,rrl,(Trace::RuleResultLog *)0,(Capability *)0,sourcePeer->address(),ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,false,true,0); return 0; // DROP case DOZTFILTER_REDIRECT: // interpreted as ACCEPT but ztFinalDest will have been changed in _doZtFilter() @@ -816,13 +816,13 @@ int Network::filterIncomingPacket( RR->sw->send(tPtr,outp,true); if (_config.remoteTraceTarget) - RR->t->networkFilter(*this,rrl,(c) ? &crrl : (Trace::RuleResultLog *)0,c,sourcePeer->address(),ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,false,true,0); + RR->t->networkFilter(tPtr,*this,rrl,(c) ? &crrl : (Trace::RuleResultLog *)0,c,sourcePeer->address(),ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,false,true,0); return 0; // DROP locally, since we redirected } } if (_config.remoteTraceTarget) - RR->t->networkFilter(*this,rrl,(c) ? &crrl : (Trace::RuleResultLog *)0,c,sourcePeer->address(),ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,false,true,accept); + RR->t->networkFilter(tPtr,*this,rrl,(c) ? &crrl : (Trace::RuleResultLog *)0,c,sourcePeer->address(),ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,false,true,accept); return accept; } @@ -1135,7 +1135,7 @@ void Network::requestConfiguration(void *tPtr) rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_FLAGS,(uint64_t)0); rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_RULES_ENGINE_REV,(uint64_t)ZT_RULES_ENGINE_REVISION); - RR->t->networkConfigRequestSent(*this,ctrl); + RR->t->networkConfigRequestSent(tPtr,*this,ctrl); if (ctrl == RR->identity.address()) { if (RR->localNetworkController) { @@ -1183,6 +1183,13 @@ bool Network::gate(void *tPtr,const SharedPtr &peer) return false; } +bool Network::recentlyAssociatedWith(const Address &addr) +{ + Mutex::Lock _l(_lock); + const Membership *m = _memberships.get(addr); + return ((m)&&(m->recentlyAssociated(RR->node->now()))); +} + void Network::clean() { const uint64_t now = RR->node->now(); diff --git a/node/Network.hpp b/node/Network.hpp index 454a3f204..be5f1a127 100644 --- a/node/Network.hpp +++ b/node/Network.hpp @@ -248,6 +248,19 @@ public: */ bool gate(void *tPtr,const SharedPtr &peer); + /** + * Check whether a given peer has recently had an association with this network + * + * This checks whether a peer has communicated with us recently about this + * network and has possessed a valid certificate of membership. This may return + * true even if the peer has been offline for a while or no longer has a valid + * certificate of membership but had one recently. + * + * @param addr Peer address + * @return True if peer has recently associated + */ + bool recentlyAssociatedWith(const Address &addr); + /** * Do periodic cleanup and housekeeping tasks */ diff --git a/node/Node.cpp b/node/Node.cpp index c54ca4500..073af4bdf 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -90,14 +90,15 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint6 } } - idtmp[0] = RR->identity.address().toInt(); idtmp[1] = 0; if (n <= 0) { RR->identity.generate(); + idtmp[0] = RR->identity.address().toInt(); idtmp[1] = 0; RR->identity.toString(false,RR->publicIdentityStr); RR->identity.toString(true,RR->secretIdentityStr); stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_SECRET,idtmp,RR->secretIdentityStr,(unsigned int)strlen(RR->secretIdentityStr)); stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,RR->publicIdentityStr,(unsigned int)strlen(RR->publicIdentityStr)); } else { + idtmp[0] = RR->identity.address().toInt(); idtmp[1] = 0; n = stateObjectGet(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,tmp,sizeof(tmp) - 1); if (n > 0) { tmp[n] = (char)0; @@ -201,7 +202,7 @@ public: for(unsigned long k=0,ptr=(unsigned long)RR->node->prng();k<(unsigned long)upstreamStableEndpoints->size();++k) { const InetAddress &addr = (*upstreamStableEndpoints)[ptr++ % upstreamStableEndpoints->size()]; if (addr.ss_family == AF_INET) { - p->sendHELLO(_tPtr,InetAddress(),addr,_now,0); + p->sendHELLO(_tPtr,-1,addr,_now,0); contacted = true; break; } @@ -211,7 +212,7 @@ public: for(unsigned long k=0,ptr=(unsigned long)RR->node->prng();k<(unsigned long)upstreamStableEndpoints->size();++k) { const InetAddress &addr = (*upstreamStableEndpoints)[ptr++ % upstreamStableEndpoints->size()]; if (addr.ss_family == AF_INET6) { - p->sendHELLO(_tPtr,InetAddress(),addr,_now,0); + p->sendHELLO(_tPtr,-1,addr,_now,0); contacted = true; break; } diff --git a/node/Node.hpp b/node/Node.hpp index 57b99fe9d..e60da1adb 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -257,6 +257,8 @@ public: virtual void ncSendRevocation(const Address &destination,const Revocation &rev); virtual void ncSendError(uint64_t nwid,uint64_t requestPacketId,const Address &destination,NetworkController::ErrorCode errorCode); + inline const Address &remoteTraceTarget() const { return _remoteTraceTarget; } + private: RuntimeEnvironment _RR; RuntimeEnvironment *RR; @@ -278,6 +280,7 @@ private: Mutex _backgroundTasksLock; + Address _remoteTraceTarget; uint64_t _now; uint64_t _lastPingCheck; uint64_t _lastHousekeepingRun; diff --git a/node/Packet.hpp b/node/Packet.hpp index 4941e96ac..a1ea73e19 100644 --- a/node/Packet.hpp +++ b/node/Packet.hpp @@ -967,9 +967,8 @@ public: /** * A trace for remote debugging or diagnostics: - * <[8] 64-bit instance ID> - * <[2] 16-bit length of Dictionary> - * <[...] dictionary containing trace information> + * <[...] null-terminated dictionary containing trace information> + * [<[...] additional null-terminated dictionaries>] * * This message contains a remote trace event. Remote trace events can * be sent to observers configured at the network level for those that diff --git a/node/Peer.cpp b/node/Peer.cpp index 79a4bc903..d362be9ff 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -72,7 +72,8 @@ void Peer::received( const Packet::Verb verb, const uint64_t inRePacketId, const Packet::Verb inReVerb, - const bool trustEstablished) + const bool trustEstablished, + const uint64_t networkId) { const uint64_t now = RR->node->now(); @@ -183,11 +184,11 @@ void Peer::received( if (replacablePath) { if (verb == Packet::VERB_OK) { - RR->t->peerLearnedNewPath(*this,replacablePath->p,path,packetId); + RR->t->peerLearnedNewPath(tPtr,networkId,*this,replacablePath->p,path,packetId); replacablePath->lr = now; replacablePath->p = path; } else { - RR->t->peerConfirmingUnknownPath(*this,path,packetId,verb); + RR->t->peerConfirmingUnknownPath(tPtr,networkId,*this,path,packetId,verb); attemptToContactAt(tPtr,path->localSocket(),path->address(),now,true,path->nextOutgoingCounter()); path->sent(now); } @@ -438,7 +439,7 @@ void Peer::redirect(void *tPtr,const int64_t localSocket,const InetAddress &remo } } - RR->t->peerRedirected(*this,op,np); + RR->t->peerRedirected(tPtr,0,*this,op,np); } } // namespace ZeroTier diff --git a/node/Peer.hpp b/node/Peer.hpp index b24318ec6..6d00e3e61 100644 --- a/node/Peer.hpp +++ b/node/Peer.hpp @@ -102,6 +102,7 @@ public: * @param inRePacketId Packet ID in reply to (default: none) * @param inReVerb Verb in reply to (for OK/ERROR, default: VERB_NOP) * @param trustEstablished If true, some form of non-trivial trust (like allowed in network) has been established + * @param networkId Network ID if this pertains to a network, or 0 otherwise */ void received( void *tPtr, @@ -111,7 +112,8 @@ public: const Packet::Verb verb, const uint64_t inRePacketId, const Packet::Verb inReVerb, - const bool trustEstablished); + const bool trustEstablished, + const uint64_t networkId); /** * @param now Current time diff --git a/node/SelfAwareness.cpp b/node/SelfAwareness.cpp index 173230fb4..cdbb63032 100644 --- a/node/SelfAwareness.cpp +++ b/node/SelfAwareness.cpp @@ -82,7 +82,7 @@ void SelfAwareness::iam(void *tPtr,const Address &reporter,const int64_t receive if ( (trusted) && ((now - entry.ts) < ZT_SELFAWARENESS_ENTRY_TIMEOUT) && (!entry.mySurface.ipsEqual(myPhysicalAddress)) ) { // Changes to external surface reported by trusted peers causes path reset in this scope - RR->t->resettingPathsInScope(reporter,reporterPhysicalAddress,myPhysicalAddress,scope); + RR->t->resettingPathsInScope(tPtr,reporter,reporterPhysicalAddress,myPhysicalAddress,scope); entry.mySurface = myPhysicalAddress; entry.ts = now; diff --git a/node/Switch.cpp b/node/Switch.cpp index 2fbd243ba..eee497754 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -318,7 +318,7 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr &network,const bool fromBridged; if ((fromBridged = (from != network->mac()))) { if (!network->config().permitsBridging(RR->identity.address())) { - RR->t->outgoingFrameDropped(network,from,to,etherType,vlanId,len,"not a bridge"); + RR->t->outgoingNetworkFrameDropped(tPtr,network,from,to,etherType,vlanId,len,"not a bridge"); return; } } @@ -340,7 +340,7 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr &network,const multicastGroup = MulticastGroup::deriveMulticastGroupForAddressResolution(InetAddress(((const unsigned char *)data) + 24,4,0)); } else if (!network->config().enableBroadcast()) { // Don't transmit broadcasts if this network doesn't want them - RR->t->outgoingFrameDropped(network,from,to,etherType,vlanId,len,"broadcast disabled"); + RR->t->outgoingNetworkFrameDropped(tPtr,network,from,to,etherType,vlanId,len,"broadcast disabled"); return; } } else if ((etherType == ZT_ETHERTYPE_IPV6)&&(len >= (40 + 8 + 16))) { @@ -428,7 +428,7 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr &network,const // Check this after NDP emulation, since that has to be allowed in exactly this case if (network->config().multicastLimit == 0) { - RR->t->outgoingFrameDropped(network,from,to,etherType,vlanId,len,"multicast disabled"); + RR->t->outgoingNetworkFrameDropped(tPtr,network,from,to,etherType,vlanId,len,"multicast disabled"); return; } @@ -441,7 +441,7 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr &network,const // First pass sets noTee to false, but noTee is set to true in OutboundMulticast to prevent duplicates. if (!network->filterOutgoingPacket(tPtr,false,RR->identity.address(),Address(),from,to,(const uint8_t *)data,len,etherType,vlanId)) { - RR->t->outgoingFrameDropped(network,from,to,etherType,vlanId,len,"filter blocked"); + RR->t->outgoingNetworkFrameDropped(tPtr,network,from,to,etherType,vlanId,len,"filter blocked"); return; } @@ -467,7 +467,7 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr &network,const SharedPtr toPeer(RR->topology->getPeer(tPtr,toZT)); if (!network->filterOutgoingPacket(tPtr,false,RR->identity.address(),toZT,from,to,(const uint8_t *)data,len,etherType,vlanId)) { - RR->t->outgoingFrameDropped(network,from,to,etherType,vlanId,len,"filter blocked"); + RR->t->outgoingNetworkFrameDropped(tPtr,network,from,to,etherType,vlanId,len,"filter blocked"); return; } @@ -499,7 +499,7 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr &network,const // for each ZT destination are also done below. This is the same rationale // and design as for multicast. if (!network->filterOutgoingPacket(tPtr,false,RR->identity.address(),Address(),from,to,(const uint8_t *)data,len,etherType,vlanId)) { - RR->t->outgoingFrameDropped(network,from,to,etherType,vlanId,len,"filter blocked"); + RR->t->outgoingNetworkFrameDropped(tPtr,network,from,to,etherType,vlanId,len,"filter blocked"); return; } @@ -548,7 +548,7 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr &network,const outp.compress(); send(tPtr,outp,true); } else { - RR->t->outgoingFrameDropped(network,from,to,etherType,vlanId,len,"filter blocked (bridge replication)"); + RR->t->outgoingNetworkFrameDropped(tPtr,network,from,to,etherType,vlanId,len,"filter blocked (bridge replication)"); } } } @@ -646,7 +646,7 @@ unsigned long Switch::doTimerTasks(void *tPtr,uint64_t now) if (_trySend(tPtr,txi->packet,txi->encrypt)) _txQueue.erase(txi++); else if ((now - txi->creationTime) > ZT_TRANSMIT_QUEUE_TIMEOUT) { - RR->t->txTimedOut(txi->dest); + RR->t->txTimedOut(tPtr,txi->dest); _txQueue.erase(txi++); } else ++txi; } diff --git a/node/Trace.cpp b/node/Trace.cpp index 6b68cfe7d..dc5ecf191 100644 --- a/node/Trace.cpp +++ b/node/Trace.cpp @@ -29,16 +29,25 @@ #include "Switch.hpp" #include "Node.hpp" #include "Utils.hpp" +#include "Dictionary.hpp" +#include "CertificateOfMembership.hpp" +#include "CertificateOfOwnership.hpp" +#include "CertificateOfRepresentation.hpp" +#include "Tag.hpp" +#include "Capability.hpp" +#include "Revocation.hpp" namespace ZeroTier { +// Defining ZT_TRACE causes debug tracing messages to be dumped to stderr #ifdef ZT_TRACE + static const char *packetVerbString(Packet::Verb v) { switch(v) { case Packet::VERB_NOP: return "NOP"; case Packet::VERB_HELLO: return "HELLO"; - case Packet::Packet::VERB_ERROR: return "ERROR"; + case Packet::VERB_ERROR: return "ERROR"; case Packet::VERB_OK: return "OK"; case Packet::VERB_WHOIS: return "WHOIS"; case Packet::VERB_RENDEZVOUS: return "RENDEZVOUS"; @@ -73,61 +82,220 @@ static const char *packetErrorString(Packet::ErrorCode e) } return "(unknown)"; } -#endif -void Trace::resettingPathsInScope(const Address &reporter,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,const InetAddress::IpScope scope) +#define TRprintf(f,...) { fprintf(stderr,(f),__VA_ARGS__); fflush(stderr); } + +#else + +#define TRprintf(f,...) + +#endif // ZT_TRACE + +#define ZT_REMOTE_TRACE_FIELD__EVENT "E" +#define ZT_REMOTE_TRACE_FIELD__PACKET_ID "pid" +#define ZT_REMOTE_TRACE_FIELD__PACKET_VERB "pv" +#define ZT_REMOTE_TRACE_FIELD__PACKET_TRUSTED_PATH_ID "ptpid" +#define ZT_REMOTE_TRACE_FIELD__PACKET_TRUSTED_PATH_APPROVED "ptpok" +#define ZT_REMOTE_TRACE_FIELD__PACKET_HOPS "phops" +#define ZT_REMOTE_TRACE_FIELD__OLD_REMOTE_PHYADDR "oldrphy" +#define ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR "rzt" +#define ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR "rphy" +#define ZT_REMOTE_TRACE_FIELD__LOCAL_ZTADDR "lzt" +#define ZT_REMOTE_TRACE_FIELD__LOCAL_PHYADDR "lphy" +#define ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET "ls" +#define ZT_REMOTE_TRACE_FIELD__IP_SCOPE "ipsc" +#define ZT_REMOTE_TRACE_FIELD__NETWORK_ID "nwid" +#define ZT_REMOTE_TRACE_FIELD__SOURCE_MAC "seth" +#define ZT_REMOTE_TRACE_FIELD__DEST_MAC "deth" +#define ZT_REMOTE_TRACE_FIELD__ETHERTYPE "et" +#define ZT_REMOTE_TRACE_FIELD__VLAN_ID "vlan" +#define ZT_REMOTE_TRACE_FIELD__FRAME_LENGTH "fl" +#define ZT_REMOTE_TRACE_FIELD__FRAME_DATA "fd" +#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE "credtype" +#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID "credid" +#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP "credts" +#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_INFO "credinfo" +#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO "crediss" +#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_REVOCATION_TARGET "credRt" +#define ZT_REMOTE_TRACE_FIELD__REASON "reason" + +#define ZT_REMOTE_TRACE_EVENT__RESETTING_PATHS_IN_SCOPE_S "1000" +#define ZT_REMOTE_TRACE_EVENT__TX_TIMED_OUT_S "1001" +#define ZT_REMOTE_TRACE_EVENT__PEER_CONFIRMING_UNKNOWN_PATH_S "1002" +#define ZT_REMOTE_TRACE_EVENT__PEER_LEARNED_NEW_PATH_S "1003" +#define ZT_REMOTE_TRACE_EVENT__PEER_REDIRECTED_S "1004" +#define ZT_REMOTE_TRACE_EVENT__PACKET_MAC_FAILURE_S "1005" +#define ZT_REMOTE_TRACE_EVENT__PACKET_INVALID_S "1006" +#define ZT_REMOTE_TRACE_EVENT__DROPPED_HELLO_S "1006" + +#define ZT_REMOTE_TRACE_EVENT__OUTGOING_NETWORK_FRAME_DROPPED_S "2000" +#define ZT_REMOTE_TRACE_EVENT__INCOMING_NETWORK_ACCESS_DENIED_S "2001" +#define ZT_REMOTE_TRACE_EVENT__INCOMING_NETWORK_FRAME_DROPPED_S "2002" +#define ZT_REMOTE_TRACE_EVENT__CREDENTIAL_REJECTED_S "2003" +#define ZT_REMOTE_TRACE_EVENT__CREDENTIAL_ACCEPTED_S "2004" + +void Trace::resettingPathsInScope(void *const tPtr,const Address &reporter,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,const InetAddress::IpScope scope) { + char tmp[128]; + Dictionary d; + d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__RESETTING_PATHS_IN_SCOPE_S); + d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR,reporter); + d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR,reporterPhysicalAddress.toString(tmp)); + d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_PHYADDR,myPhysicalAddress.toString(tmp)); + d.add(ZT_REMOTE_TRACE_FIELD__IP_SCOPE,(uint64_t)scope); + _send(tPtr,d,0); } -void Trace::txTimedOut(const Address &destination) +void Trace::txTimedOut(void *const tPtr,const Address &destination) { + Dictionary d; + d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__TX_TIMED_OUT_S); + d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR,destination); + _send(tPtr,d,0); } -void Trace::peerConfirmingUnknownPath(Peer &peer,const SharedPtr &path,const uint64_t packetId,const Packet::Verb verb) +void Trace::peerConfirmingUnknownPath(void *const tPtr,const uint64_t networkId,Peer &peer,const SharedPtr &path,const uint64_t packetId,const Packet::Verb verb) { + char tmp[128]; + Dictionary d; + d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__PEER_CONFIRMING_UNKNOWN_PATH_S); + d.add(ZT_REMOTE_TRACE_FIELD__PACKET_ID,packetId); + d.add(ZT_REMOTE_TRACE_FIELD__PACKET_VERB,(uint64_t)verb); + d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID,networkId); + d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR,peer.address()); + if (path) { + d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR,path->address().toString(tmp)); + d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET,path->localSocket()); + } + _send(tPtr,d,networkId); } -void Trace::peerLearnedNewPath(Peer &peer,const SharedPtr &oldPath,const SharedPtr &newPath,const uint64_t packetId) +void Trace::peerLearnedNewPath(void *const tPtr,const uint64_t networkId,Peer &peer,const SharedPtr &oldPath,const SharedPtr &newPath,const uint64_t packetId) { + char tmp[128]; + Dictionary d; + d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__PEER_LEARNED_NEW_PATH_S); + d.add(ZT_REMOTE_TRACE_FIELD__PACKET_ID,packetId); + d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID,networkId); + d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR,peer.address()); + if (oldPath) { + d.add(ZT_REMOTE_TRACE_FIELD__OLD_REMOTE_PHYADDR,oldPath->address().toString(tmp)); + } + if (newPath) { + d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR,newPath->address().toString(tmp)); + d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET,newPath->localSocket()); + } + _send(tPtr,d,networkId); } -void Trace::peerRedirected(Peer &peer,const SharedPtr &oldPath,const SharedPtr &newPath) +void Trace::peerRedirected(void *const tPtr,const uint64_t networkId,Peer &peer,const SharedPtr &oldPath,const SharedPtr &newPath) { + char tmp[128]; + Dictionary d; + d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__PEER_REDIRECTED_S); + d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID,networkId); + d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR,peer.address()); + if (oldPath) { + d.add(ZT_REMOTE_TRACE_FIELD__OLD_REMOTE_PHYADDR,oldPath->address().toString(tmp)); + } + if (newPath) { + d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR,newPath->address().toString(tmp)); + d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET,newPath->localSocket()); + } + _send(tPtr,d,networkId); } -void Trace::outgoingFrameDropped(const SharedPtr &network,const MAC &sourceMac,const MAC &destMac,const unsigned int etherType,const unsigned int vlanId,const unsigned int frameLen,const char *reason) +void Trace::outgoingNetworkFrameDropped(void *const tPtr,const SharedPtr &network,const MAC &sourceMac,const MAC &destMac,const unsigned int etherType,const unsigned int vlanId,const unsigned int frameLen,const char *reason) { + if (!network) return; // sanity check + Dictionary d; + d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__OUTGOING_NETWORK_FRAME_DROPPED_S); + d.add(ZT_REMOTE_TRACE_FIELD__SOURCE_MAC,sourceMac.toInt()); + d.add(ZT_REMOTE_TRACE_FIELD__DEST_MAC,destMac.toInt()); + d.add(ZT_REMOTE_TRACE_FIELD__ETHERTYPE,(uint64_t)etherType); + d.add(ZT_REMOTE_TRACE_FIELD__VLAN_ID,(uint64_t)vlanId); + d.add(ZT_REMOTE_TRACE_FIELD__FRAME_LENGTH,(uint64_t)frameLen); + if (reason) + d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason); + _send(tPtr,d,network); } -void Trace::incomingPacketTrustedPath(const SharedPtr &path,const uint64_t packetId,const Address &source,const uint64_t trustedPathId,bool approved) +void Trace::incomingNetworkAccessDenied(void *const tPtr,const SharedPtr &network,const SharedPtr &path,const uint64_t packetId,const unsigned int packetLength,const Address &source,const Packet::Verb verb,bool credentialsRequested) { + if (!network) return; // sanity check + char tmp[128]; + Dictionary d; + d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__INCOMING_NETWORK_ACCESS_DENIED_S); + d.add(ZT_REMOTE_TRACE_FIELD__PACKET_ID,packetId); + d.add(ZT_REMOTE_TRACE_FIELD__PACKET_VERB,(uint64_t)verb); + d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID,network->id()); + d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR,source); + if (path) { + d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR,path->address().toString(tmp)); + d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET,path->localSocket()); + } } -void Trace::incomingPacketMessageAuthenticationFailure(const SharedPtr &path,const uint64_t packetId,const Address &source) +void Trace::incomingNetworkFrameDropped(void *const tPtr,const SharedPtr &network,const SharedPtr &path,const uint64_t packetId,const unsigned int packetLength,const Address &source,const Packet::Verb verb,const MAC &sourceMac,const MAC &destMac) { + //Dictionary d; + //d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__INCOMING_NETWORK_FRAME_DROPPED_S); } -void Trace::incomingPacketInvalid(const SharedPtr &path,const uint64_t packetId,const Address &source,const Packet::Verb verb,const char *reason) +void Trace::incomingPacketTrustedPath(void *const tPtr,const SharedPtr &path,const uint64_t packetId,const Address &source,const uint64_t trustedPathId,bool approved) { + // TODO } -void Trace::incomingPacketDroppedHELLO(const SharedPtr &path,const uint64_t packetId,const Address &source,const char *reason) +void Trace::incomingPacketMessageAuthenticationFailure(void *const tPtr,const SharedPtr &path,const uint64_t packetId,const Address &source,const unsigned int hops) { + char tmp[128]; + Dictionary d; + d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__PACKET_MAC_FAILURE_S); + d.add(ZT_REMOTE_TRACE_FIELD__PACKET_ID,packetId); + d.add(ZT_REMOTE_TRACE_FIELD__PACKET_HOPS,(uint64_t)hops); + d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR,source); + d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR,path->address().toString(tmp)); + d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET,path->localSocket()); + _send(tPtr,d,0); } -void Trace::networkAccessDenied(const SharedPtr &network,const SharedPtr &path,const uint64_t packetId,const unsigned int packetLength,const Address &source,const Packet::Verb verb,bool credentialsRequested) +void Trace::incomingPacketInvalid(void *const tPtr,const SharedPtr &path,const uint64_t packetId,const Address &source,const unsigned int hops,const Packet::Verb verb,const char *reason) { + char tmp[128]; + Dictionary d; + d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__PACKET_INVALID_S); + d.add(ZT_REMOTE_TRACE_FIELD__PACKET_ID,packetId); + d.add(ZT_REMOTE_TRACE_FIELD__PACKET_VERB,(uint64_t)verb); + d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR,source); + d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR,path->address().toString(tmp)); + d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET,path->localSocket()); + d.add(ZT_REMOTE_TRACE_FIELD__PACKET_HOPS,(uint64_t)hops); + if (reason) + d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason); + _send(tPtr,d,0); } -void Trace::networkFrameDropped(const SharedPtr &network,const SharedPtr &path,const uint64_t packetId,const unsigned int packetLength,const Address &source,const Packet::Verb verb,const MAC &sourceMac,const MAC &destMac) +void Trace::incomingPacketDroppedHELLO(void *const tPtr,const SharedPtr &path,const uint64_t packetId,const Address &source,const char *reason) { + char tmp[128]; + Dictionary d; + d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__PACKET_INVALID_S); + d.add(ZT_REMOTE_TRACE_FIELD__PACKET_ID,packetId); + d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR,source); + d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR,path->address().toString(tmp)); + d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET,path->localSocket()); + if (reason) + d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason); + _send(tPtr,d,0); } -void Trace::networkConfigRequestSent(const Network &network,const Address &controller) +void Trace::networkConfigRequestSent(void *const tPtr,const Network &network,const Address &controller) { } void Trace::networkFilter( + void *const tPtr, const Network &network, const RuleResultLog &primaryRuleSetLog, const RuleResultLog *const matchingCapabilityRuleSetLog, @@ -144,54 +312,185 @@ void Trace::networkFilter( const bool inbound, const int accept) { + //char tmp[128]; + //Dictionary d; + //_send(tPtr,d,network.id()); } -void Trace::credentialRejected(const CertificateOfMembership &c,const char *reason) +void Trace::credentialRejected(void *const tPtr,const CertificateOfMembership &c,const char *reason) { + Dictionary d; + d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__CREDENTIAL_REJECTED_S); + d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID,c.networkId()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE,(uint64_t)c.credentialType()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP,c.timestamp()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO,c.issuedTo()); + if (reason) + d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason); } -void Trace::credentialRejected(const CertificateOfOwnership &c,const char *reason) +void Trace::credentialRejected(void *const tPtr,const CertificateOfOwnership &c,const char *reason) { + Dictionary d; + d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__CREDENTIAL_REJECTED_S); + d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID,c.networkId()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE,(uint64_t)c.credentialType()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP,c.timestamp()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO,c.issuedTo()); + if (reason) + d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason); } -void Trace::credentialRejected(const CertificateOfRepresentation &c,const char *reason) +void Trace::credentialRejected(void *const tPtr,const CertificateOfRepresentation &c,const char *reason) { + Dictionary d; + d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__CREDENTIAL_REJECTED_S); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE,(uint64_t)c.credentialType()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP,c.timestamp()); + if (reason) + d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason); } -void Trace::credentialRejected(const Capability &c,const char *reason) +void Trace::credentialRejected(void *const tPtr,const Capability &c,const char *reason) { + Dictionary d; + d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__CREDENTIAL_REJECTED_S); + d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID,c.networkId()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE,(uint64_t)c.credentialType()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP,c.timestamp()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO,c.issuedTo()); + if (reason) + d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason); } -void Trace::credentialRejected(const Tag &c,const char *reason) +void Trace::credentialRejected(void *const tPtr,const Tag &c,const char *reason) { + Dictionary d; + d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__CREDENTIAL_REJECTED_S); + d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID,c.networkId()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE,(uint64_t)c.credentialType()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP,c.timestamp()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO,c.issuedTo()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_INFO,(uint64_t)c.value()); + if (reason) + d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason); } -void Trace::credentialRejected(const Revocation &c,const char *reason) +void Trace::credentialRejected(void *const tPtr,const Revocation &c,const char *reason) { + Dictionary d; + d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__CREDENTIAL_REJECTED_S); + d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID,c.networkId()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE,(uint64_t)c.credentialType()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_REVOCATION_TARGET,c.target()); + if (reason) + d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason); } -void Trace::credentialAccepted(const CertificateOfMembership &c) +void Trace::credentialAccepted(void *const tPtr,const CertificateOfMembership &c) { + Dictionary d; + d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__CREDENTIAL_ACCEPTED_S); + d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID,c.networkId()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE,(uint64_t)c.credentialType()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP,c.timestamp()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO,c.issuedTo()); } -void Trace::credentialAccepted(const CertificateOfOwnership &c) +void Trace::credentialAccepted(void *const tPtr,const CertificateOfOwnership &c) { + Dictionary d; + d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__CREDENTIAL_ACCEPTED_S); + d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID,c.networkId()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE,(uint64_t)c.credentialType()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP,c.timestamp()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO,c.issuedTo()); } -void Trace::credentialAccepted(const CertificateOfRepresentation &c) +void Trace::credentialAccepted(void *const tPtr,const CertificateOfRepresentation &c) { + Dictionary d; + d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__CREDENTIAL_ACCEPTED_S); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE,(uint64_t)c.credentialType()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP,c.timestamp()); } -void Trace::credentialAccepted(const Capability &c) +void Trace::credentialAccepted(void *const tPtr,const Capability &c) { + Dictionary d; + d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__CREDENTIAL_ACCEPTED_S); + d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID,c.networkId()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE,(uint64_t)c.credentialType()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP,c.timestamp()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO,c.issuedTo()); } -void Trace::credentialAccepted(const Tag &c) +void Trace::credentialAccepted(void *const tPtr,const Tag &c) { + Dictionary d; + d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__CREDENTIAL_ACCEPTED_S); + d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID,c.networkId()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE,(uint64_t)c.credentialType()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP,c.timestamp()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO,c.issuedTo()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_INFO,(uint64_t)c.value()); } -void Trace::credentialAccepted(const Revocation &c) +void Trace::credentialAccepted(void *const tPtr,const Revocation &c) { + Dictionary d; + d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__CREDENTIAL_ACCEPTED_S); + d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID,c.networkId()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE,(uint64_t)c.credentialType()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id()); + d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_REVOCATION_TARGET,c.target()); +} + +void Trace::_send(void *const tPtr,const Dictionary &d) +{ + const Address rtt(RR->node->remoteTraceTarget()); + if (rtt) { + Packet outp(rtt,RR->identity.address(),Packet::VERB_REMOTE_TRACE); + outp.appendCString(d.data()); + outp.compress(); + RR->sw->send(tPtr,outp,true); + } +} + +void Trace::_send(void *const tPtr,const Dictionary &d,const uint64_t networkId) +{ + _send(tPtr,d); + if (networkId) { + const SharedPtr network(RR->node->network(networkId)); + if ((network)&&(network->config().remoteTraceTarget)) { + Packet outp(network->config().remoteTraceTarget,RR->identity.address(),Packet::VERB_REMOTE_TRACE); + outp.appendCString(d.data()); + outp.compress(); + RR->sw->send(tPtr,outp,true); + } + } +} + +void Trace::_send(void *const tPtr,const Dictionary &d,const SharedPtr &network) +{ + _send(tPtr,d); + if ((network)&&(network->config().remoteTraceTarget)) { + Packet outp(network->config().remoteTraceTarget,RR->identity.address(),Packet::VERB_REMOTE_TRACE); + outp.appendCString(d.data()); + outp.compress(); + RR->sw->send(tPtr,outp,true); + } } } // namespace ZeroTier diff --git a/node/Trace.hpp b/node/Trace.hpp index 65d1acf1e..eefd5359f 100644 --- a/node/Trace.hpp +++ b/node/Trace.hpp @@ -39,6 +39,7 @@ #include "Packet.hpp" #include "Credential.hpp" #include "InetAddress.hpp" +#include "Dictionary.hpp" namespace ZeroTier { @@ -100,25 +101,25 @@ public: Trace(const RuntimeEnvironment *renv) : RR(renv) {} - void resettingPathsInScope(const Address &reporter,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,const InetAddress::IpScope scope); - void txTimedOut(const Address &destination); + void resettingPathsInScope(void *const tPtr,const Address &reporter,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,const InetAddress::IpScope scope); + void txTimedOut(void *const tPtr,const Address &destination); - void peerConfirmingUnknownPath(Peer &peer,const SharedPtr &path,const uint64_t packetId,const Packet::Verb verb); - void peerLearnedNewPath(Peer &peer,const SharedPtr &oldPath,const SharedPtr &newPath,const uint64_t packetId); - void peerRedirected(Peer &peer,const SharedPtr &oldPath,const SharedPtr &newPath); + void peerConfirmingUnknownPath(void *const tPtr,const uint64_t networkId,Peer &peer,const SharedPtr &path,const uint64_t packetId,const Packet::Verb verb); + void peerLearnedNewPath(void *const tPtr,const uint64_t networkId,Peer &peer,const SharedPtr &oldPath,const SharedPtr &newPath,const uint64_t packetId); + void peerRedirected(void *const tPtr,const uint64_t networkId,Peer &peer,const SharedPtr &oldPath,const SharedPtr &newPath); - void outgoingFrameDropped(const SharedPtr &network,const MAC &sourceMac,const MAC &destMac,const unsigned int etherType,const unsigned int vlanId,const unsigned int frameLen,const char *reason); + void incomingPacketTrustedPath(void *const tPtr,const SharedPtr &path,const uint64_t packetId,const Address &source,const uint64_t trustedPathId,bool approved); + void incomingPacketMessageAuthenticationFailure(void *const tPtr,const SharedPtr &path,const uint64_t packetId,const Address &source,const unsigned int hops); + void incomingPacketInvalid(void *const tPtr,const SharedPtr &path,const uint64_t packetId,const Address &source,const unsigned int hops,const Packet::Verb verb,const char *reason); + void incomingPacketDroppedHELLO(void *const tPtr,const SharedPtr &path,const uint64_t packetId,const Address &source,const char *reason); - void incomingPacketTrustedPath(const SharedPtr &path,const uint64_t packetId,const Address &source,const uint64_t trustedPathId,bool approved); - void incomingPacketMessageAuthenticationFailure(const SharedPtr &path,const uint64_t packetId,const Address &source); - void incomingPacketInvalid(const SharedPtr &path,const uint64_t packetId,const Address &source,const Packet::Verb verb,const char *reason); - void incomingPacketDroppedHELLO(const SharedPtr &path,const uint64_t packetId,const Address &source,const char *reason); + void outgoingNetworkFrameDropped(void *const tPtr,const SharedPtr &network,const MAC &sourceMac,const MAC &destMac,const unsigned int etherType,const unsigned int vlanId,const unsigned int frameLen,const char *reason); + void incomingNetworkAccessDenied(void *const tPtr,const SharedPtr &network,const SharedPtr &path,const uint64_t packetId,const unsigned int packetLength,const Address &source,const Packet::Verb verb,bool credentialsRequested); + void incomingNetworkFrameDropped(void *const tPtr,const SharedPtr &network,const SharedPtr &path,const uint64_t packetId,const unsigned int packetLength,const Address &source,const Packet::Verb verb,const MAC &sourceMac,const MAC &destMac); - void networkAccessDenied(const SharedPtr &network,const SharedPtr &path,const uint64_t packetId,const unsigned int packetLength,const Address &source,const Packet::Verb verb,bool credentialsRequested); - void networkFrameDropped(const SharedPtr &network,const SharedPtr &path,const uint64_t packetId,const unsigned int packetLength,const Address &source,const Packet::Verb verb,const MAC &sourceMac,const MAC &destMac); - - void networkConfigRequestSent(const Network &network,const Address &controller); + void networkConfigRequestSent(void *const tPtr,const Network &network,const Address &controller); void networkFilter( + void *const tPtr, const Network &network, const RuleResultLog &primaryRuleSetLog, const RuleResultLog *const matchingCapabilityRuleSetLog, @@ -135,21 +136,25 @@ public: const bool inbound, const int accept); - void credentialRejected(const CertificateOfMembership &c,const char *reason); - void credentialRejected(const CertificateOfOwnership &c,const char *reason); - void credentialRejected(const CertificateOfRepresentation &c,const char *reason); - void credentialRejected(const Capability &c,const char *reason); - void credentialRejected(const Tag &c,const char *reason); - void credentialRejected(const Revocation &c,const char *reason); - void credentialAccepted(const CertificateOfMembership &c); - void credentialAccepted(const CertificateOfOwnership &c); - void credentialAccepted(const CertificateOfRepresentation &c); - void credentialAccepted(const Capability &c); - void credentialAccepted(const Tag &c); - void credentialAccepted(const Revocation &c); + void credentialRejected(void *const tPtr,const CertificateOfMembership &c,const char *reason); + void credentialRejected(void *const tPtr,const CertificateOfOwnership &c,const char *reason); + void credentialRejected(void *const tPtr,const CertificateOfRepresentation &c,const char *reason); + void credentialRejected(void *const tPtr,const Capability &c,const char *reason); + void credentialRejected(void *const tPtr,const Tag &c,const char *reason); + void credentialRejected(void *const tPtr,const Revocation &c,const char *reason); + void credentialAccepted(void *const tPtr,const CertificateOfMembership &c); + void credentialAccepted(void *const tPtr,const CertificateOfOwnership &c); + void credentialAccepted(void *const tPtr,const CertificateOfRepresentation &c); + void credentialAccepted(void *const tPtr,const Capability &c); + void credentialAccepted(void *const tPtr,const Tag &c); + void credentialAccepted(void *const tPtr,const Revocation &c); private: const RuntimeEnvironment *const RR; + + void _send(void *const tPtr,const Dictionary &d); + void _send(void *const tPtr,const Dictionary &d,const uint64_t networkId); + void _send(void *const tPtr,const Dictionary &d,const SharedPtr &network); }; } // namespace ZeroTier