mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-05-07 19:18:38 +00:00
Bunch more debugging and loop closing on new netconf.
This commit is contained in:
parent
e73c4cb68b
commit
28a73b620e
@ -113,27 +113,7 @@ Network::Network(const RuntimeEnvironment *renv,uint64_t id)
|
|||||||
_destroyOnDelete(false)
|
_destroyOnDelete(false)
|
||||||
{
|
{
|
||||||
if (controller() == _r->identity.address())
|
if (controller() == _r->identity.address())
|
||||||
throw std::runtime_error("configuration error: cannot add a network for which I am the netconf master");
|
throw std::runtime_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()
|
Network::~Network()
|
||||||
@ -149,15 +129,39 @@ Network::~Network()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Network::restoreState()
|
||||||
|
{
|
||||||
|
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(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);
|
||||||
|
}
|
||||||
|
// TODO: restore membership certs
|
||||||
|
}
|
||||||
|
|
||||||
void Network::setConfiguration(const Network::Config &conf)
|
void Network::setConfiguration(const Network::Config &conf)
|
||||||
{
|
{
|
||||||
Mutex::Lock _l(_lock);
|
Mutex::Lock _l(_lock);
|
||||||
if ((conf.networkId() == _id)&&(conf.peerAddress() == _r->identity.address())) { // sanity check
|
if ((conf.networkId() == _id)&&(conf.peerAddress() == _r->identity.address())) { // sanity check
|
||||||
TRACE("network %.16llx got netconf:\n%s",(unsigned long long)_id,conf.toString().c_str());
|
//TRACE("network %.16llx got netconf:\n%s",(unsigned long long)_id,conf.toString().c_str());
|
||||||
_configuration = conf;
|
_configuration = conf;
|
||||||
_myCertificate = conf.certificateOfMembership();
|
_myCertificate = conf.certificateOfMembership();
|
||||||
_lastConfigUpdate = Utils::now();
|
_lastConfigUpdate = Utils::now();
|
||||||
|
|
||||||
|
_tap.setIps(conf.staticAddresses());
|
||||||
|
|
||||||
std::string confPath(_r->homePath + ZT_PATH_SEPARATOR_S + "networks.d" + ZT_PATH_SEPARATOR_S + toString() + ".conf");
|
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())) {
|
if (!Utils::writeFile(confPath.c_str(),conf.toString())) {
|
||||||
LOG("error: unable to write network configuration file at: %s",confPath.c_str());
|
LOG("error: unable to write network configuration file at: %s",confPath.c_str());
|
||||||
|
@ -272,6 +272,22 @@ private:
|
|||||||
|
|
||||||
~Network();
|
~Network();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by NodeConfig after create
|
||||||
|
*
|
||||||
|
* This is called separately to avoid a rather evil race condition.
|
||||||
|
* If config is restored in the constructor, then it's possible that
|
||||||
|
* the tap will be assigned an IP and will start getting packets
|
||||||
|
* before SharedPtr<Network> has gotten the pointer from the initial
|
||||||
|
* object construct. That causes SharedPtr<Network> in the static
|
||||||
|
* method that handles tap traffic to delete the object, resulting
|
||||||
|
* in all sorts of utter madness. C++ is crazy like that.
|
||||||
|
*
|
||||||
|
* Actually the way we're using SharedPtr<Network> is hacky and
|
||||||
|
* ugly, so it's our fault sorta.
|
||||||
|
*/
|
||||||
|
void restoreState();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Causes all persistent disk presence to be erased on delete
|
* Causes all persistent disk presence to be erased on delete
|
||||||
*/
|
*/
|
||||||
|
@ -202,13 +202,14 @@ static void _netconfServiceMessageHandler(void *renv,Service &svc,const Dictiona
|
|||||||
const RuntimeEnvironment *_r = (const RuntimeEnvironment *)renv;
|
const RuntimeEnvironment *_r = (const RuntimeEnvironment *)renv;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
//TRACE("from netconf:\n%s",msg.toString().c_str());
|
||||||
const std::string &type = msg.get("type");
|
const std::string &type = msg.get("type");
|
||||||
if (type == "netconf-response") {
|
if (type == "netconf-response") {
|
||||||
uint64_t inRePacketId = strtoull(msg.get("requestId").c_str(),(char **)0,16);
|
uint64_t inRePacketId = strtoull(msg.get("requestId").c_str(),(char **)0,16);
|
||||||
SharedPtr<Network> network = _r->nc->network(strtoull(msg.get("nwid").c_str(),(char **)0,16));
|
uint64_t nwid = strtoull(msg.get("nwid").c_str(),(char **)0,16);
|
||||||
Address peerAddress(msg.get("peer").c_str());
|
Address peerAddress(msg.get("peer").c_str());
|
||||||
|
|
||||||
if ((network)&&(peerAddress)) {
|
if (peerAddress) {
|
||||||
if (msg.contains("error")) {
|
if (msg.contains("error")) {
|
||||||
Packet::ErrorCode errCode = Packet::ERROR_INVALID_REQUEST;
|
Packet::ErrorCode errCode = Packet::ERROR_INVALID_REQUEST;
|
||||||
const std::string &err = msg.get("error");
|
const std::string &err = msg.get("error");
|
||||||
@ -219,7 +220,7 @@ static void _netconfServiceMessageHandler(void *renv,Service &svc,const Dictiona
|
|||||||
outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
|
outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
|
||||||
outp.append(inRePacketId);
|
outp.append(inRePacketId);
|
||||||
outp.append((unsigned char)errCode);
|
outp.append((unsigned char)errCode);
|
||||||
outp.append(network->id());
|
outp.append(nwid);
|
||||||
_r->sw->send(outp,true);
|
_r->sw->send(outp,true);
|
||||||
} else if (msg.contains("netconf")) {
|
} else if (msg.contains("netconf")) {
|
||||||
const std::string &netconf = msg.get("netconf");
|
const std::string &netconf = msg.get("netconf");
|
||||||
@ -227,7 +228,7 @@ static void _netconfServiceMessageHandler(void *renv,Service &svc,const Dictiona
|
|||||||
Packet outp(peerAddress,_r->identity.address(),Packet::VERB_OK);
|
Packet outp(peerAddress,_r->identity.address(),Packet::VERB_OK);
|
||||||
outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
|
outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
|
||||||
outp.append(inRePacketId);
|
outp.append(inRePacketId);
|
||||||
outp.append(network->id());
|
outp.append(nwid);
|
||||||
outp.append((uint16_t)netconf.length());
|
outp.append((uint16_t)netconf.length());
|
||||||
outp.append(netconf.data(),netconf.length());
|
outp.append(netconf.data(),netconf.length());
|
||||||
outp.compress();
|
outp.compress();
|
||||||
@ -266,12 +267,12 @@ Node::~Node()
|
|||||||
delete impl->renv.netconfService;
|
delete impl->renv.netconfService;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
delete impl->renv.nc;
|
||||||
delete impl->renv.sysEnv;
|
delete impl->renv.sysEnv;
|
||||||
delete impl->renv.topology;
|
delete impl->renv.topology;
|
||||||
delete impl->renv.sw;
|
delete impl->renv.sw;
|
||||||
delete impl->renv.multicaster;
|
delete impl->renv.multicaster;
|
||||||
delete impl->renv.demarc;
|
delete impl->renv.demarc;
|
||||||
delete impl->renv.nc;
|
|
||||||
delete impl->renv.prng;
|
delete impl->renv.prng;
|
||||||
delete impl->renv.log;
|
delete impl->renv.log;
|
||||||
|
|
||||||
@ -362,6 +363,11 @@ Node::ReasonForTermination Node::run()
|
|||||||
// Create the core objects in RuntimeEnvironment: node config, demarcation
|
// Create the core objects in RuntimeEnvironment: node config, demarcation
|
||||||
// point, switch, network topology database, and system environment
|
// point, switch, network topology database, and system environment
|
||||||
// watcher.
|
// watcher.
|
||||||
|
_r->demarc = new Demarc(_r);
|
||||||
|
_r->multicaster = new Multicaster();
|
||||||
|
_r->sw = new Switch(_r);
|
||||||
|
_r->topology = new Topology(_r,(_r->homePath + ZT_PATH_SEPARATOR_S + "peer.db").c_str());
|
||||||
|
_r->sysEnv = new SysEnv(_r);
|
||||||
try {
|
try {
|
||||||
_r->nc = new NodeConfig(_r,configAuthToken.c_str());
|
_r->nc = new NodeConfig(_r,configAuthToken.c_str());
|
||||||
} catch ( ... ) {
|
} catch ( ... ) {
|
||||||
@ -369,11 +375,6 @@ Node::ReasonForTermination Node::run()
|
|||||||
// One is running.
|
// One is running.
|
||||||
return impl->terminateBecause(Node::NODE_UNRECOVERABLE_ERROR,"another instance of ZeroTier One appears to be running, or local control UDP port cannot be bound");
|
return impl->terminateBecause(Node::NODE_UNRECOVERABLE_ERROR,"another instance of ZeroTier One appears to be running, or local control UDP port cannot be bound");
|
||||||
}
|
}
|
||||||
_r->demarc = new Demarc(_r);
|
|
||||||
_r->multicaster = new Multicaster();
|
|
||||||
_r->sw = new Switch(_r);
|
|
||||||
_r->topology = new Topology(_r,(_r->homePath + ZT_PATH_SEPARATOR_S + "peer.db").c_str());
|
|
||||||
_r->sysEnv = new SysEnv(_r);
|
|
||||||
|
|
||||||
// TODO: make configurable
|
// TODO: make configurable
|
||||||
bool boundPort = false;
|
bool boundPort = false;
|
||||||
|
@ -32,6 +32,8 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
#include <openssl/sha.h>
|
#include <openssl/sha.h>
|
||||||
|
|
||||||
@ -58,6 +60,32 @@ NodeConfig::NodeConfig(const RuntimeEnvironment *renv,const char *authToken)
|
|||||||
SHA256_Init(&sha);
|
SHA256_Init(&sha);
|
||||||
SHA256_Update(&sha,authToken,strlen(authToken));
|
SHA256_Update(&sha,authToken,strlen(authToken));
|
||||||
SHA256_Final(_controlSocketKey,&sha);
|
SHA256_Final(_controlSocketKey,&sha);
|
||||||
|
|
||||||
|
std::map<std::string,bool> networksDotD(Utils::listDirectory((_r->homePath + ZT_PATH_SEPARATOR_S + "networks.d").c_str()));
|
||||||
|
std::set<uint64_t> nwids;
|
||||||
|
for(std::map<std::string,bool>::iterator d(networksDotD.begin());d!=networksDotD.end();++d) {
|
||||||
|
if (!d->second) {
|
||||||
|
std::string::size_type dot = d->first.rfind(".conf");
|
||||||
|
if (dot != std::string::npos) {
|
||||||
|
uint64_t nwid = strtoull(d->first.substr(0,dot).c_str(),(char **)0,16);
|
||||||
|
if (nwid > 0)
|
||||||
|
nwids.insert(nwid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(std::set<uint64_t>::iterator nwid(nwids.begin());nwid!=nwids.end();++nwid) {
|
||||||
|
try {
|
||||||
|
SharedPtr<Network> nw(new Network(_r,*nwid));
|
||||||
|
_networks[*nwid] = nw;
|
||||||
|
nw->restoreState();
|
||||||
|
nw->requestConfiguration();
|
||||||
|
} catch (std::exception &exc) {
|
||||||
|
LOG("unable to create network %.16llx: %s",(unsigned long long)*nwid,exc.what());
|
||||||
|
} catch ( ... ) {
|
||||||
|
LOG("unable to create network %.16llx: (unknown exception)",(unsigned long long)*nwid);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeConfig::~NodeConfig()
|
NodeConfig::~NodeConfig()
|
||||||
@ -149,14 +177,20 @@ std::vector<std::string> NodeConfig::execute(const char *command)
|
|||||||
uint64_t nwid = strtoull(cmd[1].c_str(),(char **)0,16);
|
uint64_t nwid = strtoull(cmd[1].c_str(),(char **)0,16);
|
||||||
if (nwid > 0) {
|
if (nwid > 0) {
|
||||||
Mutex::Lock _l(_networks_m);
|
Mutex::Lock _l(_networks_m);
|
||||||
try {
|
if (_networks.count(nwid)) {
|
||||||
SharedPtr<Network> nw(new Network(_r,nwid));
|
_P("400 already a member of %.16llx",(unsigned long long)nwid);
|
||||||
_networks[nwid] = nw;
|
} else {
|
||||||
_P("200 join %.16llx OK",(unsigned long long)nwid);
|
try {
|
||||||
} catch (std::exception &exc) {
|
SharedPtr<Network> nw(new Network(_r,nwid));
|
||||||
_P("500 join %.16llx ERROR: %s",(unsigned long long)nwid,exc.what());
|
_networks[nwid] = nw;
|
||||||
} catch ( ... ) {
|
nw->restoreState();
|
||||||
_P("500 join %.16llx ERROR: (unknown exception)",(unsigned long long)nwid);
|
nw->requestConfiguration();
|
||||||
|
_P("200 join %.16llx OK",(unsigned long long)nwid);
|
||||||
|
} catch (std::exception &exc) {
|
||||||
|
_P("500 join %.16llx ERROR: %s",(unsigned long long)nwid,exc.what());
|
||||||
|
} catch ( ... ) {
|
||||||
|
_P("500 join %.16llx ERROR: (unknown exception)",(unsigned long long)nwid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_P("400 join requires a network ID (>0) in hexadecimal format");
|
_P("400 join requires a network ID (>0) in hexadecimal format");
|
||||||
|
@ -463,10 +463,12 @@ bool PacketDecoder::_doMULTICAST_LIKE(const RuntimeEnvironment *_r,const SharedP
|
|||||||
_r->multicaster->likesMulticastGroup(nwid,MulticastGroup(mac,adi),source(),now);
|
_r->multicaster->likesMulticastGroup(nwid,MulticastGroup(mac,adi),source(),now);
|
||||||
++numAccepted;
|
++numAccepted;
|
||||||
} else {
|
} else {
|
||||||
TRACE("ignored MULTICAST_LIKE from %s(%s): not a member of closed network %llu",source().toString().c_str(),_remoteAddress.toString().c_str(),nwid);
|
ptr += 10;
|
||||||
|
TRACE("ignored MULTICAST_LIKE from %s(%s): not a member of closed network %.16llx",source().toString().c_str(),_remoteAddress.toString().c_str(),(unsigned long long)nwid);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
TRACE("ignored MULTICAST_LIKE from %s(%s): network %llu unknown or we are not a member",source().toString().c_str(),_remoteAddress.toString().c_str(),nwid);
|
ptr += 10;
|
||||||
|
TRACE("ignored MULTICAST_LIKE from %s(%s): network %.16llx unknown or we are not a member",source().toString().c_str(),_remoteAddress.toString().c_str(),(unsigned long long)nwid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -610,7 +612,6 @@ bool PacketDecoder::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *_r,const
|
|||||||
char tmp[128];
|
char tmp[128];
|
||||||
try {
|
try {
|
||||||
uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_NETWORK_ID);
|
uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_NETWORK_ID);
|
||||||
TRACE("NETWORK_CONFIG_REQUEST for %.16llx from %s",(unsigned long long)nwid,source().toString().c_str());
|
|
||||||
#ifndef __WINDOWS__
|
#ifndef __WINDOWS__
|
||||||
if (_r->netconfService) {
|
if (_r->netconfService) {
|
||||||
unsigned int dictLen = at<uint16_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT_LEN);
|
unsigned int dictLen = at<uint16_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT_LEN);
|
||||||
@ -624,6 +625,7 @@ bool PacketDecoder::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *_r,const
|
|||||||
request["nwid"] = tmp;
|
request["nwid"] = tmp;
|
||||||
sprintf(tmp,"%llx",(unsigned long long)packetId());
|
sprintf(tmp,"%llx",(unsigned long long)packetId());
|
||||||
request["requestId"] = tmp;
|
request["requestId"] = tmp;
|
||||||
|
//TRACE("to netconf:\n%s",request.toString().c_str());
|
||||||
_r->netconfService->send(request);
|
_r->netconfService->send(request);
|
||||||
} else {
|
} else {
|
||||||
#endif // !__WINDOWS__
|
#endif // !__WINDOWS__
|
||||||
@ -635,7 +637,6 @@ bool PacketDecoder::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *_r,const
|
|||||||
outp.encrypt(peer->cryptKey());
|
outp.encrypt(peer->cryptKey());
|
||||||
outp.hmacSet(peer->macKey());
|
outp.hmacSet(peer->macKey());
|
||||||
_r->demarc->send(_localPort,_remoteAddress,outp.data(),outp.size(),-1);
|
_r->demarc->send(_localPort,_remoteAddress,outp.data(),outp.size(),-1);
|
||||||
TRACE("sent ERROR(NETWORK_CONFIG_REQUEST,UNSUPPORTED_OPERATION) to %s(%s)",peer->address().toString().c_str(),_remoteAddress.toString().c_str());
|
|
||||||
#ifndef __WINDOWS__
|
#ifndef __WINDOWS__
|
||||||
}
|
}
|
||||||
#endif // !__WINDOWS__
|
#endif // !__WINDOWS__
|
||||||
|
@ -63,12 +63,12 @@ public:
|
|||||||
RuntimeEnvironment() :
|
RuntimeEnvironment() :
|
||||||
log((Logger *)0),
|
log((Logger *)0),
|
||||||
prng((CMWC4096 *)0),
|
prng((CMWC4096 *)0),
|
||||||
nc((NodeConfig *)0),
|
|
||||||
demarc((Demarc *)0),
|
demarc((Demarc *)0),
|
||||||
multicaster((Multicaster *)0),
|
multicaster((Multicaster *)0),
|
||||||
sw((Switch *)0),
|
sw((Switch *)0),
|
||||||
topology((Topology *)0),
|
topology((Topology *)0),
|
||||||
sysEnv((SysEnv *)0)
|
sysEnv((SysEnv *)0),
|
||||||
|
nc((NodeConfig *)0)
|
||||||
#ifndef __WINDOWS__
|
#ifndef __WINDOWS__
|
||||||
,netconfService((Service *)0)
|
,netconfService((Service *)0)
|
||||||
#endif
|
#endif
|
||||||
@ -87,12 +87,12 @@ public:
|
|||||||
|
|
||||||
Logger *log; // may be null
|
Logger *log; // may be null
|
||||||
CMWC4096 *prng;
|
CMWC4096 *prng;
|
||||||
NodeConfig *nc;
|
|
||||||
Demarc *demarc;
|
Demarc *demarc;
|
||||||
Multicaster *multicaster;
|
Multicaster *multicaster;
|
||||||
Switch *sw;
|
Switch *sw;
|
||||||
Topology *topology;
|
Topology *topology;
|
||||||
SysEnv *sysEnv;
|
SysEnv *sysEnv;
|
||||||
|
NodeConfig *nc;
|
||||||
|
|
||||||
#ifndef __WINDOWS__
|
#ifndef __WINDOWS__
|
||||||
Service *netconfService; // may be null
|
Service *netconfService; // may be null
|
||||||
|
@ -231,7 +231,7 @@ std::map<std::string,bool> Utils::listDirectory(const char *path)
|
|||||||
if (readdir_r(d,&de,&dptr))
|
if (readdir_r(d,&de,&dptr))
|
||||||
break;
|
break;
|
||||||
if (dptr) {
|
if (dptr) {
|
||||||
if ((!strcmp(dptr->d_name,"."))&&(!strcmp(dptr->d_name,"..")))
|
if ((strcmp(dptr->d_name,"."))&&(strcmp(dptr->d_name,"..")))
|
||||||
r[std::string(dptr->d_name)] = (dptr->d_type == DT_DIR);
|
r[std::string(dptr->d_name)] = (dptr->d_type == DT_DIR);
|
||||||
} else break;
|
} else break;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user