|
|
|
|
@ -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()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|