summaryrefslogtreecommitdiff
path: root/node/Network.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'node/Network.cpp')
-rw-r--r--node/Network.cpp81
1 files changed, 78 insertions, 3 deletions
diff --git a/node/Network.cpp b/node/Network.cpp
index 6deb31fe..f0770610 100644
--- a/node/Network.cpp
+++ b/node/Network.cpp
@@ -25,6 +25,8 @@
* LLC. Start here: http://www.zerotier.com/
*/
+#include <stdio.h>
+#include <string.h>
#include <stdlib.h>
#include <math.h>
@@ -35,6 +37,7 @@
#include "Network.hpp"
#include "Switch.hpp"
#include "Packet.hpp"
+#include "Utils.hpp"
namespace ZeroTier {
@@ -106,14 +109,44 @@ Network::Network(const RuntimeEnvironment *renv,uint64_t id)
_r(renv),
_tap(renv,renv->identity.address().toMAC(),ZT_IF_MTU,&_CBhandleTapData,this),
_id(id),
- _lastConfigUpdate(0)
+ _lastConfigUpdate(0),
+ _destroyOnDelete(false)
{
if (controller() == _r->identity.address())
throw std::runtime_error("configuration error: cannot add a network for which I am the netconf master");
+
+ std::string confPath(_r->homePath + ZT_PATH_SEPARATOR_S + "networks.d" + ZT_PATH_SEPARATOR_S + toString() + ".conf");
+ std::string confs;
+ if (Utils::readFile(confPath.c_str(),confs)) {
+ try {
+ if (confs.length()) {
+ Config conf(confs);
+ if (conf.containsAllFields())
+ setConfiguration(Config(conf));
+ }
+ } catch ( ... ) {} // ignore invalid config on disk, we will re-request
+ } else {
+ // If the conf file isn't present, "touch" it so we'll remember
+ // the existence of this network.
+ FILE *tmp = fopen(confPath.c_str(),"w");
+ if (tmp)
+ fclose(tmp);
+ }
+
+ requestConfiguration();
}
Network::~Network()
{
+ if (_destroyOnDelete) {
+ std::string confPath(_r->homePath + ZT_PATH_SEPARATOR_S + "networks.d" + ZT_PATH_SEPARATOR_S + toString() + ".conf");
+ std::string mcdbPath(_r->homePath + ZT_PATH_SEPARATOR_S + "networks.d" + ZT_PATH_SEPARATOR_S + toString() + ".mcerts");
+ unlink(confPath.c_str());
+ unlink(mcdbPath.c_str());
+ } else {
+ // Causes flush of membership certs to disk
+ clean();
+ }
}
void Network::setConfiguration(const Network::Config &conf)
@@ -124,6 +157,11 @@ void Network::setConfiguration(const Network::Config &conf)
_configuration = conf;
_myCertificate = conf.certificateOfMembership();
_lastConfigUpdate = Utils::now();
+
+ std::string confPath(_r->homePath + ZT_PATH_SEPARATOR_S + "networks.d" + ZT_PATH_SEPARATOR_S + toString() + ".conf");
+ if (!Utils::writeFile(confPath.c_str(),conf.toString())) {
+ LOG("error: unable to write network configuration file at: %s",confPath.c_str());
+ }
}
}
@@ -136,9 +174,17 @@ void Network::requestConfiguration()
TRACE("requesting netconf for network %.16llx from netconf master %s",(unsigned long long)_id,controller().toString().c_str());
Packet outp(controller(),_r->identity.address(),Packet::VERB_NETWORK_CONFIG_REQUEST);
outp.append((uint64_t)_id);
+ outp.append((uint16_t)0); // no meta-data
_r->sw->send(outp,true);
}
+void Network::addMembershipCertificate(const Address &peer,const Certificate &cert)
+{
+ Mutex::Lock _l(_lock);
+ if (!_configuration.isOpen())
+ _membershipCertificates[peer] = cert;
+}
+
bool Network::isAllowed(const Address &peer) const
{
// Exceptions can occur if we do not yet have *our* configuration.
@@ -164,10 +210,39 @@ void Network::clean()
if (_configuration.isOpen())
_membershipCertificates.clear();
else {
+ std::string mcdbPath(_r->homePath + ZT_PATH_SEPARATOR_S + "networks.d" + ZT_PATH_SEPARATOR_S + toString() + ".mcerts");
+ FILE *mcdb = fopen(mcdbPath.c_str(),"wb");
+ bool writeError = false;
+ if (!mcdb) {
+ LOG("error: unable to open membership cert database at: %s",mcdbPath.c_str());
+ } else {
+ if ((writeError)||(fwrite("MCDB0",5,1,mcdb) != 1)) // version
+ writeError = true;
+ }
+
for(std::map<Address,Certificate>::iterator i=(_membershipCertificates.begin());i!=_membershipCertificates.end();) {
- if (_myCertificate.qualifyMembership(i->second))
+ if (_myCertificate.qualifyMembership(i->second)) {
+ if ((!writeError)&&(mcdb)) {
+ char tmp[ZT_ADDRESS_LENGTH];
+ i->first.copyTo(tmp,ZT_ADDRESS_LENGTH);
+ if ((writeError)||(fwrite(tmp,ZT_ADDRESS_LENGTH,1,mcdb) != 1))
+ writeError = true;
+ std::string c(i->second.toString());
+ uint32_t cl = Utils::hton((uint32_t)c.length());
+ if ((writeError)||(fwrite(&cl,sizeof(cl),1,mcdb) != 1))
+ writeError = true;
+ if ((writeError)||(fwrite(c.data(),c.length(),1,mcdb) != 1))
+ writeError = true;
+ }
++i;
- else _membershipCertificates.erase(i++);
+ } else _membershipCertificates.erase(i++);
+ }
+
+ if (mcdb)
+ fclose(mcdb);
+ if (writeError) {
+ unlink(mcdbPath.c_str());
+ LOG("error: unable to write to membership cert database at: %s",mcdbPath.c_str());
}
}
}