diff --git a/node/Constants.hpp b/node/Constants.hpp index bcefe7f9e..58265bcde 100644 --- a/node/Constants.hpp +++ b/node/Constants.hpp @@ -114,14 +114,9 @@ error_no_byte_order_defined; #define ZT_ADDRESS_RESERVED_PREFIX 0xff /** - * Default local UDP port + * Default local port for ZeroTier traffic */ -#define ZT_DEFAULT_UDP_PORT 9993 - -/** - * Local control port, also used for multiple invocation check - */ -#define ZT_DEFAULT_CONTROL_UDP_PORT 39393 +#define ZT_DEFAULT_PORT 9993 /** * Default payload MTU for UDP packets diff --git a/node/Defaults.cpp b/node/Defaults.cpp index 44f344eac..3e0727da1 100644 --- a/node/Defaults.cpp +++ b/node/Defaults.cpp @@ -56,35 +56,35 @@ static inline std::map< Identity,std::vector > _mkSupernodeMap() addrs.clear(); if (!id.fromString("8acf059fe3:0:482f6ee5dfe902319b419de5bdc765209c0ecda38c4d6e4fcf0d33658398b4527dcd22f93112fb9befd02fd78bf7261b333fc105d192a623ca9e50fc60b374a5")) throw std::runtime_error("invalid identity in Defaults"); - addrs.push_back(InetAddress("162.243.77.111",ZT_DEFAULT_UDP_PORT)); + addrs.push_back(InetAddress("162.243.77.111",ZT_DEFAULT_PORT)); sn[id] = addrs; // nyarlathotep.zerotier.com - San Francisco, California, USA addrs.clear(); if (!id.fromString("7e19876aba:0:2a6e2b2318930f60eb097f70d0f4b028b2cd6d3d0c63c014b9039ff35390e41181f216fb2e6fa8d95c1ee9667156411905c3dccfea78d8c6dfafba688170b3fa")) throw std::runtime_error("invalid identity in Defaults"); - addrs.push_back(InetAddress("198.199.97.220",ZT_DEFAULT_UDP_PORT)); + addrs.push_back(InetAddress("198.199.97.220",ZT_DEFAULT_PORT)); sn[id] = addrs; // shub-niggurath.zerotier.com - Amsterdam, Netherlands addrs.clear(); if (!id.fromString("36f63d6574:0:67a776487a1a99b32f413329f2b67c43fbf6152e42c6b66e89043e69d93e48314c7d709b58a83016bd2612dd89400b856e18c553da94892f7d3ca16bf2c92c24")) throw std::runtime_error("invalid identity in Defaults"); - addrs.push_back(InetAddress("198.211.127.172",ZT_DEFAULT_UDP_PORT)); + addrs.push_back(InetAddress("198.211.127.172",ZT_DEFAULT_PORT)); sn[id] = addrs; // mi-go.zerotier.com - Singapore addrs.clear(); if (!id.fromString("abbb7f4622:0:89d2c6b2062b10f4ce314dfcb914c082566247090a6f74c8ba1c15c63b205f540758f0abae85287397152c9d8cf463cfe51e7a480946cd6a31495b24ca13253c")) throw std::runtime_error("invalid identity in Defaults"); - addrs.push_back(InetAddress("128.199.254.204",ZT_DEFAULT_UDP_PORT)); + addrs.push_back(InetAddress("128.199.254.204",ZT_DEFAULT_PORT)); sn[id] = addrs; // shoggoth.zerotier.com - Tokyo, Japan addrs.clear(); if (!id.fromString("48e8f875cb:0:5ca54f55e1094f65589f3e6d74158b6964d418ddac3570757128f1c6a2498322d92fcdcd47de459f4d1f9b38df2afd0c7b3fc247ba3d773c38ba35288f24988e")) throw std::runtime_error("invalid identity in Defaults"); - addrs.push_back(InetAddress("108.61.200.101",ZT_DEFAULT_UDP_PORT)); + addrs.push_back(InetAddress("108.61.200.101",ZT_DEFAULT_PORT)); sn[id] = addrs; return sn; diff --git a/node/IpcConnection.cpp b/node/IpcConnection.cpp index c6937004f..292403c09 100644 --- a/node/IpcConnection.cpp +++ b/node/IpcConnection.cpp @@ -156,7 +156,7 @@ void IpcConnection::threadMain() _writeLock.unlock(); } - _handler(_arg,this,IPC_EVENT_CONNECTION_CLOSING,(const char *)0); + _handler(_arg,this,IPC_EVENT_CONNECTION_CLOSED,(const char *)0); #endif } diff --git a/node/IpcListener.cpp b/node/IpcListener.cpp index dc5ef52aa..94cf065f9 100644 --- a/node/IpcListener.cpp +++ b/node/IpcListener.cpp @@ -124,7 +124,7 @@ void IpcListener::threadMain() break; } try { - _handler(_arg,new IpcConnection(s,_handler,_arg),Ipcconnection::IPC_EVENT_NEW_CONNECTION,(const char *)0); + _handler(_arg,new IpcConnection(s,_handler,_arg),IpcConnection::IPC_EVENT_NEW_CONNECTION,(const char *)0); } catch ( ... ) {} // handlers should not throw } #endif diff --git a/node/IpcListener.hpp b/node/IpcListener.hpp index 897c5451a..00a29b5d5 100644 --- a/node/IpcListener.hpp +++ b/node/IpcListener.hpp @@ -37,9 +37,9 @@ #include #ifdef __WINDOWS__ -#define ZT_IPC_ENDPOINT "\\\\.\\pipe\\ZeroTierOne-control" +#define ZT_IPC_ENDPOINT_BASE "\\\\.\\pipe\\ZeroTierOne-" #else -#define ZT_IPC_ENDPOINT "/tmp/.ZeroTierOne-control" +#define ZT_IPC_ENDPOINT_BASE "/tmp/.ZeroTierOne-" #endif namespace ZeroTier { @@ -78,7 +78,7 @@ public: private: std::string _endpoint; - void (*_handler)(void *,IpcConnection *,const char *); + void (*_handler)(void *,IpcConnection *,IpcConnection::EventType,const char *); void *_arg; volatile int _sock; Thread _thread; diff --git a/node/Node.cpp b/node/Node.cpp index ffd7568f6..a14168967 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -45,9 +45,7 @@ #include #include #include -#endif - -#ifdef __UNIX_LIKE__ +#else #include #include #include @@ -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 -{ - unsigned char key[32]; - int sock; - void (*resultHandler)(void *,unsigned long,const char *); - void *arg; - unsigned int controlPort; - InetAddress localDestAddr; - Mutex inUseLock; +// --------------------------------------------------------------------------- - void threadMain() - throw() - { - } +struct _NodeControlClientImpl +{ + void (*resultHandler)(void *,const char *); + void *arg; + IpcConnection *ipcc; + std::string err; }; -static void _CBlocalClientHandler(const SharedPtr &sock,void *arg,const InetAddress &from,Buffer &data) +static void _CBipcResultHandler(void *arg,IpcConnection *ipcc,IpcConnection::EventType event,const char *result) +{ + if ((event == IpcConnection::IPC_EVENT_COMMAND)&&(result)) + ((_NodeControlClientImpl *)arg)->resultHandler(((_NodeControlClientImpl *)arg)->arg,result); +} + +Node::NodeControlClient::NodeControlClient(const char *hp,void (*resultHandler)(void *,const char *),void *arg,const char *authToken) + throw() : + _impl((void *)new _NodeControlClientImpl) +{ + _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"; + } +} + +Node::NodeControlClient::~NodeControlClient() +{ + if (_impl) { + delete ((_NodeControlClientImpl *)_impl)->ipcc; + delete (_NodeControlClientImpl *)_impl; + } +} + +void Node::NodeControlClient::send(const char *command) + throw() { - _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 results; - if (!NodeConfig::decodeControlMessagePacket(impl->key,data.data(),data.size(),convId,results)) - return; - for(std::vector::iterator r(results.begin());r!=results.end();++r) - impl->resultHandler(impl->arg,convId,r->c_str()); + ((_NodeControlClientImpl *)_impl)->ipcc->printf("%s"ZT_EOL_S,command); } catch ( ... ) {} } -Node::LocalClient::LocalClient(const char *authToken,unsigned int controlPort,void (*resultHandler)(void *,unsigned long,const char *),void *arg) - throw() : - _impl((void *)0) -{ - _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; - } - } - - 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() -{ - if (_impl) { - ((_LocalClientImpl *)_impl)->inUseLock.lock(); - delete ((_LocalClientImpl *)_impl)->sock; - ((_LocalClientImpl *)_impl)->inUseLock.unlock(); - delete ((_LocalClientImpl *)_impl); - } -} - -unsigned long Node::LocalClient::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 tmp; - tmp.push_back(std::string(command)); - std::vector< Buffer > packets(NodeConfig::encodeControlMessage(impl->key,convId,tmp)); - - for(std::vector< Buffer >::iterator p(packets.begin());p!=packets.end();++p) - impl->sock->send(impl->localDestAddr,p->data(),p->size(),-1); - - return convId; - } catch ( ... ) { - return 0; - } -} - -std::vector Node::LocalClient::splitLine(const char *line) +std::vector 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::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 &fromSock,void *arg,const InetAddress &from,Buffer &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" diff --git a/node/Node.hpp b/node/Node.hpp index 18abdbb6e..a8b13003a 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -50,20 +50,28 @@ public: * otherwise it will be unable to open a local UDP socket to * communicate with the service. */ - class LocalClient + class NodeControlClient { public: /** * Create a new node config client * - * @param authToken Authentication token - * @param controlPort Control port or 0 for 39393 (default) + * Initialization may fail. Call error() to check. + * + * @param hp Home path of ZeroTier One instance * @param resultHandler Function to call when commands provide results + * @param arg First argument to result handler + * @param authToken Authentication token or NULL (default) to read from authtoken.secret in home path */ - LocalClient(const char *authToken,unsigned int controlPort,void (*resultHandler)(void *,unsigned long,const char *),void *arg) + NodeControlClient(const char *hp,void (*resultHandler)(void *,const char *),void *arg,const char *authToken = (const char *)0) throw(); - ~LocalClient(); + ~NodeControlClient(); + + /** + * @return Initialization error or NULL if none + */ + const char *error() const; /** * Send a command to the local node @@ -75,12 +83,13 @@ public: * @param command * @return Conversation ID that will be provided to result handler when/if results are sent back */ - unsigned long send(const char *command) + void send(const char *command) throw(); - inline unsigned long send(const std::string &command) throw() { return send(command.c_str()); } + inline void send(const std::string &command) + throw() { return send(command.c_str()); } /** - * Split a line of results by space + * Split a line of results * * @param line Line to split * @return Vector of fields @@ -89,19 +98,19 @@ public: static inline std::vector splitLine(const std::string &line) { return splitLine(line.c_str()); } /** - * @return Default path for user-local authorization token for the current user or empty string if cannot be determined + * @return Default path for current user's authtoken.secret */ - static std::string authTokenDefaultUserPath(); + static const char *authTokenDefaultUserPath(); /** - * @return Default system path for auth token on this platform + * @return Default path to system authtoken.secret */ - static std::string authTokenDefaultSystemPath(); + static const char *authTokenDefaultSystemPath(); private: - // LocalClient is not copyable - LocalClient(const LocalClient&); - const LocalClient& operator=(const LocalClient&); + // NodeControlClient is not copyable + NodeControlClient(const NodeControlClient&); + const NodeControlClient& operator=(const NodeControlClient&); void *_impl; }; @@ -129,7 +138,12 @@ public: /** * A serious unrecoverable error has occurred. */ - NODE_UNRECOVERABLE_ERROR = 3 + NODE_UNRECOVERABLE_ERROR = 3, + + /** + * An address collision occurred (typically this should cause re-invocation with resetIdentity set to true) + */ + NODE_ADDRESS_COLLISION = 4 }; /** @@ -137,11 +151,12 @@ public: * * The node is not executed until run() is called. * - * @param hp Home directory path - * @param port Port to bind for talking to the ZT1 network or 0 for 9993 (default) - * @param controlPort Port to bind locally for control packets or 0 for 39393 (default) + * @param hp Home directory path or NULL for system-wide default for this platform (default: NULL) + * @param udpPort UDP port or 0 for default (9993) (default: 0) + * @param tcpPort TCP port or 0 for default (9993) (default: 0) + * @param resetIdentity If true, delete identity before starting and regenerate (default: false) */ - Node(const char *hp,unsigned int port,unsigned int controlPort) + Node(const char *hp = (const char *)0,unsigned int udpPort = 0,unsigned int tcpPort = 0,bool resetIdentity = false) throw(); ~Node(); @@ -181,19 +196,12 @@ public: throw(); /** - * Forget p2p links and resynchronize with peers + * Forget p2p links now and resynchronize with peers */ void resync() throw(); - /** - * Get the ZeroTier version in major.minor.revision string format - * - * @return Version in string form - */ - static const char *versionString() - throw(); - + static const char *versionString() throw(); static unsigned int versionMajor() throw(); static unsigned int versionMinor() throw(); static unsigned int versionRevision() throw(); @@ -208,17 +216,4 @@ private: } // namespace ZeroTier -extern "C" { - -// Functions with C-style linkage for easy DLL symbol table -// lookup. These just create instances of Node and LocalClient. - -ZeroTier::Node *zeroTierCreateNode(const char *hp,unsigned int port,unsigned int controlPort); -void zeroTierDeleteNode(ZeroTier::Node *n); - -ZeroTier::Node::LocalClient *zeroTierCreateLocalClient(const char *authToken,unsigned int controlPort,void (*resultHandler)(void *,unsigned long,const char *),void *arg); -void zeroTierDeleteLocalClient(ZeroTier::Node::LocalClient *lc); - -} // extern "C" - #endif diff --git a/node/NodeConfig.cpp b/node/NodeConfig.cpp index 48782efa4..07fa8b25c 100644 --- a/node/NodeConfig.cpp +++ b/node/NodeConfig.cpp @@ -53,7 +53,7 @@ namespace ZeroTier { NodeConfig::NodeConfig(const RuntimeEnvironment *renv,const char *authToken) : _r(renv), - _ipcListener(ZT_IPC_ENDPOINT,&_CBcommandHandler,this), + _ipcListener((std::string(ZT_IPC_ENDPOINT_BASE) + renv->identity.address().toString()).c_str(),&_CBcommandHandler,this), _authToken(authToken) { { @@ -177,8 +177,8 @@ public: void NodeConfig::_doCommand(IpcConnection *ipcc,const char *commandLine) { - if (!commandLine) - return; // sanity check + if ((!commandLine)||(!commandLine[0])) + return; std::vector r; std::vector cmd(Utils::split(commandLine,"\r\n \t","\\","'")); diff --git a/node/PacketDecoder.cpp b/node/PacketDecoder.cpp index 061c20f30..59a4ee568 100644 --- a/node/PacketDecoder.cpp +++ b/node/PacketDecoder.cpp @@ -40,7 +40,6 @@ #include "Peer.hpp" #include "NodeConfig.hpp" #include "Service.hpp" -#include "Demarc.hpp" #include "SoftwareUpdater.hpp" namespace ZeroTier { @@ -82,7 +81,7 @@ bool PacketDecoder::tryDecode(const RuntimeEnvironment *_r) switch(verb()) { case Packet::VERB_NOP: - peer->onReceive(_r,_localPort,_remoteAddress,hops(),packetId(),Packet::VERB_NOP,0,Packet::VERB_NOP,Utils::now()); + peer->onReceive(_r,_remoteAddress,hops(),packetId(),Packet::VERB_NOP,0,Packet::VERB_NOP,Utils::now()); return true; case Packet::VERB_HELLO: return _doHELLO(_r); // legal, but why? :) @@ -156,7 +155,7 @@ bool PacketDecoder::_doERROR(const RuntimeEnvironment *_r,const SharedPtr break; } - peer->onReceive(_r,_localPort,_remoteAddress,hops(),packetId(),Packet::VERB_ERROR,inRePacketId,inReVerb,Utils::now()); + peer->onReceive(_r,_remoteAddress,hops(),packetId(),Packet::VERB_ERROR,inRePacketId,inReVerb,Utils::now()); } catch (std::exception &ex) { TRACE("dropped ERROR from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),ex.what()); } catch ( ... ) { @@ -200,7 +199,7 @@ bool PacketDecoder::_doHELLO(const RuntimeEnvironment *_r) outp.append(packetId()); outp.append((unsigned char)Packet::ERROR_IDENTITY_COLLISION); outp.armor(key,true); - _r->demarc->send(_localPort,_remoteAddress,outp.data(),outp.size(),-1); + _fromSock->send(_remoteAddress,outp.data(),outp.size()); } else { LOG("rejected HELLO from %s(%s): packet failed authentication",source().toString().c_str(),_remoteAddress.toString().c_str()); } @@ -227,7 +226,7 @@ bool PacketDecoder::_doHELLO(const RuntimeEnvironment *_r) outp.append(packetId()); outp.append((unsigned char)Packet::ERROR_IDENTITY_COLLISION); outp.armor(key,true); - _r->demarc->send(_localPort,_remoteAddress,outp.data(),outp.size(),-1); + _fromSock->send(_remoteAddress,outp.data(),outp.size()); } else { LOG("rejected HELLO from %s(%s): packet failed authentication",source().toString().c_str(),_remoteAddress.toString().c_str()); } @@ -246,7 +245,7 @@ bool PacketDecoder::_doHELLO(const RuntimeEnvironment *_r) peer = _r->topology->addPeer(newPeer); } - peer->onReceive(_r,_localPort,_remoteAddress,hops(),packetId(),Packet::VERB_HELLO,0,Packet::VERB_NOP,Utils::now()); + peer->onReceive(_r,_remoteAddress,hops(),packetId(),Packet::VERB_HELLO,0,Packet::VERB_NOP,Utils::now()); peer->setRemoteVersion(vMajor,vMinor,vRevision); // If a supernode has a version higher than ours, this causes a software @@ -263,7 +262,7 @@ bool PacketDecoder::_doHELLO(const RuntimeEnvironment *_r) outp.append((unsigned char)ZEROTIER_ONE_VERSION_MINOR); outp.append((uint16_t)ZEROTIER_ONE_VERSION_REVISION); outp.armor(peer->key(),true); - _r->demarc->send(_localPort,_remoteAddress,outp.data(),outp.size(),-1); + _fromSock->send(_remoteAddress,outp.data(),outp.size()); } catch (std::exception &ex) { TRACE("dropped HELLO from %s(%s): %s",source().toString().c_str(),_remoteAddress.toString().c_str(),ex.what()); } catch ( ... ) { @@ -324,7 +323,7 @@ bool PacketDecoder::_doOK(const RuntimeEnvironment *_r,const SharedPtr &pe break; } - peer->onReceive(_r,_localPort,_remoteAddress,hops(),packetId(),Packet::VERB_OK,inRePacketId,inReVerb,Utils::now()); + peer->onReceive(_r,_remoteAddress,hops(),packetId(),Packet::VERB_OK,inRePacketId,inReVerb,Utils::now()); } catch (std::exception &ex) { TRACE("dropped OK from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),ex.what()); } catch ( ... ) { @@ -343,7 +342,7 @@ bool PacketDecoder::_doWHOIS(const RuntimeEnvironment *_r,const SharedPtr outp.append(packetId()); id.serialize(outp,false); outp.armor(peer->key(),true); - _r->demarc->send(_localPort,_remoteAddress,outp.data(),outp.size(),-1); + _fromSock->send(_remoteAddress,outp.data(),outp.size()); //TRACE("sent WHOIS response to %s for %s",source().toString().c_str(),Address(payload(),ZT_ADDRESS_LENGTH).toString().c_str()); } else { Packet outp(source(),_r->identity.address(),Packet::VERB_ERROR); @@ -352,13 +351,13 @@ bool PacketDecoder::_doWHOIS(const RuntimeEnvironment *_r,const SharedPtr outp.append((unsigned char)Packet::ERROR_OBJ_NOT_FOUND); outp.append(payload(),ZT_ADDRESS_LENGTH); outp.armor(peer->key(),true); - _r->demarc->send(_localPort,_remoteAddress,outp.data(),outp.size(),-1); + _fromSock->send(_remoteAddress,outp.data(),outp.size()); //TRACE("sent WHOIS ERROR to %s for %s (not found)",source().toString().c_str(),Address(payload(),ZT_ADDRESS_LENGTH).toString().c_str()); } } else { TRACE("dropped WHOIS from %s(%s): missing or invalid address",source().toString().c_str(),_remoteAddress.toString().c_str()); } - peer->onReceive(_r,_localPort,_remoteAddress,hops(),packetId(),Packet::VERB_WHOIS,0,Packet::VERB_NOP,Utils::now()); + peer->onReceive(_r,_remoteAddress,hops(),packetId(),Packet::VERB_WHOIS,0,Packet::VERB_NOP,Utils::now()); return true; } @@ -387,7 +386,7 @@ bool PacketDecoder::_doRENDEZVOUS(const RuntimeEnvironment *_r,const SharedPtr

