summaryrefslogtreecommitdiff
path: root/node/Network.cpp
diff options
context:
space:
mode:
authorAdam Ierymenko <adam.ierymenko@gmail.com>2016-09-23 16:08:38 -0700
committerAdam Ierymenko <adam.ierymenko@gmail.com>2016-09-23 16:08:38 -0700
commit1f74dd4589017bd5bc34b31ff6e09e6875d5e1c7 (patch)
treedfda07dae49c2e9813031e1bb426cb5c3e2a2b11 /node/Network.cpp
parent29711e123febee2696e0f2cada72e7e533d21a8c (diff)
downloadinfinitytier-1f74dd4589017bd5bc34b31ff6e09e6875d5e1c7.tar.gz
infinitytier-1f74dd4589017bd5bc34b31ff6e09e6875d5e1c7.zip
Revocation work in progress, add WATCH which is TEE with implicit rate sync (thanks JG@DCVC!), and clean up some cruft in Network.
Diffstat (limited to 'node/Network.cpp')
-rw-r--r--node/Network.cpp289
1 files changed, 125 insertions, 164 deletions
diff --git a/node/Network.cpp b/node/Network.cpp
index 455e185e..0fab6a27 100644
--- a/node/Network.cpp
+++ b/node/Network.cpp
@@ -36,7 +36,7 @@
#include "Peer.hpp"
// Uncomment to make the rules engine dump trace info to stdout
-//#define ZT_RULES_ENGINE_DEBUGGING 1
+#define ZT_RULES_ENGINE_DEBUGGING 1
namespace ZeroTier {
@@ -155,24 +155,21 @@ enum _doZtFilterResult
static _doZtFilterResult _doZtFilter(
const RuntimeEnvironment *RR,
const NetworkConfig &nconf,
+ const Membership *membership, // can be NULL
const bool inbound,
const Address &ztSource,
- Address &ztDest, // MUTABLE
+ Address &ztDest, // MUTABLE -- is changed on REDIRECT actions
const MAC &macSource,
const MAC &macDest,
const uint8_t *const frameData,
const unsigned int frameLen,
const unsigned int etherType,
const unsigned int vlanId,
- const ZT_VirtualNetworkRule *rules,
+ const ZT_VirtualNetworkRule *rules, // cannot be NULL
const unsigned int ruleCount,
- const Tag *localTags,
- const unsigned int localTagCount,
- const uint32_t *const remoteTagIds,
- const uint32_t *const remoteTagValues,
- const unsigned int remoteTagCount,
- Address &cc, // MUTABLE
- unsigned int &ccLength) // MUTABLE
+ Address &cc, // MUTABLE -- set to TEE destination if TEE action is taken or left alone otherwise
+ unsigned int &ccLength, // MUTABLE -- set to length of packet payload to TEE
+ bool &ccWatch) // MUTABLE -- set to true for WATCH target as opposed to normal TEE
{
#ifdef ZT_RULES_ENGINE_DEBUGGING
char dpbuf[1024]; // used by FILTER_TRACE macro
@@ -204,6 +201,7 @@ static _doZtFilterResult _doZtFilter(
// These are initially handled together since preliminary logic is common
case ZT_NETWORK_RULE_ACTION_TEE:
+ case ZT_NETWORK_RULE_ACTION_WATCH:
case ZT_NETWORK_RULE_ACTION_REDIRECT: {
const Address fwdAddr(rules[rn].v.fwd.address);
if (fwdAddr == ztSource) {
@@ -242,6 +240,7 @@ static _doZtFilterResult _doZtFilter(
#endif // ZT_RULES_ENGINE_DEBUGGING
cc = fwdAddr;
ccLength = (rules[rn].v.fwd.length != 0) ? ((frameLen < (unsigned int)rules[rn].v.fwd.length) ? frameLen : (unsigned int)rules[rn].v.fwd.length) : frameLen;
+ ccWatch = (rt == ZT_NETWORK_RULE_ACTION_WATCH);
}
}
} continue;
@@ -508,50 +507,40 @@ static _doZtFilterResult _doZtFilter(
case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND:
case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR:
case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR: {
- const Tag *lt = (const Tag *)0;
- for(unsigned int i=0;i<localTagCount;++i) {
- if (rules[rn].v.tag.id == localTags[i].id()) {
- lt = &(localTags[i]);
- break;
- }
- }
- if (!lt) {
- thisRuleMatches = 0;
- FILTER_TRACE("%u %s %c local tag %u not found -> 0",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),(unsigned int)rules[rn].v.tag.id);
- } else {
- const uint32_t *rtv = (const uint32_t *)0;
- for(unsigned int i=0;i<remoteTagCount;++i) {
- if (rules[rn].v.tag.id == remoteTagIds[i]) {
- rtv = &(remoteTagValues[i]);
- break;
- }
- }
- if (!rtv) {
- if (inbound) {
- thisRuleMatches = 0;
- FILTER_TRACE("%u %s %c remote tag %u not found -> 0 (inbound side is strict)",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),(unsigned int)rules[rn].v.tag.id);
- } else {
- thisRuleMatches = 1;
- FILTER_TRACE("%u %s %c remote tag %u not found -> 1 (outbound side is not strict)",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),(unsigned int)rules[rn].v.tag.id);
- }
- } else {
+ const Tag *const localTag = std::lower_bound(&(nconf.tags[0]),&(nconf.tags[nconf.tagCount]),rules[rn].v.tag.id,Tag::IdComparePredicate());
+ if ((localTag != &(nconf.tags[nconf.tagCount]))&&(localTag->id() == rules[rn].v.tag.id)) {
+ const Tag *const remoteTag = ((membership) ? membership->getTag(nconf,rules[rn].v.tag.id) : (const Tag *)0);
+ if (remoteTag) {
+ const uint32_t ltv = localTag->value();
+ const uint32_t rtv = remoteTag->value();
if (rt == ZT_NETWORK_RULE_MATCH_TAGS_DIFFERENCE) {
- const uint32_t diff = (lt->value() > *rtv) ? (lt->value() - *rtv) : (*rtv - lt->value());
+ const uint32_t diff = (ltv > rtv) ? (ltv - rtv) : (rtv - ltv);
thisRuleMatches = (uint8_t)(diff <= rules[rn].v.tag.value);
- FILTER_TRACE("%u %s %c TAG %u local:%u remote:%u difference:%u<=%u -> %u",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),(unsigned int)rules[rn].v.tag.id,lt->value(),*rtv,diff,(unsigned int)rules[rn].v.tag.value,thisRuleMatches);
+ FILTER_TRACE("%u %s %c TAG %u local:%u remote:%u difference:%u<=%u -> %u",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),(unsigned int)rules[rn].v.tag.id,ltv,rtv,diff,(unsigned int)rules[rn].v.tag.value,thisRuleMatches);
} else if (rt == ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND) {
- thisRuleMatches = (uint8_t)((lt->value() & *rtv) == rules[rn].v.tag.value);
- FILTER_TRACE("%u %s %c TAG %u local:%.8x & remote:%.8x == %.8x -> %u",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),(unsigned int)rules[rn].v.tag.id,lt->value(),*rtv,(unsigned int)rules[rn].v.tag.value,(unsigned int)thisRuleMatches);
+ thisRuleMatches = (uint8_t)((ltv & rtv) == rules[rn].v.tag.value);
+ FILTER_TRACE("%u %s %c TAG %u local:%.8x & remote:%.8x == %.8x -> %u",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),(unsigned int)rules[rn].v.tag.id,ltv,rtv,(unsigned int)rules[rn].v.tag.value,(unsigned int)thisRuleMatches);
} else if (rt == ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR) {
- thisRuleMatches = (uint8_t)((lt->value() | *rtv) == rules[rn].v.tag.value);
- FILTER_TRACE("%u %s %c TAG %u local:%.8x | remote:%.8x == %.8x -> %u",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),(unsigned int)rules[rn].v.tag.id,lt->value(),*rtv,(unsigned int)rules[rn].v.tag.value,(unsigned int)thisRuleMatches);
+ thisRuleMatches = (uint8_t)((ltv | rtv) == rules[rn].v.tag.value);
+ FILTER_TRACE("%u %s %c TAG %u local:%.8x | remote:%.8x == %.8x -> %u",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),(unsigned int)rules[rn].v.tag.id,ltv,rtv,(unsigned int)rules[rn].v.tag.value,(unsigned int)thisRuleMatches);
} else if (rt == ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR) {
- thisRuleMatches = (uint8_t)((lt->value() ^ *rtv) == rules[rn].v.tag.value);
- FILTER_TRACE("%u %s %c TAG %u local:%.8x ^ remote:%.8x == %.8x -> %u",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),(unsigned int)rules[rn].v.tag.id,lt->value(),*rtv,(unsigned int)rules[rn].v.tag.value,(unsigned int)thisRuleMatches);
+ thisRuleMatches = (uint8_t)((ltv ^ rtv) == rules[rn].v.tag.value);
+ FILTER_TRACE("%u %s %c TAG %u local:%.8x ^ remote:%.8x == %.8x -> %u",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),(unsigned int)rules[rn].v.tag.id,ltv,rtv,(unsigned int)rules[rn].v.tag.value,(unsigned int)thisRuleMatches);
} else { // sanity check, can't really happen
thisRuleMatches = 0;
}
+ } else {
+ if (inbound) {
+ thisRuleMatches = 0;
+ FILTER_TRACE("%u %s %c remote tag %u not found -> 0 (inbound side is strict)",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),(unsigned int)rules[rn].v.tag.id);
+ } else {
+ thisRuleMatches = 1;
+ FILTER_TRACE("%u %s %c remote tag %u not found -> 1 (outbound side is not strict)",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),(unsigned int)rules[rn].v.tag.id);
+ }
}
+ } else {
+ thisRuleMatches = 0;
+ FILTER_TRACE("%u %s %c local tag %u not found -> 0",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),(unsigned int)rules[rn].v.tag.id);
}
} break;
@@ -582,7 +571,6 @@ Network::Network(const RuntimeEnvironment *renv,uint64_t nwid,void *uptr) :
_portInitialized(false),
_inboundConfigPacketId(0),
_lastConfigUpdate(0),
- _lastRequestedConfiguration(0),
_destroyed(false),
_netconfFailure(NETCONF_FAILURE_NONE),
_portError(0)
@@ -598,7 +586,7 @@ Network::Network(const RuntimeEnvironment *renv,uint64_t nwid,void *uptr) :
if (conf.length()) {
dconf->load(conf.c_str());
if (nconf->fromDictionary(*dconf)) {
- this->setConfiguration(*nconf,false);
+ this->_setConfiguration(*nconf,false);
_lastConfigUpdate = 0; // we still want to re-request a new config from the network
gotConf = true;
}
@@ -646,32 +634,27 @@ bool Network::filterOutgoingPacket(
const unsigned int etherType,
const unsigned int vlanId)
{
- uint32_t remoteTagIds[ZT_MAX_NETWORK_TAGS];
- uint32_t remoteTagValues[ZT_MAX_NETWORK_TAGS];
+ const uint64_t now = RR->node->now();
Address ztFinalDest(ztDest);
- Address cc;
- const Capability *relevantCap = (const Capability *)0;
- unsigned int ccLength = 0;
+ int localCapabilityIndex = -1;
bool accept = false;
- const uint64_t now = RR->node->now();
Mutex::Lock _l(_lock);
- Membership *m = (Membership *)0;
- unsigned int remoteTagCount = 0;
- if (ztDest) {
- m = &(_memberships[ztDest]);
- remoteTagCount = m->getAllTags(_config,remoteTagIds,remoteTagValues,ZT_MAX_NETWORK_TAGS);
- }
+ Membership *const membership = (ztDest) ? _memberships.get(ztDest) : (Membership *)0;
- switch(_doZtFilter(RR,_config,false,ztSource,ztFinalDest,macSource,macDest,frameData,frameLen,etherType,vlanId,_config.rules,_config.ruleCount,_config.tags,_config.tagCount,remoteTagIds,remoteTagValues,remoteTagCount,cc,ccLength)) {
+ Address cc;
+ unsigned int ccLength = 0;
+ bool ccWatch = false;
+ switch(_doZtFilter(RR,_config,membership,false,ztSource,ztFinalDest,macSource,macDest,frameData,frameLen,etherType,vlanId,_config.rules,_config.ruleCount,cc,ccLength,ccWatch)) {
case DOZTFILTER_NO_MATCH:
for(unsigned int c=0;c<_config.capabilityCount;++c) {
- ztFinalDest = ztDest; // sanity check
+ ztFinalDest = ztDest; // sanity check, shouldn't be possible if there was no match
Address cc2;
unsigned int ccLength2 = 0;
- switch (_doZtFilter(RR,_config,false,ztSource,ztFinalDest,macSource,macDest,frameData,frameLen,etherType,vlanId,_config.capabilities[c].rules(),_config.capabilities[c].ruleCount(),_config.tags,_config.tagCount,remoteTagIds,remoteTagValues,remoteTagCount,cc2,ccLength2)) {
+ bool ccWatch2 = false;
+ switch (_doZtFilter(RR,_config,membership,false,ztSource,ztFinalDest,macSource,macDest,frameData,frameLen,etherType,vlanId,_config.capabilities[c].rules(),_config.capabilities[c].ruleCount(),cc2,ccLength2,ccWatch2)) {
case DOZTFILTER_NO_MATCH:
case DOZTFILTER_DROP: // explicit DROP in a capability just terminates its evaluation and is an anti-pattern
break;
@@ -679,16 +662,16 @@ bool Network::filterOutgoingPacket(
case DOZTFILTER_REDIRECT: // interpreted as ACCEPT but ztFinalDest will have been changed in _doZtFilter()
case DOZTFILTER_ACCEPT:
case DOZTFILTER_SUPER_ACCEPT: // no difference in behavior on outbound side
- relevantCap = &(_config.capabilities[c]);
+ localCapabilityIndex = (int)c;
accept = true;
if ((!noTee)&&(cc2)) {
Membership &m2 = _membership(cc2);
- m2.sendCredentialsIfNeeded(RR,now,cc2,_config,relevantCap);
+ m2.pushCredentials(RR,now,cc2,_config,localCapabilityIndex,false);
Packet outp(cc2,RR->identity.address(),Packet::VERB_EXT_FRAME);
outp.append(_id);
- outp.append((uint8_t)0x02); // TEE/REDIRECT from outbound side: 0x02
+ outp.append((uint8_t)(ccWatch2 ? 0x16 : 0x02));
macDest.appendTo(outp);
macSource.appendTo(outp);
outp.append((uint16_t)etherType);
@@ -715,13 +698,16 @@ bool Network::filterOutgoingPacket(
}
if (accept) {
+ if (membership)
+ membership->pushCredentials(RR,now,ztDest,_config,localCapabilityIndex,false);
+
if ((!noTee)&&(cc)) {
Membership &m2 = _membership(cc);
- m2.sendCredentialsIfNeeded(RR,now,cc,_config,relevantCap);
+ m2.pushCredentials(RR,now,cc,_config,localCapabilityIndex,false);
Packet outp(cc,RR->identity.address(),Packet::VERB_EXT_FRAME);
outp.append(_id);
- outp.append((uint8_t)0x02); // TEE/REDIRECT from outbound side: 0x02
+ outp.append((uint8_t)(ccWatch ? 0x16 : 0x02));
macDest.appendTo(outp);
macSource.appendTo(outp);
outp.append((uint16_t)etherType);
@@ -732,11 +718,11 @@ bool Network::filterOutgoingPacket(
if ((ztDest != ztFinalDest)&&(ztFinalDest)) {
Membership &m2 = _membership(ztFinalDest);
- m2.sendCredentialsIfNeeded(RR,now,ztFinalDest,_config,relevantCap);
+ m2.pushCredentials(RR,now,ztFinalDest,_config,localCapabilityIndex,false);
Packet outp(ztFinalDest,RR->identity.address(),Packet::VERB_EXT_FRAME);
outp.append(_id);
- outp.append((uint8_t)0x02); // TEE/REDIRECT from outbound side: 0x02
+ outp.append((uint8_t)0x04);
macDest.appendTo(outp);
macSource.appendTo(outp);
outp.append((uint16_t)etherType);
@@ -745,11 +731,9 @@ bool Network::filterOutgoingPacket(
RR->sw->send(outp,true);
return false; // DROP locally, since we redirected
- } else if (m) {
- m->sendCredentialsIfNeeded(RR,now,ztDest,_config,relevantCap);
+ } else {
+ return true;
}
-
- return true;
} else {
return false;
}
@@ -765,28 +749,27 @@ int Network::filterIncomingPacket(
const unsigned int etherType,
const unsigned int vlanId)
{
- uint32_t remoteTagIds[ZT_MAX_NETWORK_TAGS];
- uint32_t remoteTagValues[ZT_MAX_NETWORK_TAGS];
Address ztFinalDest(ztDest);
- Address cc;
- unsigned int ccLength = 0;
int accept = 0;
Mutex::Lock _l(_lock);
- Membership &m = _membership(sourcePeer->address());
- const unsigned int remoteTagCount = m.getAllTags(_config,remoteTagIds,remoteTagValues,ZT_MAX_NETWORK_TAGS);
+ Membership &membership = _membership(sourcePeer->address());
- switch (_doZtFilter(RR,_config,true,sourcePeer->address(),ztFinalDest,macSource,macDest,frameData,frameLen,etherType,vlanId,_config.rules,_config.ruleCount,_config.tags,_config.tagCount,remoteTagIds,remoteTagValues,remoteTagCount,cc,ccLength)) {
+ Address cc;
+ unsigned int ccLength = 0;
+ bool ccWatch = false;
+ switch (_doZtFilter(RR,_config,&membership,true,sourcePeer->address(),ztFinalDest,macSource,macDest,frameData,frameLen,etherType,vlanId,_config.rules,_config.ruleCount,cc,ccLength,ccWatch)) {
case DOZTFILTER_NO_MATCH: {
- Membership::CapabilityIterator mci(m);
+ Membership::CapabilityIterator mci(membership,_config);
const Capability *c;
- while ((c = mci.next(_config))) {
- ztFinalDest = ztDest; // sanity check
+ while ((c = mci.next())) {
+ ztFinalDest = ztDest; // sanity check, should be unmodified if there was no match
Address cc2;
unsigned int ccLength2 = 0;
- switch(_doZtFilter(RR,_config,true,sourcePeer->address(),ztFinalDest,macSource,macDest,frameData,frameLen,etherType,vlanId,c->rules(),c->ruleCount(),_config.tags,_config.tagCount,remoteTagIds,remoteTagValues,remoteTagCount,cc2,ccLength2)) {
+ bool ccWatch2 = false;
+ switch(_doZtFilter(RR,_config,&membership,true,sourcePeer->address(),ztFinalDest,macSource,macDest,frameData,frameLen,etherType,vlanId,c->rules(),c->ruleCount(),cc2,ccLength2,ccWatch2)) {
case DOZTFILTER_NO_MATCH:
case DOZTFILTER_DROP: // explicit DROP in a capability just terminates its evaluation and is an anti-pattern
break;
@@ -801,11 +784,11 @@ int Network::filterIncomingPacket(
if (accept) {
if (cc2) {
- _membership(cc2).sendCredentialsIfNeeded(RR,RR->node->now(),cc2,_config,(const Capability *)0);
+ _membership(cc2).pushCredentials(RR,RR->node->now(),cc2,_config,-1,false);
Packet outp(cc2,RR->identity.address(),Packet::VERB_EXT_FRAME);
outp.append(_id);
- outp.append((uint8_t)0x06); // TEE/REDIRECT from inbound side: 0x06
+ outp.append((uint8_t)(ccWatch2 ? 0x1c : 0x08));
macDest.appendTo(outp);
macSource.appendTo(outp);
outp.append((uint16_t)etherType);
@@ -832,11 +815,11 @@ int Network::filterIncomingPacket(
if (accept) {
if (cc) {
- _membership(cc).sendCredentialsIfNeeded(RR,RR->node->now(),cc,_config,(const Capability *)0);
+ _membership(cc).pushCredentials(RR,RR->node->now(),cc,_config,-1,false);
Packet outp(cc,RR->identity.address(),Packet::VERB_EXT_FRAME);
outp.append(_id);
- outp.append((uint8_t)0x06); // TEE/REDIRECT from inbound side: 0x06
+ outp.append((uint8_t)(ccWatch ? 0x1c : 0x08));
macDest.appendTo(outp);
macSource.appendTo(outp);
outp.append((uint16_t)etherType);
@@ -846,11 +829,11 @@ int Network::filterIncomingPacket(
}
if ((ztDest != ztFinalDest)&&(ztFinalDest)) {
- _membership(ztFinalDest).sendCredentialsIfNeeded(RR,RR->node->now(),ztFinalDest,_config,(const Capability *)0);
+ _membership(ztFinalDest).pushCredentials(RR,RR->node->now(),ztFinalDest,_config,-1,false);
Packet outp(ztFinalDest,RR->identity.address(),Packet::VERB_EXT_FRAME);
outp.append(_id);
- outp.append((uint8_t)0x06); // TEE/REDIRECT from inbound side: 0x06
+ outp.append((uint8_t)0x0a);
macDest.appendTo(outp);
macSource.appendTo(outp);
outp.append((uint16_t)etherType);
@@ -892,60 +875,6 @@ void Network::multicastUnsubscribe(const MulticastGroup &mg)
_myMulticastGroups.erase(i);
}
-bool Network::applyConfiguration(const NetworkConfig &conf)
-{
- if (_destroyed) // sanity check
- return false;
- try {
- if ((conf.networkId == _id)&&(conf.issuedTo == RR->identity.address())) {
- ZT_VirtualNetworkConfig ctmp;
- bool portInitialized;
- {
- Mutex::Lock _l(_lock);
- _config = conf;
- _lastConfigUpdate = RR->node->now();
- _netconfFailure = NETCONF_FAILURE_NONE;
- _externalConfig(&ctmp);
- portInitialized = _portInitialized;
- _portInitialized = true;
- }
- _portError = RR->node->configureVirtualNetworkPort(_id,&_uPtr,(portInitialized) ? ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE : ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP,&ctmp);
- return true;
- } else {
- TRACE("ignored invalid configuration for network %.16llx (configuration contains mismatched network ID or issued-to address)",(unsigned long long)_id);
- }
- } catch (std::exception &exc) {
- TRACE("ignored invalid configuration for network %.16llx (%s)",(unsigned long long)_id,exc.what());
- } catch ( ... ) {
- TRACE("ignored invalid configuration for network %.16llx (unknown exception)",(unsigned long long)_id);
- }
- return false;
-}
-
-int Network::setConfiguration(const NetworkConfig &nconf,bool saveToDisk)
-{
- try {
- {
- Mutex::Lock _l(_lock);
- if (_config == nconf)
- return 1; // OK config, but duplicate of what we already have
- }
- if (applyConfiguration(nconf)) {
- if (saveToDisk) {
- char n[64];
- Utils::snprintf(n,sizeof(n),"networks.d/%.16llx.conf",_id);
- Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> d;
- if (nconf.toDictionary(d,false))
- RR->node->dataStorePut(n,(const void *)d.data(),d.sizeBytes(),true);
- }
- return 2; // OK and configuration has changed
- }
- } catch ( ... ) {
- TRACE("ignored invalid configuration for network %.16llx",(unsigned long long)_id);
- }
- return 0;
-}
-
void Network::handleInboundConfigChunk(const uint64_t inRePacketId,const void *data,unsigned int chunkSize,unsigned int chunkIndex,unsigned int totalSize)
{
std::string newConfig;
@@ -979,7 +908,8 @@ void Network::handleInboundConfigChunk(const uint64_t inRePacketId,const void *d
Identity controllerId(RR->topology->getIdentity(this->controller()));
if (controllerId) {
if (nc->fromDictionary(*dict)) {
- this->setConfiguration(*nc,true);
+ Mutex::Lock _l(_lock);
+ this->_setConfiguration(*nc,true);
} else {
TRACE("error parsing new config with length %u: deserialization of NetworkConfig failed (certificate error?)",(unsigned int)newConfig.length());
}
@@ -997,12 +927,6 @@ void Network::handleInboundConfigChunk(const uint64_t inRePacketId,const void *d
void Network::requestConfiguration()
{
- // Sanity limit: do not request more often than once per second
- const uint64_t now = RR->node->now();
- if ((now - _lastRequestedConfiguration) < 1000ULL)
- return;
- _lastRequestedConfiguration = RR->node->now();
-
const Address ctrl(controller());
Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> rmd;
@@ -1024,9 +948,10 @@ void Network::requestConfiguration()
if (RR->localNetworkController) {
NetworkConfig nconf;
switch(RR->localNetworkController->doNetworkConfigRequest(InetAddress(),RR->identity,RR->identity,_id,rmd,nconf)) {
- case NetworkController::NETCONF_QUERY_OK:
- this->setConfiguration(nconf,true);
- return;
+ case NetworkController::NETCONF_QUERY_OK: {
+ Mutex::Lock _l(_lock);
+ this->_setConfiguration(nconf,true);
+ } return;
case NetworkController::NETCONF_QUERY_OBJECT_NOT_FOUND:
this->setNotFound();
return;
@@ -1073,7 +998,7 @@ bool Network::gate(const SharedPtr<Peer> &peer,const Packet::Verb verb,const uin
if ( (_config.isPublic()) || ((m)&&(m->isAllowedOnNetwork(_config))) ) {
if (!m)
m = &(_membership(peer->address()));
- m->sendCredentialsIfNeeded(RR,now,peer->address(),_config,(const Capability *)0);
+ m->pushCredentials(RR,now,peer->address(),_config,-1,false);
if (m->shouldLikeMulticasts(now)) {
_announceMulticastGroupsTo(peer->address(),_allMulticastGroups());
m->likingMulticasts(now);
@@ -1124,9 +1049,8 @@ void Network::clean()
Membership *m = (Membership *)0;
Hashtable<Address,Membership>::Iterator i(_memberships);
while (i.next(a,m)) {
- if (RR->topology->getPeerNoCache(*a))
- m->clean(_config);
- else _memberships.erase(*a);
+ if (!RR->topology->getPeerNoCache(*a))
+ _memberships.erase(*a);
}
}
}
@@ -1177,21 +1101,25 @@ void Network::learnBridgedMulticastGroup(const MulticastGroup &mg,uint64_t now)
_sendUpdatesToMembers(&mg);
}
-int Network::addCredential(const CertificateOfMembership &com)
+Membership::AddCredentialResult Network::addCredential(const CertificateOfMembership &com)
{
if (com.networkId() != _id)
- return -1;
+ return Membership::ADD_REJECTED;
const Address a(com.issuedTo());
Mutex::Lock _l(_lock);
Membership &m = _membership(a);
- const int result = m.addCredential(RR,com);
- if (result == 0) {
- m.sendCredentialsIfNeeded(RR,RR->node->now(),a,_config,(const Capability *)0);
+ const Membership::AddCredentialResult result = m.addCredential(RR,_config,com);
+ if ((result == Membership::ADD_ACCEPTED_NEW)||(result == Membership::ADD_ACCEPTED_REDUNDANT)) {
+ m.pushCredentials(RR,RR->node->now(),a,_config,-1,false);
RR->mc->addCredential(com,true);
}
return result;
}
+Membership::AddCredentialResult Network::addCredential(const Revocation &rev)
+{
+}
+
void Network::destroy()
{
Mutex::Lock _l(_lock);
@@ -1215,6 +1143,39 @@ ZT_VirtualNetworkStatus Network::_status() const
}
}
+int Network::_setConfiguration(const NetworkConfig &nconf,bool saveToDisk)
+{
+ // assumes _lock is locked
+ try {
+ if ((nconf.issuedTo != RR->identity.address())||(nconf.networkId != _id))
+ return 0;
+ if (_config == nconf)
+ return 1; // OK config, but duplicate of what we already have
+
+ ZT_VirtualNetworkConfig ctmp;
+ _config = nconf;
+ _lastConfigUpdate = RR->node->now();
+ _netconfFailure = NETCONF_FAILURE_NONE;
+ _externalConfig(&ctmp);
+ const bool oldPortInitialized = _portInitialized;
+ _portInitialized = true;
+ _portError = RR->node->configureVirtualNetworkPort(_id,&_uPtr,(oldPortInitialized) ? ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE : ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP,&ctmp);
+
+ if (saveToDisk) {
+ char n[64];
+ Utils::snprintf(n,sizeof(n),"networks.d/%.16llx.conf",_id);
+ Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> d;
+ if (nconf.toDictionary(d,false))
+ RR->node->dataStorePut(n,(const void *)d.data(),d.sizeBytes(),true);
+ }
+
+ return 2; // OK and configuration has changed
+ } catch ( ... ) {
+ TRACE("ignored invalid configuration for network %.16llx",(unsigned long long)_id);
+ }
+ return 0;
+}
+
void Network::_externalConfig(ZT_VirtualNetworkConfig *ec) const
{
// assumes _lock is locked
@@ -1308,7 +1269,7 @@ void Network::_sendUpdatesToMembers(const MulticastGroup *const newMulticastGrou
Membership *m = (Membership *)0;
Hashtable<Address,Membership>::Iterator i(_memberships);
while (i.next(a,m)) {
- m->sendCredentialsIfNeeded(RR,now,*a,_config,(const Capability *)0);
+ m->pushCredentials(RR,now,*a,_config,-1,false);
if ( ((newMulticastGroup)||(m->shouldLikeMulticasts(now))) && (m->isAllowedOnNetwork(_config)) ) {
if (!newMulticastGroup)
m->likingMulticasts(now);