mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-05 03:53:44 +02:00
It builds... almost ready to test some rules engine stuff.
This commit is contained in:
parent
8007ca56aa
commit
00fd9c3a15
14 changed files with 121 additions and 154 deletions
|
@ -71,16 +71,18 @@ public:
|
||||||
/**
|
/**
|
||||||
* @param id Capability ID
|
* @param id Capability ID
|
||||||
* @param nwid Network ID
|
* @param nwid Network ID
|
||||||
|
* @param ts Timestamp (at controller)
|
||||||
* @param expiration Expiration relative to network config timestamp
|
* @param expiration Expiration relative to network config timestamp
|
||||||
* @param name Capability short name (max strlen == ZT_MAX_CAPABILITY_NAME_LENGTH, overflow ignored)
|
* @param name Capability short name (max strlen == ZT_MAX_CAPABILITY_NAME_LENGTH, overflow ignored)
|
||||||
* @param mccl Maximum custody chain length (1 to create non-transferrable capability)
|
* @param mccl Maximum custody chain length (1 to create non-transferrable capability)
|
||||||
* @param rules Network flow rules for this capability
|
* @param rules Network flow rules for this capability
|
||||||
* @param ruleCount Number of flow rules
|
* @param ruleCount Number of flow rules
|
||||||
*/
|
*/
|
||||||
Capability(uint32_t id,uint64_t nwid,uint64_t expiration,const char *name,unsigned int mccl,const ZT_VirtualNetworkRule *rules,unsigned int ruleCount)
|
Capability(uint32_t id,uint64_t nwid,uint64_t ts,uint64_t expiration,const char *name,unsigned int mccl,const ZT_VirtualNetworkRule *rules,unsigned int ruleCount)
|
||||||
{
|
{
|
||||||
memset(this,0,sizeof(Capability));
|
memset(this,0,sizeof(Capability));
|
||||||
_nwid = nwid;
|
_nwid = nwid;
|
||||||
|
_ts = ts;
|
||||||
_expiration = expiration;
|
_expiration = expiration;
|
||||||
_id = id;
|
_id = id;
|
||||||
_maxCustodyChainLength = (mccl > 0) ? ((mccl < ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH) ? mccl : (unsigned int)ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH) : 1;
|
_maxCustodyChainLength = (mccl > 0) ? ((mccl < ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH) ? mccl : (unsigned int)ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH) : 1;
|
||||||
|
@ -115,20 +117,22 @@ public:
|
||||||
inline uint64_t expiration() const { return _expiration; }
|
inline uint64_t expiration() const { return _expiration; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check to see if a given address is a 'to' address in the custody chain
|
* @return Timestamp
|
||||||
*
|
|
||||||
* This does not actually do certificate checking. That must be done with verify().
|
|
||||||
*
|
|
||||||
* @param a Address to check
|
|
||||||
* @return True if address is present
|
|
||||||
*/
|
*/
|
||||||
inline bool wasIssuedTo(const Address &a) const
|
inline uint64_t timestamp() const { return _ts; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Last 'to' address in chain of custody
|
||||||
|
*/
|
||||||
|
inline Address issuedTo() const
|
||||||
{
|
{
|
||||||
|
Address i2;
|
||||||
for(unsigned int i=0;i<ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH;++i) {
|
for(unsigned int i=0;i<ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH;++i) {
|
||||||
if (_custody[i].to == a)
|
if (!_custody[i].to)
|
||||||
return true;
|
return i2;
|
||||||
|
else i2 = _custody[i].to;
|
||||||
}
|
}
|
||||||
return false;
|
return i2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -265,9 +269,10 @@ public:
|
||||||
{
|
{
|
||||||
if (forSign) b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
|
if (forSign) b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
|
||||||
|
|
||||||
b.append(_id);
|
|
||||||
b.append(_nwid);
|
b.append(_nwid);
|
||||||
|
b.append(_ts);
|
||||||
b.append(_expiration);
|
b.append(_expiration);
|
||||||
|
b.append(_id);
|
||||||
serializeRules(b,_rules,_ruleCount);
|
serializeRules(b,_rules,_ruleCount);
|
||||||
b.append((uint8_t)_maxCustodyChainLength);
|
b.append((uint8_t)_maxCustodyChainLength);
|
||||||
|
|
||||||
|
@ -375,15 +380,16 @@ public:
|
||||||
|
|
||||||
unsigned int p = startAt;
|
unsigned int p = startAt;
|
||||||
|
|
||||||
_id = b.template at<uint32_t>(p); p += 4;
|
|
||||||
_nwid = b.template at<uint64_t>(p); p += 8;
|
_nwid = b.template at<uint64_t>(p); p += 8;
|
||||||
|
_ts = b.template at<uint64_t>(p); p += 8;
|
||||||
_expiration = b.template at<uint64_t>(p); p += 8;
|
_expiration = b.template at<uint64_t>(p); p += 8;
|
||||||
|
_id = b.template at<uint32_t>(p); p += 4;
|
||||||
deserializeRules(b,p,_rules,_ruleCount,ZT_MAX_CAPABILITY_RULES);
|
deserializeRules(b,p,_rules,_ruleCount,ZT_MAX_CAPABILITY_RULES);
|
||||||
_maxCustodyChainLength = (unsigned int)b[p++];
|
_maxCustodyChainLength = (unsigned int)b[p++];
|
||||||
|
|
||||||
if ((_maxCustodyChainLength < 1)||(_maxCustodyChainLength > ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH))
|
if ((_maxCustodyChainLength < 1)||(_maxCustodyChainLength > ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH))
|
||||||
throw std::runtime_error("invalid max custody chain length");
|
throw std::runtime_error("invalid max custody chain length");
|
||||||
for(unsigned int i;;++i) {
|
for(unsigned int i=0;;++i) {
|
||||||
const Address to(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); p += ZT_ADDRESS_LENGTH;
|
const Address to(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); p += ZT_ADDRESS_LENGTH;
|
||||||
if (!to)
|
if (!to)
|
||||||
break;
|
break;
|
||||||
|
@ -409,6 +415,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint64_t _nwid;
|
uint64_t _nwid;
|
||||||
|
uint64_t _ts;
|
||||||
uint64_t _expiration;
|
uint64_t _expiration;
|
||||||
uint32_t _id;
|
uint32_t _id;
|
||||||
|
|
||||||
|
|
|
@ -437,8 +437,11 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &p
|
||||||
if ((flags & 0x01) != 0) { // deprecated but still used by older peers
|
if ((flags & 0x01) != 0) { // deprecated but still used by older peers
|
||||||
CertificateOfMembership com;
|
CertificateOfMembership com;
|
||||||
offset += com.deserialize(*this,ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_COM_AND_GATHER_RESULTS);
|
offset += com.deserialize(*this,ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_COM_AND_GATHER_RESULTS);
|
||||||
LockingPtr<Membership> m(peer->membership(com.networkId(),true));
|
if (com) {
|
||||||
if (m) m->addCredential(RR,RR->node->now(),com);
|
SharedPtr<Network> network(RR->node->network(com.networkId()));
|
||||||
|
if (network)
|
||||||
|
network->addCredential(com);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((flags & 0x02) != 0) {
|
if ((flags & 0x02) != 0) {
|
||||||
|
@ -567,8 +570,8 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,const SharedPtr<P
|
||||||
if ((flags & 0x01) != 0) { // deprecated but still used by old peers
|
if ((flags & 0x01) != 0) { // deprecated but still used by old peers
|
||||||
CertificateOfMembership com;
|
CertificateOfMembership com;
|
||||||
comLen = com.deserialize(*this,ZT_PROTO_VERB_EXT_FRAME_IDX_COM);
|
comLen = com.deserialize(*this,ZT_PROTO_VERB_EXT_FRAME_IDX_COM);
|
||||||
LockingPtr<Membership> m(peer->membership(com.networkId(),true));
|
if (com)
|
||||||
if (m) m->addCredential(RR,RR->node->now(),com);
|
network->addCredential(com);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!network->isAllowed(peer)) {
|
if (!network->isAllowed(peer)) {
|
||||||
|
@ -661,7 +664,6 @@ bool IncomingPacket::_doMULTICAST_LIKE(const RuntimeEnvironment *RR,const Shared
|
||||||
bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer)
|
bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
const uint64_t now = RR->node->now();
|
|
||||||
CertificateOfMembership com;
|
CertificateOfMembership com;
|
||||||
Capability cap;
|
Capability cap;
|
||||||
Tag tag;
|
Tag tag;
|
||||||
|
@ -669,9 +671,13 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const S
|
||||||
unsigned int p = ZT_PACKET_IDX_PAYLOAD;
|
unsigned int p = ZT_PACKET_IDX_PAYLOAD;
|
||||||
while ((p < size())&&((*this)[p])) {
|
while ((p < size())&&((*this)[p])) {
|
||||||
p += com.deserialize(*this,p);
|
p += com.deserialize(*this,p);
|
||||||
LockingPtr<Membership> m(peer->membership(com.networkId(),true));
|
if (com) {
|
||||||
if (!m) return true; // sanity check
|
SharedPtr<Network> network(RR->node->network(com.networkId()));
|
||||||
if (m->addCredential(RR,now,com) == 1) return false; // wait for WHOIS
|
if (network) {
|
||||||
|
if (network->addCredential(com) == 1)
|
||||||
|
return false; // wait for WHOIS
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
++p; // skip trailing 0 after COMs if present
|
++p; // skip trailing 0 after COMs if present
|
||||||
|
|
||||||
|
@ -679,17 +685,21 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const S
|
||||||
const unsigned int numCapabilities = at<uint16_t>(p); p += 2;
|
const unsigned int numCapabilities = at<uint16_t>(p); p += 2;
|
||||||
for(unsigned int i=0;i<numCapabilities;++i) {
|
for(unsigned int i=0;i<numCapabilities;++i) {
|
||||||
p += cap.deserialize(*this,p);
|
p += cap.deserialize(*this,p);
|
||||||
LockingPtr<Membership> m(peer->membership(cap.networkId(),true));
|
SharedPtr<Network> network(RR->node->network(cap.networkId()));
|
||||||
if (!m) return true; // sanity check
|
if (network) {
|
||||||
if (m->addCredential(RR,now,cap) == 1) return false; // wait for WHOIS
|
if (network->addCredential(cap) == 1)
|
||||||
|
return false; // wait for WHOIS
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const unsigned int numTags = at<uint16_t>(p); p += 2;
|
const unsigned int numTags = at<uint16_t>(p); p += 2;
|
||||||
for(unsigned int i=0;i<numTags;++i) {
|
for(unsigned int i=0;i<numTags;++i) {
|
||||||
p += tag.deserialize(*this,p);
|
p += tag.deserialize(*this,p);
|
||||||
LockingPtr<Membership> m(peer->membership(tag.networkId(),true));
|
SharedPtr<Network> network(RR->node->network(tag.networkId()));
|
||||||
if (!m) return true; // sanity check
|
if (network) {
|
||||||
if (m->addCredential(RR,now,tag) == 1) return false; // wait for WHOIS
|
if (network->addCredential(tag) == 1)
|
||||||
|
return false; // wait for WHOIS
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -830,8 +840,8 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,const Share
|
||||||
if ((flags & 0x01) != 0) { // deprecated but still used by older peers
|
if ((flags & 0x01) != 0) { // deprecated but still used by older peers
|
||||||
CertificateOfMembership com;
|
CertificateOfMembership com;
|
||||||
offset += com.deserialize(*this,ZT_PROTO_VERB_MULTICAST_FRAME_IDX_COM);
|
offset += com.deserialize(*this,ZT_PROTO_VERB_MULTICAST_FRAME_IDX_COM);
|
||||||
LockingPtr<Membership> m(peer->membership(com.networkId(),true));
|
if (com)
|
||||||
if (m) m->addCredential(RR,RR->node->now(),com);
|
network->addCredential(com);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check membership after we've read any included COM, since
|
// Check membership after we've read any included COM, since
|
||||||
|
@ -1037,17 +1047,8 @@ bool IncomingPacket::_doCIRCUIT_TEST(const RuntimeEnvironment *RR,const SharedPt
|
||||||
NetworkConfig originatorCredentialNetworkConfig;
|
NetworkConfig originatorCredentialNetworkConfig;
|
||||||
if (originatorCredentialNetworkId) {
|
if (originatorCredentialNetworkId) {
|
||||||
if (Network::controllerFor(originatorCredentialNetworkId) == originatorAddress) {
|
if (Network::controllerFor(originatorCredentialNetworkId) == originatorAddress) {
|
||||||
SharedPtr<Network> nw(RR->node->network(originatorCredentialNetworkId));
|
if (!RR->node->network(originatorCredentialNetworkId)) {
|
||||||
if ((nw)&&(nw->hasConfig())) {
|
TRACE("dropped CIRCUIT_TEST from %s(%s): originator %s specified network ID %.16llx as credential, and we are not a member of that network",source().toString().c_str(),_remoteAddress.toString().c_str(),originatorAddress.toString().c_str(),originatorCredentialNetworkId);
|
||||||
originatorCredentialNetworkConfig = nw->config();
|
|
||||||
if ( ( (originatorCredentialNetworkConfig.isPublic()) || (peer->address() == originatorAddress) || ((originatorCredentialNetworkConfig.com)&&(previousHopCom)&&(originatorCredentialNetworkConfig.com.agreesWith(previousHopCom))) ) ) {
|
|
||||||
TRACE("CIRCUIT_TEST %.16llx received from hop %s(%s) and originator %s with valid network ID credential %.16llx (verified from originator and next hop)",testId,source().toString().c_str(),_remoteAddress.toString().c_str(),originatorAddress.toString().c_str(),originatorCredentialNetworkId);
|
|
||||||
} else {
|
|
||||||
TRACE("dropped CIRCUIT_TEST from %s(%s): originator %s specified network ID %.16llx as credential, and previous hop %s did not supply a valid COM",source().toString().c_str(),_remoteAddress.toString().c_str(),originatorAddress.toString().c_str(),originatorCredentialNetworkId,peer->address().toString().c_str());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
TRACE("dropped CIRCUIT_TEST from %s(%s): originator %s specified network ID %.16llx as credential, and we are not a member",source().toString().c_str(),_remoteAddress.toString().c_str(),originatorAddress.toString().c_str(),originatorCredentialNetworkId);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -79,19 +79,19 @@ bool Membership::sendCredentialsIfNeeded(const RuntimeEnvironment *RR,const uint
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Membership::addCredential(const RuntimeEnvironment *RR,const uint64_t now,const CertificateOfMembership &com)
|
int Membership::addCredential(const RuntimeEnvironment *RR,const CertificateOfMembership &com)
|
||||||
{
|
{
|
||||||
if (com.issuedTo() != RR->identity.address())
|
if (com.issuedTo() != RR->identity.address())
|
||||||
return -1;
|
return -1;
|
||||||
if (_com == com)
|
if (_com == com)
|
||||||
return 0;
|
return 0;
|
||||||
const int vr = com.verify(RR);
|
const int vr = com.verify(RR);
|
||||||
if (vr == 0)
|
if ((vr == 0)&&(com.revision() > _com.revision()))
|
||||||
_com = com;
|
_com = com;
|
||||||
return vr;
|
return vr;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Membership::addCredential(const RuntimeEnvironment *RR,const uint64_t now,const Tag &tag)
|
int Membership::addCredential(const RuntimeEnvironment *RR,const Tag &tag)
|
||||||
{
|
{
|
||||||
if (tag.issuedTo() != RR->identity.address())
|
if (tag.issuedTo() != RR->identity.address())
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -102,15 +102,17 @@ int Membership::addCredential(const RuntimeEnvironment *RR,const uint64_t now,co
|
||||||
if (vr == 0) {
|
if (vr == 0) {
|
||||||
if (!t)
|
if (!t)
|
||||||
t = &(_tags[tag.id()]);
|
t = &(_tags[tag.id()]);
|
||||||
t->lastReceived = now;
|
if (t->tag.timestamp() <= tag.timestamp()) {
|
||||||
|
t->lastReceived = RR->node->now();
|
||||||
t->tag = tag;
|
t->tag = tag;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return vr;
|
return vr;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Membership::addCredential(const RuntimeEnvironment *RR,const uint64_t now,const Capability &cap)
|
int Membership::addCredential(const RuntimeEnvironment *RR,const Capability &cap)
|
||||||
{
|
{
|
||||||
if (!cap.wasIssuedTo(RR->identity.address()))
|
if (cap.issuedTo() != RR->identity.address())
|
||||||
return -1;
|
return -1;
|
||||||
std::map<uint32_t,CState>::iterator c(_caps.find(cap.id()));
|
std::map<uint32_t,CState>::iterator c(_caps.find(cap.id()));
|
||||||
if ((c != _caps.end())&&(c->second.lastReceived != 0)&&(c->second.cap == cap))
|
if ((c != _caps.end())&&(c->second.lastReceived != 0)&&(c->second.cap == cap))
|
||||||
|
@ -119,10 +121,10 @@ int Membership::addCredential(const RuntimeEnvironment *RR,const uint64_t now,co
|
||||||
if (vr == 0) {
|
if (vr == 0) {
|
||||||
if (c == _caps.end()) {
|
if (c == _caps.end()) {
|
||||||
CState &c2 = _caps[cap.id()];
|
CState &c2 = _caps[cap.id()];
|
||||||
c2.lastReceived = now;
|
c2.lastReceived = RR->node->now();
|
||||||
c2.cap = cap;
|
c2.cap = cap;
|
||||||
} else {
|
} else if (c->second.cap.timestamp() <= cap.timestamp()) {
|
||||||
c->second.lastReceived = now;
|
c->second.lastReceived = RR->node->now();
|
||||||
c->second.cap = cap;
|
c->second.cap = cap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -180,21 +180,21 @@ public:
|
||||||
*
|
*
|
||||||
* @return 0 == OK, 1 == waiting for WHOIS, -1 == BAD signature or credential
|
* @return 0 == OK, 1 == waiting for WHOIS, -1 == BAD signature or credential
|
||||||
*/
|
*/
|
||||||
int addCredential(const RuntimeEnvironment *RR,const uint64_t now,const CertificateOfMembership &com);
|
int addCredential(const RuntimeEnvironment *RR,const CertificateOfMembership &com);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate and add a credential if signature is okay and it's otherwise good
|
* Validate and add a credential if signature is okay and it's otherwise good
|
||||||
*
|
*
|
||||||
* @return 0 == OK, 1 == waiting for WHOIS, -1 == BAD signature or credential
|
* @return 0 == OK, 1 == waiting for WHOIS, -1 == BAD signature or credential
|
||||||
*/
|
*/
|
||||||
int addCredential(const RuntimeEnvironment *RR,const uint64_t now,const Tag &tag);
|
int addCredential(const RuntimeEnvironment *RR,const Tag &tag);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate and add a credential if signature is okay and it's otherwise good
|
* Validate and add a credential if signature is okay and it's otherwise good
|
||||||
*
|
*
|
||||||
* @return 0 == OK, 1 == waiting for WHOIS, -1 == BAD signature or credential
|
* @return 0 == OK, 1 == waiting for WHOIS, -1 == BAD signature or credential
|
||||||
*/
|
*/
|
||||||
int addCredential(const RuntimeEnvironment *RR,const uint64_t now,const Capability &cap);
|
int addCredential(const RuntimeEnvironment *RR,const Capability &cap);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clean up old or stale entries
|
* Clean up old or stale entries
|
||||||
|
|
|
@ -152,7 +152,6 @@ std::vector<Address> Multicaster::getMembers(uint64_t nwid,const MulticastGroup
|
||||||
}
|
}
|
||||||
|
|
||||||
void Multicaster::send(
|
void Multicaster::send(
|
||||||
const CertificateOfMembership *com,
|
|
||||||
unsigned int limit,
|
unsigned int limit,
|
||||||
uint64_t now,
|
uint64_t now,
|
||||||
uint64_t nwid,
|
uint64_t nwid,
|
||||||
|
@ -194,7 +193,6 @@ void Multicaster::send(
|
||||||
RR,
|
RR,
|
||||||
now,
|
now,
|
||||||
nwid,
|
nwid,
|
||||||
com,
|
|
||||||
limit,
|
limit,
|
||||||
1, // we'll still gather a little from peers to keep multicast list fresh
|
1, // we'll still gather a little from peers to keep multicast list fresh
|
||||||
src,
|
src,
|
||||||
|
@ -236,22 +234,12 @@ void Multicaster::send(
|
||||||
if (!p)
|
if (!p)
|
||||||
continue;
|
continue;
|
||||||
//TRACE(">>MC upstream GATHER up to %u for group %.16llx/%s",gatherLimit,nwid,mg.toString().c_str());
|
//TRACE(">>MC upstream GATHER up to %u for group %.16llx/%s",gatherLimit,nwid,mg.toString().c_str());
|
||||||
|
|
||||||
const CertificateOfMembership *com = (CertificateOfMembership *)0;
|
|
||||||
{
|
|
||||||
SharedPtr<Network> nw(RR->node->network(nwid));
|
|
||||||
if ((nw)&&(nw->hasConfig())&&(nw->config().com)&&(nw->config().isPrivate())&&(p->needsOurNetworkMembershipCertificate(nwid,now,true)))
|
|
||||||
com = &(nw->config().com);
|
|
||||||
}
|
|
||||||
|
|
||||||
Packet outp(p->address(),RR->identity.address(),Packet::VERB_MULTICAST_GATHER);
|
Packet outp(p->address(),RR->identity.address(),Packet::VERB_MULTICAST_GATHER);
|
||||||
outp.append(nwid);
|
outp.append(nwid);
|
||||||
outp.append((uint8_t)(com ? 0x01 : 0x00));
|
outp.append((uint8_t)0x00);
|
||||||
mg.mac().appendTo(outp);
|
mg.mac().appendTo(outp);
|
||||||
outp.append((uint32_t)mg.adi());
|
outp.append((uint32_t)mg.adi());
|
||||||
outp.append((uint32_t)gatherLimit);
|
outp.append((uint32_t)gatherLimit);
|
||||||
if (com)
|
|
||||||
com->serialize(outp);
|
|
||||||
RR->sw->send(outp,true,0);
|
RR->sw->send(outp,true,0);
|
||||||
}
|
}
|
||||||
gatherLimit = 0;
|
gatherLimit = 0;
|
||||||
|
@ -264,7 +252,6 @@ void Multicaster::send(
|
||||||
RR,
|
RR,
|
||||||
now,
|
now,
|
||||||
nwid,
|
nwid,
|
||||||
com,
|
|
||||||
limit,
|
limit,
|
||||||
gatherLimit,
|
gatherLimit,
|
||||||
src,
|
src,
|
||||||
|
|
|
@ -150,7 +150,6 @@ public:
|
||||||
/**
|
/**
|
||||||
* Send a multicast
|
* Send a multicast
|
||||||
*
|
*
|
||||||
* @param com Certificate of membership to include or NULL for none
|
|
||||||
* @param limit Multicast limit
|
* @param limit Multicast limit
|
||||||
* @param now Current time
|
* @param now Current time
|
||||||
* @param nwid Network ID
|
* @param nwid Network ID
|
||||||
|
@ -162,7 +161,6 @@ public:
|
||||||
* @param len Length of packet data
|
* @param len Length of packet data
|
||||||
*/
|
*/
|
||||||
void send(
|
void send(
|
||||||
const CertificateOfMembership *com,
|
|
||||||
unsigned int limit,
|
unsigned int limit,
|
||||||
uint64_t now,
|
uint64_t now,
|
||||||
uint64_t nwid,
|
uint64_t nwid,
|
||||||
|
|
|
@ -348,7 +348,7 @@ Network::Network(const RuntimeEnvironment *renv,uint64_t nwid,void *uptr) :
|
||||||
_netconfFailure(NETCONF_FAILURE_NONE),
|
_netconfFailure(NETCONF_FAILURE_NONE),
|
||||||
_portError(0)
|
_portError(0)
|
||||||
{
|
{
|
||||||
char confn[128],mcdbn[128];
|
char confn[128];
|
||||||
Utils::snprintf(confn,sizeof(confn),"networks.d/%.16llx.conf",_id);
|
Utils::snprintf(confn,sizeof(confn),"networks.d/%.16llx.conf",_id);
|
||||||
|
|
||||||
if (_id == ZT_TEST_NETWORK_ID) {
|
if (_id == ZT_TEST_NETWORK_ID) {
|
||||||
|
|
|
@ -336,6 +336,42 @@ public:
|
||||||
*/
|
*/
|
||||||
void learnBridgedMulticastGroup(const MulticastGroup &mg,uint64_t now);
|
void learnBridgedMulticastGroup(const MulticastGroup &mg,uint64_t now);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param com Certificate of membership
|
||||||
|
* @return 0 == OK, 1 == waiting for WHOIS, -1 == BAD signature or credential
|
||||||
|
*/
|
||||||
|
inline int addCredential(const CertificateOfMembership &com)
|
||||||
|
{
|
||||||
|
if (com.networkId() != _id)
|
||||||
|
return -1;
|
||||||
|
Mutex::Lock _l(_lock);
|
||||||
|
return _memberships[com.issuedTo()].addCredential(RR,com);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param cap Capability
|
||||||
|
* @return 0 == OK, 1 == waiting for WHOIS, -1 == BAD signature or credential
|
||||||
|
*/
|
||||||
|
inline int addCredential(const Capability &cap)
|
||||||
|
{
|
||||||
|
if (cap.networkId() != _id)
|
||||||
|
return -1;
|
||||||
|
Mutex::Lock _l(_lock);
|
||||||
|
return _memberships[cap.issuedTo()].addCredential(RR,cap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param cap Tag
|
||||||
|
* @return 0 == OK, 1 == waiting for WHOIS, -1 == BAD signature or credential
|
||||||
|
*/
|
||||||
|
inline int addCredential(const Tag &tag)
|
||||||
|
{
|
||||||
|
if (tag.networkId() != _id)
|
||||||
|
return -1;
|
||||||
|
Mutex::Lock _l(_lock);
|
||||||
|
return _memberships[tag.issuedTo()].addCredential(RR,tag);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy this network
|
* Destroy this network
|
||||||
*
|
*
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace ZeroTier {
|
||||||
|
|
||||||
const unsigned char Packet::ZERO_KEY[32] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
|
const unsigned char Packet::ZERO_KEY[32] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
|
||||||
|
|
||||||
//#ifdef ZT_TRACE
|
#ifdef ZT_TRACE
|
||||||
|
|
||||||
const char *Packet::verbString(Verb v)
|
const char *Packet::verbString(Verb v)
|
||||||
throw()
|
throw()
|
||||||
|
@ -60,14 +60,13 @@ const char *Packet::errorString(ErrorCode e)
|
||||||
case ERROR_OBJ_NOT_FOUND: return "OBJECT_NOT_FOUND";
|
case ERROR_OBJ_NOT_FOUND: return "OBJECT_NOT_FOUND";
|
||||||
case ERROR_IDENTITY_COLLISION: return "IDENTITY_COLLISION";
|
case ERROR_IDENTITY_COLLISION: return "IDENTITY_COLLISION";
|
||||||
case ERROR_UNSUPPORTED_OPERATION: return "UNSUPPORTED_OPERATION";
|
case ERROR_UNSUPPORTED_OPERATION: return "UNSUPPORTED_OPERATION";
|
||||||
case ERROR_NEED_MEMBERSHIP_CERTIFICATE: return "NEED_MEMBERSHIP_CERTIFICATE";
|
|
||||||
case ERROR_NETWORK_ACCESS_DENIED_: return "NETWORK_ACCESS_DENIED";
|
case ERROR_NETWORK_ACCESS_DENIED_: return "NETWORK_ACCESS_DENIED";
|
||||||
case ERROR_UNWANTED_MULTICAST: return "UNWANTED_MULTICAST";
|
case ERROR_UNWANTED_MULTICAST: return "UNWANTED_MULTICAST";
|
||||||
}
|
}
|
||||||
return "(unknown)";
|
return "(unknown)";
|
||||||
}
|
}
|
||||||
|
|
||||||
//#endif // ZT_TRACE
|
#endif // ZT_TRACE
|
||||||
|
|
||||||
void Packet::armor(const void *key,bool encryptPayload)
|
void Packet::armor(const void *key,bool encryptPayload)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1060,12 +1060,12 @@ public:
|
||||||
ERROR_UNWANTED_MULTICAST = 0x08
|
ERROR_UNWANTED_MULTICAST = 0x08
|
||||||
};
|
};
|
||||||
|
|
||||||
//#ifdef ZT_TRACE
|
#ifdef ZT_TRACE
|
||||||
static const char *verbString(Verb v)
|
static const char *verbString(Verb v)
|
||||||
throw();
|
throw();
|
||||||
static const char *errorString(ErrorCode e)
|
static const char *errorString(ErrorCode e)
|
||||||
throw();
|
throw();
|
||||||
//#endif
|
#endif
|
||||||
|
|
||||||
template<unsigned int C2>
|
template<unsigned int C2>
|
||||||
Packet(const Buffer<C2> &b) :
|
Packet(const Buffer<C2> &b) :
|
||||||
|
|
|
@ -53,9 +53,7 @@ Peer::Peer(const RuntimeEnvironment *renv,const Identity &myIdentity,const Ident
|
||||||
_id(peerIdentity),
|
_id(peerIdentity),
|
||||||
_numPaths(0),
|
_numPaths(0),
|
||||||
_latency(0),
|
_latency(0),
|
||||||
_directPathPushCutoffCount(0),
|
_directPathPushCutoffCount(0)
|
||||||
_networkComs(4),
|
|
||||||
_lastPushedComs(4)
|
|
||||||
{
|
{
|
||||||
if (!myIdentity.agree(peerIdentity,_key,ZT_PEER_SECRET_KEY_LENGTH))
|
if (!myIdentity.agree(peerIdentity,_key,ZT_PEER_SECRET_KEY_LENGTH))
|
||||||
throw std::runtime_error("new peer identity key agreement failed");
|
throw std::runtime_error("new peer identity key agreement failed");
|
||||||
|
|
|
@ -35,7 +35,6 @@
|
||||||
#include "Peer.hpp"
|
#include "Peer.hpp"
|
||||||
#include "SelfAwareness.hpp"
|
#include "SelfAwareness.hpp"
|
||||||
#include "Packet.hpp"
|
#include "Packet.hpp"
|
||||||
#include "Filter.hpp"
|
|
||||||
#include "Cluster.hpp"
|
#include "Cluster.hpp"
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
@ -438,26 +437,12 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
|
||||||
|
|
||||||
//TRACE("%.16llx: MULTICAST %s -> %s %s %u",network->id(),from.toString().c_str(),mg.toString().c_str(),etherTypeName(etherType),len);
|
//TRACE("%.16llx: MULTICAST %s -> %s %s %u",network->id(),from.toString().c_str(),mg.toString().c_str(),etherTypeName(etherType),len);
|
||||||
|
|
||||||
if (!Filter::run(
|
if (!network->filterOutgoingPacket(RR->identity.address(),Address(),from,to,(const uint8_t *)data,len,etherType,vlanId)) {
|
||||||
RR,
|
TRACE("%.16llx: %s -> %s %s packet not sent: filterOutgoingPacket() returned false",network->id(),from.toString().c_str(),to.toString().c_str(),etherTypeName(etherType));
|
||||||
network->id(),
|
|
||||||
RR->identity.address(),
|
|
||||||
Address(), // 0 destination ZT address for multicasts since this is unknown at time of send
|
|
||||||
from,
|
|
||||||
to,
|
|
||||||
(const uint8_t *)data,
|
|
||||||
len,
|
|
||||||
etherType,
|
|
||||||
vlanId,
|
|
||||||
network->config().rules,
|
|
||||||
network->config().ruleCount))
|
|
||||||
{
|
|
||||||
TRACE("%.16llx: %s -> %s %s packet not sent: Filter::run() == false (multicast)",network->id(),from.toString().c_str(),to.toString().c_str(),etherTypeName(etherType));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
RR->mc->send(
|
RR->mc->send(
|
||||||
((!network->config().isPublic())&&(network->config().com)) ? &(network->config().com) : (const CertificateOfMembership *)0,
|
|
||||||
network->config().multicastLimit,
|
network->config().multicastLimit,
|
||||||
RR->node->now(),
|
RR->node->now(),
|
||||||
network->id(),
|
network->id(),
|
||||||
|
@ -477,34 +462,15 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
|
||||||
Address toZT(to.toAddress(network->id())); // since in-network MACs are derived from addresses and network IDs, we can reverse this
|
Address toZT(to.toAddress(network->id())); // since in-network MACs are derived from addresses and network IDs, we can reverse this
|
||||||
SharedPtr<Peer> toPeer(RR->topology->getPeer(toZT));
|
SharedPtr<Peer> toPeer(RR->topology->getPeer(toZT));
|
||||||
|
|
||||||
if (!Filter::run(
|
if (!network->filterOutgoingPacket(RR->identity.address(),toZT,from,to,(const uint8_t *)data,len,etherType,vlanId)) {
|
||||||
RR,
|
TRACE("%.16llx: %s -> %s %s packet not sent: filterOutgoingPacket() returned false",network->id(),from.toString().c_str(),to.toString().c_str(),etherTypeName(etherType));
|
||||||
network->id(),
|
|
||||||
RR->identity.address(),
|
|
||||||
toZT,
|
|
||||||
from,
|
|
||||||
to,
|
|
||||||
(const uint8_t *)data,
|
|
||||||
len,
|
|
||||||
etherType,
|
|
||||||
vlanId,
|
|
||||||
network->config().rules,
|
|
||||||
network->config().ruleCount))
|
|
||||||
{
|
|
||||||
TRACE("%.16llx: %s -> %s %s packet not sent: Filter::run() == false",network->id(),from.toString().c_str(),to.toString().c_str(),etherTypeName(etherType));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool includeCom = ( (network->config().isPrivate()) && (network->config().com) && ((!toPeer)||(toPeer->needsOurNetworkMembershipCertificate(network->id(),RR->node->now(),true))) );
|
if (fromBridged) {
|
||||||
if ((fromBridged)||(includeCom)) {
|
|
||||||
Packet outp(toZT,RR->identity.address(),Packet::VERB_EXT_FRAME);
|
Packet outp(toZT,RR->identity.address(),Packet::VERB_EXT_FRAME);
|
||||||
outp.append(network->id());
|
outp.append(network->id());
|
||||||
if (includeCom) {
|
|
||||||
outp.append((unsigned char)0x01); // 0x01 -- COM included
|
|
||||||
network->config().com.serialize(outp);
|
|
||||||
} else {
|
|
||||||
outp.append((unsigned char)0x00);
|
outp.append((unsigned char)0x00);
|
||||||
}
|
|
||||||
to.appendTo(outp);
|
to.appendTo(outp);
|
||||||
from.appendTo(outp);
|
from.appendTo(outp);
|
||||||
outp.append((uint16_t)etherType);
|
outp.append((uint16_t)etherType);
|
||||||
|
@ -564,12 +530,7 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
|
||||||
SharedPtr<Peer> bridgePeer(RR->topology->getPeer(bridges[b]));
|
SharedPtr<Peer> bridgePeer(RR->topology->getPeer(bridges[b]));
|
||||||
Packet outp(bridges[b],RR->identity.address(),Packet::VERB_EXT_FRAME);
|
Packet outp(bridges[b],RR->identity.address(),Packet::VERB_EXT_FRAME);
|
||||||
outp.append(network->id());
|
outp.append(network->id());
|
||||||
if ( (network->config().isPrivate()) && (network->config().com) && ((!bridgePeer)||(bridgePeer->needsOurNetworkMembershipCertificate(network->id(),RR->node->now(),true))) ) {
|
outp.append((uint8_t)0x00);
|
||||||
outp.append((unsigned char)0x01); // 0x01 -- COM included
|
|
||||||
network->config().com.serialize(outp);
|
|
||||||
} else {
|
|
||||||
outp.append((unsigned char)0);
|
|
||||||
}
|
|
||||||
to.appendTo(outp);
|
to.appendTo(outp);
|
||||||
from.appendTo(outp);
|
from.appendTo(outp);
|
||||||
outp.append((uint16_t)etherType);
|
outp.append((uint16_t)etherType);
|
||||||
|
|
|
@ -61,13 +61,15 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param nwid Network ID
|
* @param nwid Network ID
|
||||||
|
* @param ts Timestamp
|
||||||
* @param expiration Tag expiration relative to network config timestamp
|
* @param expiration Tag expiration relative to network config timestamp
|
||||||
* @param issuedTo Address to which this tag was issued
|
* @param issuedTo Address to which this tag was issued
|
||||||
* @param id Tag ID
|
* @param id Tag ID
|
||||||
* @param value Tag value
|
* @param value Tag value
|
||||||
*/
|
*/
|
||||||
Tag(const uint64_t nwid,const uint64_t expiration,const Address &issuedTo,const uint32_t id,const uint32_t value) :
|
Tag(const uint64_t nwid,const uint64_t ts,const uint64_t expiration,const Address &issuedTo,const uint32_t id,const uint32_t value) :
|
||||||
_nwid(nwid),
|
_nwid(nwid),
|
||||||
|
_ts(ts),
|
||||||
_expiration(expiration),
|
_expiration(expiration),
|
||||||
_id(id),
|
_id(id),
|
||||||
_value(value),
|
_value(value),
|
||||||
|
@ -78,6 +80,7 @@ public:
|
||||||
|
|
||||||
inline uint64_t networkId() const { return _nwid; }
|
inline uint64_t networkId() const { return _nwid; }
|
||||||
inline uint64_t expiration() const { return _expiration; }
|
inline uint64_t expiration() const { return _expiration; }
|
||||||
|
inline uint64_t timestamp() const { return _ts; }
|
||||||
inline uint32_t id() const { return _id; }
|
inline uint32_t id() const { return _id; }
|
||||||
inline const uint32_t &value() const { return _value; }
|
inline const uint32_t &value() const { return _value; }
|
||||||
inline const Address &issuedTo() const { return _issuedTo; }
|
inline const Address &issuedTo() const { return _issuedTo; }
|
||||||
|
@ -115,6 +118,7 @@ public:
|
||||||
if (forSign) b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
|
if (forSign) b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
|
||||||
|
|
||||||
b.append(_nwid);
|
b.append(_nwid);
|
||||||
|
b.append(_ts);
|
||||||
b.append(_expiration);
|
b.append(_expiration);
|
||||||
b.append(_id);
|
b.append(_id);
|
||||||
b.append(_value);
|
b.append(_value);
|
||||||
|
@ -136,6 +140,7 @@ public:
|
||||||
unsigned int p = startAt;
|
unsigned int p = startAt;
|
||||||
|
|
||||||
_nwid = b.template at<uint64_t>(p); p += 8;
|
_nwid = b.template at<uint64_t>(p); p += 8;
|
||||||
|
_ts = b.template at<uint64_t>(p); p += 8;
|
||||||
_expiration = b.template at<uint64_t>(p); p += 8;
|
_expiration = b.template at<uint64_t>(p); p += 8;
|
||||||
_id = b.template at<uint32_t>(p); p += 4;
|
_id = b.template at<uint32_t>(p); p += 4;
|
||||||
_value = b.template at<uint32_t>(p); p += 4;
|
_value = b.template at<uint32_t>(p); p += 4;
|
||||||
|
@ -163,6 +168,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint64_t _nwid;
|
uint64_t _nwid;
|
||||||
|
uint64_t _ts;
|
||||||
uint64_t _expiration;
|
uint64_t _expiration;
|
||||||
uint32_t _id;
|
uint32_t _id;
|
||||||
uint32_t _value;
|
uint32_t _value;
|
||||||
|
|
|
@ -74,34 +74,6 @@ Topology::Topology(const RuntimeEnvironment *renv) :
|
||||||
|
|
||||||
Topology::~Topology()
|
Topology::~Topology()
|
||||||
{
|
{
|
||||||
Buffer<ZT_PEER_SUGGESTED_SERIALIZATION_BUFFER_SIZE> *pbuf = 0;
|
|
||||||
try {
|
|
||||||
pbuf = new Buffer<ZT_PEER_SUGGESTED_SERIALIZATION_BUFFER_SIZE>();
|
|
||||||
std::string all;
|
|
||||||
|
|
||||||
Address *a = (Address *)0;
|
|
||||||
SharedPtr<Peer> *p = (SharedPtr<Peer> *)0;
|
|
||||||
Hashtable< Address,SharedPtr<Peer> >::Iterator i(_peers);
|
|
||||||
while (i.next(a,p)) {
|
|
||||||
if (std::find(_rootAddresses.begin(),_rootAddresses.end(),*a) == _rootAddresses.end()) {
|
|
||||||
pbuf->clear();
|
|
||||||
try {
|
|
||||||
(*p)->serialize(*pbuf);
|
|
||||||
try {
|
|
||||||
all.append((const char *)pbuf->data(),pbuf->size());
|
|
||||||
} catch ( ... ) {
|
|
||||||
return; // out of memory? just skip
|
|
||||||
}
|
|
||||||
} catch ( ... ) {} // peer too big? shouldn't happen, but it so skip
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RR->node->dataStorePut("peers.save",all,true);
|
|
||||||
|
|
||||||
delete pbuf;
|
|
||||||
} catch ( ... ) {
|
|
||||||
delete pbuf;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedPtr<Peer> Topology::addPeer(const SharedPtr<Peer> &peer)
|
SharedPtr<Peer> Topology::addPeer(const SharedPtr<Peer> &peer)
|
||||||
|
|
Loading…
Add table
Reference in a new issue