0)&&((addrlen == 4)||(addrlen == 16))) { InetAddress atAddr(field(ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRESS,addrlen),addrlen,port); TRACE("RENDEZVOUS from %s says %s might be at %s, starting NAT-t",source().toString().c_str(),with.toString().c_str(),atAddr.toString().c_str()); - peer->onReceive(_r,_localPort,_remoteAddress,hops(),packetId(),Packet::VERB_RENDEZVOUS,0,Packet::VERB_NOP,Utils::now()); + peer->onReceive(_r,_remoteAddress,hops(),packetId(),Packet::VERB_RENDEZVOUS,0,Packet::VERB_NOP,Utils::now()); _r->sw->contact(withPeer,atAddr); } else { TRACE("dropped corrupt RENDEZVOUS from %s(%s) (bad address or port)",source().toString().c_str(),_remoteAddress.toString().c_str()); @@ -426,7 +425,7 @@ bool PacketDecoder::_doFRAME(const RuntimeEnvironment *_r,const SharedPtr // we receive unicast frames from it. This is called "implicit social // ordering" in other docs. _r->mc->bringCloser(network->id(),source()); - peer->onReceive(_r,_localPort,_remoteAddress,hops(),packetId(),Packet::VERB_FRAME,0,Packet::VERB_NOP,Utils::now()); + peer->onReceive(_r,_remoteAddress,hops(),packetId(),Packet::VERB_FRAME,0,Packet::VERB_NOP,Utils::now()); } else { TRACE("dropped FRAME from %s(%s): sender not a member of closed network %.16llx",source().toString().c_str(),_remoteAddress.toString().c_str(),network->id()); @@ -436,7 +435,7 @@ bool PacketDecoder::_doFRAME(const RuntimeEnvironment *_r,const SharedPtr outp.append((unsigned char)Packet::ERROR_NEED_MEMBERSHIP_CERTIFICATE); outp.append(network->id()); outp.armor(peer->key(),true); - _r->demarc->send(_localPort,_remoteAddress,outp.data(),outp.size(),-1); + _fromSock->send(_remoteAddress,outp.data(),outp.size()); return true; } @@ -569,11 +568,11 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared source().toString().c_str(), frameLen, startingFifoItems); - _r->demarc->send(Demarc::ANY_PORT,ZT_DEFAULTS.multicastTraceWatcher,mct,strlen(mct),-1); + _r->sm->send(ZT_DEFAULTS.multicastTraceWatcher,false,mct,strlen(mct)); #endif // At this point the frame is basically valid, so we can call it a receive - peer->onReceive(_r,_localPort,_remoteAddress,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,Utils::now()); + peer->onReceive(_r,_remoteAddress,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,Utils::now()); // This gets updated later in most cases but start with the global limit. unsigned int maxDepth = ZT_MULTICAST_GLOBAL_MAX_DEPTH; @@ -592,7 +591,7 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared mctdepth, (_r->topology->amSupernode() ? 'S' : '-'), _r->identity.address().toString().c_str()); - _r->demarc->send(Demarc::ANY_PORT,ZT_DEFAULTS.multicastTraceWatcher,mct,strlen(mct),-1); + _r->sm->send(ZT_DEFAULTS.multicastTraceWatcher,false,mct,strlen(mct)); #endif TRACE("dropped MULTICAST_FRAME from %s(%s): duplicate",source().toString().c_str(),_remoteAddress.toString().c_str()); return true; @@ -619,7 +618,7 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared outp.append((unsigned char)Packet::ERROR_NEED_MEMBERSHIP_CERTIFICATE); outp.append(nwid); outp.armor(peer->key(),true); - _r->demarc->send(_localPort,_remoteAddress,outp.data(),outp.size(),-1); + _fromSock->send(_remoteAddress,outp.data(),outp.size()); // We do not terminate here, since if the member just has an out of // date cert or hasn't sent us a cert yet we still want to propagate @@ -638,7 +637,7 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared mctdepth, (_r->topology->amSupernode() ? 'S' : '-'), _r->identity.address().toString().c_str()); - _r->demarc->send(Demarc::ANY_PORT,ZT_DEFAULTS.multicastTraceWatcher,mct,strlen(mct),-1); + _r->sm->send(ZT_DEFAULTS.multicastTraceWatcher,false,mct,strlen(mct)); #endif TRACE("dropped MULTICAST_FRAME from %s(%s) into %.16llx: source mac %s doesn't belong to %s, and bridging is not supported on network",source().toString().c_str(),_remoteAddress.toString().c_str(),nwid,sourceMac.toString().c_str(),origin.toString().c_str()); return true; @@ -654,7 +653,7 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared mctdepth, (_r->topology->amSupernode() ? 'S' : '-'), _r->identity.address().toString().c_str()); - _r->demarc->send(Demarc::ANY_PORT,ZT_DEFAULTS.multicastTraceWatcher,mct,strlen(mct),-1); + _r->sm->send(ZT_DEFAULTS.multicastTraceWatcher,false,mct,strlen(mct)); #endif TRACE("dropped MULTICAST_FRAME from %s(%s) into %.16llx: ethertype %u is not allowed",source().toString().c_str(),nwid,_remoteAddress.toString().c_str(),etherType); return true; @@ -671,7 +670,7 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared mctdepth, (_r->topology->amSupernode() ? 'S' : '-'), _r->identity.address().toString().c_str()); - _r->demarc->send(Demarc::ANY_PORT,ZT_DEFAULTS.multicastTraceWatcher,mct,strlen(mct),-1); + _r->sm->send(ZT_DEFAULTS.multicastTraceWatcher,false,mct,strlen(mct)); #endif TRACE("dropped MULTICAST_FRAME from %s(%s): rate limits exceeded for sender %s",source().toString().c_str(),_remoteAddress.toString().c_str(),origin.toString().c_str()); return true; @@ -692,7 +691,7 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared mctdepth, (_r->topology->amSupernode() ? 'S' : '-'), _r->identity.address().toString().c_str()); - _r->demarc->send(Demarc::ANY_PORT,ZT_DEFAULTS.multicastTraceWatcher,mct,strlen(mct),-1); + _r->sm->send(ZT_DEFAULTS.multicastTraceWatcher,false,mct,strlen(mct)); #endif TRACE("not forwarding MULTICAST_FRAME from %s(%s): depth == 0xffff (do not forward)",source().toString().c_str(),_remoteAddress.toString().c_str()); return true; @@ -707,7 +706,7 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared mctdepth, (_r->topology->amSupernode() ? 'S' : '-'), _r->identity.address().toString().c_str()); - _r->demarc->send(Demarc::ANY_PORT,ZT_DEFAULTS.multicastTraceWatcher,mct,strlen(mct),-1); + _r->sm->send(ZT_DEFAULTS.multicastTraceWatcher,false,mct,strlen(mct)); #endif TRACE("not forwarding MULTICAST_FRAME from %s(%s): max propagation depth reached",source().toString().c_str(),_remoteAddress.toString().c_str()); return true; @@ -766,7 +765,7 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared mctdepth, (_r->topology->amSupernode() ? 'S' : '-'), _r->identity.address().toString().c_str()); - _r->demarc->send(Demarc::ANY_PORT,ZT_DEFAULTS.multicastTraceWatcher,mct,strlen(mct),-1); + _r->sm->send(ZT_DEFAULTS.multicastTraceWatcher,false,mct,strlen(mct)); #endif //TRACE("not forwarding MULTICAST_FRAME from %s(%s): no next hop",source().toString().c_str(),_remoteAddress.toString().c_str()); return true; @@ -787,7 +786,7 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared origin.toString().c_str(), nextHop.toString().c_str(), numAdded); - _r->demarc->send(Demarc::ANY_PORT,ZT_DEFAULTS.multicastTraceWatcher,mct,strlen(mct),-1); + _r->sm->send(ZT_DEFAULTS.multicastTraceWatcher,false,mct,strlen(mct)); #endif // Send to next hop, reusing this packet as scratch space @@ -824,7 +823,7 @@ bool PacketDecoder::_doMULTICAST_LIKE(const RuntimeEnvironment *_r,const SharedP } } - peer->onReceive(_r,_localPort,_remoteAddress,hops(),packetId(),Packet::VERB_MULTICAST_LIKE,0,Packet::VERB_NOP,now); + peer->onReceive(_r,_remoteAddress,hops(),packetId(),Packet::VERB_MULTICAST_LIKE,0,Packet::VERB_NOP,now); } catch (std::exception &ex) { TRACE("dropped MULTICAST_LIKE from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),ex.what()); } catch ( ... ) { @@ -860,7 +859,7 @@ bool PacketDecoder::_doNETWORK_MEMBERSHIP_CERTIFICATE(const RuntimeEnvironment * } } - peer->onReceive(_r,_localPort,_remoteAddress,hops(),packetId(),Packet::VERB_NETWORK_MEMBERSHIP_CERTIFICATE,0,Packet::VERB_NOP,Utils::now()); + peer->onReceive(_r,_remoteAddress,hops(),packetId(),Packet::VERB_NETWORK_MEMBERSHIP_CERTIFICATE,0,Packet::VERB_NOP,Utils::now()); } catch (std::exception &ex) { TRACE("dropped NETWORK_MEMBERSHIP_CERTIFICATE from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),ex.what()); } catch ( ... ) { @@ -899,11 +898,11 @@ bool PacketDecoder::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *_r,const outp.append((unsigned char)Packet::ERROR_UNSUPPORTED_OPERATION); outp.append(nwid); outp.armor(peer->key(),true); - _r->demarc->send(_localPort,_remoteAddress,outp.data(),outp.size(),-1); + _fromSock->send(_remoteAddress,outp.data(),outp.size()); #ifndef __WINDOWS__ } #endif // !__WINDOWS__ - peer->onReceive(_r,_localPort,_remoteAddress,hops(),packetId(),Packet::VERB_NETWORK_CONFIG_REQUEST,0,Packet::VERB_NOP,Utils::now()); + peer->onReceive(_r,_remoteAddress,hops(),packetId(),Packet::VERB_NETWORK_CONFIG_REQUEST,0,Packet::VERB_NOP,Utils::now()); } catch (std::exception &exc) { TRACE("dropped NETWORK_CONFIG_REQUEST from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),exc.what()); } catch ( ... ) { @@ -924,7 +923,7 @@ bool PacketDecoder::_doNETWORK_CONFIG_REFRESH(const RuntimeEnvironment *_r,const nw->requestConfiguration(); } } - peer->onReceive(_r,_localPort,_remoteAddress,hops(),packetId(),Packet::VERB_NETWORK_CONFIG_REFRESH,0,Packet::VERB_NOP,Utils::now()); + peer->onReceive(_r,_remoteAddress,hops(),packetId(),Packet::VERB_NETWORK_CONFIG_REFRESH,0,Packet::VERB_NOP,Utils::now()); } catch (std::exception &exc) { TRACE("dropped NETWORK_CONFIG_REFRESH from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),exc.what()); } catch ( ... ) { diff --git a/node/PacketDecoder.hpp b/node/PacketDecoder.hpp index 26aa85ce0..9552c7fe1 100644 --- a/node/PacketDecoder.hpp +++ b/node/PacketDecoder.hpp @@ -37,6 +37,7 @@ #include "SharedPtr.hpp" #include "AtomicCounter.hpp" #include "Peer.hpp" +#include "Socket.hpp" /* * The big picture: @@ -70,16 +71,16 @@ public: * Create a new packet-in-decode * * @param b Source buffer with raw packet data - * @param localPort Local port on which packet was received + * @param fromSock Socket on which packet was received * @param remoteAddress Address from which packet came * @throws std::out_of_range Range error processing packet */ template - PacketDecoder(const Buffer &b,Demarc::Port localPort,const InetAddress &remoteAddress) + PacketDecoder(const Buffer &b,const SharedPtr &fromSock,const InetAddress &remoteAddress) throw(std::out_of_range) : Packet(b), _receiveTime(Utils::now()), - _localPort(localPort), + _fromSock(fromSock), _remoteAddress(remoteAddress), _step(DECODE_WAITING_FOR_SENDER_LOOKUP), __refCount() @@ -124,7 +125,7 @@ private: bool _doNETWORK_CONFIG_REFRESH(const RuntimeEnvironment *_r,const SharedPtr &peer); uint64_t _receiveTime; - Demarc::Port _localPort; + SharedPtr _fromSock; InetAddress _remoteAddress; enum { diff --git a/node/Peer.cpp b/node/Peer.cpp index bd2e7e43f..6bfa5b1d3 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -67,7 +67,6 @@ Peer::Peer(const Identity &myIdentity,const Identity &peerIdentity) void Peer::onReceive( const RuntimeEnvironment *_r, - Demarc::Port localPort, const InetAddress &remoteAddr, unsigned int hops, uint64_t packetId, @@ -80,7 +79,6 @@ void Peer::onReceive( // Update last receive info for our direct path WanPath *const wp = (remoteAddr.isV4() ? &_ipv4p : &_ipv6p); wp->lastReceive = now; - wp->localPort = ((localPort) ? localPort : Demarc::ANY_PORT); if (!wp->fixed) wp->addr = remoteAddr; @@ -101,14 +99,14 @@ void Peer::onReceive( bool Peer::send(const RuntimeEnvironment *_r,const void *data,unsigned int len,uint64_t now) { if ((_ipv6p.isActive(now))||((!(_ipv4p.addr))&&(_ipv6p.addr))) { - if (_r->demarc->send(_ipv6p.addr,data,len,-1)) { + if (_r->sm->send(_ipv6p.addr,false,data,len)) { _ipv6p.lastSend = now; return true; } } if (_ipv4p.addr) { - if (_r->sm->send(_ipv4p.addr,data,len,-1)) { + if (_r->sm->send(_ipv4p.addr,false,data,len)) { _ipv4p.lastSend = now; return true; } @@ -121,14 +119,14 @@ bool Peer::sendFirewallOpener(const RuntimeEnvironment *_r,uint64_t now) { bool sent = false; if (_ipv4p.addr) { - if (_r->demarc->send(_ipv4p.localPort,_ipv4p.addr,"\0",1,ZT_FIREWALL_OPENER_HOPS)) { + if (_r->sm->sendFirewallOpener(_ipv4p.addr,ZT_FIREWALL_OPENER_HOPS)) { _ipv4p.lastFirewallOpener = now; sent = true; } } if (_ipv6p.addr) { - if (_r->demarc->send(_ipv6p.localPort,_ipv6p.addr,"\0",1,ZT_FIREWALL_OPENER_HOPS)) { + if (_r->sm->sendFirewallOpener(_ipv6p.addr,ZT_FIREWALL_OPENER_HOPS)) { _ipv6p.lastFirewallOpener = now; sent = true; } @@ -142,7 +140,7 @@ bool Peer::sendPing(const RuntimeEnvironment *_r,uint64_t now) bool sent = false; if (_ipv4p.addr) { TRACE("PING %s(%s)",_id.address().toString().c_str(),_ipv4p.addr.toString().c_str()); - if (_r->sw->sendHELLO(SharedPtr(this),_ipv4p.localPort,_ipv4p.addr)) { + if (_r->sw->sendHELLO(SharedPtr(this),_ipv4p.addr,false)) { _ipv4p.lastSend = now; sent = true; } @@ -150,7 +148,7 @@ bool Peer::sendPing(const RuntimeEnvironment *_r,uint64_t now) if (_ipv6p.addr) { TRACE("PING %s(%s)",_id.address().toString().c_str(),_ipv6p.addr.toString().c_str()); - if (_r->sw->sendHELLO(SharedPtr(this),_ipv6p.localPort,_ipv6p.addr)) { + if (_r->sw->sendHELLO(SharedPtr(this),_ipv6p.addr,false)) { _ipv6p.lastSend = now; sent = true; } diff --git a/node/SocketManager.cpp b/node/SocketManager.cpp index 5dbbf6d7a..2c583f09d 100644 --- a/node/SocketManager.cpp +++ b/node/SocketManager.cpp @@ -427,7 +427,7 @@ void SocketManager::poll(unsigned long timeout) ts.reserve(_tcpSockets.size()); uint64_t now = Utils::now(); for(std::map< InetAddress,SharedPtr >::iterator s(_tcpSockets.begin());s!=_tcpSockets.end();) { - if ((now - ((TcpSocket *)s->second.get())->_lastActivity) < ZT_TCP_TUNNEL_ACTIVITY_TIMEOUT) { + if ((now - ((TcpSocket *)s->second.ptr())->_lastActivity) < ZT_TCP_TUNNEL_ACTIVITY_TIMEOUT) { ts.push_back(s->second); ++s; } else { diff --git a/node/Switch.cpp b/node/Switch.cpp index 301601100..a59473b7d 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -47,7 +47,6 @@ #include "RuntimeEnvironment.hpp" #include "Peer.hpp" #include "NodeConfig.hpp" -#include "Demarc.hpp" #include "CMWC4096.hpp" #include "../version.h" @@ -64,14 +63,14 @@ Switch::~Switch() { } -void Switch::onRemotePacket(Demarc::Port localPort,const InetAddress &fromAddr,const Buffer<4096> &data) +void Switch::onRemotePacket(const SharedPtr &fromSock,const InetAddress &fromAddr,Buffer &data) { try { if (data.size() > ZT_PROTO_MIN_FRAGMENT_LENGTH) { if (data[ZT_PACKET_FRAGMENT_IDX_FRAGMENT_INDICATOR] == ZT_PACKET_FRAGMENT_INDICATOR) - _handleRemotePacketFragment(localPort,fromAddr,data); + _handleRemotePacketFragment(fromSock,fromAddr,data); else if (data.size() >= ZT_PROTO_MIN_PACKET_LENGTH) - _handleRemotePacketHead(localPort,fromAddr,data); + _handleRemotePacketHead(fromSock,fromAddr,data); } } catch (std::exception &ex) { TRACE("dropped packet from %s: unexpected exception: %s",fromAddr.toString().c_str(),ex.what()); @@ -207,7 +206,7 @@ void Switch::sendHELLO(const Address &dest) send(outp,false); } -bool Switch::sendHELLO(const SharedPtr &dest,Demarc::Port localPort,const InetAddress &remoteAddr) +bool Switch::sendHELLO(const SharedPtr &fromSock,const SharedPtr &dest,const InetAddress &remoteAddr) { uint64_t now = Utils::now(); Packet outp(dest->address(),_r->identity.address(),Packet::VERB_HELLO); @@ -218,7 +217,21 @@ bool Switch::sendHELLO(const SharedPtr &dest,Demarc::Port localPort,const outp.append(now); _r->identity.serialize(outp,false); outp.armor(dest->key(),false); - return (_r->demarc->send(localPort,remoteAddr,outp.data(),outp.size(),-1) != Demarc::NULL_PORT); + return fromSock->send(remoteAddr,outp.data(),outp.size()); +} + +bool Switch::sendHELLO(const SharedPtr &dest,const InetAddress &remoteAddr,bool tcp) +{ + uint64_t now = Utils::now(); + Packet outp(dest->address(),_r->identity.address(),Packet::VERB_HELLO); + outp.append((unsigned char)ZT_PROTO_VERSION); + outp.append((unsigned char)ZEROTIER_ONE_VERSION_MAJOR); + outp.append((unsigned char)ZEROTIER_ONE_VERSION_MINOR); + outp.append((uint16_t)ZEROTIER_ONE_VERSION_REVISION); + outp.append(now); + _r->identity.serialize(outp,false); + outp.armor(dest->key(),false); + return _r->sm->send(remoteAddr,tcp,outp.data(),outp.size()); } bool Switch::unite(const Address &p1,const Address &p2,bool force) @@ -311,12 +324,11 @@ bool Switch::unite(const Address &p1,const Address &p2,bool force) void Switch::contact(const SharedPtr &peer,const InetAddress &atAddr) { - Demarc::Port fromPort = _r->demarc->pick(atAddr); - _r->demarc->send(fromPort,atAddr,"\0",1,ZT_FIREWALL_OPENER_HOPS); + _r->sm->sendFirewallOpener(atAddr,ZT_FIREWALL_OPENER_HOPS); { Mutex::Lock _l(_contactQueue_m); - _contactQueue.push_back(ContactQueueEntry(peer,Utils::now() + ZT_RENDEZVOUS_NAT_T_DELAY,fromPort,atAddr)); + _contactQueue.push_back(ContactQueueEntry(peer,Utils::now() + ZT_RENDEZVOUS_NAT_T_DELAY,atAddr)); } // Kick main loop out of wait so that it can pick up this @@ -334,7 +346,7 @@ unsigned long Switch::doTimerTasks() for(std::list::iterator qi(_contactQueue.begin());qi!=_contactQueue.end();) { if (now >= qi->fireAtTime) { TRACE("sending NAT-T HELLO to %s(%s)",qi->peer->address().toString().c_str(),qi->inaddr.toString().c_str()); - sendHELLO(qi->peer,qi->localPort,qi->inaddr); + sendHELLO(qi->peer,qi->inaddr,false); _contactQueue.erase(qi++); } else { nextDelay = std::min(nextDelay,(unsigned long)(qi->fireAtTime - now)); @@ -529,7 +541,7 @@ const char *Switch::etherTypeName(const unsigned int etherType) return "UNKNOWN"; } -void Switch::_handleRemotePacketFragment(Demarc::Port localPort,const InetAddress &fromAddr,const Buffer<4096> &data) +void Switch::_handleRemotePacketFragment(const SharedPtr &fromSock,const InetAddress &fromAddr,const Buffer<4096> &data) { Packet::Fragment fragment(data); Address destination(fragment.destination()); @@ -598,9 +610,9 @@ void Switch::_handleRemotePacketFragment(Demarc::Port localPort,const InetAddres } } -void Switch::_handleRemotePacketHead(Demarc::Port localPort,const InetAddress &fromAddr,const Buffer<4096> &data) +void Switch::_handleRemotePacketHead(const SharedPtr &fromSock,const InetAddress &fromAddr,const Buffer<4096> &data) { - SharedPtr packet(new PacketDecoder(data,localPort,fromAddr)); + SharedPtr packet(new PacketDecoder(data,fromSock,fromAddr)); Address source(packet->source()); Address destination(packet->destination()); @@ -711,8 +723,7 @@ bool Switch::_trySend(const Packet &packet,bool encrypt) tmp.armor(peer->key(),encrypt); - Demarc::Port localPort; - if ((localPort = via->send(_r,tmp.data(),chunkSize,now))) { + if (via->send(_r,tmp.data(),chunkSize,now)) { if (chunkSize < tmp.size()) { // Too big for one bite, fragment the rest unsigned int fragStart = chunkSize; diff --git a/node/Switch.hpp b/node/Switch.hpp index ca55ae945..fd5837b7a 100644 --- a/node/Switch.hpp +++ b/node/Switch.hpp @@ -44,9 +44,9 @@ #include "Array.hpp" #include "Network.hpp" #include "SharedPtr.hpp" -#include "SocketManager.hpp" #include "Multicaster.hpp" #include "PacketDecoder.hpp" +#include "Socket.hpp" /* Ethernet frame types that might be relevant to us */ #define ZT_ETHERTYPE_IPV4 0x0800 @@ -78,11 +78,11 @@ public: /** * Called when a packet is received from the real network * - * @param localPort Local port on which packet was received + * @param fromSock Originating socket * @param fromAddr Internet IP address of origin * @param data Packet data */ - void onRemotePacket(Demarc::Port localPort,const InetAddress &fromAddr,const Buffer<4096> &data); + void onRemotePacket(const SharedPtr &fromSock,const InetAddress &fromAddr,Buffer &data); /** * Called when a packet comes from a local Ethernet tap @@ -122,12 +122,22 @@ public: /** * Send a HELLO announcement immediately to the indicated address * - * @param localPort Originating local port or ANY_PORT to pick - * @param remoteAddr IP address to send to + * @param fromSock Send from this local socket * @param dest Destination peer + * @param remoteAddr Remote address * @return True if send appears successful */ - bool sendHELLO(const SharedPtr &dest,Demarc::Port localPort,const InetAddress &remoteAddr); + bool sendHELLO(const SharedPtr &fromSock,const SharedPtr &dest,const InetAddress &remoteAddr); + + /** + * Send a HELLO announcement immediately to the indicated address + * + * @param dest Destination peer + * @param remoteAddr Remote address + * @param tcp Attempt to use TCP? + * @return True if send appears successful + */ + bool sendHELLO(const SharedPtr &dest,const InetAddress &remoteAddr,bool tcp); /** * Send RENDEZVOUS to two peers to permit them to directly connect @@ -214,12 +224,12 @@ public: private: void _handleRemotePacketFragment( - Demarc::Port localPort, + const SharedPtr &fromSock, const InetAddress &fromAddr, const Buffer<4096> &data); void _handleRemotePacketHead( - Demarc::Port localPort, + const SharedPtr &fromSock, const InetAddress &fromAddr, const Buffer<4096> &data); @@ -279,15 +289,13 @@ private: struct ContactQueueEntry { ContactQueueEntry() {} - ContactQueueEntry(const SharedPtr &p,uint64_t ft,Demarc::Port lp,const InetAddress &a) : + ContactQueueEntry(const SharedPtr &p,uint64_t ft,const InetAddress &a) : peer(p), fireAtTime(ft), - localPort(lp), inaddr(a) {} SharedPtr peer; uint64_t fireAtTime; - Demarc::Port localPort; InetAddress inaddr; }; std::list _contactQueue; diff --git a/selftest.cpp b/selftest.cpp index 0e89a53b5..4991aef7c 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -44,7 +44,6 @@ #include "node/Salsa20.hpp" #include "node/MAC.hpp" #include "node/Peer.hpp" -#include "node/Condition.hpp" #include "node/NodeConfig.hpp" #include "node/Dictionary.hpp" #include "node/EthernetTap.hpp" @@ -66,7 +65,7 @@ using namespace ZeroTier; static unsigned char fuzzbuf[1048576]; -static Condition webDoneCondition; +static volatile bool webDone = false; static std::string webSha512ShouldBe; static void testHttpHandler(void *arg,int code,const std::string &url,bool onDisk,const std::string &body) { @@ -77,45 +76,52 @@ static void testHttpHandler(void *arg,int code,const std::string &url,bool onDis std::cout << "got " << body.length() << " bytes, response code " << code << ", SHA-512 OK" << std::endl; else std::cout << "got " << body.length() << " bytes, response code " << code << ", SHA-512 FAILED!" << std::endl; } else std::cout << "ERROR " << code << ": " << body << std::endl; - webDoneCondition.signal(); + webDone = true; } static int testHttp() { webSha512ShouldBe = "221b348c8278ad2063c158fb15927c35dc6bb42880daf130d0574025f88ec350811c34fae38a014b576d3ef5c98af32bb540e68204810db87a51fa9b239ea567"; std::cout << "[http] fetching http://download.zerotier.com/dev/1k ... "; std::cout.flush(); + webDone = false; HttpClient::GET("http://download.zerotier.com/dev/1k",HttpClient::NO_HEADERS,30,&testHttpHandler,(void *)0); - webDoneCondition.wait(); + while (!webDone) Thread::sleep(500); webSha512ShouldBe = "342e1a058332aad2d7a5412c1d9cd4ad02b4038178ca0c3ed9d34e3cf0905c118b684e5d2a935a158195d453d7d69e9c6e201e252620fb53f29611794a5d4b0c"; std::cout << "[http] fetching http://download.zerotier.com/dev/2k ... "; std::cout.flush(); + webDone = false; HttpClient::GET("http://download.zerotier.com/dev/2k",HttpClient::NO_HEADERS,30,&testHttpHandler,(void *)0); - webDoneCondition.wait(); + while (!webDone) Thread::sleep(500); webSha512ShouldBe = "439562e1471dd6bdb558cb680f38dd7742e521497e280cb1456a31f74b9216b7d98145b3896c2f68008e6ac0c1662a4cb70562caeac294c5d01f378b22a21292"; std::cout << "[http] fetching http://download.zerotier.com/dev/4k ... "; std::cout.flush(); + webDone = false; HttpClient::GET("http://download.zerotier.com/dev/4k",HttpClient::NO_HEADERS,30,&testHttpHandler,(void *)0); - webDoneCondition.wait(); + while (!webDone) Thread::sleep(500); webSha512ShouldBe = "fbd3901a9956158b9d290efa1af4fff459d8c03187c98b0e630d10a19fab61940e668652257763973f6cde34f2aa81574f9a50b1979b675b45ddd18d69a4ceb8"; std::cout << "[http] fetching http://download.zerotier.com/dev/8k ... "; std::cout.flush(); + webDone = false; HttpClient::GET("http://download.zerotier.com/dev/8k",HttpClient::NO_HEADERS,30,&testHttpHandler,(void *)0); - webDoneCondition.wait(); + while (!webDone) Thread::sleep(500); webSha512ShouldBe = "098ae593f8c3a962f385f9f008ec2116ad22eea8bc569fc88a06a0193480fdfb27470345c427116d19179fb2a74df21d95fe5f1df575a9f2d10d99595708b765"; std::cout << "[http] fetching http://download.zerotier.com/dev/4m ... "; std::cout.flush(); + webDone = false; HttpClient::GET("http://download.zerotier.com/dev/4m",HttpClient::NO_HEADERS,30,&testHttpHandler,(void *)0); - webDoneCondition.wait(); + while (!webDone) Thread::sleep(500); webSha512ShouldBe = ""; std::cout << "[http] fetching http://download.zerotier.com/dev/NOEXIST ... "; std::cout.flush(); + webDone = false; HttpClient::GET("http://download.zerotier.com/dev/NOEXIST",HttpClient::NO_HEADERS,30,&testHttpHandler,(void *)0); - webDoneCondition.wait(); + while (!webDone) Thread::sleep(500); webSha512ShouldBe = ""; std::cout << "[http] fetching http://1.1.1.1/SHOULD_TIME_OUT ... "; std::cout.flush(); + webDone = false; HttpClient::GET("http://1.1.1.1/SHOULD_TIME_OUT",HttpClient::NO_HEADERS,4,&testHttpHandler,(void *)0); - webDoneCondition.wait(); + while (!webDone) Thread::sleep(500); return 0; } @@ -512,38 +518,6 @@ static int testOther() } std::cout << "PASS" << std::endl; - std::cout << "[other] Testing command bus encode/decode... "; std::cout.flush(); - try { - static char key[32] = { 0 }; - for(unsigned int k=0;k<100;++k) { - std::vector original; - for(unsigned int i=0,j=rand() % 256,l=(rand() % 1024)+1;i > packets(NodeConfig::encodeControlMessage(key,1,original)); - //std::cout << packets.size() << ' '; std::cout.flush(); - std::vector after; - for(std::vector< Buffer >::iterator i(packets.begin());i!=packets.end();++i) { - unsigned long convId = 9999; - if (!NodeConfig::decodeControlMessagePacket(key,i->data(),i->size(),convId,after)) { - std::cout << "FAIL (decode)" << std::endl; - return -1; - } - if (convId != 1) { - std::cout << "FAIL (conversation ID)" << std::endl; - return -1; - } - } - if (after != original) { - std::cout << "FAIL (compare)" << std::endl; - return -1; - } - } - } catch (std::exception &exc) { - std::cout << "FAIL (" << exc.what() << ")" << std::endl; - return -1; - } - std::cout << "PASS" << std::endl; - std::cout << "[other] Testing Dictionary... "; std::cout.flush(); for(int k=0;k<1000;++k) { Dictionary a,b; @@ -617,8 +591,8 @@ int main(int argc,char **argv) std::cout << "[info] sizeof(void *) == " << sizeof(void *) << std::endl; std::cout << "[info] default home: " << ZT_DEFAULTS.defaultHomePath << std::endl; - std::cout << "[info] system authtoken.secret: " << Node::LocalClient::authTokenDefaultSystemPath() << std::endl; - std::cout << "[info] user authtoken.secret: " << Node::LocalClient::authTokenDefaultUserPath() << std::endl; + std::cout << "[info] system authtoken.secret: " << Node::NodeControlClient::authTokenDefaultSystemPath() << std::endl; + std::cout << "[info] user authtoken.secret: " << Node::NodeControlClient::authTokenDefaultUserPath() << std::endl; srand((unsigned int)time(0));