diff options
author | Adam Ierymenko <adam.ierymenko@gmail.com> | 2013-08-06 01:28:56 -0400 |
---|---|---|
committer | Adam Ierymenko <adam.ierymenko@gmail.com> | 2013-08-06 01:28:56 -0400 |
commit | 28a73b620e60dd5d9c77aa7494d4c71da8b1d08c (patch) | |
tree | 5b708b71a3703afd52301a6e0fc1a4e192db6a73 /node | |
parent | e73c4cb68b7461b8a2bdf7b6e5919bd0fcef2c1e (diff) | |
download | infinitytier-28a73b620e60dd5d9c77aa7494d4c71da8b1d08c.tar.gz infinitytier-28a73b620e60dd5d9c77aa7494d4c71da8b1d08c.zip |
Bunch more debugging and loop closing on new netconf.
Diffstat (limited to 'node')
-rw-r--r-- | node/Network.cpp | 40 | ||||
-rw-r--r-- | node/Network.hpp | 16 | ||||
-rw-r--r-- | node/Node.cpp | 21 | ||||
-rw-r--r-- | node/NodeConfig.cpp | 50 | ||||
-rw-r--r-- | node/PacketDecoder.cpp | 9 | ||||
-rw-r--r-- | node/RuntimeEnvironment.hpp | 6 | ||||
-rw-r--r-- | node/Utils.cpp | 2 |
7 files changed, 100 insertions, 44 deletions
diff --git a/node/Network.cpp b/node/Network.cpp index f0770610..d075bc7c 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -113,8 +113,24 @@ Network::Network(const RuntimeEnvironment *renv,uint64_t id) _destroyOnDelete(false) { 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"); +} +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::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)) { @@ -122,7 +138,7 @@ Network::Network(const RuntimeEnvironment *renv,uint64_t id) if (confs.length()) { Config conf(confs); if (conf.containsAllFields()) - setConfiguration(Config(conf)); + setConfiguration(conf); } } catch ( ... ) {} // ignore invalid config on disk, we will re-request } else { @@ -132,32 +148,20 @@ Network::Network(const RuntimeEnvironment *renv,uint64_t id) 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(); - } + // TODO: restore membership certs } void Network::setConfiguration(const Network::Config &conf) { Mutex::Lock _l(_lock); 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; _myCertificate = conf.certificateOfMembership(); _lastConfigUpdate = Utils::now(); + _tap.setIps(conf.staticAddresses()); + 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()); diff --git a/node/Network.hpp b/node/Network.hpp index 6b7b3055..d5c091e8 100644 --- a/node/Network.hpp +++ b/node/Network.hpp @@ -273,6 +273,22 @@ private: ~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 */ inline void destroyOnDelete() diff --git a/node/Node.cpp b/node/Node.cpp index 03710dce..e5332480 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -202,13 +202,14 @@ static void _netconfServiceMessageHandler(void *renv,Service &svc,const Dictiona const RuntimeEnvironment *_r = (const RuntimeEnvironment *)renv; try { + //TRACE("from netconf:\n%s",msg.toString().c_str()); const std::string &type = msg.get("type"); if (type == "netconf-response") { 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()); - if ((network)&&(peerAddress)) { + if (peerAddress) { if (msg.contains("error")) { Packet::ErrorCode errCode = Packet::ERROR_INVALID_REQUEST; 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(inRePacketId); outp.append((unsigned char)errCode); - outp.append(network->id()); + outp.append(nwid); _r->sw->send(outp,true); } else if (msg.contains("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); outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST); outp.append(inRePacketId); - outp.append(network->id()); + outp.append(nwid); outp.append((uint16_t)netconf.length()); outp.append(netconf.data(),netconf.length()); outp.compress(); @@ -266,12 +267,12 @@ Node::~Node() delete impl->renv.netconfService; #endif + delete impl->renv.nc; delete impl->renv.sysEnv; delete impl->renv.topology; delete impl->renv.sw; delete impl->renv.multicaster; delete impl->renv.demarc; - delete impl->renv.nc; delete impl->renv.prng; delete impl->renv.log; @@ -362,6 +363,11 @@ Node::ReasonForTermination Node::run() // Create the core objects in RuntimeEnvironment: node config, demarcation // point, switch, network topology database, and system environment // 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 { _r->nc = new NodeConfig(_r,configAuthToken.c_str()); } catch ( ... ) { @@ -369,11 +375,6 @@ Node::ReasonForTermination Node::run() // 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"); } - _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 bool boundPort = false; diff --git a/node/NodeConfig.cpp b/node/NodeConfig.cpp index b6d58e40..a8599508 100644 --- a/node/NodeConfig.cpp +++ b/node/NodeConfig.cpp @@ -32,6 +32,8 @@ #include <memory> #include <string> +#include <map> +#include <set> #include <openssl/sha.h> @@ -58,6 +60,32 @@ NodeConfig::NodeConfig(const RuntimeEnvironment *renv,const char *authToken) SHA256_Init(&sha); SHA256_Update(&sha,authToken,strlen(authToken)); 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() @@ -149,14 +177,20 @@ std::vector<std::string> NodeConfig::execute(const char *command) uint64_t nwid = strtoull(cmd[1].c_str(),(char **)0,16); if (nwid > 0) { Mutex::Lock _l(_networks_m); - try { - SharedPtr<Network> nw(new Network(_r,nwid)); - _networks[nwid] = nw; - _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); + if (_networks.count(nwid)) { + _P("400 already a member of %.16llx",(unsigned long long)nwid); + } else { + try { + SharedPtr<Network> nw(new Network(_r,nwid)); + _networks[nwid] = nw; + nw->restoreState(); + 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 { _P("400 join requires a network ID (>0) in hexadecimal format"); diff --git a/node/PacketDecoder.cpp b/node/PacketDecoder.cpp index 062cdbc2..ea6a3475 100644 --- a/node/PacketDecoder.cpp +++ b/node/PacketDecoder.cpp @@ -463,10 +463,12 @@ bool PacketDecoder::_doMULTICAST_LIKE(const RuntimeEnvironment *_r,const SharedP _r->multicaster->likesMulticastGroup(nwid,MulticastGroup(mac,adi),source(),now); ++numAccepted; } 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 { - 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]; try { 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__ if (_r->netconfService) { 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; sprintf(tmp,"%llx",(unsigned long long)packetId()); request["requestId"] = tmp; + //TRACE("to netconf:\n%s",request.toString().c_str()); _r->netconfService->send(request); } else { #endif // !__WINDOWS__ @@ -635,7 +637,6 @@ bool PacketDecoder::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *_r,const outp.encrypt(peer->cryptKey()); outp.hmacSet(peer->macKey()); _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__ } #endif // !__WINDOWS__ diff --git a/node/RuntimeEnvironment.hpp b/node/RuntimeEnvironment.hpp index 00d393af..54cbf740 100644 --- a/node/RuntimeEnvironment.hpp +++ b/node/RuntimeEnvironment.hpp @@ -63,12 +63,12 @@ public: RuntimeEnvironment() : log((Logger *)0), prng((CMWC4096 *)0), - nc((NodeConfig *)0), demarc((Demarc *)0), multicaster((Multicaster *)0), sw((Switch *)0), topology((Topology *)0), - sysEnv((SysEnv *)0) + sysEnv((SysEnv *)0), + nc((NodeConfig *)0) #ifndef __WINDOWS__ ,netconfService((Service *)0) #endif @@ -87,12 +87,12 @@ public: Logger *log; // may be null CMWC4096 *prng; - NodeConfig *nc; Demarc *demarc; Multicaster *multicaster; Switch *sw; Topology *topology; SysEnv *sysEnv; + NodeConfig *nc; #ifndef __WINDOWS__ Service *netconfService; // may be null diff --git a/node/Utils.cpp b/node/Utils.cpp index 7a4d51ba..b6284fca 100644 --- a/node/Utils.cpp +++ b/node/Utils.cpp @@ -231,7 +231,7 @@ std::map<std::string,bool> Utils::listDirectory(const char *path) if (readdir_r(d,&de,&dptr)) break; 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); } else break; } |