summaryrefslogtreecommitdiff
path: root/node
diff options
context:
space:
mode:
authorAdam Ierymenko <adam.ierymenko@gmail.com>2013-08-06 01:28:56 -0400
committerAdam Ierymenko <adam.ierymenko@gmail.com>2013-08-06 01:28:56 -0400
commit28a73b620e60dd5d9c77aa7494d4c71da8b1d08c (patch)
tree5b708b71a3703afd52301a6e0fc1a4e192db6a73 /node
parente73c4cb68b7461b8a2bdf7b6e5919bd0fcef2c1e (diff)
downloadinfinitytier-28a73b620e60dd5d9c77aa7494d4c71da8b1d08c.tar.gz
infinitytier-28a73b620e60dd5d9c77aa7494d4c71da8b1d08c.zip
Bunch more debugging and loop closing on new netconf.
Diffstat (limited to 'node')
-rw-r--r--node/Network.cpp40
-rw-r--r--node/Network.hpp16
-rw-r--r--node/Node.cpp21
-rw-r--r--node/NodeConfig.cpp50
-rw-r--r--node/PacketDecoder.cpp9
-rw-r--r--node/RuntimeEnvironment.hpp6
-rw-r--r--node/Utils.cpp2
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;
}