summaryrefslogtreecommitdiff
path: root/service
diff options
context:
space:
mode:
Diffstat (limited to 'service')
-rw-r--r--service/OneService.cpp609
1 files changed, 67 insertions, 542 deletions
diff --git a/service/OneService.cpp b/service/OneService.cpp
index b5b11111..6497ae20 100644
--- a/service/OneService.cpp
+++ b/service/OneService.cpp
@@ -59,8 +59,6 @@
#include "../osdep/ManagedRoute.hpp"
#include "OneService.hpp"
-#include "ClusterGeoIpService.hpp"
-#include "ClusterDefinition.hpp"
#include "SoftwareUpdater.hpp"
#ifdef __WINDOWS__
@@ -157,9 +155,6 @@ namespace ZeroTier { typedef BSDEthernetTap EthernetTap; }
// Maximum write buffer size for outgoing TCP connections (sanity limit)
#define ZT_TCP_MAX_WRITEQ_SIZE 33554432
-// How often to check TCP connections and cluster links and send status to cluster peers
-#define ZT_TCP_CHECK_PERIOD 15000
-
// TCP activity timeout
#define ZT_TCP_ACTIVITY_TIMEOUT 60000
@@ -311,9 +306,9 @@ static int SnodeVirtualNetworkConfigFunction(ZT_Node *node,void *uptr,void *tptr
static void SnodeEventCallback(ZT_Node *node,void *uptr,void *tptr,enum ZT_Event event,const void *metaData);
static void SnodeStatePutFunction(ZT_Node *node,void *uptr,void *tptr,enum ZT_StateObjectType type,const uint64_t id[2],const void *data,int len);
static int SnodeStateGetFunction(ZT_Node *node,void *uptr,void *tptr,enum ZT_StateObjectType type,const uint64_t id[2],void *data,unsigned int maxlen);
-static int SnodeWirePacketSendFunction(ZT_Node *node,void *uptr,void *tptr,const struct sockaddr_storage *localAddr,const struct sockaddr_storage *addr,const void *data,unsigned int len,unsigned int ttl);
+static int SnodeWirePacketSendFunction(ZT_Node *node,void *uptr,void *tptr,int64_t localSocket,const struct sockaddr_storage *addr,const void *data,unsigned int len,unsigned int ttl);
static void SnodeVirtualNetworkFrameFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t nwid,void **nuptr,uint64_t sourceMac,uint64_t destMac,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len);
-static int SnodePathCheckFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t ztaddr,const struct sockaddr_storage *localAddr,const struct sockaddr_storage *remoteAddr);
+static int SnodePathCheckFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t ztaddr,int64_t localSocket,const struct sockaddr_storage *remoteAddr);
static int SnodePathLookupFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t ztaddr,int family,struct sockaddr_storage *result);
static void StapFrameHandler(void *uptr,void *tptr,uint64_t nwid,const MAC &from,const MAC &to,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len);
@@ -362,8 +357,7 @@ struct TcpConnection
TCP_UNCATEGORIZED_INCOMING, // uncategorized incoming connection
TCP_HTTP_INCOMING,
TCP_HTTP_OUTGOING,
- TCP_TUNNEL_OUTGOING, // TUNNELED mode proxy outbound connection
- TCP_CLUSTER_BACKPLANE
+ TCP_TUNNEL_OUTGOING // TUNNELED mode proxy outbound connection
} type;
OneServiceImpl *parent;
@@ -380,29 +374,11 @@ struct TcpConnection
std::string status;
std::map< std::string,std::string > headers;
- // Used for cluster backplane connections
- uint64_t clusterMemberId;
- unsigned int clusterMemberVersionMajor;
- unsigned int clusterMemberVersionMinor;
- unsigned int clusterMemberVersionRev;
- std::vector< InetAddress > clusterMemberLocalAddresses;
- Mutex clusterMemberLocalAddresses_m;
-
std::string readq;
std::string writeq;
Mutex writeq_m;
};
-/**
- * Message types for cluster backplane communication
- */
-enum ClusterMessageType
-{
- CLUSTER_MESSAGE_STATUS = 0,
- CLUSTER_MESSAGE_STATE_OBJECT = 1,
- CLUSTER_MESSAGE_PROXY_SEND = 2
-};
-
class OneServiceImpl : public OneService
{
public:
@@ -421,8 +397,6 @@ public:
bool _updateAutoApply;
unsigned int _primaryPort;
volatile unsigned int _udpPortPickerCounter;
- uint64_t _clusterMemberId;
- uint8_t _clusterKey[32]; // secret key for cluster backplane config
// Local configuration and memo-ized information from it
json _localConfig;
@@ -434,7 +408,6 @@ public:
std::vector< InetAddress > _globalV6Blacklist;
std::vector< InetAddress > _allowManagementFrom;
std::vector< std::string > _interfacePrefixBlacklist;
- std::vector< InetAddress > _clusterBackplaneAddresses;
Mutex _localConfig_m;
/*
@@ -518,7 +491,6 @@ public:
,_updateAutoApply(false)
,_primaryPort(port)
,_udpPortPickerCounter(0)
- ,_clusterMemberId(0)
,_lastDirectReceiveFromGlobal(0)
#ifdef ZT_TCP_FALLBACK_RELAY
,_lastSendToGlobalV4(0)
@@ -754,23 +726,6 @@ public:
}
}
- // Derive the cluster's shared secret backplane encryption key by hashing its shared secret identity
- {
- uint8_t tmp[64];
- uint8_t sk[ZT_C25519_PRIVATE_KEY_LEN + 4];
- memcpy(sk,_node->identity().privateKeyPair().priv.data,ZT_C25519_PRIVATE_KEY_LEN);
- sk[ZT_C25519_PRIVATE_KEY_LEN] = 0xab;
- sk[ZT_C25519_PRIVATE_KEY_LEN + 1] = 0xcd;
- sk[ZT_C25519_PRIVATE_KEY_LEN + 2] = 0xef;
- sk[ZT_C25519_PRIVATE_KEY_LEN + 3] = 0xab; // add an arbitrary nonce, just because
- SHA512::hash(tmp,sk,ZT_C25519_PRIVATE_KEY_LEN + 4);
- memcpy(_clusterKey,tmp,32);
- }
-
- // Assign a random non-zero cluster member ID to identify vs. other cluster members
- Utils::getSecureRandom(&_clusterMemberId,sizeof(_clusterMemberId));
- if (!_clusterMemberId) _clusterMemberId = 1;
-
// Main I/O loop
_nextBackgroundTaskDeadline = 0;
uint64_t clockShouldBe = OSUtils::now();
@@ -779,7 +734,6 @@ public:
uint64_t lastBindRefresh = 0;
uint64_t lastUpdateCheck = clockShouldBe;
uint64_t lastLocalInterfaceAddressCheck = (clockShouldBe - ZT_LOCAL_INTERFACE_CHECK_INTERVAL) + 15000; // do this in 15s to give portmapper time to configure and other things time to settle
- uint64_t lastTcpCheck = 0;
for(;;) {
_run_m.lock();
if (!_run) {
@@ -873,58 +827,6 @@ public:
_node->addLocalInterfaceAddress(reinterpret_cast<const struct sockaddr_storage *>(&(*i)));
}
- // Check TCP connections and cluster links
- if ((now - lastTcpCheck) >= ZT_TCP_CHECK_PERIOD) {
- lastTcpCheck = now;
-
- // Send status to active cluster links and close overflowed and dead ones
- std::vector<PhySocket *> toClose;
- std::vector<InetAddress> clusterLinksUp;
- {
- Mutex::Lock _l(_tcpConnections_m);
- for(std::vector<TcpConnection *>::const_iterator c(_tcpConnections.begin());c!=_tcpConnections.end();++c) {
- TcpConnection *const tc = *c;
- tc->writeq_m.lock();
- const unsigned long wql = (unsigned long)tc->writeq.length();
- tc->writeq_m.unlock();
- if ((tc->sock)&&((wql > ZT_TCP_MAX_WRITEQ_SIZE)||((now - tc->lastReceive) > ZT_TCP_ACTIVITY_TIMEOUT))) {
- toClose.push_back(tc->sock);
- } else if ((tc->type == TcpConnection::TCP_CLUSTER_BACKPLANE)&&(tc->clusterMemberId)) {
- clusterLinksUp.push_back(tc->remoteAddr);
- sendMyCurrentClusterState(tc);
- }
- }
- }
- for(std::vector<PhySocket *>::iterator s(toClose.begin());s!=toClose.end();++s)
- _phy.close(*s,true);
-
- // Attempt to connect to cluster links we don't have an active connection to
- {
- Mutex::Lock _l(_localConfig_m);
- for(std::vector<InetAddress>::const_iterator ca(_clusterBackplaneAddresses.begin());ca!=_clusterBackplaneAddresses.end();++ca) {
- if ( (std::find(clusterLinksUp.begin(),clusterLinksUp.end(),*ca) == clusterLinksUp.end()) && (!_binder.isBoundLocalInterfaceAddress(*ca)) ) {
- TcpConnection *tc = new TcpConnection();
- {
- Mutex::Lock _l(_tcpConnections_m);
- _tcpConnections.push_back(tc);
- }
-
- tc->type = TcpConnection::TCP_CLUSTER_BACKPLANE;
- tc->remoteAddr = *ca;
- tc->lastReceive = OSUtils::now();
- tc->parent = this;
- tc->sock = (PhySocket *)0; // set in connect handler
- tc->messageSize = 0;
-
- tc->clusterMemberId = 0; // not known yet
-
- bool connected = false;
- _phy.tcpConnect(reinterpret_cast<const struct sockaddr *>(&(*ca)),connected,(void *)tc,true);
- }
- }
- }
- }
-
const unsigned long delay = (dl > now) ? (unsigned long)(dl - now) : 100;
clockShouldBe = now + (uint64_t)delay;
_phy.poll(delay);
@@ -1211,21 +1113,6 @@ public:
res["planetWorldId"] = planet.id();
res["planetWorldTimestamp"] = planet.timestamp();
- {
- json cj(json::object());
- Mutex::Lock _l(_tcpConnections_m);
- Mutex::Lock _l2(_localConfig_m);
- for(std::vector<InetAddress>::const_iterator ca(_clusterBackplaneAddresses.begin());ca!=_clusterBackplaneAddresses.end();++ca) {
- uint64_t up = 0;
- for(std::vector<TcpConnection *>::const_iterator c(_tcpConnections.begin());c!=_tcpConnections.end();++c) {
- if (((*c)->remoteAddr == *ca)&&((*c)->clusterMemberId)&&((*c)->lastReceive > up))
- up = (*c)->lastReceive;
- }
- cj[ca->toString()] = up;
- }
- res["cluster"] = cj;
- }
-
scode = 200;
} else if (ps[0] == "moon") {
std::vector<World> moons(_node->moons());
@@ -1576,16 +1463,6 @@ public:
}
}
- json &cl = settings["cluster"];
- _clusterBackplaneAddresses.clear();
- if (cl.is_array()) {
- for(unsigned long i=0;i<cl.size();++i) {
- const InetAddress cip(OSUtils::jsonString(cl[i],""));
- if ((cip.ss_family == AF_INET)||(cip.ss_family == AF_INET6))
- _clusterBackplaneAddresses.push_back(cip);
- }
- }
-
json &controllerDbHttpHost = settings["controllerDbHttpHost"];
json &controllerDbHttpPort = settings["controllerDbHttpPort"];
json &controllerDbHttpPath = settings["controllerDbHttpPath"];
@@ -1755,250 +1632,6 @@ public:
}
// =========================================================================
- // Cluster messaging functions
- // =========================================================================
-
- // mlen must be at least 24
- void encryptClusterMessage(char *data,unsigned int mlen)
- {
- uint8_t key[32];
- memcpy(key,_clusterKey,32);
- for(int i=0;i<8;++i) key[i] ^= data[i];
- Salsa20 s20(key,data + 8);
-
- uint8_t macKey[32];
- uint8_t mac[16];
- memset(macKey,0,32);
- s20.crypt12(macKey,macKey,32);
- s20.crypt12(data + 24,data + 24,mlen - 24);
- Poly1305::compute(mac,data + 24,mlen - 24,macKey);
- memcpy(data + 16,mac,8);
- }
-
- void announceStatusToClusterMember(TcpConnection *tc)
- {
- try {
- Buffer<8194> buf;
-
- buf.appendRandom(16);
- buf.addSize(8); // space for MAC
- buf.append((uint8_t)CLUSTER_MESSAGE_STATUS);
- buf.append(_clusterMemberId);
- buf.append((uint16_t)ZEROTIER_ONE_VERSION_MAJOR);
- buf.append((uint16_t)ZEROTIER_ONE_VERSION_MINOR);
- buf.append((uint16_t)ZEROTIER_ONE_VERSION_REVISION);
-
- std::vector<InetAddress> lif(_binder.allBoundLocalInterfaceAddresses());
- buf.append((uint16_t)lif.size());
- for(std::vector<InetAddress>::const_iterator i(lif.begin());i!=lif.end();++i)
- i->serialize(buf);
-
- Mutex::Lock _l(tc->writeq_m);
-
- if (tc->writeq.length() == 0)
- _phy.setNotifyWritable(tc->sock,true);
-
- const unsigned int mlen = buf.size();
- tc->writeq.push_back((char)((mlen >> 16) & 0xff));
- tc->writeq.push_back((char)((mlen >> 8) & 0xff));
- tc->writeq.push_back((char)(mlen & 0xff));
-
- char *const data = reinterpret_cast<char *>(buf.unsafeData());
- encryptClusterMessage(data,mlen);
- tc->writeq.append(data,mlen);
- } catch ( ... ) {
- fprintf(stderr,"WARNING: unexpected exception announcing status to cluster members" ZT_EOL_S);
- }
- }
-
- bool proxySendViaCluster(const InetAddress &fromAddress,const InetAddress &dest,const void *data,unsigned int len,unsigned int ttl)
- {
- Mutex::Lock _l(_tcpConnections_m);
- for(std::vector<TcpConnection *>::const_iterator c(_tcpConnections.begin());c!=_tcpConnections.end();++c) {
- TcpConnection *const tc = *c;
- if ((tc->type == TcpConnection::TCP_CLUSTER_BACKPLANE)&&(tc->clusterMemberId)) {
- Mutex::Lock _l2(tc->clusterMemberLocalAddresses_m);
- for(std::vector<InetAddress>::const_iterator i(tc->clusterMemberLocalAddresses.begin());i!=tc->clusterMemberLocalAddresses.end();++i) {
- if (*i == fromAddress) {
- Buffer<1024> buf;
-
- buf.appendRandom(16);
- buf.addSize(8); // space for MAC
- buf.append((uint8_t)CLUSTER_MESSAGE_PROXY_SEND);
- buf.append((uint8_t)ttl);
- dest.serialize(buf);
- fromAddress.serialize(buf);
-
- Mutex::Lock _l3(tc->writeq_m);
-
- if (tc->writeq.length() == 0)
- _phy.setNotifyWritable(tc->sock,true);
-
- const unsigned int mlen = buf.size() + len;
- tc->writeq.push_back((char)((mlen >> 16) & 0xff));
- tc->writeq.push_back((char)((mlen >> 8) & 0xff));
- tc->writeq.push_back((char)(mlen & 0xff));
-
- const unsigned long startpos = (unsigned long)tc->writeq.length();
- tc->writeq.append(reinterpret_cast<const char *>(buf.data()),buf.size());
- tc->writeq.append(reinterpret_cast<const char *>(data),len);
-
- char *const outdata = const_cast<char *>(tc->writeq.data()) + startpos;
- encryptClusterMessage(outdata,mlen);
-
- return true;
- }
- }
- }
- }
- return false;
- }
-
- void replicateStateObject(const ZT_StateObjectType type,const uint64_t id[2],const void *const data,const unsigned int len,TcpConnection *tc)
- {
- char buf[42];
- Mutex::Lock _l2(tc->writeq_m);
-
- if (tc->writeq.length() == 0)
- _phy.setNotifyWritable(tc->sock,true);
-
- const unsigned int mlen = len + 42;
-
- tc->writeq.push_back((char)((mlen >> 16) & 0xff));
- tc->writeq.push_back((char)((mlen >> 8) & 0xff));
- tc->writeq.push_back((char)(mlen & 0xff));
-
- Utils::getSecureRandom(buf,16);
- buf[24] = (char)CLUSTER_MESSAGE_STATE_OBJECT;
- buf[25] = (char)type;
- buf[26] = (char)((id[0] >> 56) & 0xff);
- buf[27] = (char)((id[0] >> 48) & 0xff);
- buf[28] = (char)((id[0] >> 40) & 0xff);
- buf[29] = (char)((id[0] >> 32) & 0xff);
- buf[30] = (char)((id[0] >> 24) & 0xff);
- buf[31] = (char)((id[0] >> 16) & 0xff);
- buf[32] = (char)((id[0] >> 8) & 0xff);
- buf[33] = (char)(id[0] & 0xff);
- buf[34] = (char)((id[1] >> 56) & 0xff);
- buf[35] = (char)((id[1] >> 48) & 0xff);
- buf[36] = (char)((id[1] >> 40) & 0xff);
- buf[37] = (char)((id[1] >> 32) & 0xff);
- buf[38] = (char)((id[1] >> 24) & 0xff);
- buf[39] = (char)((id[1] >> 16) & 0xff);
- buf[40] = (char)((id[1] >> 8) & 0xff);
- buf[41] = (char)(id[1] & 0xff);
-
- const unsigned long startpos = (unsigned long)tc->writeq.length();
- tc->writeq.append(buf,42);
- tc->writeq.append(reinterpret_cast<const char *>(data),len);
-
- char *const outdata = const_cast<char *>(tc->writeq.data()) + startpos;
- encryptClusterMessage(outdata,mlen);
- tc->writeq.append(outdata,mlen);
- }
-
- void writeStateObject(enum ZT_StateObjectType type,const uint64_t id[2],const void *data,int len)
- {
- char buf[65535];
- char p[1024];
- FILE *f;
- bool secure = false;
-
- switch(type) {
- case ZT_STATE_OBJECT_IDENTITY_PUBLIC:
- Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.public",_homePath.c_str());
- break;
- case ZT_STATE_OBJECT_IDENTITY_SECRET:
- Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.secret",_homePath.c_str());
- secure = true;
- break;
- //case ZT_STATE_OBJECT_PEER_STATE:
- // break;
- case ZT_STATE_OBJECT_NETWORK_CONFIG:
- Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "networks.d/%.16llx.conf",_homePath.c_str(),(unsigned long long)id[0]);
- secure = true;
- break;
- //case ZT_STATE_OBJECT_NETWORK_MEMBERSHIP:
- // break;
- case ZT_STATE_OBJECT_PLANET:
- Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str());
- break;
- case ZT_STATE_OBJECT_MOON:
- Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "moons.d/%.16llx.moon",_homePath.c_str(),(unsigned long long)id[0]);
- break;
- default:
- p[0] = (char)0;
- break;
- }
-
- if (p[0]) {
- if (len >= 0) {
- // Check to see if we've already written this first. This reduces
- // redundant writes and I/O overhead on most platforms and has
- // little effect on others.
- f = fopen(p,"r");
- bool redundant = false;
- if (f) {
- long l = (long)fread(buf,1,sizeof(buf),f);
- fclose(f);
- redundant = ((l == (long)len)&&(memcmp(data,buf,l) == 0));
- }
- if (!redundant) {
- f = fopen(p,"w");
- if (f) {
- if (fwrite(data,len,1,f) != 1)
- fprintf(stderr,"WARNING: unable to write to file: %s (I/O error)" ZT_EOL_S,p);
- fclose(f);
- if (secure)
- OSUtils::lockDownFile(p,false);
- } else {
- fprintf(stderr,"WARNING: unable to write to file: %s (unable to open)" ZT_EOL_S,p);
- }
- }
- } else {
- OSUtils::rm(p);
- }
- }
- }
-
- void sendMyCurrentClusterState(TcpConnection *tc)
- {
- // We currently don't need to dump everything. Networks and moons are most important.
- // The rest will get caught up rapidly due to constant peer updates, etc.
- std::string buf;
- std::vector<std::string> l(OSUtils::listDirectory((_homePath + ZT_PATH_SEPARATOR_S + "networks.d").c_str(),false));
- for(std::vector<std::string>::const_iterator f(l.begin());f!=l.end();++f) {
- buf.clear();
- if (OSUtils::readFile((_homePath + ZT_PATH_SEPARATOR_S + *f).c_str(),buf)) {
- if (f->length() == 21) {
- const uint64_t nwid = Utils::hexStrToU64(f->substr(0,16).c_str());
- if (nwid) {
- uint64_t tmp[2];
- tmp[0] = nwid;
- tmp[1] = 0;
- replicateStateObject(ZT_STATE_OBJECT_NETWORK_CONFIG,tmp,buf.data(),(int)buf.length(),tc);
- }
- }
- }
- }
- l = OSUtils::listDirectory((_homePath + ZT_PATH_SEPARATOR_S + "moons.d").c_str(),false);
- for(std::vector<std::string>::const_iterator f(l.begin());f!=l.end();++f) {
- buf.clear();
- if (OSUtils::readFile((_homePath + ZT_PATH_SEPARATOR_S + *f).c_str(),buf)) {
- if (f->length() == 21) {
- const uint64_t moonId = Utils::hexStrToU64(f->substr(0,16).c_str());
- if (moonId) {
- uint64_t tmp[2];
- tmp[0] = moonId;
- tmp[1] = 0;
- replicateStateObject(ZT_STATE_OBJECT_MOON,tmp,buf.data(),(int)buf.length(),tc);
- }
- }
- }
- }
- }
-
- // =========================================================================
// Handlers for Node and Phy<> callbacks
// =========================================================================
@@ -2010,7 +1643,7 @@ public:
const ZT_ResultCode rc = _node->processWirePacket(
(void *)0,
OSUtils::now(),
- reinterpret_cast<const struct sockaddr_storage *>(localAddr),
+ (int64_t)((uintptr_t)sock),
(const struct sockaddr_storage *)from, // Phy<> uses sockaddr_storage, so it'll always be that big
data,
len,
@@ -2044,13 +1677,6 @@ public:
_phy.close(_tcpFallbackTunnel->sock);
_tcpFallbackTunnel = tc;
_phy.streamSend(sock,ZT_TCP_TUNNEL_HELLO,sizeof(ZT_TCP_TUNNEL_HELLO));
- } else if (tc->type == TcpConnection::TCP_CLUSTER_BACKPLANE) {
- {
- Mutex::Lock _l(tc->writeq_m);
- tc->writeq.push_back((char)0x93); // identifies type of connection as cluster backplane
- }
- announceStatusToClusterMember(tc);
- _phy.setNotifyWritable(sock,true);
} else {
_phy.close(sock,true);
}
@@ -2106,31 +1732,6 @@ public:
case TcpConnection::TCP_UNCATEGORIZED_INCOMING:
switch(reinterpret_cast<uint8_t *>(data)[0]) {
- // 0x93 is first byte of cluster backplane connections
- case 0x93: {
- // We only allow this from cluster backplane IPs. We also authenticate
- // each packet cryptographically, so this is just a first line of defense.
- bool allow = false;
- {
- Mutex::Lock _l(_localConfig_m);
- for(std::vector< InetAddress >::const_iterator i(_clusterBackplaneAddresses.begin());i!=_clusterBackplaneAddresses.end();++i) {
- if (tc->remoteAddr.ipsEqual(*i)) {
- allow = true;
- break;
- }
- }
- }
- if (allow) {
- tc->type = TcpConnection::TCP_CLUSTER_BACKPLANE;
- tc->clusterMemberId = 0; // unknown, waiting for first status message
- announceStatusToClusterMember(tc);
- if (len > 1)
- phyOnTcpData(sock,uptr,reinterpret_cast<uint8_t *>(data) + 1,len - 1);
- } else {
- _phy.close(sock);
- }
- } break;
-
// HTTP: GET, PUT, POST, HEAD
case 'G':
case 'P':
@@ -2223,7 +1824,7 @@ public:
const ZT_ResultCode rc = _node->processWirePacket(
(void *)0,
OSUtils::now(),
- reinterpret_cast<struct sockaddr_storage *>(&fakeTcpLocalInterfaceAddress),
+ -1,
reinterpret_cast<struct sockaddr_storage *>(&from),
data,
plen,
@@ -2248,114 +1849,6 @@ public:
}
return;
- case TcpConnection::TCP_CLUSTER_BACKPLANE:
- tc->readq.append((const char *)data,len);
- if (tc->readq.length() >= 28) { // got 3-byte message size + 16-byte IV + 8-byte MAC + 1-byte type (encrypted)
- uint8_t *data = reinterpret_cast<uint8_t *>(const_cast<char *>(tc->readq.data()));
- unsigned long mlen = ( ((unsigned long)data[0] << 16) | ((unsigned long)data[1] << 8) | (unsigned long)data[2] );
- if ((mlen < 25)||(mlen > ZT_TCP_MAX_WRITEQ_SIZE)) {
- _phy.close(sock);
- return;
- } else if (tc->readq.length() >= (mlen + 3)) { // got entire message
- data += 3;
-
- uint8_t key[32];
- memcpy(key,_clusterKey,32);
- for(int i=0;i<8;++i) key[i] ^= data[i]; // first 8 bytes of IV get XORed with key
- Salsa20 s20(key,data + 8); // last 8 bytes of IV are fed into Salsa20 directly as its 64-bit IV
-
- uint8_t macKey[32];
- uint8_t mac[16];
- memset(macKey,0,32);
- s20.crypt12(macKey,macKey,32);
- Poly1305::compute(mac,data + 24,mlen - 24,macKey);
- if (!Utils::secureEq(mac,data + 16,8)) {
- _phy.close(sock);
- return;
- }
- s20.crypt12(data + 24,data + 24,mlen - 24);
-
- switch((ClusterMessageType)data[24]) {
- case CLUSTER_MESSAGE_STATUS:
- if (mlen > (25 + 16)) {
- Buffer<4096> tmp(data + 25,mlen - 25);
- try {
- const uint64_t cmid = tmp.at<uint64_t>(0);
- if (cmid == _clusterMemberId) { // shouldn't happen, but don't allow self-to-self
- _phy.close(sock);
- return;
- }
- if (!tc->clusterMemberId) {
- tc->clusterMemberId = cmid;
- sendMyCurrentClusterState(tc);
- }
- tc->clusterMemberVersionMajor = tmp.at<uint16_t>(8);
- tc->clusterMemberVersionMinor = tmp.at<uint16_t>(10);
- tc->clusterMemberVersionRev = tmp.at<uint16_t>(12);
- const unsigned int clusterMemberLocalAddressCount = tmp.at<uint16_t>(14);
- std::vector<InetAddress> la;
- unsigned int ptr = 16;
- for(unsigned int k=0;k<clusterMemberLocalAddressCount;++k) {
- la.push_back(InetAddress());
- ptr += la.back().deserialize(tmp,ptr);
- }
- {
- Mutex::Lock _l2(tc->clusterMemberLocalAddresses_m);
- tc->clusterMemberLocalAddresses.swap(la);
- }
- } catch ( ... ) {}
- }
- break;
-
- case CLUSTER_MESSAGE_STATE_OBJECT:
- if (mlen > 42) { // type + object ID + [data]
- uint64_t objId[2];
- objId[0] = (
- ((uint64_t)data[26] << 56) |
- ((uint64_t)data[27] << 48) |
- ((uint64_t)data[28] << 40) |
- ((uint64_t)data[29] << 32) |
- ((uint64_t)data[30] << 24) |
- ((uint64_t)data[31] << 16) |
- ((uint64_t)data[32] << 8) |
- (uint64_t)data[33]
- );
- objId[1] = (
- ((uint64_t)data[34] << 56) |
- ((uint64_t)data[35] << 48) |
- ((uint64_t)data[36] << 40) |
- ((uint64_t)data[37] << 32) |
- ((uint64_t)data[38] << 24) |
- ((uint64_t)data[39] << 16) |
- ((uint64_t)data[40] << 8) |
- (uint64_t)data[41]
- );
- if (_node->processStateUpdate((void *)0,(ZT_StateObjectType)data[25],objId,data + 42,(unsigned int)(mlen - 42)) == ZT_RESULT_OK)
- writeStateObject((ZT_StateObjectType)data[25],objId,data + 42,(unsigned int)(mlen - 42));
- }
- break;
-
- case CLUSTER_MESSAGE_PROXY_SEND:
- if (mlen > 25) {
- Buffer<4096> tmp(data + 25,mlen - 25);
- try {
- InetAddress dest,src;
- const unsigned int ttl = (unsigned int)tmp[0];
- unsigned int ptr = 1;
- ptr += dest.deserialize(tmp);
- ptr += src.deserialize(tmp,ptr);
- if (ptr < tmp.size())
- _binder.udpSend(_phy,src,dest,reinterpret_cast<const uint8_t *>(tmp.data()) + ptr,tmp.size() - ptr,ttl);
- } catch ( ... ) {}
- }
- break;
- }
-
- tc->readq.erase(tc->readq.begin(),tc->readq.begin() + mlen);
- }
- }
- return;
-
}
} catch ( ... ) {
_phy.close(sock);
@@ -2549,18 +2042,57 @@ public:
inline void nodeStatePutFunction(enum ZT_StateObjectType type,const uint64_t id[2],const void *data,int len)
{
- writeStateObject(type,id,data,len);
+ char p[1024];
+ FILE *f;
+ bool secure = false;
- std::vector<uint64_t> sentTo;
- {
- Mutex::Lock _l(_tcpConnections_m);
- for(std::vector<TcpConnection *>::const_iterator ci(_tcpConnections.begin());ci!=_tcpConnections.end();++ci) {
- TcpConnection *const c = *ci;
- if ((c->type == TcpConnection::TCP_CLUSTER_BACKPLANE)&&(c->clusterMemberId != 0)&&(std::find(sentTo.begin(),sentTo.end(),c->clusterMemberId) == sentTo.end())) {
- sentTo.push_back(c->clusterMemberId);
- replicateStateObject(type,id,data,len,c);
- }
+ switch(type) {
+ case ZT_STATE_OBJECT_IDENTITY_PUBLIC:
+ Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.public",_homePath.c_str());
+ break;
+ case ZT_STATE_OBJECT_IDENTITY_SECRET:
+ Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.secret",_homePath.c_str());
+ secure = true;
+ break;
+ case ZT_STATE_OBJECT_PLANET:
+ Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str());
+ break;
+ case ZT_STATE_OBJECT_MOON:
+ Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "moons.d/%.16llx.moon",_homePath.c_str(),(unsigned long long)id[0]);
+ break;
+ case ZT_STATE_OBJECT_NETWORK_CONFIG:
+ Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "networks.d/%.16llx.conf",_homePath.c_str(),(unsigned long long)id[0]);
+ secure = true;
+ break;
+ default:
+ return;
+ }
+
+ if (len >= 0) {
+ // Check to see if we've already written this first. This reduces
+ // redundant writes and I/O overhead on most platforms and has
+ // little effect on others.
+ f = fopen(p,"r");
+ if (f) {
+ char buf[65535];
+ long l = (long)fread(buf,1,sizeof(buf),f);
+ fclose(f);
+ if ((l == (long)len)&&(memcmp(data,buf,l) == 0))
+ return;
}
+
+ f = fopen(p,"w");
+ if (f) {
+ if (fwrite(data,len,1,f) != 1)
+ fprintf(stderr,"WARNING: unable to write to file: %s (I/O error)" ZT_EOL_S,p);
+ fclose(f);
+ if (secure)
+ OSUtils::lockDownFile(p,false);
+ } else {
+ fprintf(stderr,"WARNING: unable to write to file: %s (unable to open)" ZT_EOL_S,p);
+ }
+ } else {
+ OSUtils::rm(p);
}
}
@@ -2596,7 +2128,7 @@ public:
return -1;
}
- inline int nodeWirePacketSendFunction(const struct sockaddr_storage *localAddr,const struct sockaddr_storage *addr,const void *data,unsigned int len,unsigned int ttl)
+ inline int nodeWirePacketSendFunction(const int64_t localSocket,const struct sockaddr_storage *addr,const void *data,unsigned int len,unsigned int ttl)
{
#ifdef ZT_TCP_FALLBACK_RELAY
if (addr->ss_family == AF_INET) {
@@ -2646,20 +2178,13 @@ public:
// proxy fallback, which is slow.
#endif // ZT_TCP_FALLBACK_RELAY
- switch (_binder.udpSend(_phy,*(reinterpret_cast<const InetAddress *>(localAddr)),*(reinterpret_cast<const InetAddress *>(addr)),data,len,ttl)) {
- case -1: // local bound address not found, so see if a cluster peer owns it
- if (localAddr->ss_family != 0) {
- return (proxySendViaCluster(*(reinterpret_cast<const InetAddress *>(localAddr)),*(reinterpret_cast<const InetAddress *>(addr)),data,len,ttl)) ? 0 : -1;
- } else {
- return -1; // failure
- }
- break;
-
- case 0: // failure
- return -1;
-
- default: // success
- return 0;
+ if ((localSocket != 0)&&(localSocket != -1)) {
+ if ((ttl)&&(addr->ss_family == AF_INET)) _phy.setIp4UdpTtl((PhySocket *)((uintptr_t)localSocket),ttl);
+ const bool r = _phy.udpSend((PhySocket *)((uintptr_t)localSocket),(const struct sockaddr *)addr,data,len);
+ if ((ttl)&&(addr->ss_family == AF_INET)) _phy.setIp4UdpTtl((PhySocket *)((uintptr_t)localSocket),255);
+ return ((r) ? 0 : -1);
+ } else {
+ return ((_binder.udpSendAll(_phy,addr,data,len,ttl)) ? 0 : -1);
}
}
@@ -2671,7 +2196,7 @@ public:
n->tap->put(MAC(sourceMac),MAC(destMac),etherType,data,len);
}
- inline int nodePathCheckFunction(uint64_t ztaddr,const struct sockaddr_storage *localAddr,const struct sockaddr_storage *remoteAddr)
+ inline int nodePathCheckFunction(uint64_t ztaddr,const int64_t localSocket,const struct sockaddr_storage *remoteAddr)
{
// Make sure we're not trying to do ZeroTier-over-ZeroTier
{
@@ -2882,12 +2407,12 @@ static void SnodeStatePutFunction(ZT_Node *node,void *uptr,void *tptr,enum ZT_St
{ reinterpret_cast<OneServiceImpl *>(uptr)->nodeStatePutFunction(type,id,data,len); }
static int SnodeStateGetFunction(ZT_Node *node,void *uptr,void *tptr,enum ZT_StateObjectType type,const uint64_t id[2],void *data,unsigned int maxlen)
{ return reinterpret_cast<OneServiceImpl *>(uptr)->nodeStateGetFunction(type,id,data,maxlen); }
-static int SnodeWirePacketSendFunction(ZT_Node *node,void *uptr,void *tptr,const struct sockaddr_storage *localAddr,const struct sockaddr_storage *addr,const void *data,unsigned int len,unsigned int ttl)
-{ return reinterpret_cast<OneServiceImpl *>(uptr)->nodeWirePacketSendFunction(localAddr,addr,data,len,ttl); }
+static int SnodeWirePacketSendFunction(ZT_Node *node,void *uptr,void *tptr,int64_t localSocket,const struct sockaddr_storage *addr,const void *data,unsigned int len,unsigned int ttl)
+{ return reinterpret_cast<OneServiceImpl *>(uptr)->nodeWirePacketSendFunction(localSocket,addr,data,len,ttl); }
static void SnodeVirtualNetworkFrameFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t nwid,void **nuptr,uint64_t sourceMac,uint64_t destMac,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len)
{ reinterpret_cast<OneServiceImpl *>(uptr)->nodeVirtualNetworkFrameFunction(nwid,nuptr,sourceMac,destMac,etherType,vlanId,data,len); }
-static int SnodePathCheckFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t ztaddr,const struct sockaddr_storage *localAddr,const struct sockaddr_storage *remoteAddr)
-{ return reinterpret_cast<OneServiceImpl *>(uptr)->nodePathCheckFunction(ztaddr,localAddr,remoteAddr); }
+static int SnodePathCheckFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t ztaddr,int64_t localSocket,const struct sockaddr_storage *remoteAddr)
+{ return reinterpret_cast<OneServiceImpl *>(uptr)->nodePathCheckFunction(ztaddr,localSocket,remoteAddr); }
static int SnodePathLookupFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t ztaddr,int family,struct sockaddr_storage *result)
{ return reinterpret_cast<OneServiceImpl *>(uptr)->nodePathLookupFunction(ztaddr,family,result); }
static void StapFrameHandler(void *uptr,void *tptr,uint64_t nwid,const MAC &from,const MAC &to,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len)