summaryrefslogtreecommitdiff
path: root/node/Node.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'node/Node.cpp')
-rw-r--r--node/Node.cpp270
1 files changed, 118 insertions, 152 deletions
diff --git a/node/Node.cpp b/node/Node.cpp
index ffd7568f..a1416896 100644
--- a/node/Node.cpp
+++ b/node/Node.cpp
@@ -45,9 +45,7 @@
#include <WinSock2.h>
#include <Windows.h>
#include <ShlObj.h>
-#endif
-
-#ifdef __UNIX_LIKE__
+#else
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
@@ -55,176 +53,151 @@
#endif
#include "Node.hpp"
+#include "RuntimeEnvironment.hpp"
+#include "Logger.hpp"
+#include "Utils.hpp"
+#include "Defaults.hpp"
+#include "Identity.hpp"
#include "Topology.hpp"
#include "SocketManager.hpp"
-#include "Packet.hpp"
#include "Switch.hpp"
-#include "Utils.hpp"
#include "EthernetTap.hpp"
-#include "Logger.hpp"
-#include "InetAddress.hpp"
-#include "Salsa20.hpp"
-#include "RuntimeEnvironment.hpp"
+#include "CMWC4096.hpp"
#include "NodeConfig.hpp"
-#include "Defaults.hpp"
#include "SysEnv.hpp"
#include "Network.hpp"
#include "MulticastGroup.hpp"
#include "Mutex.hpp"
#include "Multicaster.hpp"
-#include "CMWC4096.hpp"
-#include "SHA512.hpp"
#include "Service.hpp"
#include "SoftwareUpdater.hpp"
#include "Buffer.hpp"
+#include "IpcConnection.hpp"
#include "../version.h"
namespace ZeroTier {
-struct _LocalClientImpl
+// ---------------------------------------------------------------------------
+
+struct _NodeControlClientImpl
{
- unsigned char key[32];
- int sock;
- void (*resultHandler)(void *,unsigned long,const char *);
+ void (*resultHandler)(void *,const char *);
void *arg;
- unsigned int controlPort;
- InetAddress localDestAddr;
- Mutex inUseLock;
-
- void threadMain()
- throw()
- {
- }
+ IpcConnection *ipcc;
+ std::string err;
};
-static void _CBlocalClientHandler(const SharedPtr<Socket> &sock,void *arg,const InetAddress &from,Buffer<ZT_SOCKET_MAX_MESSAGE_LEN> &data)
+static void _CBipcResultHandler(void *arg,IpcConnection *ipcc,IpcConnection::EventType event,const char *result)
{
- _LocalClientImpl *impl = (_LocalClientImpl *)arg;
- if (!impl)
- return;
- if (!impl->resultHandler)
- return; // sanity check
- Mutex::Lock _l(impl->inUseLock);
- try {
- unsigned long convId = 0;
- std::vector<std::string> results;
- if (!NodeConfig::decodeControlMessagePacket(impl->key,data.data(),data.size(),convId,results))
- return;
- for(std::vector<std::string>::iterator r(results.begin());r!=results.end();++r)
- impl->resultHandler(impl->arg,convId,r->c_str());
- } catch ( ... ) {}
+ if ((event == IpcConnection::IPC_EVENT_COMMAND)&&(result))
+ ((_NodeControlClientImpl *)arg)->resultHandler(((_NodeControlClientImpl *)arg)->arg,result);
}
-Node::LocalClient::LocalClient(const char *authToken,unsigned int controlPort,void (*resultHandler)(void *,unsigned long,const char *),void *arg)
+Node::NodeControlClient::NodeControlClient(const char *hp,void (*resultHandler)(void *,const char *),void *arg,const char *authToken)
throw() :
- _impl((void *)0)
+ _impl((void *)new _NodeControlClientImpl)
{
- _LocalClientImpl *impl = new _LocalClientImpl;
-
- impl->sock =
-
- SocketManager *sm = (SocketManager *)0;
- for(unsigned int i=0;i<5000;++i) {
- try {
- sm = new SocketManager(0,32768 + (rand() % 20000),&_CBlocalClientHandler,impl);
- break;
- } catch ( ... ) {
- sm = (SocketManager *)0;
- }
+ _NodeControlClientImpl *impl = (_NodeControlClientImpl *)_impl;
+
+ std::string at;
+ if (authToken)
+ at = authToken;
+ else if (!Utils::readFile((std::string(hp) + ZT_PATH_SEPARATOR_S + "authtoken.secret").c_str(),at))
+ impl->err = "no authentication token specified and authtoken.secret not readable";
+ else {
+ std::string myid;
+ if (Utils::readFile((std::string(hp) + ZT_PATH_SEPARATOR_S + "identity.public").c_str(),myid)) {
+ std::string myaddr(myid.substr(0,myid.find(':')));
+ if (myaddr.length() != 10)
+ impl->err = "invalid address extracted from identity.public";
+ else {
+ try {
+ impl->resultHandler = resultHandler;
+ impl->arg = arg;
+ impl->ipcc = new IpcConnection((std::string(ZT_IPC_ENDPOINT_BASE) + myaddr).c_str(),&_CBipcResultHandler,_impl);
+ impl->ipcc->printf("auth %s"ZT_EOL_S,at.c_str());
+ } catch ( ... ) {
+ impl->err = "failure connecting to running ZeroTier One service";
+ }
+ }
+ } else impl->err = "unable to read identity.public";
}
-
- if (sm) {
- {
- unsigned int csk[64];
- SHA512::hash(csk,authToken,(unsigned int)strlen(authToken));
- memcpy(impl->key,csk,32);
- }
-
- impl->sock = sock;
- impl->resultHandler = resultHandler;
- impl->arg = arg;
- impl->controlPort = (controlPort) ? controlPort : (unsigned int)ZT_DEFAULT_CONTROL_UDP_PORT;
- impl->localDestAddr = InetAddress::LO4;
- impl->localDestAddr.setPort(impl->controlPort);
- _impl = impl;
- } else delete impl; // big problem, no ports?
}
-Node::LocalClient::~LocalClient()
+Node::NodeControlClient::~NodeControlClient()
{
if (_impl) {
- ((_LocalClientImpl *)_impl)->inUseLock.lock();
- delete ((_LocalClientImpl *)_impl)->sock;
- ((_LocalClientImpl *)_impl)->inUseLock.unlock();
- delete ((_LocalClientImpl *)_impl);
+ delete ((_NodeControlClientImpl *)_impl)->ipcc;
+ delete (_NodeControlClientImpl *)_impl;
}
}
-unsigned long Node::LocalClient::send(const char *command)
+void Node::NodeControlClient::send(const char *command)
throw()
{
- if (!_impl)
- return 0;
- _LocalClientImpl *impl = (_LocalClientImpl *)_impl;
- Mutex::Lock _l(impl->inUseLock);
-
try {
- uint32_t convId = (uint32_t)rand();
- if (!convId)
- convId = 1;
-
- std::vector<std::string> tmp;
- tmp.push_back(std::string(command));
- std::vector< Buffer<ZT_NODECONFIG_MAX_PACKET_SIZE> > packets(NodeConfig::encodeControlMessage(impl->key,convId,tmp));
-
- for(std::vector< Buffer<ZT_NODECONFIG_MAX_PACKET_SIZE> >::iterator p(packets.begin());p!=packets.end();++p)
- impl->sock->send(impl->localDestAddr,p->data(),p->size(),-1);
-
- return convId;
- } catch ( ... ) {
- return 0;
- }
+ ((_NodeControlClientImpl *)_impl)->ipcc->printf("%s"ZT_EOL_S,command);
+ } catch ( ... ) {}
}
-std::vector<std::string> Node::LocalClient::splitLine(const char *line)
+std::vector<std::string> Node::NodeControlClient::splitLine(const char *line)
{
return Utils::split(line," ","\\","\"");
}
-std::string Node::LocalClient::authTokenDefaultUserPath()
+const char *Node::NodeControlClient::authTokenDefaultUserPath()
{
+ static std::string dlp;
+ static Mutex dlp_m;
+
+ Mutex::Lock _l(dlp_m);
+
#ifdef __WINDOWS__
- char buf[16384];
- if (SUCCEEDED(SHGetFolderPathA(NULL,CSIDL_APPDATA,NULL,0,buf)))
- return (std::string(buf) + "\\ZeroTier\\One\\authtoken.secret");
- else return std::string();
+ if (!dlp.length()) {
+ char buf[16384];
+ if (SUCCEEDED(SHGetFolderPathA(NULL,CSIDL_APPDATA,NULL,0,buf)))
+ dlp = (std::string(buf) + "\\ZeroTier\\One\\authtoken.secret");
+ }
#else // not __WINDOWS__
- const char *home = getenv("HOME");
- if (home) {
+ if (!dlp.length()) {
+ const char *home = getenv("HOME");
+ if (home) {
#ifdef __APPLE__
- return (std::string(home) + "/Library/Application Support/ZeroTier/One/authtoken.secret");
+ dlp = (std::string(home) + "/Library/Application Support/ZeroTier/One/authtoken.secret");
#else
- return (std::string(home) + "/.zeroTierOneAuthToken");
+ dlp = (std::string(home) + "/.zeroTierOneAuthToken");
#endif
- } else return std::string();
+ }
+ }
#endif // __WINDOWS__ or not __WINDOWS__
+
+ return dlp.c_str();
}
-std::string Node::LocalClient::authTokenDefaultSystemPath()
+const char *Node::NodeControlClient::authTokenDefaultSystemPath()
{
- return (ZT_DEFAULTS.defaultHomePath + ZT_PATH_SEPARATOR_S"authtoken.secret");
+ static std::string dsp;
+ static Mutex dsp_m;
+
+ Mutex::Lock _l(dsp_m);
+
+ if (!dsp.length())
+ dsp = (ZT_DEFAULTS.defaultHomePath + ZT_PATH_SEPARATOR_S"authtoken.secret");
+
+ return dsp.c_str();
}
+// ---------------------------------------------------------------------------
+
struct _NodeImpl
{
RuntimeEnvironment renv;
- unsigned int port;
- unsigned int controlPort;
+ unsigned int udpPort,tcpPort;
std::string reasonForTerminationStr;
volatile Node::ReasonForTermination reasonForTermination;
volatile bool started;
@@ -352,16 +325,35 @@ static void _netconfServiceMessageHandler(void *renv,Service &svc,const Dictiona
}
#endif // !__WINDOWS__
-Node::Node(const char *hp,unsigned int port,unsigned int controlPort)
+Node::Node(const char *hp,unsigned int udpPort,unsigned int tcpPort,bool resetIdentity)
throw() :
_impl(new _NodeImpl)
{
_NodeImpl *impl = (_NodeImpl *)_impl;
- if ((hp)&&(strlen(hp) > 0))
+
+ if ((hp)&&(hp[0]))
impl->renv.homePath = hp;
else impl->renv.homePath = ZT_DEFAULTS.defaultHomePath;
- impl->port = (port) ? port : (unsigned int)ZT_DEFAULT_UDP_PORT;
- impl->controlPort = (controlPort) ? controlPort : (unsigned int)ZT_DEFAULT_CONTROL_UDP_PORT;
+
+ if (resetIdentity) {
+ // Forget identity and peer database, peer keys, etc.
+ Utils::rm((impl->renv.homePath + ZT_PATH_SEPARATOR_S + "identity.public").c_str());
+ Utils::rm((impl->renv.homePath + ZT_PATH_SEPARATOR_S + "identity.secret").c_str());
+ Utils::rm((impl->renv.homePath + ZT_PATH_SEPARATOR_S + "peers.persist").c_str());
+
+ // Truncate network config information in networks.d but leave the files since we
+ // still want to remember any networks we have joined. This will force re-config.
+ std::string networksDotD(impl->renv.homePath + ZT_PATH_SEPARATOR_S + "networks.d");
+ std::map< std::string,bool > nwfiles(Utils::listDirectory(networksDotD.c_str()));
+ for(std::map<std::string,bool>::iterator nwf(nwfiles.begin());nwf!=nwfiles.end();++nwf) {
+ FILE *foo = fopen((networksDotD + ZT_PATH_SEPARATOR_S + nwf->first).c_str(),"w");
+ if (foo)
+ fclose(foo);
+ }
+ }
+
+ impl->udpPort = ((udpPort > 0)&&(udpPort <= 0xffff)) ? udpPort : (unsigned int)ZT_DEFAULT_PORT;
+ impl->tcpPort = ((tcpPort > 0)&&(tcpPort <= 0xffff)) ? tcpPort : (unsigned int)ZT_DEFAULT_PORT;
impl->reasonForTermination = Node::NODE_RUNNING;
impl->started = false;
impl->running = false;
@@ -373,6 +365,13 @@ Node::~Node()
delete (_NodeImpl *)_impl;
}
+static void _CBztTraffic(const SharedPtr<Socket> &fromSock,void *arg,const InetAddress &from,Buffer<ZT_SOCKET_MAX_MESSAGE_LEN> &data)
+{
+ const RuntimeEnvironment *_r = (const RuntimeEnvironment *)arg;
+ if ((_r->sw)&&(!_r->shutdownInProgress))
+ _r->sw->onRemotePacket(fromSock,from,data);
+}
+
Node::ReasonForTermination Node::run()
throw()
{
@@ -452,15 +451,13 @@ Node::ReasonForTermination Node::run()
// Create the objects that make up runtime state.
_r->mc = new Multicaster();
_r->sw = new Switch(_r);
- _r->demarc = new Demarc(_r);
+ _r->sm = new SocketManager(impl->udpPort,impl->tcpPort,&_CBztTraffic,_r);
_r->topology = new Topology(_r,Utils::fileExists((_r->homePath + ZT_PATH_SEPARATOR_S + "iddb.d").c_str()));
_r->sysEnv = new SysEnv();
try {
- _r->nc = new NodeConfig(_r,configAuthToken.c_str(),impl->controlPort);
+ _r->nc = new NodeConfig(_r,configAuthToken.c_str());
} catch (std::exception &exc) {
- char foo[1024];
- Utils::snprintf(foo,sizeof(foo),"unable to bind to local control port %u: is another instance of ZeroTier One already running?",impl->controlPort);
- return impl->terminateBecause(Node::NODE_UNRECOVERABLE_ERROR,foo);
+ return impl->terminateBecause(Node::NODE_UNRECOVERABLE_ERROR,"unable to initialize IPC socket: is ZeroTier One already running?");
}
_r->node = this;
#ifdef ZT_AUTO_UPDATE
@@ -472,13 +469,6 @@ Node::ReasonForTermination Node::run()
}
#endif
- // Bind local port for core I/O
- if (!_r->demarc->bindLocalUdp(impl->port)) {
- char foo[1024];
- Utils::snprintf(foo,sizeof(foo),"unable to bind to global I/O port %u: is another instance of ZeroTier One already running?",impl->controlPort);
- return impl->terminateBecause(Node::NODE_UNRECOVERABLE_ERROR,foo);
- }
-
// Set initial supernode list
_r->topology->setSupernodes(ZT_DEFAULTS.supernodes);
} catch (std::bad_alloc &exc) {
@@ -669,14 +659,14 @@ void Node::terminate(ReasonForTermination reason,const char *reasonText)
{
((_NodeImpl *)_impl)->reasonForTermination = reason;
((_NodeImpl *)_impl)->reasonForTerminationStr = ((reasonText) ? reasonText : "");
- ((_NodeImpl *)_impl)->renv.sw->whack();
+ ((_NodeImpl *)_impl)->renv.sm->whack();
}
void Node::resync()
throw()
{
((_NodeImpl *)_impl)->resynchronize = true;
- ((_NodeImpl *)_impl)->renv.sw->whack();
+ ((_NodeImpl *)_impl)->renv.sm->whack();
}
class _VersionStringMaker
@@ -698,27 +688,3 @@ unsigned int Node::versionMinor() throw() { return ZEROTIER_ONE_VERSION_MINOR; }
unsigned int Node::versionRevision() throw() { return ZEROTIER_ONE_VERSION_REVISION; }
} // namespace ZeroTier
-
-extern "C" {
-
-ZeroTier::Node *zeroTierCreateNode(const char *hp,unsigned int port,unsigned int controlPort)
-{
- return new ZeroTier::Node(hp,port,controlPort);
-}
-
-void zeroTierDeleteNode(ZeroTier::Node *n)
-{
- delete n;
-}
-
-ZeroTier::Node::LocalClient *zeroTierCreateLocalClient(const char *authToken,unsigned int controlPort,void (*resultHandler)(void *,unsigned long,const char *),void *arg)
-{
- return new ZeroTier::Node::LocalClient(authToken,controlPort,resultHandler,arg);
-}
-
-void zeroTierDeleteLocalClient(ZeroTier::Node::LocalClient *lc)
-{
- delete lc;
-}
-
-} // extern "C"