Updated core for tptr support

This commit is contained in:
Joseph Henry
2017-03-28 18:56:38 -07:00
parent b1e83a236e
commit bd3b07e00a
68 changed files with 1271 additions and 2033 deletions

View File

@@ -357,7 +357,7 @@ namespace ZeroTier {
src_mac.setTo(ethhdr->saddr, 6);
dest_mac.setTo(ethhdr->daddr, 6);
picotap->_handler(picotap->_arg,picotap->_nwid,src_mac,dest_mac,
picotap->_handler(picotap->_arg,NULL,picotap->_nwid,src_mac,dest_mac,
Utils::ntoh((uint16_t)ethhdr->proto),0, ((char*)buf) + sizeof(struct pico_eth_hdr),len - sizeof(struct pico_eth_hdr));
return len;
}

View File

@@ -94,7 +94,7 @@ NetconEthernetTap::NetconEthernetTap(
unsigned int metric,
uint64_t nwid,
const char *friendlyName,
void (*handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int),
void (*handler)(void *,void*, uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int),
void *arg) :
_homePath(homePath),
_mac(mac),

View File

@@ -122,7 +122,7 @@ namespace ZeroTier {
unsigned int metric,
uint64_t nwid,
const char *friendlyName,
void (*handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int),
void (*handler)(void *,void*,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int),
void *arg);
~NetconEthernetTap();
@@ -149,7 +149,7 @@ namespace ZeroTier {
MAC _mac;
unsigned int _mtu;
uint64_t _nwid;
void (*_handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int);
void (*_handler)(void *,void*, uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int);
void *_arg;
Phy<NetconEthernetTap *> _phy;
PhySocket *_unixListenSocket;

View File

@@ -11,8 +11,8 @@ ifeq ($(OSTYPE),Linux)
endif
ifeq ($(OSTYPE),FreeBSD)
CC=gcc
CXX=g++
CC=clang
CXX=clang++
ZT_BUILD_PLATFORM=7
include make-bsd.mk
endif

View File

@@ -1,32 +1,40 @@
ZeroTier Release Notes
======
*As of 1.2.0 this will serve as a detailed changelog, which we've needed for a long time.*
# 2017-03-17 -- Version 1.2.2
# 2017-03-13 -- Version 1.2.0
Version 1.2.2 fixes a few bugs discovered after the 1.2.0 release. These are:
Version 1.2.0 is a major milestone release and introduces a large number of new capabilities to the ZeroTier core network hypervisor. It also includes some security tightening, major UI improvements for Windows and Macintosh platforms, and a number of bug fixes and platform issue workarounds.
* A bug causing unreliable multicast propagation (GitHub issue #461).
* A crash in ARM binaries due to a build chain and flags problem.
* A bug in the network controller preventing members from being listed (GitHub issue #460).
## Features in 1.2.0
------
# 2017-03-14 -- Version 1.2.0
Version 1.2.0 is a major milestone release representing almost nine months of work. It includes our rules engine for distributed network packet filtering and security monitoring, federated roots, and many other architectural and UI improvements and bug fixes.
## New Features in 1.2.0
### The ZeroTier Rules Engine
The largest new feature in 1.2.0, and the product of many months of work, is our advanced network rules engine. With this release we achieve traffic control, security monitoring, and micro-segmentation capability on par with many enterprise SDN solutions designed for use in advanced data centers and corporate networks.
Rules allow you to filter packets on your network and vector traffic to security observers (e.g. a node running Snort). Security observation can be performed in-band using REDIRECT or out of band using TEE, and for tha latter it can be done for headers only, for select traffic, or probabilistically to reduce overhead on large distributed networks.
Rules allow you to filter packets on your network and vector traffic to security observers. Security observation can be performed in-band using REDIRECT or out of band using TEE.
Tags and capabilites provide advanced methods for implementing fine grained permission structures and micro-segmentation schemes without bloating the size and complexity of your rules table.
See our manual for more information.
See the [rules engine announcement blog post](https://www.zerotier.com/blog/?p=927) for an in-depth discussion of theory and implementation. The [manual](https://www.zerotier.com/manual.shtml) contains detailed information on rule, tag, and capability use, and the `rule-compiler/` subfolder of the ZeroTier source tree contains a JavaScript function to compile rules in our human-readable rule definition language into rules suitable for import into a network controller. (ZeroTier Central uses this same script to compile rules on [my.zerotier.com](https://my.zerotier.com/).)
### Root Server Federation
It's now possible to create your own root servers and add them to the root server pool on your nodes. This is done by creating what's called a "moon," which is a signed enumeration of root servers and their stable points on the network. Refer to the manual for more details on how to do this and how it works.
It's now possible to create your own root servers and add them to the root server pool on your nodes. This is done by creating what's called a "moon," which is a signed enumeration of root servers and their stable points on the network. Refer to the [manual](https://www.zerotier.com/manual.shtml) for instructions.
Federated roots achieve a number of things:
* You can deploy your own infrastructure to reduce dependency on ours.
* You can deploy them *inside your LAN* to ensure that network connectivity inside your facility still works if the Internet goes down. This is the first step toward making ZeroTier viable as an in-house SDN solution.
* You can deploy roots *inside your LAN* to ensure that network connectivity inside your facility still works if the Internet goes down. This is the first step toward making ZeroTier viable as an in-house SDN solution.
* Roots can be deployed inside national boundaries for countries with data residency laws or "great firewalls." (As of 1.2.0 there is still no way to force all traffic to use these roots, but that will be easy to do in a later version.)
* Last but not least this makes ZeroTier somewhat less centralized by eliminating any hard dependency on ZeroTier, Inc.'s infrastructure.
@@ -50,23 +58,28 @@ A good software update system for Windows and Mac clients has been a missing fea
We've greatly improved this mechanism in 1.2.0. Not only does it now do a better job of actually invoking the update, but it also transfers updates in-band using the ZeroTier protocol. This means it can work in environments that do not allows http/https traffic or that force it through proxies. There's also now an update channel setting: `beta` or `release` (the default).
As before software updates are authenticated in two ways:
Software updates are authenticated three ways:
1. ZeroTier's own signing key is used to sign all updates and this signature is checked prior to installation. Our signatures are done on an air-gapped machine.
1. ZeroTier's own signing key is used to sign all updates and this signature is checked prior to installation. ZeroTier, Inc.'s signatures are performed on an air-gapped machine.
2. Updates for Mac and Windows are signed using Apple and Microsoft (DigiCert) keys and will not install unless these signatures are also valid.
2. Updates for Mac and Windows are signed using Apple and Microsoft (DigiCert EV) keys and will not install unless these signatures are also valid.
Version 1.2.0's in-band mechanism effectively adds a third way: updates are fetched in-band from a designated ZeroTier node, thus authenticating the source using ZeroTier's built-in encryption and authentication mechanisms.
3. The new in-band update mechanism also authenticates the source of the update via ZeroTier's built-in security features. This provides transport security, while 1 and 2 provide security of the update at rest.
Updates are now configurable via `local.conf`. There are three options: `disable`, `download`, and `apply`. The third is the default for official builds on Windows and Mac, making updates happen silently and automatically as they do for popular browsers like Chrome and Firefox. For managed enterprise deployments IT people could ship a local.conf that disables updates and instead push updates via their management capabilities. Updates are disabled on Linux and other Unix-type platforms as these get updates through package repositories.
Updates are now configurable via `local.conf`. There are three options: `disable`, `download`, and `apply`. The third (apply) is the default for official builds on Windows and Mac, making updates happen silently and automatically as they do for popular browsers like Chrome and Firefox. Updates are disabled by default on Linux and other Unix-type systems as these are typically updated through package managers.
### Path Quality Monitoring (QoS and SD-WAN phase one)
### Path Link Quality Awareness
Version 1.2.0 is now aware of the link quality of direct paths with other 1.2.0 nodes. This information isn't used yet but is visible through the JSON API. (Quality always shows as 100% with pre-1.2.0 nodes.)
Version 1.2.0 is now aware of the link quality of direct paths with other 1.2.0 nodes. This information isn't used yet but is visible through the JSON API. (Quality always shows as 100% with pre-1.2.0 nodes.) Quality is measured passively with no additional overhead using a counter based packet loss detection algorithm.
Link quality monitoring is a precursor to intelligent multi-path and QoS support, which will in future versions bring us to feature parity with SD-WAN products like Cisco iWAN.
This information is visible from the command line via `listpeers`:
"Connect all the things!"
200 listpeers XXXXXXXXXX 199.XXX.XXX.XXX/9993;10574;15250;1.00 48 1.2.0 LEAF
200 listpeers XXXXXXXXXX 195.XXX.XXX.XXX/45584;467;7608;0.44 290 1.2.0 LEAF
The first peer's path is at 100% (1.00), while the second peer's path is suffering quite a bit of packet loss (0.44).
Link quality awareness is a precursor to intelligent multi-path and QoS support, which will in future versions bring us to feature parity with SD-WAN products like Cisco iWAN.
### Security Improvements
@@ -78,15 +91,42 @@ Revocations propagate using a "rumor mill" peer to peer algorithm. This means th
### Windows and Macintosh UI Improvements (ZeroTier One)
The Mac has a whole new UI built natively in Objective-C. It provides a pulldown similar in appearance and operation to the Mac WiFi task bar menu. The Windows UI has also been improved and now provides a task bar icon that can be right-clicked to manage networks. Both now expose managed route and IP permissions, allowing nodes to easily opt in to full tunnel operation if you have a router configured on your network.
The Mac has a whole new UI built natively in Objective-C. It provides a pulldown similar in appearance and operation to the Mac WiFi task bar menu.
The Windows UI has also been improved and now provides a task bar icon that can be right-clicked to manage networks. Both now expose managed route and IP permissions, allowing nodes to easily opt in to full tunnel operation if you have a router configured on your network.
### Ad-Hoc Networks
A special kind of public network called an ad-hoc network may be accessed by joining a network ID with the format:
ffSSSSEEEE000000
| | | |
| | | Reserved for future use, must be 0
| | End of port range (hex)
| Start of port range (hex)
Reserved ZeroTier address prefix indicating a controller-less network
Ad-hoc networks are public (no access control) networks that have no network controller. Instead their configuration and other credentials are generated locally. Ad-hoc networks permit only IPv6 UDP and TCP unicast traffic (no multicast or broadcast) using 6plane format NDP-emulated IPv6 addresses. In addition an ad-hoc network ID encodes an IP port range. UDP packets and TCP SYN (connection open) packets are only allowed to desintation ports within the encoded range.
For example `ff00160016000000` is an ad-hoc network allowing only SSH, while `ff0000ffff000000` is an ad-hoc network allowing any UDP or TCP port.
Keep in mind that these networks are public and anyone in the entire world can join them. Care must be taken to avoid exposing vulnerable services or sharing unwanted files or other resources.
### Network Controller (Partial) Rewrite
The network controller has been largely rewritten to use a simple in-filesystem JSON data store in place of SQLite, and it is now included by default in all Windows, Mac, Linux, and BSD builds. This means any desktop or server node running ZeroTier One can now be a controller with no recompilation needed.
If you have data in an old SQLite3 controller we've included a NodeJS script in `controller/migrate-sqlite` to migrate data to the new format. If you don't migrate, members will start getting `NOT_FOUND` when they attempt to query for updates.
## Major Bug Fixes in 1.2.0
* **The Windows HyperV 100% CPU bug**
* This long-running problem turns out to have been an issue with Windows itself, but one we were triggering by placing invalid data into the Windows registry. Microsoft is aware of the issue but we've also fixed the triggering problem on our side. ZeroTier should now co-exist quite well with HyperV and should now be able to be bridged with a HyperV virtual switch.
* **Segmenation Faults on musl-libc based Linux Systems**
* Alpine Linux and some embedded Linux systems that use musl libc (a minimal libc) experienced segmentation faults. These were due to a smaller default stack size. A work-around that sets the stack size for new threads has been added.
* **Windows Firewall Blocks Local JSON API**
* On some Windows systems the firewall likes to block 127.0.0.1:9993 for mysterious reasons. This is now fixed in the installer via the addition of another firewall exemption rule.
* **UI Crash on Embedded Windows Due to Missing Fonts**
* The MSI installer now ships fonts and will install them if they are not present, so this should be fixed.
* **The Windows HyperV 100% CPU bug is FINALLY DEAD**: This long-running problem turns out to have been an issue with Windows itself, but one we were triggering by placing invalid data into the Windows registry. Microsoft is aware of the issue but we've also fixed the triggering problem on our side. ZeroTier should now co-exist quite well with HyperV and should now be able to be bridged with a HyperV virtual switch.
* **Segmenation faults on musl-libc based Linux systems**: Alpine Linux and some embedded Linux systems that use musl libc (a minimal libc) experienced segmentation faults. These were due to a smaller default stack size. A work-around that sets the stack size for new threads has been added.
* **Windows firewall blocks local JSON API**: On some Windows systems the firewall likes to block 127.0.0.1:9993 for mysterious reasons. This is now fixed in the installer via the addition of another firewall exemption rule.
* **UI crash on embedded Windows due to missing fonts**: The MSI installer now ships fonts and will install them if they are not present, so this should be fixed.
## Other Improvements in 1.2.0
* **Improved dead path detection**: ZeroTier is now more aggressive about expiring paths that do not seem to be active. If a path seems marginal it is re-confirmed before re-use.
* **Minor performance improvements**: We've reduced unnecessary memcpy's and made a few other performance improvements in the core.
* **Linux static binaries**: For our official packages (the ones in the download.zerotier.com apt and yum repositories) we now build Linux binaries with static linking. Hopefully this will stop all the bug reports relating to library inconsistencies, as well as allowing our deb packages to run on a wider variety of Debian-based distributions. (There are far too many of these to support officially!) The overhead for this is very small, especially since we built our static versions against musl-libc. Distribution maintainers are of course free to build dynamically linked versions for inclusion into distributions; this only affects our official binaries.

View File

@@ -61,9 +61,6 @@ using json = nlohmann::json;
// Nodes are considered active if they've queried in less than this long
#define ZT_NETCONF_NODE_ACTIVE_THRESHOLD (ZT_NETWORK_AUTOCONF_DELAY * 2)
// Timeout for disk read cache (ms)
#define ZT_NETCONF_DB_CACHE_TTL 60000
namespace ZeroTier {
static json _renderRule(ZT_VirtualNetworkRule &rule)
@@ -432,6 +429,7 @@ static bool _parseRule(json &r,ZT_VirtualNetworkRule &rule)
}
EmbeddedNetworkController::EmbeddedNetworkController(Node *node,const char *dbPath) :
_startTime(OSUtils::now()),
_threadsStarted(false),
_db(dbPath),
_node(node)
@@ -503,7 +501,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET(
json network;
{
Mutex::Lock _l(_db_m);
network = _db.get("network",nwids,ZT_NETCONF_DB_CACHE_TTL);
network = _db.get("network",nwids);
}
if (!network.size())
return 404;
@@ -518,7 +516,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET(
json member;
{
Mutex::Lock _l(_db_m);
member = _db.get("network",nwids,"member",Address(address).toString(),ZT_NETCONF_DB_CACHE_TTL);
member = _db.get("network",nwids,"member",Address(address).toString());
}
if (!member.size())
return 404;
@@ -533,11 +531,10 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET(
Mutex::Lock _l(_db_m);
responseBody = "{";
std::string pfx(std::string("network/") + nwids + "member/");
_db.filter(pfx,ZT_NETCONF_DB_CACHE_TTL,[&responseBody](const std::string &n,const json &member) {
if (member.size() > 0) {
_db.filter((std::string("network/") + nwids + "/member/"),[&responseBody](const std::string &n,const json &member) {
if ((member.is_object())&&(member.size() > 0)) {
responseBody.append((responseBody.length() == 1) ? "\"" : ",\"");
responseBody.append(OSUtils::jsonString(member["id"],""));
responseBody.append(OSUtils::jsonString(member["id"],"0"));
responseBody.append("\":");
responseBody.append(OSUtils::jsonString(member["revision"],"0"));
}
@@ -567,7 +564,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET(
std::set<std::string> networkIds;
{
Mutex::Lock _l(_db_m);
_db.filter("network/",120000,[&networkIds](const std::string &n,const json &obj) {
_db.filter("network/",[&networkIds](const std::string &n,const json &obj) {
if (n.length() == (16 + 8))
networkIds.insert(n.substr(8));
return true; // do not delete
@@ -642,7 +639,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST(
json member;
{
Mutex::Lock _l(_db_m);
member = _db.get("network",nwids,"member",Address(address).toString(),ZT_NETCONF_DB_CACHE_TTL);
member = _db.get("network",nwids,"member",Address(address).toString());
}
json origMember(member); // for detecting changes
_initMember(member);
@@ -793,7 +790,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST(
test->timestamp = OSUtils::now();
if (_node) {
_node->circuitTestBegin(test,&(EmbeddedNetworkController::_circuitTestCallback));
_node->circuitTestBegin((void *)0,test,&(EmbeddedNetworkController::_circuitTestCallback));
} else {
_tests.pop_back();
return 500;
@@ -825,7 +822,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST(
uint64_t tryNwid = nwidPrefix | (nwidPostfix & 0xffffffULL);
if ((tryNwid & 0xffffffULL) == 0ULL) tryNwid |= 1ULL;
Utils::snprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)tryNwid);
if (_db.get("network",nwids,ZT_NETCONF_DB_CACHE_TTL).size() <= 0) {
if (_db.get("network",nwids).size() <= 0) {
nwid = tryNwid;
break;
}
@@ -834,7 +831,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST(
return 503;
}
network = _db.get("network",nwids,ZT_NETCONF_DB_CACHE_TTL);
network = _db.get("network",nwids);
}
json origNetwork(network); // for detecting changes
_initNetwork(network);
@@ -1054,7 +1051,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST(
}
// Send an update to all members of the network
_db.filter((std::string("network/") + nwids + "/member/"),120000,[this,&now,&nwid](const std::string &n,const json &obj) {
_db.filter((std::string("network/") + nwids + "/member/"),[this,&now,&nwid](const std::string &n,const json &obj) {
_pushMemberUpdate(now,nwid,obj);
return true; // do not delete
});
@@ -1071,7 +1068,15 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST(
} // else 404
} // else 404
} else if (path[0] == "dbtest") {
json testRec;
const uint64_t now = OSUtils::now();
testRec["clock"] = now;
testRec["uptime"] = (now - _startTime);
_db.put("dbtest",testRec);
}
return 404;
}
@@ -1096,7 +1101,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpDELETE(
json network;
{
Mutex::Lock _l(_db_m);
network = _db.get("network",nwids,ZT_NETCONF_DB_CACHE_TTL);
network = _db.get("network",nwids);
}
if (!network.size())
return 404;
@@ -1107,7 +1112,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpDELETE(
Mutex::Lock _l(_db_m);
json member = _db.get("network",nwids,"member",Address(address).toString(),ZT_NETCONF_DB_CACHE_TTL);
json member = _db.get("network",nwids,"member",Address(address).toString());
_db.erase("network",nwids,"member",Address(address).toString());
if (!member.size())
@@ -1120,7 +1125,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpDELETE(
Mutex::Lock _l(_db_m);
std::string pfx("network/"); pfx.append(nwids);
_db.filter(pfx,120000,[](const std::string &n,const json &obj) {
_db.filter(pfx,[](const std::string &n,const json &obj) {
return false; // delete
});
@@ -1247,8 +1252,8 @@ void EmbeddedNetworkController::_request(
json member;
{
Mutex::Lock _l(_db_m);
network = _db.get("network",nwids,ZT_NETCONF_DB_CACHE_TTL);
member = _db.get("network",nwids,"member",identity.address().toString(),ZT_NETCONF_DB_CACHE_TTL);
network = _db.get("network",nwids);
member = _db.get("network",nwids,"member",identity.address().toString());
}
if (!network.size()) {
@@ -1773,7 +1778,7 @@ void EmbeddedNetworkController::_getNetworkMemberInfo(uint64_t now,uint64_t nwid
{
Mutex::Lock _l(_db_m);
_db.filter(pfx,120000,[&nmi,&now](const std::string &n,const json &member) {
_db.filter(pfx,[&nmi,&now](const std::string &n,const json &member) {
try {
if (OSUtils::jsonBool(member["authorized"],false)) {
++nmi.authorizedMemberCount;

View File

@@ -98,14 +98,6 @@ public:
throw();
private:
static void _circuitTestCallback(ZT_Node *node,ZT_CircuitTest *test,const ZT_CircuitTestReport *report);
void _request(
uint64_t nwid,
const InetAddress &fromAddr,
uint64_t requestPacketId,
const Identity &identity,
const Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> &metaData);
struct _RQEntry
{
uint64_t nwid;
@@ -114,11 +106,6 @@ private:
Identity identity;
Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> metaData;
};
BlockingQueue<_RQEntry *> _queue;
Thread _threads[ZT_EMBEDDEDNETWORKCONTROLLER_BACKGROUND_THREAD_COUNT];
bool _threadsStarted;
Mutex _threads_m;
// Gathers a bunch of statistics about members of a network, IP assignments, etc. that we need in various places
struct _NetworkMemberInfo
@@ -132,15 +119,11 @@ private:
uint64_t mostRecentDeauthTime;
uint64_t nmiTimestamp; // time this NMI structure was computed
};
std::map<uint64_t,_NetworkMemberInfo> _nmiCache;
Mutex _nmiCache_m;
void _getNetworkMemberInfo(uint64_t now,uint64_t nwid,_NetworkMemberInfo &nmi);
inline void _clearNetworkMemberInfoCache(const uint64_t nwid)
{
Mutex::Lock _l(_nmiCache_m);
_nmiCache.erase(nwid);
}
static void _circuitTestCallback(ZT_Node *node,ZT_CircuitTest *test,const ZT_CircuitTestReport *report);
void _request(uint64_t nwid,const InetAddress &fromAddr,uint64_t requestPacketId,const Identity &identity,const Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> &metaData);
void _getNetworkMemberInfo(uint64_t now,uint64_t nwid,_NetworkMemberInfo &nmi);
inline void _clearNetworkMemberInfoCache(const uint64_t nwid) { Mutex::Lock _l(_nmiCache_m); _nmiCache.erase(nwid); }
void _pushMemberUpdate(uint64_t now,uint64_t nwid,const nlohmann::json &member);
// These init objects with default and static/informational fields
@@ -196,6 +179,16 @@ private:
member["clock"] = now;
}
const uint64_t _startTime;
BlockingQueue<_RQEntry *> _queue;
Thread _threads[ZT_EMBEDDEDNETWORKCONTROLLER_BACKGROUND_THREAD_COUNT];
bool _threadsStarted;
Mutex _threads_m;
std::map<uint64_t,_NetworkMemberInfo> _nmiCache;
Mutex _nmiCache_m;
JSONDB _db;
Mutex _db_m;

View File

@@ -53,52 +53,26 @@ bool JSONDB::put(const std::string &n,const nlohmann::json &obj)
_E &e = _db[n];
e.obj = obj;
e.lastModifiedOnDisk = OSUtils::getLastModified(path.c_str());
e.lastCheck = OSUtils::now();
return true;
}
const nlohmann::json &JSONDB::get(const std::string &n,unsigned long maxSinceCheck)
const nlohmann::json &JSONDB::get(const std::string &n)
{
if (!_isValidObjectName(n))
return _EMPTY_JSON;
const uint64_t now = OSUtils::now();
std::string buf;
std::map<std::string,_E>::iterator e(_db.find(n));
if (e != _db.end()) {
if ((now - e->second.lastCheck) <= (uint64_t)maxSinceCheck)
if (e != _db.end())
return e->second.obj;
const std::string path(_genPath(n,false));
if (!path.length()) // sanity check
return _EMPTY_JSON;
// We are somewhat tolerant to momentary disk failures here. This may
// occur over e.g. EC2's elastic filesystem (NFS).
const uint64_t lm = OSUtils::getLastModified(path.c_str());
if (e->second.lastModifiedOnDisk != lm) {
if (OSUtils::readFile(path.c_str(),buf)) {
try {
e->second.obj = OSUtils::jsonParse(buf);
e->second.lastModifiedOnDisk = lm; // don't update these if there is a parse error -- try again and again ASAP
e->second.lastCheck = now;
} catch ( ... ) {} // parse errors result in "holding pattern" behavior
}
}
return e->second.obj;
} else {
const std::string path(_genPath(n,false));
if (!path.length())
return _EMPTY_JSON;
std::string buf;
if (!OSUtils::readFile(path.c_str(),buf))
return _EMPTY_JSON;
const uint64_t lm = OSUtils::getLastModified(path.c_str());
_E &e2 = _db[n];
try {
e2.obj = OSUtils::jsonParse(buf);
@@ -106,11 +80,8 @@ const nlohmann::json &JSONDB::get(const std::string &n,unsigned long maxSinceChe
e2.obj = _EMPTY_JSON;
buf = "{}";
}
e2.lastModifiedOnDisk = lm;
e2.lastCheck = now;
return e2.obj;
}
}
void JSONDB::erase(const std::string &n)
@@ -126,22 +97,14 @@ void JSONDB::erase(const std::string &n)
_db.erase(n);
}
void JSONDB::_reload(const std::string &p)
void JSONDB::_reload(const std::string &p,const std::string &b)
{
std::map<std::string,char> l(OSUtils::listDirectoryFull(p.c_str()));
for(std::map<std::string,char>::iterator li(l.begin());li!=l.end();++li) {
if (li->second == 'f') {
// assume p starts with _basePath, which it always does -- will throw otherwise
std::string n(p.substr(_basePath.length()));
while ((n.length() > 0)&&(n[0] == ZT_PATH_SEPARATOR)) n = n.substr(1);
if (ZT_PATH_SEPARATOR != '/') std::replace(n.begin(),n.end(),ZT_PATH_SEPARATOR,'/');
if ((n.length() > 0)&&(n[n.length() - 1] != '/')) n.push_back('/');
n.append(li->first);
if ((n.length() > 5)&&(n.substr(n.length() - 5) == ".json")) {
this->get(n.substr(0,n.length() - 5),0); // causes load and cache or update
}
} else if (li->second == 'd') {
this->_reload(p + ZT_PATH_SEPARATOR + li->first);
std::vector<std::string> dl(OSUtils::listDirectory(p.c_str()));
for(std::vector<std::string>::const_iterator di(dl.begin());di!=dl.end();++di) {
if ((di->length() > 5)&&(di->substr(di->length() - 5) == ".json")) {
this->get(b + di->substr(0,di->length() - 5));
} else {
this->_reload((p + ZT_PATH_SEPARATOR + *di),(b + *di + ZT_PATH_SEPARATOR));
}
}
}

View File

@@ -45,13 +45,13 @@ public:
JSONDB(const std::string &basePath) :
_basePath(basePath)
{
_reload(_basePath);
_reload(_basePath,std::string());
}
inline void reload()
{
_db.clear();
_reload(_basePath);
_reload(_basePath,std::string());
}
bool writeRaw(const std::string &n,const std::string &obj);
@@ -63,12 +63,12 @@ public:
inline bool put(const std::string &n1,const std::string &n2,const std::string &n3,const std::string &n4,const nlohmann::json &obj) { return this->put((n1 + "/" + n2 + "/" + n3 + "/" + n4),obj); }
inline bool put(const std::string &n1,const std::string &n2,const std::string &n3,const std::string &n4,const std::string &n5,const nlohmann::json &obj) { return this->put((n1 + "/" + n2 + "/" + n3 + "/" + n4 + "/" + n5),obj); }
const nlohmann::json &get(const std::string &n,unsigned long maxSinceCheck = 0);
const nlohmann::json &get(const std::string &n);
inline const nlohmann::json &get(const std::string &n1,const std::string &n2,unsigned long maxSinceCheck = 0) { return this->get((n1 + "/" + n2),maxSinceCheck); }
inline const nlohmann::json &get(const std::string &n1,const std::string &n2,const std::string &n3,unsigned long maxSinceCheck = 0) { return this->get((n1 + "/" + n2 + "/" + n3),maxSinceCheck); }
inline const nlohmann::json &get(const std::string &n1,const std::string &n2,const std::string &n3,const std::string &n4,unsigned long maxSinceCheck = 0) { return this->get((n1 + "/" + n2 + "/" + n3 + "/" + n4),maxSinceCheck); }
inline const nlohmann::json &get(const std::string &n1,const std::string &n2,const std::string &n3,const std::string &n4,const std::string &n5,unsigned long maxSinceCheck = 0) { return this->get((n1 + "/" + n2 + "/" + n3 + "/" + n4 + "/" + n5),maxSinceCheck); }
inline const nlohmann::json &get(const std::string &n1,const std::string &n2) { return this->get((n1 + "/" + n2)); }
inline const nlohmann::json &get(const std::string &n1,const std::string &n2,const std::string &n3) { return this->get((n1 + "/" + n2 + "/" + n3)); }
inline const nlohmann::json &get(const std::string &n1,const std::string &n2,const std::string &n3,const std::string &n4) { return this->get((n1 + "/" + n2 + "/" + n3 + "/" + n4)); }
inline const nlohmann::json &get(const std::string &n1,const std::string &n2,const std::string &n3,const std::string &n4,const std::string &n5) { return this->get((n1 + "/" + n2 + "/" + n3 + "/" + n4 + "/" + n5)); }
void erase(const std::string &n);
@@ -78,11 +78,11 @@ public:
inline void erase(const std::string &n1,const std::string &n2,const std::string &n3,const std::string &n4,const std::string &n5) { this->erase(n1 + "/" + n2 + "/" + n3 + "/" + n4 + "/" + n5); }
template<typename F>
inline void filter(const std::string &prefix,unsigned long maxSinceCheck,F func)
inline void filter(const std::string &prefix,F func)
{
for(std::map<std::string,_E>::iterator i(_db.lower_bound(prefix));i!=_db.end();) {
if ((i->first.length() >= prefix.length())&&(!memcmp(i->first.data(),prefix.data(),prefix.length()))) {
if (!func(i->first,get(i->first,maxSinceCheck))) {
if (!func(i->first,get(i->first))) {
std::map<std::string,_E>::iterator i2(i); ++i2;
this->erase(i->first);
i = i2;
@@ -95,16 +95,13 @@ public:
inline bool operator!=(const JSONDB &db) const { return (!(*this == db)); }
private:
void _reload(const std::string &p);
void _reload(const std::string &p,const std::string &b);
bool _isValidObjectName(const std::string &n);
std::string _genPath(const std::string &n,bool create);
struct _E
{
nlohmann::json obj;
uint64_t lastModifiedOnDisk;
uint64_t lastCheck;
inline bool operator==(const _E &e) const { return (obj == e.obj); }
inline bool operator!=(const _E &e) const { return (obj != e.obj); }
};

View File

@@ -1408,6 +1408,7 @@ typedef void ZT_Node;
typedef int (*ZT_VirtualNetworkConfigFunction)(
ZT_Node *, /* Node */
void *, /* User ptr */
void *, /* Thread ptr */
uint64_t, /* Network ID */
void **, /* Modifiable network user PTR */
enum ZT_VirtualNetworkConfigOperation, /* Config operation */
@@ -1423,6 +1424,7 @@ typedef int (*ZT_VirtualNetworkConfigFunction)(
typedef void (*ZT_VirtualNetworkFrameFunction)(
ZT_Node *, /* Node */
void *, /* User ptr */
void *, /* Thread ptr */
uint64_t, /* Network ID */
void **, /* Modifiable network user PTR */
uint64_t, /* Source MAC */
@@ -1442,10 +1444,11 @@ typedef void (*ZT_VirtualNetworkFrameFunction)(
* in the definition of ZT_Event.
*/
typedef void (*ZT_EventCallback)(
ZT_Node *,
void *,
enum ZT_Event,
const void *);
ZT_Node *, /* Node */
void *, /* User ptr */
void *, /* Thread ptr */
enum ZT_Event, /* Event type */
const void *); /* Event payload (if applicable) */
/**
* Function to get an object from the data store
@@ -1468,8 +1471,9 @@ typedef void (*ZT_EventCallback)(
* object.
*/
typedef long (*ZT_DataStoreGetFunction)(
ZT_Node *,
void *,
ZT_Node *, /* Node */
void *, /* User ptr */
void *, /* Thread ptr */
const char *,
void *,
unsigned long,
@@ -1495,6 +1499,7 @@ typedef long (*ZT_DataStoreGetFunction)(
typedef int (*ZT_DataStorePutFunction)(
ZT_Node *,
void *,
void *, /* Thread ptr */
const char *,
const void *,
unsigned long,
@@ -1529,6 +1534,7 @@ typedef int (*ZT_DataStorePutFunction)(
typedef int (*ZT_WirePacketSendFunction)(
ZT_Node *, /* Node */
void *, /* User ptr */
void *, /* Thread ptr */
const struct sockaddr_storage *, /* Local address */
const struct sockaddr_storage *, /* Remote address */
const void *, /* Packet data */
@@ -1562,6 +1568,7 @@ typedef int (*ZT_WirePacketSendFunction)(
typedef int (*ZT_PathCheckFunction)(
ZT_Node *, /* Node */
void *, /* User ptr */
void *, /* Thread ptr */
uint64_t, /* ZeroTier address */
const struct sockaddr_storage *, /* Local address */
const struct sockaddr_storage *); /* Remote address */
@@ -1584,6 +1591,7 @@ typedef int (*ZT_PathCheckFunction)(
typedef int (*ZT_PathLookupFunction)(
ZT_Node *, /* Node */
void *, /* User ptr */
void *, /* Thread ptr */
uint64_t, /* ZeroTier address (40 bits) */
int, /* Desired ss_family or -1 for any */
struct sockaddr_storage *); /* Result buffer */
@@ -1654,11 +1662,12 @@ struct ZT_Node_Callbacks
*
* @param node Result: pointer is set to new node instance on success
* @param uptr User pointer to pass to functions/callbacks
* @param tptr Thread pointer to pass to functions/callbacks resulting from this call
* @param callbacks Callback function configuration
* @param now Current clock in milliseconds
* @return OK (0) or error code if a fatal error condition has occurred
*/
enum ZT_ResultCode ZT_Node_new(ZT_Node **node,void *uptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now);
enum ZT_ResultCode ZT_Node_new(ZT_Node **node,void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now);
/**
* Delete a node and free all resources it consumes
@@ -1674,6 +1683,7 @@ void ZT_Node_delete(ZT_Node *node);
* Process a packet received from the physical wire
*
* @param node Node instance
* @param tptr Thread pointer to pass to functions/callbacks resulting from this call
* @param now Current clock in milliseconds
* @param localAddress Local address, or point to ZT_SOCKADDR_NULL if unspecified
* @param remoteAddress Origin of packet
@@ -1684,6 +1694,7 @@ void ZT_Node_delete(ZT_Node *node);
*/
enum ZT_ResultCode ZT_Node_processWirePacket(
ZT_Node *node,
void *tptr,
uint64_t now,
const struct sockaddr_storage *localAddress,
const struct sockaddr_storage *remoteAddress,
@@ -1695,6 +1706,7 @@ enum ZT_ResultCode ZT_Node_processWirePacket(
* Process a frame from a virtual network port (tap)
*
* @param node Node instance
* @param tptr Thread pointer to pass to functions/callbacks resulting from this call
* @param now Current clock in milliseconds
* @param nwid ZeroTier 64-bit virtual network ID
* @param sourceMac Source MAC address (least significant 48 bits)
@@ -1708,6 +1720,7 @@ enum ZT_ResultCode ZT_Node_processWirePacket(
*/
enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame(
ZT_Node *node,
void *tptr,
uint64_t now,
uint64_t nwid,
uint64_t sourceMac,
@@ -1722,11 +1735,12 @@ enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame(
* Perform periodic background operations
*
* @param node Node instance
* @param tptr Thread pointer to pass to functions/callbacks resulting from this call
* @param now Current clock in milliseconds
* @param nextBackgroundTaskDeadline Value/result: set to deadline for next call to processBackgroundTasks()
* @return OK (0) or error code if a fatal error condition has occurred
*/
enum ZT_ResultCode ZT_Node_processBackgroundTasks(ZT_Node *node,uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline);
enum ZT_ResultCode ZT_Node_processBackgroundTasks(ZT_Node *node,void *tptr,uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline);
/**
* Join a network
@@ -1742,7 +1756,7 @@ enum ZT_ResultCode ZT_Node_processBackgroundTasks(ZT_Node *node,uint64_t now,vol
* @param uptr An arbitrary pointer to associate with this network (default: NULL)
* @return OK (0) or error code if a fatal error condition has occurred
*/
enum ZT_ResultCode ZT_Node_join(ZT_Node *node,uint64_t nwid,void *uptr);
enum ZT_ResultCode ZT_Node_join(ZT_Node *node,uint64_t nwid,void *uptr,void *tptr);
/**
* Leave a network
@@ -1759,7 +1773,7 @@ enum ZT_ResultCode ZT_Node_join(ZT_Node *node,uint64_t nwid,void *uptr);
* @param uptr Target pointer is set to uptr (if not NULL)
* @return OK (0) or error code if a fatal error condition has occurred
*/
enum ZT_ResultCode ZT_Node_leave(ZT_Node *node,uint64_t nwid,void **uptr);
enum ZT_ResultCode ZT_Node_leave(ZT_Node *node,uint64_t nwid,void **uptr,void *tptr);
/**
* Subscribe to an Ethernet multicast group
@@ -1781,12 +1795,13 @@ enum ZT_ResultCode ZT_Node_leave(ZT_Node *node,uint64_t nwid,void **uptr);
* This does not generate an update call to networkConfigCallback().
*
* @param node Node instance
* @param tptr Thread pointer to pass to functions/callbacks resulting from this call
* @param nwid 64-bit network ID
* @param multicastGroup Ethernet multicast or broadcast MAC (least significant 48 bits)
* @param multicastAdi Multicast ADI (least significant 32 bits only, use 0 if not needed)
* @return OK (0) or error code if a fatal error condition has occurred
*/
enum ZT_ResultCode ZT_Node_multicastSubscribe(ZT_Node *node,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi);
enum ZT_ResultCode ZT_Node_multicastSubscribe(ZT_Node *node,void *tptr,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi);
/**
* Unsubscribe from an Ethernet multicast group (or all groups)
@@ -1811,21 +1826,24 @@ enum ZT_ResultCode ZT_Node_multicastUnsubscribe(ZT_Node *node,uint64_t nwid,uint
* across invocations if the contents of moon.d are scanned and orbit is
* called for each on startup.
*
* @param node Node instance
* @param tptr Thread pointer to pass to functions/callbacks resulting from this call
* @param moonWorldId Moon's world ID
* @param moonSeed If non-zero, the ZeroTier address of any member of the moon to query for moon definition
* @param len Length of moonWorld in bytes
* @return Error if moon was invalid or failed to be added
*/
enum ZT_ResultCode ZT_Node_orbit(ZT_Node *node,uint64_t moonWorldId,uint64_t moonSeed);
enum ZT_ResultCode ZT_Node_orbit(ZT_Node *node,void *tptr,uint64_t moonWorldId,uint64_t moonSeed);
/**
* Remove a moon (does nothing if not present)
*
* @param node Node instance
* @param tptr Thread pointer to pass to functions/callbacks resulting from this call
* @param moonWorldId World ID of moon to remove
* @return Error if anything bad happened
*/
enum ZT_ResultCode ZT_Node_deorbit(ZT_Node *node,uint64_t moonWorldId);
enum ZT_ResultCode ZT_Node_deorbit(ZT_Node *node,void *tptr,uint64_t moonWorldId);
/**
* Get this node's 40-bit ZeroTier address
@@ -1919,13 +1937,15 @@ void ZT_Node_clearLocalInterfaceAddresses(ZT_Node *node);
* There is no delivery guarantee here. Failure can occur if the message is
* too large or if dest is not a valid ZeroTier address.
*
* @param node Node instance
* @param tptr Thread pointer to pass to functions/callbacks resulting from this call
* @param dest Destination ZeroTier address
* @param typeId VERB_USER_MESSAGE type ID
* @param data Payload data to attach to user message
* @param len Length of data in bytes
* @return Boolean: non-zero on success, zero on failure
*/
int ZT_Node_sendUserMessage(ZT_Node *node,uint64_t dest,uint64_t typeId,const void *data,unsigned int len);
int ZT_Node_sendUserMessage(ZT_Node *node,void *tptr,uint64_t dest,uint64_t typeId,const void *data,unsigned int len);
/**
* Set a network configuration master instance for this node
@@ -1957,11 +1977,12 @@ void ZT_Node_setNetconfMaster(ZT_Node *node,void *networkConfigMasterInstance);
* for results forever.
*
* @param node Node instance
* @param tptr Thread pointer to pass to functions/callbacks resulting from this call
* @param test Test configuration
* @param reportCallback Function to call each time a report is received
* @return OK or error if, for example, test is too big for a packet or support isn't compiled in
*/
enum ZT_ResultCode ZT_Node_circuitTestBegin(ZT_Node *node,ZT_CircuitTest *test,void (*reportCallback)(ZT_Node *, ZT_CircuitTest *,const ZT_CircuitTestReport *));
enum ZT_ResultCode ZT_Node_circuitTestBegin(ZT_Node *node,void *tptr,ZT_CircuitTest *test,void (*reportCallback)(ZT_Node *, ZT_CircuitTest *,const ZT_CircuitTestReport *));
/**
* Stop listening for results to a given circuit test

View File

@@ -96,6 +96,18 @@ endif
ifeq ($(CC_MACH),arm)
ZT_ARCHITECTURE=3
endif
ifeq ($(CC_MACH),armel)
ZT_ARCHITECTURE=3
endif
ifeq ($(CC_MACH),armhf)
ZT_ARCHITECTURE=3
endif
ifeq ($(CC_MACH),armv6)
ZT_ARCHITECTURE=3
endif
ifeq ($(CC_MACH),armv7)
ZT_ARCHITECTURE=3
endif
ifeq ($(CC_MACH),arm64)
ZT_ARCHITECTURE=4
endif
@@ -104,6 +116,13 @@ ifeq ($(CC_MACH),aarch64)
endif
DEFS+=-DZT_BUILD_PLATFORM=1 -DZT_BUILD_ARCHITECTURE=$(ZT_ARCHITECTURE) -DZT_SOFTWARE_UPDATE_DEFAULT="\"disable\""
# Define some conservative CPU instruction set flags for arm32 since there's a ton of variation out there
ifeq ($(ZT_ARCHITECTURE),3)
override CFLAGS+=-march=armv6zk -mcpu=arm1176jzf-s -mfloat-abi=hard -mfpu=vfp
override CXXFLAGS+=-march=armv6zk -mcpu=arm1176jzf-s -mfloat-abi=hard -mfpu=vfp
override DEFS+=-DZT_NO_TYPE_PUNNING
endif
# Define this to build a static binary, which is needed to make this runnable on a few ancient Linux distros
ifeq ($(ZT_STATIC),1)
override LDFLAGS+=-static

View File

@@ -25,7 +25,7 @@
namespace ZeroTier {
int Capability::verify(const RuntimeEnvironment *RR) const
int Capability::verify(const RuntimeEnvironment *RR,void *tPtr) const
{
try {
// There must be at least one entry, and sanity check for bad chain max length
@@ -46,12 +46,12 @@ int Capability::verify(const RuntimeEnvironment *RR) const
return -1; // otherwise if we have another entry it must be from the previous holder in the chain
}
const Identity id(RR->topology->getIdentity(_custody[c].from));
const Identity id(RR->topology->getIdentity(tPtr,_custody[c].from));
if (id) {
if (!id.verify(tmp.data(),tmp.size(),_custody[c].signature))
return -1;
} else {
RR->sw->requestWhois(_custody[c].from);
RR->sw->requestWhois(tPtr,_custody[c].from);
return 1;
}
}

View File

@@ -161,7 +161,7 @@ public:
* @param RR Runtime environment to provide for peer lookup, etc.
* @return 0 == OK, 1 == waiting for WHOIS, -1 == BAD signature or chain
*/
int verify(const RuntimeEnvironment *RR) const;
int verify(const RuntimeEnvironment *RR,void *tPtr) const;
template<unsigned int C>
static inline void serializeRules(Buffer<C> &b,const ZT_VirtualNetworkRule *rules,unsigned int ruleCount)

View File

@@ -207,14 +207,14 @@ bool CertificateOfMembership::sign(const Identity &with)
}
}
int CertificateOfMembership::verify(const RuntimeEnvironment *RR) const
int CertificateOfMembership::verify(const RuntimeEnvironment *RR,void *tPtr) const
{
if ((!_signedBy)||(_signedBy != Network::controllerFor(networkId()))||(_qualifierCount > ZT_NETWORK_COM_MAX_QUALIFIERS))
return -1;
const Identity id(RR->topology->getIdentity(_signedBy));
const Identity id(RR->topology->getIdentity(tPtr,_signedBy));
if (!id) {
RR->sw->requestWhois(_signedBy);
RR->sw->requestWhois(tPtr,_signedBy);
return 1;
}

View File

@@ -250,9 +250,10 @@ public:
* Verify this COM and its signature
*
* @param RR Runtime environment for looking up peers
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @return 0 == OK, 1 == waiting for WHOIS, -1 == BAD signature or credential
*/
int verify(const RuntimeEnvironment *RR) const;
int verify(const RuntimeEnvironment *RR,void *tPtr) const;
/**
* @return True if signed

View File

@@ -25,13 +25,13 @@
namespace ZeroTier {
int CertificateOfOwnership::verify(const RuntimeEnvironment *RR) const
int CertificateOfOwnership::verify(const RuntimeEnvironment *RR,void *tPtr) const
{
if ((!_signedBy)||(_signedBy != Network::controllerFor(_networkId)))
return -1;
const Identity id(RR->topology->getIdentity(_signedBy));
const Identity id(RR->topology->getIdentity(tPtr,_signedBy));
if (!id) {
RR->sw->requestWhois(_signedBy);
RR->sw->requestWhois(tPtr,_signedBy);
return 1;
}
try {

View File

@@ -56,12 +56,9 @@ public:
THING_IPV6_ADDRESS = 3
};
CertificateOfOwnership() :
_networkId(0),
_ts(0),
_id(0),
_thingCount(0)
CertificateOfOwnership()
{
memset(this,0,sizeof(CertificateOfOwnership));
}
CertificateOfOwnership(const uint64_t nwid,const uint64_t ts,const Address &issuedTo,const uint32_t id) :
@@ -140,9 +137,10 @@ public:
/**
* @param RR Runtime environment to allow identity lookup for signedBy
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @return 0 == OK, 1 == waiting for WHOIS, -1 == BAD signature
*/
int verify(const RuntimeEnvironment *RR) const;
int verify(const RuntimeEnvironment *RR,void *tPtr) const;
template<unsigned int C>
inline void serialize(Buffer<C> &b,const bool forSign = false) const

View File

@@ -346,7 +346,7 @@ void Cluster::handleIncomingStateMessage(const void *msg,unsigned int len)
Mutex::Lock _l(_remotePeers_m);
_RemotePeer &rp = _remotePeers[std::pair<Address,unsigned int>(id.address(),(unsigned int)fromMemberId)];
if (!rp.lastHavePeerReceived) {
RR->topology->saveIdentity(id);
RR->topology->saveIdentity((void *)0,id);
RR->identity.agree(id,rp.key,ZT_PEER_SECRET_KEY_LENGTH);
}
rp.lastHavePeerReceived = RR->node->now();
@@ -459,7 +459,7 @@ void Cluster::handleIncomingStateMessage(const void *msg,unsigned int len)
Mutex::Lock _l2(_members[fromMemberId].lock);
_send(fromMemberId,CLUSTER_MESSAGE_PROXY_SEND,rendezvousForRemote.data(),rendezvousForRemote.size());
}
RR->sw->send(rendezvousForLocal,true);
RR->sw->send((void *)0,rendezvousForLocal,true);
}
}
} break;
@@ -470,7 +470,7 @@ void Cluster::handleIncomingStateMessage(const void *msg,unsigned int len)
const unsigned int len = dmsg.at<uint16_t>(ptr); ptr += 2;
Packet outp(rcpt,RR->identity.address(),verb);
outp.append(dmsg.field(ptr,len),len); ptr += len;
RR->sw->send(outp,true);
RR->sw->send((void *)0,outp,true);
//TRACE("[%u] proxy send %s to %s length %u",(unsigned int)fromMemberId,Packet::verbString(verb),rcpt.toString().c_str(),len);
} break;
@@ -479,7 +479,7 @@ void Cluster::handleIncomingStateMessage(const void *msg,unsigned int len)
if (network) {
// Copy into a Packet just to conform to Network API. Eventually
// will want to refactor.
network->handleConfigChunk(0,Address(),Buffer<ZT_PROTO_MAX_PACKET_LENGTH>(dmsg),ptr);
network->handleConfigChunk((void *)0,0,Address(),Buffer<ZT_PROTO_MAX_PACKET_LENGTH>(dmsg),ptr);
}
} break;
}
@@ -576,7 +576,7 @@ bool Cluster::sendViaCluster(int mostRecentMemberId,const Address &toPeerAddress
for(std::vector<InetAddress>::const_iterator i2(_members[mostRecentMemberId].zeroTierPhysicalEndpoints.begin());i2!=_members[mostRecentMemberId].zeroTierPhysicalEndpoints.end();++i2) {
if (i1->ss_family == i2->ss_family) {
TRACE("sendViaCluster sending %u bytes to %s by way of %u (%s->%s)",len,toPeerAddress.toString().c_str(),(unsigned int)mostRecentMemberId,i1->toString().c_str(),i2->toString().c_str());
RR->node->putPacket(*i1,*i2,data,len);
RR->node->putPacket((void *)0,*i1,*i2,data,len);
return true;
}
}
@@ -679,7 +679,7 @@ void Cluster::relayViaCluster(const Address &fromPeerAddress,const Address &toPe
for(std::vector<InetAddress>::const_iterator i2(_members[mostRecentMemberId].zeroTierPhysicalEndpoints.begin());i2!=_members[mostRecentMemberId].zeroTierPhysicalEndpoints.end();++i2) {
if (i1->ss_family == i2->ss_family) {
TRACE("relayViaCluster relaying %u bytes from %s to %s by way of %u (%s->%s)",len,fromPeerAddress.toString().c_str(),toPeerAddress.toString().c_str(),(unsigned int)mostRecentMemberId,i1->toString().c_str(),i2->toString().c_str());
RR->node->putPacket(*i1,*i2,data,len);
RR->node->putPacket((void *)0,*i1,*i2,data,len);
return;
}
}
@@ -981,7 +981,7 @@ void Cluster::_flush(uint16_t memberId)
void Cluster::_doREMOTE_WHOIS(uint64_t fromMemberId,const Packet &remotep)
{
if (remotep.payloadLength() >= ZT_ADDRESS_LENGTH) {
Identity queried(RR->topology->getIdentity(Address(remotep.payload(),ZT_ADDRESS_LENGTH)));
Identity queried(RR->topology->getIdentity((void *)0,Address(remotep.payload(),ZT_ADDRESS_LENGTH)));
if (queried) {
Buffer<1024> routp;
remotep.source().appendTo(routp);

View File

@@ -61,15 +61,23 @@ public:
Dictionary(const char *s)
{
if (s) {
Utils::scopy(_d,sizeof(_d),s);
} else {
_d[0] = (char)0;
}
}
Dictionary(const char *s,unsigned int len)
{
if (s) {
if (len > (C-1))
len = C-1;
memcpy(_d,s,len);
_d[len] = (char)0;
} else {
_d[0] = (char)0;
}
}
Dictionary(const Dictionary &d)
@@ -91,7 +99,12 @@ public:
*/
inline bool load(const char *s)
{
if (s) {
return Utils::scopy(_d,sizeof(_d),s);
} else {
_d[0] = (char)0;
return true;
}
}
/**

View File

@@ -44,7 +44,7 @@
namespace ZeroTier {
bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR)
bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR,void *tPtr)
{
const Address sourceAddress(source());
@@ -65,20 +65,22 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR)
}
} else if ((c == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_NONE)&&(verb() == Packet::VERB_HELLO)) {
// Only HELLO is allowed in the clear, but will still have a MAC
return _doHELLO(RR,false);
return _doHELLO(RR,tPtr,false);
}
const SharedPtr<Peer> peer(RR->topology->getPeer(sourceAddress));
const SharedPtr<Peer> peer(RR->topology->getPeer(tPtr,sourceAddress));
if (peer) {
if (!trusted) {
if (!dearmor(peer->key())) {
//fprintf(stderr,"dropped packet from %s(%s), MAC authentication failed (size: %u)" ZT_EOL_S,sourceAddress.toString().c_str(),_path->address().toString().c_str(),size());
TRACE("dropped packet from %s(%s), MAC authentication failed (size: %u)",sourceAddress.toString().c_str(),_path->address().toString().c_str(),size());
return true;
}
}
if (!uncompress()) {
TRACE("dropped packet from %s(%s), compressed data invalid (verb may be %u)",sourceAddress.toString().c_str(),_path->address().toString().c_str(),(unsigned int)verb());
//fprintf(stderr,"dropped packet from %s(%s), compressed data invalid (size %u, verb may be %u)" ZT_EOL_S,sourceAddress.toString().c_str(),_path->address().toString().c_str(),size(),(unsigned int)verb());
TRACE("dropped packet from %s(%s), compressed data invalid (size %u, verb may be %u)",sourceAddress.toString().c_str(),_path->address().toString().c_str(),size(),(unsigned int)verb());
return true;
}
@@ -87,30 +89,30 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR)
switch(v) {
//case Packet::VERB_NOP:
default: // ignore unknown verbs, but if they pass auth check they are "received"
peer->received(_path,hops(),packetId(),v,0,Packet::VERB_NOP,false);
peer->received(tPtr,_path,hops(),packetId(),v,0,Packet::VERB_NOP,false);
return true;
case Packet::VERB_HELLO: return _doHELLO(RR,true);
case Packet::VERB_ERROR: return _doERROR(RR,peer);
case Packet::VERB_OK: return _doOK(RR,peer);
case Packet::VERB_WHOIS: return _doWHOIS(RR,peer);
case Packet::VERB_RENDEZVOUS: return _doRENDEZVOUS(RR,peer);
case Packet::VERB_FRAME: return _doFRAME(RR,peer);
case Packet::VERB_EXT_FRAME: return _doEXT_FRAME(RR,peer);
case Packet::VERB_ECHO: return _doECHO(RR,peer);
case Packet::VERB_MULTICAST_LIKE: return _doMULTICAST_LIKE(RR,peer);
case Packet::VERB_NETWORK_CREDENTIALS: return _doNETWORK_CREDENTIALS(RR,peer);
case Packet::VERB_NETWORK_CONFIG_REQUEST: return _doNETWORK_CONFIG_REQUEST(RR,peer);
case Packet::VERB_NETWORK_CONFIG: return _doNETWORK_CONFIG(RR,peer);
case Packet::VERB_MULTICAST_GATHER: return _doMULTICAST_GATHER(RR,peer);
case Packet::VERB_MULTICAST_FRAME: return _doMULTICAST_FRAME(RR,peer);
case Packet::VERB_PUSH_DIRECT_PATHS: return _doPUSH_DIRECT_PATHS(RR,peer);
case Packet::VERB_CIRCUIT_TEST: return _doCIRCUIT_TEST(RR,peer);
case Packet::VERB_CIRCUIT_TEST_REPORT: return _doCIRCUIT_TEST_REPORT(RR,peer);
case Packet::VERB_USER_MESSAGE: return _doUSER_MESSAGE(RR,peer);
case Packet::VERB_HELLO: return _doHELLO(RR,tPtr,true);
case Packet::VERB_ERROR: return _doERROR(RR,tPtr,peer);
case Packet::VERB_OK: return _doOK(RR,tPtr,peer);
case Packet::VERB_WHOIS: return _doWHOIS(RR,tPtr,peer);
case Packet::VERB_RENDEZVOUS: return _doRENDEZVOUS(RR,tPtr,peer);
case Packet::VERB_FRAME: return _doFRAME(RR,tPtr,peer);
case Packet::VERB_EXT_FRAME: return _doEXT_FRAME(RR,tPtr,peer);
case Packet::VERB_ECHO: return _doECHO(RR,tPtr,peer);
case Packet::VERB_MULTICAST_LIKE: return _doMULTICAST_LIKE(RR,tPtr,peer);
case Packet::VERB_NETWORK_CREDENTIALS: return _doNETWORK_CREDENTIALS(RR,tPtr,peer);
case Packet::VERB_NETWORK_CONFIG_REQUEST: return _doNETWORK_CONFIG_REQUEST(RR,tPtr,peer);
case Packet::VERB_NETWORK_CONFIG: return _doNETWORK_CONFIG(RR,tPtr,peer);
case Packet::VERB_MULTICAST_GATHER: return _doMULTICAST_GATHER(RR,tPtr,peer);
case Packet::VERB_MULTICAST_FRAME: return _doMULTICAST_FRAME(RR,tPtr,peer);
case Packet::VERB_PUSH_DIRECT_PATHS: return _doPUSH_DIRECT_PATHS(RR,tPtr,peer);
case Packet::VERB_CIRCUIT_TEST: return _doCIRCUIT_TEST(RR,tPtr,peer);
case Packet::VERB_CIRCUIT_TEST_REPORT: return _doCIRCUIT_TEST_REPORT(RR,tPtr,peer);
case Packet::VERB_USER_MESSAGE: return _doUSER_MESSAGE(RR,tPtr,peer);
}
} else {
RR->sw->requestWhois(sourceAddress);
RR->sw->requestWhois(tPtr,sourceAddress);
return false;
}
} catch ( ... ) {
@@ -121,7 +123,7 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR)
}
}
bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer)
bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer)
{
try {
const Packet::Verb inReVerb = (Packet::Verb)(*this)[ZT_PROTO_VERB_ERROR_IDX_IN_RE_VERB];
@@ -161,7 +163,7 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,const SharedPtr<Peer>
case Packet::ERROR_IDENTITY_COLLISION:
// FIXME: for federation this will need a payload with a signature or something.
if (RR->topology->isUpstream(peer->identity()))
RR->node->postEvent(ZT_EVENT_FATAL_ERROR_IDENTITY_COLLISION);
RR->node->postEvent(tPtr,ZT_EVENT_FATAL_ERROR_IDENTITY_COLLISION);
break;
case Packet::ERROR_NEED_MEMBERSHIP_CERTIFICATE: {
@@ -169,7 +171,7 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,const SharedPtr<Peer>
const SharedPtr<Network> network(RR->node->network(at<uint64_t>(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD)));
const uint64_t now = RR->node->now();
if ( (network) && (network->config().com) && (peer->rateGateIncomingComRequest(now)) )
network->pushCredentialsNow(peer->address(),now);
network->pushCredentialsNow(tPtr,peer->address(),now);
} break;
case Packet::ERROR_NETWORK_ACCESS_DENIED_: {
@@ -183,7 +185,7 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,const SharedPtr<Peer>
// Members of networks can use this error to indicate that they no longer
// want to receive multicasts on a given channel.
const SharedPtr<Network> network(RR->node->network(at<uint64_t>(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD)));
if ((network)&&(network->gate(peer))) {
if ((network)&&(network->gate(tPtr,peer))) {
const MulticastGroup mg(MAC(field(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD + 8,6),6),at<uint32_t>(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD + 14));
TRACE("%.16llx: peer %s unsubscrubed from multicast group %s",network->id(),peer->address().toString().c_str(),mg.toString().c_str());
RR->mc->remove(network->id(),mg,peer->address());
@@ -193,14 +195,14 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,const SharedPtr<Peer>
default: break;
}
peer->received(_path,hops(),packetId(),Packet::VERB_ERROR,inRePacketId,inReVerb,false);
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_ERROR,inRePacketId,inReVerb,false);
} catch ( ... ) {
TRACE("dropped ERROR from %s(%s): unexpected exception",peer->address().toString().c_str(),_path->address().toString().c_str());
}
return true;
}
bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,const bool alreadyAuthenticated)
bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool alreadyAuthenticated)
{
try {
const uint64_t now = RR->node->now();
@@ -224,7 +226,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,const bool alreadyAut
return true;
}
SharedPtr<Peer> peer(RR->topology->getPeer(id.address()));
SharedPtr<Peer> peer(RR->topology->getPeer(tPtr,id.address()));
if (peer) {
// We already have an identity with this address -- check for collisions
if (!alreadyAuthenticated) {
@@ -244,7 +246,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,const bool alreadyAut
outp.append((uint64_t)pid);
outp.append((uint8_t)Packet::ERROR_IDENTITY_COLLISION);
outp.armor(key,true,_path->nextOutgoingCounter());
_path->send(RR,outp.data(),outp.size(),RR->node->now());
_path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now());
} else {
TRACE("rejected HELLO from %s(%s): packet failed authentication",id.address().toString().c_str(),_path->address().toString().c_str());
}
@@ -290,7 +292,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,const bool alreadyAut
return true;
}
peer = RR->topology->addPeer(newPeer);
peer = RR->topology->addPeer(tPtr,newPeer);
// Continue at // VALID
}
@@ -302,7 +304,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,const bool alreadyAut
if (ptr < size()) {
ptr += externalSurfaceAddress.deserialize(*this,ptr);
if ((externalSurfaceAddress)&&(hops() == 0))
RR->sa->iam(id.address(),_path->localAddress(),_path->address(),externalSurfaceAddress,RR->topology->isUpstream(id),now);
RR->sa->iam(tPtr,id.address(),_path->localAddress(),_path->address(),externalSurfaceAddress,RR->topology->isUpstream(id),now);
}
// Get primary planet world ID and world timestamp if present
@@ -406,17 +408,17 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,const bool alreadyAut
outp.setAt(corSizeAt,(uint16_t)(outp.size() - (corSizeAt + 2)));
outp.armor(peer->key(),true,_path->nextOutgoingCounter());
_path->send(RR,outp.data(),outp.size(),now);
_path->send(RR,tPtr,outp.data(),outp.size(),now);
peer->setRemoteVersion(protoVersion,vMajor,vMinor,vRevision); // important for this to go first so received() knows the version
peer->received(_path,hops(),pid,Packet::VERB_HELLO,0,Packet::VERB_NOP,false);
peer->received(tPtr,_path,hops(),pid,Packet::VERB_HELLO,0,Packet::VERB_NOP,false);
} catch ( ... ) {
TRACE("dropped HELLO from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
}
return true;
}
bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer)
bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer)
{
try {
const Packet::Verb inReVerb = (Packet::Verb)(*this)[ZT_PROTO_VERB_OK_IDX_IN_RE_VERB];
@@ -461,7 +463,7 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &p
while (ptr < endOfWorlds) {
World w;
ptr += w.deserialize(*this,ptr);
RR->topology->addWorld(w,false);
RR->topology->addWorld(tPtr,w,false);
}
} else {
ptr += worldsLen;
@@ -477,27 +479,31 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &p
} else ptr += 2;
}
TRACE("%s(%s): OK(HELLO), version %u.%u.%u, latency %u, reported external address %s",source().toString().c_str(),_path->address().toString().c_str(),vMajor,vMinor,vRevision,latency,((externalSurfaceAddress) ? externalSurfaceAddress.toString().c_str() : "(none)"));
#ifdef ZT_TRACE
const std::string tmp1(source().toString());
const std::string tmp2(_path->address().toString());
TRACE("%s(%s): OK(HELLO), version %u.%u.%u, latency %u",tmp1.c_str(),tmp2.c_str(),vMajor,vMinor,vRevision,latency);
#endif
if (!hops())
peer->addDirectLatencyMeasurment((unsigned int)latency);
peer->setRemoteVersion(vProto,vMajor,vMinor,vRevision);
if ((externalSurfaceAddress)&&(hops() == 0))
RR->sa->iam(peer->address(),_path->localAddress(),_path->address(),externalSurfaceAddress,RR->topology->isUpstream(peer->identity()),RR->node->now());
RR->sa->iam(tPtr,peer->address(),_path->localAddress(),_path->address(),externalSurfaceAddress,RR->topology->isUpstream(peer->identity()),RR->node->now());
} break;
case Packet::VERB_WHOIS:
if (RR->topology->isUpstream(peer->identity())) {
const Identity id(*this,ZT_PROTO_VERB_WHOIS__OK__IDX_IDENTITY);
RR->sw->doAnythingWaitingForPeer(RR->topology->addPeer(SharedPtr<Peer>(new Peer(RR,RR->identity,id))));
RR->sw->doAnythingWaitingForPeer(tPtr,RR->topology->addPeer(tPtr,SharedPtr<Peer>(new Peer(RR,RR->identity,id))));
}
break;
case Packet::VERB_NETWORK_CONFIG_REQUEST: {
const SharedPtr<Network> network(RR->node->network(at<uint64_t>(ZT_PROTO_VERB_OK_IDX_PAYLOAD)));
if (network)
network->handleConfigChunk(packetId(),source(),*this,ZT_PROTO_VERB_OK_IDX_PAYLOAD);
network->handleConfigChunk(tPtr,packetId(),source(),*this,ZT_PROTO_VERB_OK_IDX_PAYLOAD);
} break;
case Packet::VERB_MULTICAST_GATHER: {
@@ -507,7 +513,7 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &p
const MulticastGroup mg(MAC(field(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_MAC,6),6),at<uint32_t>(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_ADI));
//TRACE("%s(%s): OK(MULTICAST_GATHER) %.16llx/%s length %u",source().toString().c_str(),_path->address().toString().c_str(),nwid,mg.toString().c_str(),size());
const unsigned int count = at<uint16_t>(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_GATHER_RESULTS + 4);
RR->mc->addMultiple(RR->node->now(),nwid,mg,field(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_GATHER_RESULTS + 6,count * 5),count,at<uint32_t>(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_GATHER_RESULTS));
RR->mc->addMultiple(tPtr,RR->node->now(),nwid,mg,field(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_GATHER_RESULTS + 6,count * 5),count,at<uint32_t>(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_GATHER_RESULTS));
}
} break;
@@ -526,7 +532,7 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &p
CertificateOfMembership com;
offset += com.deserialize(*this,ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_COM_AND_GATHER_RESULTS);
if (com)
network->addCredential(com);
network->addCredential(tPtr,com);
}
if ((flags & 0x02) != 0) {
@@ -534,7 +540,7 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &p
offset += ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_COM_AND_GATHER_RESULTS;
unsigned int totalKnown = at<uint32_t>(offset); offset += 4;
unsigned int count = at<uint16_t>(offset); offset += 2;
RR->mc->addMultiple(RR->node->now(),nwid,mg,field(offset,count * 5),count,totalKnown);
RR->mc->addMultiple(tPtr,RR->node->now(),nwid,mg,field(offset,count * 5),count,totalKnown);
}
}
} break;
@@ -542,14 +548,14 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &p
default: break;
}
peer->received(_path,hops(),packetId(),Packet::VERB_OK,inRePacketId,inReVerb,false);
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_OK,inRePacketId,inReVerb,false);
} catch ( ... ) {
TRACE("dropped OK from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
}
return true;
}
bool IncomingPacket::_doWHOIS(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer)
bool IncomingPacket::_doWHOIS(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer)
{
try {
if ((!RR->topology->amRoot())&&(!peer->rateGateInboundWhoisRequest(RR->node->now()))) {
@@ -567,13 +573,13 @@ bool IncomingPacket::_doWHOIS(const RuntimeEnvironment *RR,const SharedPtr<Peer>
const Address addr(field(ptr,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH);
ptr += ZT_ADDRESS_LENGTH;
const Identity id(RR->topology->getIdentity(addr));
const Identity id(RR->topology->getIdentity(tPtr,addr));
if (id) {
id.serialize(outp,false);
++count;
} else {
// Request unknown WHOIS from upstream from us (if we have one)
RR->sw->requestWhois(addr);
RR->sw->requestWhois(tPtr,addr);
#ifdef ZT_ENABLE_CLUSTER
// Distribute WHOIS queries across a cluster if we do not know the ID.
// This may result in duplicate OKs to the querying peer, which is fine.
@@ -585,32 +591,32 @@ bool IncomingPacket::_doWHOIS(const RuntimeEnvironment *RR,const SharedPtr<Peer>
if (count > 0) {
outp.armor(peer->key(),true,_path->nextOutgoingCounter());
_path->send(RR,outp.data(),outp.size(),RR->node->now());
_path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now());
}
peer->received(_path,hops(),packetId(),Packet::VERB_WHOIS,0,Packet::VERB_NOP,false);
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_WHOIS,0,Packet::VERB_NOP,false);
} catch ( ... ) {
TRACE("dropped WHOIS from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
}
return true;
}
bool IncomingPacket::_doRENDEZVOUS(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer)
bool IncomingPacket::_doRENDEZVOUS(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer)
{
try {
if (!RR->topology->isUpstream(peer->identity())) {
TRACE("RENDEZVOUS from %s ignored since source is not upstream",peer->address().toString().c_str());
} else {
const Address with(field(ZT_PROTO_VERB_RENDEZVOUS_IDX_ZTADDRESS,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH);
const SharedPtr<Peer> rendezvousWith(RR->topology->getPeer(with));
const SharedPtr<Peer> rendezvousWith(RR->topology->getPeer(tPtr,with));
if (rendezvousWith) {
const unsigned int port = at<uint16_t>(ZT_PROTO_VERB_RENDEZVOUS_IDX_PORT);
const unsigned int addrlen = (*this)[ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRLEN];
if ((port > 0)&&((addrlen == 4)||(addrlen == 16))) {
const InetAddress atAddr(field(ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRESS,addrlen),addrlen,port);
if (RR->node->shouldUsePathForZeroTierTraffic(with,_path->localAddress(),atAddr)) {
RR->node->putPacket(_path->localAddress(),atAddr,"ABRE",4,2); // send low-TTL junk packet to 'open' local NAT(s) and stateful firewalls
rendezvousWith->attemptToContactAt(_path->localAddress(),atAddr,RR->node->now(),false,0);
if (RR->node->shouldUsePathForZeroTierTraffic(tPtr,with,_path->localAddress(),atAddr)) {
RR->node->putPacket(tPtr,_path->localAddress(),atAddr,"ABRE",4,2); // send low-TTL junk packet to 'open' local NAT(s) and stateful firewalls
rendezvousWith->attemptToContactAt(tPtr,_path->localAddress(),atAddr,RR->node->now(),false,0);
TRACE("RENDEZVOUS from %s says %s might be at %s, sent verification attempt",peer->address().toString().c_str(),with.toString().c_str(),atAddr.toString().c_str());
} else {
TRACE("RENDEZVOUS from %s says %s might be at %s, ignoring since path is not suitable",peer->address().toString().c_str(),with.toString().c_str(),atAddr.toString().c_str());
@@ -622,46 +628,46 @@ bool IncomingPacket::_doRENDEZVOUS(const RuntimeEnvironment *RR,const SharedPtr<
TRACE("ignored RENDEZVOUS from %s(%s) to meet unknown peer %s",peer->address().toString().c_str(),_path->address().toString().c_str(),with.toString().c_str());
}
}
peer->received(_path,hops(),packetId(),Packet::VERB_RENDEZVOUS,0,Packet::VERB_NOP,false);
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_RENDEZVOUS,0,Packet::VERB_NOP,false);
} catch ( ... ) {
TRACE("dropped RENDEZVOUS from %s(%s): unexpected exception",peer->address().toString().c_str(),_path->address().toString().c_str());
}
return true;
}
bool IncomingPacket::_doFRAME(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer)
bool IncomingPacket::_doFRAME(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer)
{
try {
const uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID);
const SharedPtr<Network> network(RR->node->network(nwid));
bool trustEstablished = false;
if (network) {
if (network->gate(peer)) {
if (network->gate(tPtr,peer)) {
trustEstablished = true;
if (size() > ZT_PROTO_VERB_FRAME_IDX_PAYLOAD) {
const unsigned int etherType = at<uint16_t>(ZT_PROTO_VERB_FRAME_IDX_ETHERTYPE);
const MAC sourceMac(peer->address(),nwid);
const unsigned int frameLen = size() - ZT_PROTO_VERB_FRAME_IDX_PAYLOAD;
const uint8_t *const frameData = reinterpret_cast<const uint8_t *>(data()) + ZT_PROTO_VERB_FRAME_IDX_PAYLOAD;
if (network->filterIncomingPacket(peer,RR->identity.address(),sourceMac,network->mac(),frameData,frameLen,etherType,0) > 0)
RR->node->putFrame(nwid,network->userPtr(),sourceMac,network->mac(),etherType,0,(const void *)frameData,frameLen);
if (network->filterIncomingPacket(tPtr,peer,RR->identity.address(),sourceMac,network->mac(),frameData,frameLen,etherType,0) > 0)
RR->node->putFrame(tPtr,nwid,network->userPtr(),sourceMac,network->mac(),etherType,0,(const void *)frameData,frameLen);
}
} else {
TRACE("dropped FRAME from %s(%s): not a member of private network %.16llx",peer->address().toString().c_str(),_path->address().toString().c_str(),(unsigned long long)network->id());
_sendErrorNeedCredentials(RR,peer,nwid);
_sendErrorNeedCredentials(RR,tPtr,peer,nwid);
}
} else {
TRACE("dropped FRAME from %s(%s): we are not a member of network %.16llx",source().toString().c_str(),_path->address().toString().c_str(),at<uint64_t>(ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID));
_sendErrorNeedCredentials(RR,peer,nwid);
_sendErrorNeedCredentials(RR,tPtr,peer,nwid);
}
peer->received(_path,hops(),packetId(),Packet::VERB_FRAME,0,Packet::VERB_NOP,trustEstablished);
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_FRAME,0,Packet::VERB_NOP,trustEstablished);
} catch ( ... ) {
TRACE("dropped FRAME from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
}
return true;
}
bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer)
bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer)
{
try {
const uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_EXT_FRAME_IDX_NETWORK_ID);
@@ -674,13 +680,13 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,const SharedPtr<P
CertificateOfMembership com;
comLen = com.deserialize(*this,ZT_PROTO_VERB_EXT_FRAME_IDX_COM);
if (com)
network->addCredential(com);
network->addCredential(tPtr,com);
}
if (!network->gate(peer)) {
if (!network->gate(tPtr,peer)) {
TRACE("dropped EXT_FRAME from %s(%s): not a member of private network %.16llx",peer->address().toString().c_str(),_path->address().toString().c_str(),network->id());
_sendErrorNeedCredentials(RR,peer,nwid);
peer->received(_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,false);
_sendErrorNeedCredentials(RR,tPtr,peer,nwid);
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,false);
return true;
}
@@ -693,36 +699,36 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,const SharedPtr<P
if ((!from)||(from.isMulticast())||(from == network->mac())) {
TRACE("dropped EXT_FRAME from %s@%s(%s) to %s: invalid source MAC %s",from.toString().c_str(),peer->address().toString().c_str(),_path->address().toString().c_str(),to.toString().c_str(),from.toString().c_str());
peer->received(_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay
return true;
}
switch (network->filterIncomingPacket(peer,RR->identity.address(),from,to,frameData,frameLen,etherType,0)) {
switch (network->filterIncomingPacket(tPtr,peer,RR->identity.address(),from,to,frameData,frameLen,etherType,0)) {
case 1:
if (from != MAC(peer->address(),nwid)) {
if (network->config().permitsBridging(peer->address())) {
network->learnBridgeRoute(from,peer->address());
} else {
TRACE("dropped EXT_FRAME from %s@%s(%s) to %s: sender not allowed to bridge into %.16llx",from.toString().c_str(),peer->address().toString().c_str(),_path->address().toString().c_str(),to.toString().c_str(),network->id());
peer->received(_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay
return true;
}
} else if (to != network->mac()) {
if (to.isMulticast()) {
if (network->config().multicastLimit == 0) {
TRACE("dropped EXT_FRAME from %s@%s(%s) to %s: network %.16llx does not allow multicast",from.toString().c_str(),peer->address().toString().c_str(),_path->address().toString().c_str(),to.toString().c_str(),network->id());
peer->received(_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay
return true;
}
} else if (!network->config().permitsBridging(RR->identity.address())) {
TRACE("dropped EXT_FRAME from %s@%s(%s) to %s: I cannot bridge to %.16llx or bridging disabled on network",from.toString().c_str(),peer->address().toString().c_str(),_path->address().toString().c_str(),to.toString().c_str(),network->id());
peer->received(_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay
return true;
}
}
// fall through -- 2 means accept regardless of bridging checks or other restrictions
case 2:
RR->node->putFrame(nwid,network->userPtr(),from,to,etherType,0,(const void *)frameData,frameLen);
RR->node->putFrame(tPtr,nwid,network->userPtr(),from,to,etherType,0,(const void *)frameData,frameLen);
break;
}
}
@@ -733,14 +739,14 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,const SharedPtr<P
outp.append((uint64_t)packetId());
outp.append((uint64_t)nwid);
outp.armor(peer->key(),true,_path->nextOutgoingCounter());
_path->send(RR,outp.data(),outp.size(),RR->node->now());
_path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now());
}
peer->received(_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,true);
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,true);
} else {
TRACE("dropped EXT_FRAME from %s(%s): we are not connected to network %.16llx",source().toString().c_str(),_path->address().toString().c_str(),at<uint64_t>(ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID));
_sendErrorNeedCredentials(RR,peer,nwid);
peer->received(_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,false);
_sendErrorNeedCredentials(RR,tPtr,peer,nwid);
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,false);
}
} catch ( ... ) {
TRACE("dropped EXT_FRAME from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
@@ -748,7 +754,7 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,const SharedPtr<P
return true;
}
bool IncomingPacket::_doECHO(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer)
bool IncomingPacket::_doECHO(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer)
{
try {
if (!peer->rateGateEchoRequest(RR->node->now())) {
@@ -763,16 +769,16 @@ bool IncomingPacket::_doECHO(const RuntimeEnvironment *RR,const SharedPtr<Peer>
if (size() > ZT_PACKET_IDX_PAYLOAD)
outp.append(reinterpret_cast<const unsigned char *>(data()) + ZT_PACKET_IDX_PAYLOAD,size() - ZT_PACKET_IDX_PAYLOAD);
outp.armor(peer->key(),true,_path->nextOutgoingCounter());
_path->send(RR,outp.data(),outp.size(),RR->node->now());
_path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now());
peer->received(_path,hops(),pid,Packet::VERB_ECHO,0,Packet::VERB_NOP,false);
peer->received(tPtr,_path,hops(),pid,Packet::VERB_ECHO,0,Packet::VERB_NOP,false);
} catch ( ... ) {
TRACE("dropped ECHO from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
}
return true;
}
bool IncomingPacket::_doMULTICAST_LIKE(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer)
bool IncomingPacket::_doMULTICAST_LIKE(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer)
{
try {
const uint64_t now = RR->node->now();
@@ -796,9 +802,9 @@ bool IncomingPacket::_doMULTICAST_LIKE(const RuntimeEnvironment *RR,const Shared
if (!auth) {
if ((!network)||(network->id() != nwid))
network = RR->node->network(nwid);
const bool authOnNet = ((network)&&(network->gate(peer)));
const bool authOnNet = ((network)&&(network->gate(tPtr,peer)));
if (!authOnNet)
_sendErrorNeedCredentials(RR,peer,nwid);
_sendErrorNeedCredentials(RR,tPtr,peer,nwid);
trustEstablished |= authOnNet;
if (authOnNet||RR->mc->cacheAuthorized(peer->address(),nwid,now)) {
auth = true;
@@ -809,18 +815,18 @@ bool IncomingPacket::_doMULTICAST_LIKE(const RuntimeEnvironment *RR,const Shared
if (auth) {
const MulticastGroup group(MAC(field(ptr + 8,6),6),at<uint32_t>(ptr + 14));
RR->mc->add(now,nwid,group,peer->address());
RR->mc->add(tPtr,now,nwid,group,peer->address());
}
}
peer->received(_path,hops(),packetId(),Packet::VERB_MULTICAST_LIKE,0,Packet::VERB_NOP,trustEstablished);
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_MULTICAST_LIKE,0,Packet::VERB_NOP,trustEstablished);
} catch ( ... ) {
TRACE("dropped MULTICAST_LIKE from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
}
return true;
}
bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer)
bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer)
{
try {
if (!peer->rateGateCredentialsReceived(RR->node->now())) {
@@ -836,12 +842,12 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const S
bool trustEstablished = false;
unsigned int p = ZT_PACKET_IDX_PAYLOAD;
while ((p < size())&&((*this)[p])) {
while ((p < size())&&((*this)[p] != 0)) {
p += com.deserialize(*this,p);
if (com) {
const SharedPtr<Network> network(RR->node->network(com.networkId()));
if (network) {
switch (network->addCredential(com)) {
switch (network->addCredential(tPtr,com)) {
case Membership::ADD_REJECTED:
break;
case Membership::ADD_ACCEPTED_NEW:
@@ -851,7 +857,7 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const S
case Membership::ADD_DEFERRED_FOR_WHOIS:
return false;
}
} else RR->mc->addCredential(com,false);
} else RR->mc->addCredential(tPtr,com,false);
}
}
++p; // skip trailing 0 after COMs if present
@@ -862,7 +868,7 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const S
p += cap.deserialize(*this,p);
const SharedPtr<Network> network(RR->node->network(cap.networkId()));
if (network) {
switch (network->addCredential(cap)) {
switch (network->addCredential(tPtr,cap)) {
case Membership::ADD_REJECTED:
break;
case Membership::ADD_ACCEPTED_NEW:
@@ -882,7 +888,7 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const S
p += tag.deserialize(*this,p);
const SharedPtr<Network> network(RR->node->network(tag.networkId()));
if (network) {
switch (network->addCredential(tag)) {
switch (network->addCredential(tPtr,tag)) {
case Membership::ADD_REJECTED:
break;
case Membership::ADD_ACCEPTED_NEW:
@@ -902,7 +908,7 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const S
p += revocation.deserialize(*this,p);
const SharedPtr<Network> network(RR->node->network(revocation.networkId()));
if (network) {
switch(network->addCredential(peer->address(),revocation)) {
switch(network->addCredential(tPtr,peer->address(),revocation)) {
case Membership::ADD_REJECTED:
break;
case Membership::ADD_ACCEPTED_NEW:
@@ -922,7 +928,7 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const S
p += coo.deserialize(*this,p);
const SharedPtr<Network> network(RR->node->network(coo.networkId()));
if (network) {
switch(network->addCredential(coo)) {
switch(network->addCredential(tPtr,coo)) {
case Membership::ADD_REJECTED:
break;
case Membership::ADD_ACCEPTED_NEW:
@@ -936,16 +942,18 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const S
}
}
peer->received(_path,hops(),packetId(),Packet::VERB_NETWORK_CREDENTIALS,0,Packet::VERB_NOP,trustEstablished);
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_NETWORK_CREDENTIALS,0,Packet::VERB_NOP,trustEstablished);
} catch (std::exception &exc) {
//fprintf(stderr,"dropped NETWORK_CREDENTIALS from %s(%s): %s" ZT_EOL_S,source().toString().c_str(),_path->address().toString().c_str(),exc.what());
TRACE("dropped NETWORK_CREDENTIALS from %s(%s): %s",source().toString().c_str(),_path->address().toString().c_str(),exc.what());
} catch ( ... ) {
TRACE("dropped NETWORK_CREDENTIALS from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
//fprintf(stderr,"dropped NETWORK_CREDENTIALS from %s(%s): unknown exception" ZT_EOL_S,source().toString().c_str(),_path->address().toString().c_str());
TRACE("dropped NETWORK_CREDENTIALS from %s(%s): unknown exception",source().toString().c_str(),_path->address().toString().c_str());
}
return true;
}
bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer)
bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer)
{
try {
const uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_NETWORK_ID);
@@ -953,8 +961,8 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons
const uint64_t requestPacketId = packetId();
if (RR->localNetworkController) {
const unsigned int metaDataLength = at<uint16_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT_LEN);
const char *metaDataBytes = (const char *)field(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT,metaDataLength);
const unsigned int metaDataLength = (ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT_LEN <= size()) ? at<uint16_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT_LEN) : 0;
const char *metaDataBytes = (metaDataLength != 0) ? (const char *)field(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT,metaDataLength) : (const char *)0;
const Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> metaData(metaDataBytes,metaDataLength);
RR->localNetworkController->request(nwid,(hopCount > 0) ? InetAddress() : _path->address(),requestPacketId,peer->identity(),metaData);
} else {
@@ -964,26 +972,26 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons
outp.append((unsigned char)Packet::ERROR_UNSUPPORTED_OPERATION);
outp.append(nwid);
outp.armor(peer->key(),true,_path->nextOutgoingCounter());
_path->send(RR,outp.data(),outp.size(),RR->node->now());
_path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now());
}
peer->received(_path,hopCount,requestPacketId,Packet::VERB_NETWORK_CONFIG_REQUEST,0,Packet::VERB_NOP,false);
peer->received(tPtr,_path,hopCount,requestPacketId,Packet::VERB_NETWORK_CONFIG_REQUEST,0,Packet::VERB_NOP,false);
} catch (std::exception &exc) {
fprintf(stderr,"WARNING: network config request failed with exception: %s" ZT_EOL_S,exc.what());
//fprintf(stderr,"dropped NETWORK_CONFIG_REQUEST from %s(%s): %s" ZT_EOL_S,source().toString().c_str(),_path->address().toString().c_str(),exc.what());
TRACE("dropped NETWORK_CONFIG_REQUEST from %s(%s): %s",source().toString().c_str(),_path->address().toString().c_str(),exc.what());
} catch ( ... ) {
fprintf(stderr,"WARNING: network config request failed with exception: unknown exception" ZT_EOL_S);
//fprintf(stderr,"dropped NETWORK_CONFIG_REQUEST from %s(%s): unknown exception" ZT_EOL_S,source().toString().c_str(),_path->address().toString().c_str());
TRACE("dropped NETWORK_CONFIG_REQUEST from %s(%s): unknown exception",source().toString().c_str(),_path->address().toString().c_str());
}
return true;
}
bool IncomingPacket::_doNETWORK_CONFIG(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer)
bool IncomingPacket::_doNETWORK_CONFIG(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer)
{
try {
const SharedPtr<Network> network(RR->node->network(at<uint64_t>(ZT_PACKET_IDX_PAYLOAD)));
if (network) {
const uint64_t configUpdateId = network->handleConfigChunk(packetId(),source(),*this,ZT_PACKET_IDX_PAYLOAD);
const uint64_t configUpdateId = network->handleConfigChunk(tPtr,packetId(),source(),*this,ZT_PACKET_IDX_PAYLOAD);
if (configUpdateId) {
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_OK);
outp.append((uint8_t)Packet::VERB_ECHO);
@@ -991,17 +999,17 @@ bool IncomingPacket::_doNETWORK_CONFIG(const RuntimeEnvironment *RR,const Shared
outp.append((uint64_t)network->id());
outp.append((uint64_t)configUpdateId);
outp.armor(peer->key(),true,_path->nextOutgoingCounter());
_path->send(RR,outp.data(),outp.size(),RR->node->now());
_path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now());
}
}
peer->received(_path,hops(),packetId(),Packet::VERB_NETWORK_CONFIG,0,Packet::VERB_NOP,false);
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_NETWORK_CONFIG,0,Packet::VERB_NOP,false);
} catch ( ... ) {
TRACE("dropped NETWORK_CONFIG_REFRESH from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
}
return true;
}
bool IncomingPacket::_doMULTICAST_GATHER(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer)
bool IncomingPacket::_doMULTICAST_GATHER(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer)
{
try {
const uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_MULTICAST_GATHER_IDX_NETWORK_ID);
@@ -1019,17 +1027,17 @@ bool IncomingPacket::_doMULTICAST_GATHER(const RuntimeEnvironment *RR,const Shar
com.deserialize(*this,ZT_PROTO_VERB_MULTICAST_GATHER_IDX_COM);
if (com) {
if (network)
network->addCredential(com);
else RR->mc->addCredential(com,false);
network->addCredential(tPtr,com);
else RR->mc->addCredential(tPtr,com,false);
}
} catch ( ... ) {
TRACE("MULTICAST_GATHER from %s(%s): discarded invalid COM",peer->address().toString().c_str(),_path->address().toString().c_str());
}
}
const bool trustEstablished = ((network)&&(network->gate(peer)));
const bool trustEstablished = ((network)&&(network->gate(tPtr,peer)));
if (!trustEstablished)
_sendErrorNeedCredentials(RR,peer,nwid);
_sendErrorNeedCredentials(RR,tPtr,peer,nwid);
if ( ( trustEstablished || RR->mc->cacheAuthorized(peer->address(),nwid,RR->node->now()) ) && (gatherLimit > 0) ) {
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_OK);
outp.append((unsigned char)Packet::VERB_MULTICAST_GATHER);
@@ -1040,7 +1048,7 @@ bool IncomingPacket::_doMULTICAST_GATHER(const RuntimeEnvironment *RR,const Shar
const unsigned int gatheredLocally = RR->mc->gather(peer->address(),nwid,mg,outp,gatherLimit);
if (gatheredLocally > 0) {
outp.armor(peer->key(),true,_path->nextOutgoingCounter());
_path->send(RR,outp.data(),outp.size(),RR->node->now());
_path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now());
}
// If we are a member of a cluster, distribute this GATHER across it
@@ -1050,14 +1058,14 @@ bool IncomingPacket::_doMULTICAST_GATHER(const RuntimeEnvironment *RR,const Shar
#endif
}
peer->received(_path,hops(),packetId(),Packet::VERB_MULTICAST_GATHER,0,Packet::VERB_NOP,trustEstablished);
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_MULTICAST_GATHER,0,Packet::VERB_NOP,trustEstablished);
} catch ( ... ) {
TRACE("dropped MULTICAST_GATHER from %s(%s): unexpected exception",peer->address().toString().c_str(),_path->address().toString().c_str());
}
return true;
}
bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer)
bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer)
{
try {
const uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID);
@@ -1073,19 +1081,19 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,const Share
CertificateOfMembership com;
offset += com.deserialize(*this,ZT_PROTO_VERB_MULTICAST_FRAME_IDX_COM);
if (com)
network->addCredential(com);
network->addCredential(tPtr,com);
}
if (!network->gate(peer)) {
if (!network->gate(tPtr,peer)) {
TRACE("dropped MULTICAST_FRAME from %s(%s): not a member of private network %.16llx",peer->address().toString().c_str(),_path->address().toString().c_str(),(unsigned long long)network->id());
_sendErrorNeedCredentials(RR,peer,nwid);
peer->received(_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,false);
_sendErrorNeedCredentials(RR,tPtr,peer,nwid);
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,false);
return true;
}
if (network->config().multicastLimit == 0) {
TRACE("dropped MULTICAST_FRAME from %s(%s): network %.16llx does not allow multicast",peer->address().toString().c_str(),_path->address().toString().c_str(),(unsigned long long)network->id());
peer->received(_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,false);
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,false);
return true;
}
@@ -1112,12 +1120,12 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,const Share
if ((frameLen > 0)&&(frameLen <= ZT_IF_MTU)) {
if (!to.mac().isMulticast()) {
TRACE("dropped MULTICAST_FRAME from %s@%s(%s) to %s: destination is unicast, must use FRAME or EXT_FRAME",from.toString().c_str(),peer->address().toString().c_str(),_path->address().toString().c_str(),to.toString().c_str());
peer->received(_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay
return true;
}
if ((!from)||(from.isMulticast())||(from == network->mac())) {
TRACE("dropped MULTICAST_FRAME from %s@%s(%s) to %s: invalid source MAC",from.toString().c_str(),peer->address().toString().c_str(),_path->address().toString().c_str(),to.toString().c_str());
peer->received(_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay
return true;
}
@@ -1126,14 +1134,14 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,const Share
network->learnBridgeRoute(from,peer->address());
} else {
TRACE("dropped MULTICAST_FRAME from %s@%s(%s) to %s: sender not allowed to bridge into %.16llx",from.toString().c_str(),peer->address().toString().c_str(),_path->address().toString().c_str(),to.toString().c_str(),network->id());
peer->received(_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay
return true;
}
}
const uint8_t *const frameData = (const uint8_t *)field(offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME,frameLen);
if (network->filterIncomingPacket(peer,RR->identity.address(),from,to.mac(),frameData,frameLen,etherType,0) > 0) {
RR->node->putFrame(nwid,network->userPtr(),from,to.mac(),etherType,0,(const void *)frameData,frameLen);
if (network->filterIncomingPacket(tPtr,peer,RR->identity.address(),from,to.mac(),frameData,frameLen,etherType,0) > 0) {
RR->node->putFrame(tPtr,nwid,network->userPtr(),from,to.mac(),etherType,0,(const void *)frameData,frameLen);
}
}
@@ -1147,14 +1155,14 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,const Share
outp.append((unsigned char)0x02); // flag 0x02 = contains gather results
if (RR->mc->gather(peer->address(),nwid,to,outp,gatherLimit)) {
outp.armor(peer->key(),true,_path->nextOutgoingCounter());
_path->send(RR,outp.data(),outp.size(),RR->node->now());
_path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now());
}
}
peer->received(_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,true);
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,true);
} else {
_sendErrorNeedCredentials(RR,peer,nwid);
peer->received(_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,false);
_sendErrorNeedCredentials(RR,tPtr,peer,nwid);
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,false);
}
} catch ( ... ) {
TRACE("dropped MULTICAST_FRAME from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
@@ -1162,7 +1170,7 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,const Share
return true;
}
bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer)
bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer)
{
try {
const uint64_t now = RR->node->now();
@@ -1170,7 +1178,7 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,const Sha
// First, subject this to a rate limit
if (!peer->rateGatePushDirectPaths(now)) {
TRACE("dropped PUSH_DIRECT_PATHS from %s(%s): circuit breaker tripped",source().toString().c_str(),_path->address().toString().c_str());
peer->received(_path,hops(),packetId(),Packet::VERB_PUSH_DIRECT_PATHS,0,Packet::VERB_NOP,false);
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_PUSH_DIRECT_PATHS,0,Packet::VERB_NOP,false);
return true;
}
@@ -1201,10 +1209,10 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,const Sha
redundant = peer->hasActivePathTo(now,a);
}
if ( ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_FORGET_PATH) == 0) && (!redundant) && (RR->node->shouldUsePathForZeroTierTraffic(peer->address(),_path->localAddress(),a)) ) {
if ( ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_FORGET_PATH) == 0) && (!redundant) && (RR->node->shouldUsePathForZeroTierTraffic(tPtr,peer->address(),_path->localAddress(),a)) ) {
if (++countPerScope[(int)a.ipScope()][0] <= ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY) {
TRACE("attempting to contact %s at pushed direct path %s",peer->address().toString().c_str(),a.toString().c_str());
peer->attemptToContactAt(InetAddress(),a,now,false,0);
peer->attemptToContactAt(tPtr,InetAddress(),a,now,false,0);
} else {
TRACE("ignoring contact for %s at %s -- too many per scope",peer->address().toString().c_str(),a.toString().c_str());
}
@@ -1220,10 +1228,10 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,const Sha
redundant = peer->hasActivePathTo(now,a);
}
if ( ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_FORGET_PATH) == 0) && (!redundant) && (RR->node->shouldUsePathForZeroTierTraffic(peer->address(),_path->localAddress(),a)) ) {
if ( ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_FORGET_PATH) == 0) && (!redundant) && (RR->node->shouldUsePathForZeroTierTraffic(tPtr,peer->address(),_path->localAddress(),a)) ) {
if (++countPerScope[(int)a.ipScope()][1] <= ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY) {
TRACE("attempting to contact %s at pushed direct path %s",peer->address().toString().c_str(),a.toString().c_str());
peer->attemptToContactAt(InetAddress(),a,now,false,0);
peer->attemptToContactAt(tPtr,InetAddress(),a,now,false,0);
} else {
TRACE("ignoring contact for %s at %s -- too many per scope",peer->address().toString().c_str(),a.toString().c_str());
}
@@ -1233,20 +1241,20 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,const Sha
ptr += addrLen;
}
peer->received(_path,hops(),packetId(),Packet::VERB_PUSH_DIRECT_PATHS,0,Packet::VERB_NOP,false);
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_PUSH_DIRECT_PATHS,0,Packet::VERB_NOP,false);
} catch ( ... ) {
TRACE("dropped PUSH_DIRECT_PATHS from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
}
return true;
}
bool IncomingPacket::_doCIRCUIT_TEST(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer)
bool IncomingPacket::_doCIRCUIT_TEST(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer)
{
try {
const Address originatorAddress(field(ZT_PACKET_IDX_PAYLOAD,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH);
SharedPtr<Peer> originator(RR->topology->getPeer(originatorAddress));
SharedPtr<Peer> originator(RR->topology->getPeer(tPtr,originatorAddress));
if (!originator) {
RR->sw->requestWhois(originatorAddress);
RR->sw->requestWhois(tPtr,originatorAddress);
return false;
}
@@ -1277,7 +1285,7 @@ bool IncomingPacket::_doCIRCUIT_TEST(const RuntimeEnvironment *RR,const SharedPt
const unsigned int signatureLength = at<uint16_t>(ZT_PACKET_IDX_PAYLOAD + 27 + vlf);
if (!originator->identity().verify(field(ZT_PACKET_IDX_PAYLOAD,27 + vlf),27 + vlf,field(ZT_PACKET_IDX_PAYLOAD + 29 + vlf,signatureLength),signatureLength)) {
TRACE("dropped CIRCUIT_TEST from %s(%s): signature by originator %s invalid",source().toString().c_str(),_path->address().toString().c_str(),originatorAddress.toString().c_str());
peer->received(_path,hops(),packetId(),Packet::VERB_CIRCUIT_TEST,0,Packet::VERB_NOP,false);
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_CIRCUIT_TEST,0,Packet::VERB_NOP,false);
return true;
}
vlf += signatureLength;
@@ -1296,14 +1304,14 @@ bool IncomingPacket::_doCIRCUIT_TEST(const RuntimeEnvironment *RR,const SharedPt
SharedPtr<Network> network(RR->node->network(originatorCredentialNetworkId));
if ((!network)||(!network->config().circuitTestingAllowed(originatorAddress))) {
TRACE("dropped CIRCUIT_TEST from %s(%s): originator %s specified network ID %.16llx as credential, and we don't belong to that network or originator is not allowed'",source().toString().c_str(),_path->address().toString().c_str(),originatorAddress.toString().c_str(),originatorCredentialNetworkId);
peer->received(_path,hops(),packetId(),Packet::VERB_CIRCUIT_TEST,0,Packet::VERB_NOP,false);
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_CIRCUIT_TEST,0,Packet::VERB_NOP,false);
return true;
}
if (network->gate(peer))
if (network->gate(tPtr,peer))
reportFlags |= ZT_CIRCUIT_TEST_REPORT_FLAGS_UPSTREAM_AUTHORIZED_IN_PATH;
} else {
TRACE("dropped CIRCUIT_TEST from %s(%s): originator %s did not specify a credential or credential type",source().toString().c_str(),_path->address().toString().c_str(),originatorAddress.toString().c_str());
peer->received(_path,hops(),packetId(),Packet::VERB_CIRCUIT_TEST,0,Packet::VERB_NOP,false);
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_CIRCUIT_TEST,0,Packet::VERB_NOP,false);
return true;
}
@@ -1319,7 +1327,7 @@ bool IncomingPacket::_doCIRCUIT_TEST(const RuntimeEnvironment *RR,const SharedPt
for(unsigned int h=0;h<breadth;++h) {
nextHop[h].setTo(field(remainingHopsPtr,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH);
remainingHopsPtr += ZT_ADDRESS_LENGTH;
SharedPtr<Peer> nhp(RR->topology->getPeer(nextHop[h]));
SharedPtr<Peer> nhp(RR->topology->getPeer(tPtr,nextHop[h]));
if (nhp) {
SharedPtr<Path> nhbp(nhp->getBestPath(now,false));
if ((nhbp)&&(nhbp->alive(now)))
@@ -1354,7 +1362,7 @@ bool IncomingPacket::_doCIRCUIT_TEST(const RuntimeEnvironment *RR,const SharedPt
nextHop[h].appendTo(outp);
nextHopBestPathAddress[h].serialize(outp); // appends 0 if null InetAddress
}
RR->sw->send(outp,true);
RR->sw->send(tPtr,outp,true);
}
// If there are next hops, forward the test along through the graph
@@ -1369,19 +1377,19 @@ bool IncomingPacket::_doCIRCUIT_TEST(const RuntimeEnvironment *RR,const SharedPt
if (RR->identity.address() != nextHop[h]) { // next hops that loop back to the current hop are not valid
outp.newInitializationVector();
outp.setDestination(nextHop[h]);
RR->sw->send(outp,true);
RR->sw->send(tPtr,outp,true);
}
}
}
peer->received(_path,hops(),packetId(),Packet::VERB_CIRCUIT_TEST,0,Packet::VERB_NOP,false);
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_CIRCUIT_TEST,0,Packet::VERB_NOP,false);
} catch ( ... ) {
TRACE("dropped CIRCUIT_TEST from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
}
return true;
}
bool IncomingPacket::_doCIRCUIT_TEST_REPORT(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer)
bool IncomingPacket::_doCIRCUIT_TEST_REPORT(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer)
{
try {
ZT_CircuitTestReport report;
@@ -1423,14 +1431,14 @@ bool IncomingPacket::_doCIRCUIT_TEST_REPORT(const RuntimeEnvironment *RR,const S
RR->node->postCircuitTestReport(&report);
peer->received(_path,hops(),packetId(),Packet::VERB_CIRCUIT_TEST_REPORT,0,Packet::VERB_NOP,false);
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_CIRCUIT_TEST_REPORT,0,Packet::VERB_NOP,false);
} catch ( ... ) {
TRACE("dropped CIRCUIT_TEST_REPORT from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
}
return true;
}
bool IncomingPacket::_doUSER_MESSAGE(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer)
bool IncomingPacket::_doUSER_MESSAGE(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer)
{
try {
if (size() >= (ZT_PACKET_IDX_PAYLOAD + 8)) {
@@ -1439,16 +1447,16 @@ bool IncomingPacket::_doUSER_MESSAGE(const RuntimeEnvironment *RR,const SharedPt
um.typeId = at<uint64_t>(ZT_PACKET_IDX_PAYLOAD);
um.data = reinterpret_cast<const void *>(reinterpret_cast<const uint8_t *>(data()) + ZT_PACKET_IDX_PAYLOAD + 8);
um.length = size() - (ZT_PACKET_IDX_PAYLOAD + 8);
RR->node->postEvent(ZT_EVENT_USER_MESSAGE,reinterpret_cast<const void *>(&um));
RR->node->postEvent(tPtr,ZT_EVENT_USER_MESSAGE,reinterpret_cast<const void *>(&um));
}
peer->received(_path,hops(),packetId(),Packet::VERB_CIRCUIT_TEST_REPORT,0,Packet::VERB_NOP,false);
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_CIRCUIT_TEST_REPORT,0,Packet::VERB_NOP,false);
} catch ( ... ) {
TRACE("dropped CIRCUIT_TEST_REPORT from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
}
return true;
}
void IncomingPacket::_sendErrorNeedCredentials(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer,const uint64_t nwid)
void IncomingPacket::_sendErrorNeedCredentials(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer,const uint64_t nwid)
{
const uint64_t now = RR->node->now();
if (peer->rateGateOutgoingComRequest(now)) {
@@ -1458,7 +1466,7 @@ void IncomingPacket::_sendErrorNeedCredentials(const RuntimeEnvironment *RR,cons
outp.append((uint8_t)Packet::ERROR_NEED_MEMBERSHIP_CERTIFICATE);
outp.append(nwid);
outp.armor(peer->key(),true,_path->nextOutgoingCounter());
_path->send(RR,outp.data(),outp.size(),now);
_path->send(RR,tPtr,outp.data(),outp.size(),now);
}
}

View File

@@ -102,9 +102,10 @@ public:
* may no longer be valid.
*
* @param RR Runtime environment
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @return True if decoding and processing is complete, false if caller should try again
*/
bool tryDecode(const RuntimeEnvironment *RR);
bool tryDecode(const RuntimeEnvironment *RR,void *tPtr);
/**
* @return Time of packet receipt / start of decode
@@ -114,26 +115,26 @@ public:
private:
// These are called internally to handle packet contents once it has
// been authenticated, decrypted, decompressed, and classified.
bool _doERROR(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
bool _doHELLO(const RuntimeEnvironment *RR,const bool alreadyAuthenticated);
bool _doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
bool _doWHOIS(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
bool _doRENDEZVOUS(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
bool _doFRAME(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
bool _doEXT_FRAME(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
bool _doECHO(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
bool _doMULTICAST_LIKE(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
bool _doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
bool _doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
bool _doNETWORK_CONFIG(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
bool _doMULTICAST_GATHER(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
bool _doMULTICAST_FRAME(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
bool _doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
bool _doCIRCUIT_TEST(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
bool _doCIRCUIT_TEST_REPORT(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
bool _doUSER_MESSAGE(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
bool _doERROR(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
bool _doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool alreadyAuthenticated);
bool _doOK(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
bool _doWHOIS(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
bool _doRENDEZVOUS(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
bool _doFRAME(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
bool _doEXT_FRAME(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
bool _doECHO(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
bool _doMULTICAST_LIKE(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
bool _doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
bool _doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
bool _doNETWORK_CONFIG(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
bool _doMULTICAST_GATHER(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
bool _doMULTICAST_FRAME(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
bool _doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
bool _doCIRCUIT_TEST(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
bool _doCIRCUIT_TEST_REPORT(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
bool _doUSER_MESSAGE(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
void _sendErrorNeedCredentials(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer,const uint64_t nwid);
void _sendErrorNeedCredentials(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer,const uint64_t nwid);
uint64_t _receiveTime;
SharedPtr<Path> _path;

View File

@@ -40,7 +40,7 @@ Membership::Membership() :
for(unsigned int i=0;i<ZT_MAX_CERTIFICATES_OF_OWNERSHIP;++i) _remoteCoos[i] = &(_cooMem[i]);
}
void Membership::pushCredentials(const RuntimeEnvironment *RR,const uint64_t now,const Address &peerAddress,const NetworkConfig &nconf,int localCapabilityIndex,const bool force)
void Membership::pushCredentials(const RuntimeEnvironment *RR,void *tPtr,const uint64_t now,const Address &peerAddress,const NetworkConfig &nconf,int localCapabilityIndex,const bool force)
{
bool sendCom = ( (nconf.com) && ( ((now - _lastPushedCom) >= ZT_CREDENTIAL_PUSH_EVERY) || (force) ) );
@@ -113,7 +113,7 @@ void Membership::pushCredentials(const RuntimeEnvironment *RR,const uint64_t now
outp.setAt(cooCountAt,(uint16_t)thisPacketCooCount);
outp.compress();
RR->sw->send(outp,true);
RR->sw->send(tPtr,outp,true);
}
}
@@ -123,7 +123,7 @@ const Tag *Membership::getTag(const NetworkConfig &nconf,const uint32_t id) cons
return ( ((t != &(_remoteTags[ZT_MAX_NETWORK_CAPABILITIES]))&&((*t)->id == (uint64_t)id)) ? ((((*t)->lastReceived)&&(_isCredentialTimestampValid(nconf,**t))) ? &((*t)->credential) : (const Tag *)0) : (const Tag *)0);
}
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,const NetworkConfig &nconf,const CertificateOfMembership &com)
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const CertificateOfMembership &com)
{
const uint64_t newts = com.timestamp().first;
if (newts <= _comRevocationThreshold) {
@@ -141,7 +141,7 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
return ADD_ACCEPTED_REDUNDANT;
}
switch(com.verify(RR)) {
switch(com.verify(RR,tPtr)) {
default:
TRACE("addCredential(CertificateOfMembership) for %s on %.16llx REJECTED (invalid signature or object)",com.issuedTo().toString().c_str(),com.networkId());
return ADD_REJECTED;
@@ -154,7 +154,7 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
}
}
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,const NetworkConfig &nconf,const Tag &tag)
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const Tag &tag)
{
_RemoteCredential<Tag> *const *htmp = std::lower_bound(&(_remoteTags[0]),&(_remoteTags[ZT_MAX_NETWORK_TAGS]),(uint64_t)tag.id(),_RemoteCredentialComp<Tag>());
_RemoteCredential<Tag> *have = ((htmp != &(_remoteTags[ZT_MAX_NETWORK_TAGS]))&&((*htmp)->id == (uint64_t)tag.id())) ? *htmp : (_RemoteCredential<Tag> *)0;
@@ -169,7 +169,7 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
}
}
switch(tag.verify(RR)) {
switch(tag.verify(RR,tPtr)) {
default:
TRACE("addCredential(Tag) for %s on %.16llx REJECTED (invalid)",tag.issuedTo().toString().c_str(),tag.networkId());
return ADD_REJECTED;
@@ -184,7 +184,7 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
}
}
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,const NetworkConfig &nconf,const Capability &cap)
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const Capability &cap)
{
_RemoteCredential<Capability> *const *htmp = std::lower_bound(&(_remoteCaps[0]),&(_remoteCaps[ZT_MAX_NETWORK_CAPABILITIES]),(uint64_t)cap.id(),_RemoteCredentialComp<Capability>());
_RemoteCredential<Capability> *have = ((htmp != &(_remoteCaps[ZT_MAX_NETWORK_CAPABILITIES]))&&((*htmp)->id == (uint64_t)cap.id())) ? *htmp : (_RemoteCredential<Capability> *)0;
@@ -199,7 +199,7 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
}
}
switch(cap.verify(RR)) {
switch(cap.verify(RR,tPtr)) {
default:
TRACE("addCredential(Capability) for %s on %.16llx REJECTED (invalid)",cap.issuedTo().toString().c_str(),cap.networkId());
return ADD_REJECTED;
@@ -214,9 +214,9 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
}
}
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,const NetworkConfig &nconf,const Revocation &rev)
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const Revocation &rev)
{
switch(rev.verify(RR)) {
switch(rev.verify(RR,tPtr)) {
default:
return ADD_REJECTED;
case 0: {
@@ -239,7 +239,7 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
}
}
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,const NetworkConfig &nconf,const CertificateOfOwnership &coo)
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const CertificateOfOwnership &coo)
{
_RemoteCredential<CertificateOfOwnership> *const *htmp = std::lower_bound(&(_remoteCoos[0]),&(_remoteCoos[ZT_MAX_CERTIFICATES_OF_OWNERSHIP]),(uint64_t)coo.id(),_RemoteCredentialComp<CertificateOfOwnership>());
_RemoteCredential<CertificateOfOwnership> *have = ((htmp != &(_remoteCoos[ZT_MAX_CERTIFICATES_OF_OWNERSHIP]))&&((*htmp)->id == (uint64_t)coo.id())) ? *htmp : (_RemoteCredential<CertificateOfOwnership> *)0;
@@ -254,7 +254,7 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
}
}
switch(coo.verify(RR)) {
switch(coo.verify(RR,tPtr)) {
default:
TRACE("addCredential(CertificateOfOwnership) for %s on %.16llx REJECTED (invalid)",coo.issuedTo().toString().c_str(),coo.networkId());
return ADD_REJECTED;

View File

@@ -158,13 +158,14 @@ public:
* sends VERB_NETWORK_CREDENTIALS if the recipient might need them.
*
* @param RR Runtime environment
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param now Current time
* @param peerAddress Address of member peer (the one that this Membership describes)
* @param nconf My network config
* @param localCapabilityIndex Index of local capability to include (in nconf.capabilities[]) or -1 if none
* @param force If true, send objects regardless of last push time
*/
void pushCredentials(const RuntimeEnvironment *RR,const uint64_t now,const Address &peerAddress,const NetworkConfig &nconf,int localCapabilityIndex,const bool force);
void pushCredentials(const RuntimeEnvironment *RR,void *tPtr,const uint64_t now,const Address &peerAddress,const NetworkConfig &nconf,int localCapabilityIndex,const bool force);
/**
* Check whether we should push MULTICAST_LIKEs to this peer
@@ -226,27 +227,27 @@ public:
/**
* Validate and add a credential if signature is okay and it's otherwise good
*/
AddCredentialResult addCredential(const RuntimeEnvironment *RR,const NetworkConfig &nconf,const CertificateOfMembership &com);
AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const CertificateOfMembership &com);
/**
* Validate and add a credential if signature is okay and it's otherwise good
*/
AddCredentialResult addCredential(const RuntimeEnvironment *RR,const NetworkConfig &nconf,const Tag &tag);
AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const Tag &tag);
/**
* Validate and add a credential if signature is okay and it's otherwise good
*/
AddCredentialResult addCredential(const RuntimeEnvironment *RR,const NetworkConfig &nconf,const Capability &cap);
AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const Capability &cap);
/**
* Validate and add a credential if signature is okay and it's otherwise good
*/
AddCredentialResult addCredential(const RuntimeEnvironment *RR,const NetworkConfig &nconf,const Revocation &rev);
AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const Revocation &rev);
/**
* Validate and add a credential if signature is okay and it's otherwise good
*/
AddCredentialResult addCredential(const RuntimeEnvironment *RR,const NetworkConfig &nconf,const CertificateOfOwnership &coo);
AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const CertificateOfOwnership &coo);
private:
_RemoteCredential<Tag> *_newTag(const uint64_t id);

View File

@@ -43,14 +43,14 @@ Multicaster::~Multicaster()
{
}
void Multicaster::addMultiple(uint64_t now,uint64_t nwid,const MulticastGroup &mg,const void *addresses,unsigned int count,unsigned int totalKnown)
void Multicaster::addMultiple(void *tPtr,uint64_t now,uint64_t nwid,const MulticastGroup &mg,const void *addresses,unsigned int count,unsigned int totalKnown)
{
const unsigned char *p = (const unsigned char *)addresses;
const unsigned char *e = p + (5 * count);
Mutex::Lock _l(_groups_m);
MulticastGroupStatus &gs = _groups[Multicaster::Key(nwid,mg)];
while (p != e) {
_add(now,nwid,mg,gs,Address(p,5));
_add(tPtr,now,nwid,mg,gs,Address(p,5));
p += 5;
}
}
@@ -152,6 +152,7 @@ std::vector<Address> Multicaster::getMembers(uint64_t nwid,const MulticastGroup
}
void Multicaster::send(
void *tPtr,
unsigned int limit,
uint64_t now,
uint64_t nwid,
@@ -207,7 +208,7 @@ void Multicaster::send(
for(std::vector<Address>::const_iterator ast(alwaysSendTo.begin());ast!=alwaysSendTo.end();++ast) {
if (*ast != RR->identity.address()) {
out.sendOnly(RR,*ast); // optimization: don't use dedup log if it's a one-pass send
out.sendOnly(RR,tPtr,*ast); // optimization: don't use dedup log if it's a one-pass send
if (++count >= limit)
break;
}
@@ -217,7 +218,7 @@ void Multicaster::send(
while ((count < limit)&&(idx < gs.members.size())) {
Address ma(gs.members[indexes[idx++]].address);
if (std::find(alwaysSendTo.begin(),alwaysSendTo.end(),ma) == alwaysSendTo.end()) {
out.sendOnly(RR,ma); // optimization: don't use dedup log if it's a one-pass send
out.sendOnly(RR,tPtr,ma); // optimization: don't use dedup log if it's a one-pass send
++count;
}
}
@@ -256,7 +257,7 @@ void Multicaster::send(
if (com)
com->serialize(outp);
RR->node->expectReplyTo(outp.packetId());
RR->sw->send(outp,true);
RR->sw->send(tPtr,outp,true);
}
}
@@ -280,7 +281,7 @@ void Multicaster::send(
for(std::vector<Address>::const_iterator ast(alwaysSendTo.begin());ast!=alwaysSendTo.end();++ast) {
if (*ast != RR->identity.address()) {
out.sendAndLog(RR,*ast);
out.sendAndLog(RR,tPtr,*ast);
if (++count >= limit)
break;
}
@@ -290,7 +291,7 @@ void Multicaster::send(
while ((count < limit)&&(idx < gs.members.size())) {
Address ma(gs.members[indexes[idx++]].address);
if (std::find(alwaysSendTo.begin(),alwaysSendTo.end(),ma) == alwaysSendTo.end()) {
out.sendAndLog(RR,ma);
out.sendAndLog(RR,tPtr,ma);
++count;
}
}
@@ -352,15 +353,15 @@ void Multicaster::clean(uint64_t now)
}
}
void Multicaster::addCredential(const CertificateOfMembership &com,bool alreadyValidated)
void Multicaster::addCredential(void *tPtr,const CertificateOfMembership &com,bool alreadyValidated)
{
if ((alreadyValidated)||(com.verify(RR) == 0)) {
if ((alreadyValidated)||(com.verify(RR,tPtr) == 0)) {
Mutex::Lock _l(_gatherAuth_m);
_gatherAuth[_GatherAuthKey(com.networkId(),com.issuedTo())] = RR->node->now();
}
}
void Multicaster::_add(uint64_t now,uint64_t nwid,const MulticastGroup &mg,MulticastGroupStatus &gs,const Address &member)
void Multicaster::_add(void *tPtr,uint64_t now,uint64_t nwid,const MulticastGroup &mg,MulticastGroupStatus &gs,const Address &member)
{
// assumes _groups_m is locked
@@ -383,7 +384,7 @@ void Multicaster::_add(uint64_t now,uint64_t nwid,const MulticastGroup &mg,Multi
if (tx->atLimit())
gs.txQueue.erase(tx++);
else {
tx->sendIfNew(RR,member);
tx->sendIfNew(RR,tPtr,member);
if (tx->atLimit())
gs.txQueue.erase(tx++);
else ++tx;

View File

@@ -90,10 +90,10 @@ public:
* @param mg Multicast group
* @param member New member address
*/
inline void add(uint64_t now,uint64_t nwid,const MulticastGroup &mg,const Address &member)
inline void add(void *tPtr,uint64_t now,uint64_t nwid,const MulticastGroup &mg,const Address &member)
{
Mutex::Lock _l(_groups_m);
_add(now,nwid,mg,_groups[Multicaster::Key(nwid,mg)],member);
_add(tPtr,now,nwid,mg,_groups[Multicaster::Key(nwid,mg)],member);
}
/**
@@ -101,6 +101,7 @@ public:
*
* It's up to the caller to check bounds on the array before calling this.
*
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param now Current time
* @param nwid Network ID
* @param mg Multicast group
@@ -108,7 +109,7 @@ public:
* @param count Number of addresses
* @param totalKnown Total number of known addresses as reported by peer
*/
void addMultiple(uint64_t now,uint64_t nwid,const MulticastGroup &mg,const void *addresses,unsigned int count,unsigned int totalKnown);
void addMultiple(void *tPtr,uint64_t now,uint64_t nwid,const MulticastGroup &mg,const void *addresses,unsigned int count,unsigned int totalKnown);
/**
* Remove a multicast group member (if present)
@@ -150,6 +151,7 @@ public:
/**
* Send a multicast
*
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param limit Multicast limit
* @param now Current time
* @param nwid Network ID
@@ -162,6 +164,7 @@ public:
* @param len Length of packet data
*/
void send(
void *tPtr,
unsigned int limit,
uint64_t now,
uint64_t nwid,
@@ -191,7 +194,7 @@ public:
* @param com Certificate of membership
* @param alreadyValidated If true, COM has already been checked and found to be valid and signed
*/
void addCredential(const CertificateOfMembership &com,bool alreadyValidated);
void addCredential(void *tPtr,const CertificateOfMembership &com,bool alreadyValidated);
/**
* Check authorization for GATHER and LIKE for non-network-members
@@ -209,7 +212,7 @@ public:
}
private:
void _add(uint64_t now,uint64_t nwid,const MulticastGroup &mg,MulticastGroupStatus &gs,const Address &member);
void _add(void *tPtr,uint64_t now,uint64_t nwid,const MulticastGroup &mg,MulticastGroupStatus &gs,const Address &member);
const RuntimeEnvironment *RR;

View File

@@ -674,7 +674,7 @@ static _doZtFilterResult _doZtFilter(
const ZeroTier::MulticastGroup Network::BROADCAST(ZeroTier::MAC(0xffffffffffffULL),0);
Network::Network(const RuntimeEnvironment *renv,uint64_t nwid,void *uptr) :
Network::Network(const RuntimeEnvironment *renv,void *tPtr,uint64_t nwid,void *uptr) :
RR(renv),
_uPtr(uptr),
_id(nwid),
@@ -696,11 +696,11 @@ Network::Network(const RuntimeEnvironment *renv,uint64_t nwid,void *uptr) :
Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> *dconf = new Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY>();
NetworkConfig *nconf = new NetworkConfig();
try {
std::string conf(RR->node->dataStoreGet(confn));
std::string conf(RR->node->dataStoreGet(tPtr,confn));
if (conf.length()) {
dconf->load(conf.c_str());
if (nconf->fromDictionary(*dconf)) {
this->setConfiguration(*nconf,false);
this->setConfiguration(tPtr,*nconf,false);
_lastConfigUpdate = 0; // we still want to re-request a new config from the network
gotConf = true;
}
@@ -711,13 +711,13 @@ Network::Network(const RuntimeEnvironment *renv,uint64_t nwid,void *uptr) :
if (!gotConf) {
// Save a one-byte CR to persist membership while we request a real netconf
RR->node->dataStorePut(confn,"\n",1,false);
RR->node->dataStorePut(tPtr,confn,"\n",1,false);
}
if (!_portInitialized) {
ZT_VirtualNetworkConfig ctmp;
_externalConfig(&ctmp);
_portError = RR->node->configureVirtualNetworkPort(_id,&_uPtr,ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP,&ctmp);
_portError = RR->node->configureVirtualNetworkPort(tPtr,_id,&_uPtr,ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP,&ctmp);
_portInitialized = true;
}
}
@@ -729,15 +729,16 @@ Network::~Network()
char n[128];
if (_destroyed) {
RR->node->configureVirtualNetworkPort(_id,&_uPtr,ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY,&ctmp);
RR->node->configureVirtualNetworkPort((void *)0,_id,&_uPtr,ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY,&ctmp);
Utils::snprintf(n,sizeof(n),"networks.d/%.16llx.conf",_id);
RR->node->dataStoreDelete(n);
RR->node->dataStoreDelete((void *)0,n);
} else {
RR->node->configureVirtualNetworkPort(_id,&_uPtr,ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DOWN,&ctmp);
RR->node->configureVirtualNetworkPort((void *)0,_id,&_uPtr,ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DOWN,&ctmp);
}
}
bool Network::filterOutgoingPacket(
void *tPtr,
const bool noTee,
const Address &ztSource,
const Address &ztDest,
@@ -781,7 +782,7 @@ bool Network::filterOutgoingPacket(
if ((!noTee)&&(cc2)) {
Membership &m2 = _membership(cc2);
m2.pushCredentials(RR,now,cc2,_config,localCapabilityIndex,false);
m2.pushCredentials(RR,tPtr,now,cc2,_config,localCapabilityIndex,false);
Packet outp(cc2,RR->identity.address(),Packet::VERB_EXT_FRAME);
outp.append(_id);
@@ -791,7 +792,7 @@ bool Network::filterOutgoingPacket(
outp.append((uint16_t)etherType);
outp.append(frameData,ccLength2);
outp.compress();
RR->sw->send(outp,true);
RR->sw->send(tPtr,outp,true);
}
break;
@@ -813,11 +814,11 @@ bool Network::filterOutgoingPacket(
if (accept) {
if (membership)
membership->pushCredentials(RR,now,ztDest,_config,localCapabilityIndex,false);
membership->pushCredentials(RR,tPtr,now,ztDest,_config,localCapabilityIndex,false);
if ((!noTee)&&(cc)) {
Membership &m2 = _membership(cc);
m2.pushCredentials(RR,now,cc,_config,localCapabilityIndex,false);
m2.pushCredentials(RR,tPtr,now,cc,_config,localCapabilityIndex,false);
Packet outp(cc,RR->identity.address(),Packet::VERB_EXT_FRAME);
outp.append(_id);
@@ -827,12 +828,12 @@ bool Network::filterOutgoingPacket(
outp.append((uint16_t)etherType);
outp.append(frameData,ccLength);
outp.compress();
RR->sw->send(outp,true);
RR->sw->send(tPtr,outp,true);
}
if ((ztDest != ztFinalDest)&&(ztFinalDest)) {
Membership &m2 = _membership(ztFinalDest);
m2.pushCredentials(RR,now,ztFinalDest,_config,localCapabilityIndex,false);
m2.pushCredentials(RR,tPtr,now,ztFinalDest,_config,localCapabilityIndex,false);
Packet outp(ztFinalDest,RR->identity.address(),Packet::VERB_EXT_FRAME);
outp.append(_id);
@@ -842,7 +843,7 @@ bool Network::filterOutgoingPacket(
outp.append((uint16_t)etherType);
outp.append(frameData,frameLen);
outp.compress();
RR->sw->send(outp,true);
RR->sw->send(tPtr,outp,true);
return false; // DROP locally, since we redirected
} else {
@@ -854,6 +855,7 @@ bool Network::filterOutgoingPacket(
}
int Network::filterIncomingPacket(
void *tPtr,
const SharedPtr<Peer> &sourcePeer,
const Address &ztDest,
const MAC &macSource,
@@ -898,7 +900,7 @@ int Network::filterIncomingPacket(
if (accept) {
if (cc2) {
_membership(cc2).pushCredentials(RR,RR->node->now(),cc2,_config,-1,false);
_membership(cc2).pushCredentials(RR,tPtr,RR->node->now(),cc2,_config,-1,false);
Packet outp(cc2,RR->identity.address(),Packet::VERB_EXT_FRAME);
outp.append(_id);
@@ -908,7 +910,7 @@ int Network::filterIncomingPacket(
outp.append((uint16_t)etherType);
outp.append(frameData,ccLength2);
outp.compress();
RR->sw->send(outp,true);
RR->sw->send(tPtr,outp,true);
}
break;
}
@@ -929,7 +931,7 @@ int Network::filterIncomingPacket(
if (accept) {
if (cc) {
_membership(cc).pushCredentials(RR,RR->node->now(),cc,_config,-1,false);
_membership(cc).pushCredentials(RR,tPtr,RR->node->now(),cc,_config,-1,false);
Packet outp(cc,RR->identity.address(),Packet::VERB_EXT_FRAME);
outp.append(_id);
@@ -939,11 +941,11 @@ int Network::filterIncomingPacket(
outp.append((uint16_t)etherType);
outp.append(frameData,ccLength);
outp.compress();
RR->sw->send(outp,true);
RR->sw->send(tPtr,outp,true);
}
if ((ztDest != ztFinalDest)&&(ztFinalDest)) {
_membership(ztFinalDest).pushCredentials(RR,RR->node->now(),ztFinalDest,_config,-1,false);
_membership(ztFinalDest).pushCredentials(RR,tPtr,RR->node->now(),ztFinalDest,_config,-1,false);
Packet outp(ztFinalDest,RR->identity.address(),Packet::VERB_EXT_FRAME);
outp.append(_id);
@@ -953,7 +955,7 @@ int Network::filterIncomingPacket(
outp.append((uint16_t)etherType);
outp.append(frameData,frameLen);
outp.compress();
RR->sw->send(outp,true);
RR->sw->send(tPtr,outp,true);
return 0; // DROP locally, since we redirected
}
@@ -972,12 +974,12 @@ bool Network::subscribedToMulticastGroup(const MulticastGroup &mg,bool includeBr
return false;
}
void Network::multicastSubscribe(const MulticastGroup &mg)
void Network::multicastSubscribe(void *tPtr,const MulticastGroup &mg)
{
Mutex::Lock _l(_lock);
if (!std::binary_search(_myMulticastGroups.begin(),_myMulticastGroups.end(),mg)) {
_myMulticastGroups.insert(std::upper_bound(_myMulticastGroups.begin(),_myMulticastGroups.end(),mg),mg);
_sendUpdatesToMembers(&mg);
_sendUpdatesToMembers(tPtr,&mg);
}
}
@@ -989,7 +991,7 @@ void Network::multicastUnsubscribe(const MulticastGroup &mg)
_myMulticastGroups.erase(i);
}
uint64_t Network::handleConfigChunk(const uint64_t packetId,const Address &source,const Buffer<ZT_PROTO_MAX_PACKET_LENGTH> &chunk,unsigned int ptr)
uint64_t Network::handleConfigChunk(void *tPtr,const uint64_t packetId,const Address &source,const Buffer<ZT_PROTO_MAX_PACKET_LENGTH> &chunk,unsigned int ptr)
{
const unsigned int start = ptr;
@@ -1043,7 +1045,7 @@ uint64_t Network::handleConfigChunk(const uint64_t packetId,const Address &sourc
}
// If it's not a duplicate, check chunk signature
const Identity controllerId(RR->topology->getIdentity(controller()));
const Identity controllerId(RR->topology->getIdentity(tPtr,controller()));
if (!controllerId) { // we should always have the controller identity by now, otherwise how would we have queried it the first time?
TRACE("unable to verify chunk from %s: don't have controller identity",source.toString().c_str());
return 0;
@@ -1067,7 +1069,7 @@ uint64_t Network::handleConfigChunk(const uint64_t packetId,const Address &sourc
if ((*a != source)&&(*a != controller())) {
Packet outp(*a,RR->identity.address(),Packet::VERB_NETWORK_CONFIG);
outp.append(reinterpret_cast<const uint8_t *>(chunk.data()) + start,chunk.size() - start);
RR->sw->send(outp,true);
RR->sw->send(tPtr,outp,true);
}
}
}
@@ -1126,7 +1128,7 @@ uint64_t Network::handleConfigChunk(const uint64_t packetId,const Address &sourc
}
if (nc) {
this->setConfiguration(*nc,true);
this->setConfiguration(tPtr,*nc,true);
delete nc;
return configUpdateId;
} else {
@@ -1136,7 +1138,7 @@ uint64_t Network::handleConfigChunk(const uint64_t packetId,const Address &sourc
return 0;
}
int Network::setConfiguration(const NetworkConfig &nconf,bool saveToDisk)
int Network::setConfiguration(void *tPtr,const NetworkConfig &nconf,bool saveToDisk)
{
// _lock is NOT locked when this is called
try {
@@ -1156,7 +1158,7 @@ int Network::setConfiguration(const NetworkConfig &nconf,bool saveToDisk)
_portInitialized = true;
_externalConfig(&ctmp);
}
_portError = RR->node->configureVirtualNetworkPort(_id,&_uPtr,(oldPortInitialized) ? ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE : ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP,&ctmp);
_portError = RR->node->configureVirtualNetworkPort(tPtr,_id,&_uPtr,(oldPortInitialized) ? ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE : ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP,&ctmp);
if (saveToDisk) {
Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> *d = new Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY>();
@@ -1164,7 +1166,7 @@ int Network::setConfiguration(const NetworkConfig &nconf,bool saveToDisk)
char n[64];
Utils::snprintf(n,sizeof(n),"networks.d/%.16llx.conf",_id);
if (nconf.toDictionary(*d,false))
RR->node->dataStorePut(n,(const void *)d->data(),d->sizeBytes(),true);
RR->node->dataStorePut(tPtr,n,(const void *)d->data(),d->sizeBytes(),true);
} catch ( ... ) {}
delete d;
}
@@ -1176,7 +1178,7 @@ int Network::setConfiguration(const NetworkConfig &nconf,bool saveToDisk)
return 0;
}
void Network::requestConfiguration()
void Network::requestConfiguration(void *tPtr)
{
/* ZeroTier addresses can't begin with 0xff, so this is used to mark controllerless
* network IDs. Controllerless network IDs only support unicast IPv6 using the 6plane
@@ -1236,7 +1238,7 @@ void Network::requestConfiguration()
nconf->type = ZT_NETWORK_TYPE_PUBLIC;
Utils::snprintf(nconf->name,sizeof(nconf->name),"adhoc-%.04x-%.04x",(int)startPortRange,(int)endPortRange);
this->setConfiguration(*nconf,false);
this->setConfiguration(tPtr,*nconf,false);
delete nconf;
} else {
this->setNotFound();
@@ -1282,12 +1284,12 @@ void Network::requestConfiguration()
} else {
outp.append((unsigned char)0,16);
}
RR->node->expectReplyTo(outp.packetId());
outp.compress();
RR->sw->send(outp,true);
RR->node->expectReplyTo(outp.packetId());
RR->sw->send(tPtr,outp,true);
}
bool Network::gate(const SharedPtr<Peer> &peer)
bool Network::gate(void *tPtr,const SharedPtr<Peer> &peer)
{
const uint64_t now = RR->node->now();
Mutex::Lock _l(_lock);
@@ -1298,8 +1300,8 @@ bool Network::gate(const SharedPtr<Peer> &peer)
if (!m)
m = &(_membership(peer->address()));
if (m->shouldLikeMulticasts(now)) {
m->pushCredentials(RR,now,peer->address(),_config,-1,false);
_announceMulticastGroupsTo(peer->address(),_allMulticastGroups());
m->pushCredentials(RR,tPtr,now,peer->address(),_config,-1,false);
_announceMulticastGroupsTo(tPtr,peer->address(),_allMulticastGroups());
m->likingMulticasts(now);
}
return true;
@@ -1377,31 +1379,31 @@ void Network::learnBridgeRoute(const MAC &mac,const Address &addr)
}
}
void Network::learnBridgedMulticastGroup(const MulticastGroup &mg,uint64_t now)
void Network::learnBridgedMulticastGroup(void *tPtr,const MulticastGroup &mg,uint64_t now)
{
Mutex::Lock _l(_lock);
const unsigned long tmp = (unsigned long)_multicastGroupsBehindMe.size();
_multicastGroupsBehindMe.set(mg,now);
if (tmp != _multicastGroupsBehindMe.size())
_sendUpdatesToMembers(&mg);
_sendUpdatesToMembers(tPtr,&mg);
}
Membership::AddCredentialResult Network::addCredential(const CertificateOfMembership &com)
Membership::AddCredentialResult Network::addCredential(void *tPtr,const CertificateOfMembership &com)
{
if (com.networkId() != _id)
return Membership::ADD_REJECTED;
const Address a(com.issuedTo());
Mutex::Lock _l(_lock);
Membership &m = _membership(a);
const Membership::AddCredentialResult result = m.addCredential(RR,_config,com);
const Membership::AddCredentialResult result = m.addCredential(RR,tPtr,_config,com);
if ((result == Membership::ADD_ACCEPTED_NEW)||(result == Membership::ADD_ACCEPTED_REDUNDANT)) {
m.pushCredentials(RR,RR->node->now(),a,_config,-1,false);
RR->mc->addCredential(com,true);
m.pushCredentials(RR,tPtr,RR->node->now(),a,_config,-1,false);
RR->mc->addCredential(tPtr,com,true);
}
return result;
}
Membership::AddCredentialResult Network::addCredential(const Address &sentFrom,const Revocation &rev)
Membership::AddCredentialResult Network::addCredential(void *tPtr,const Address &sentFrom,const Revocation &rev)
{
if (rev.networkId() != _id)
return Membership::ADD_REJECTED;
@@ -1409,7 +1411,7 @@ Membership::AddCredentialResult Network::addCredential(const Address &sentFrom,c
Mutex::Lock _l(_lock);
Membership &m = _membership(rev.target());
const Membership::AddCredentialResult result = m.addCredential(RR,_config,rev);
const Membership::AddCredentialResult result = m.addCredential(RR,tPtr,_config,rev);
if ((result == Membership::ADD_ACCEPTED_NEW)&&(rev.fastPropagate())) {
Address *a = (Address *)0;
@@ -1424,7 +1426,7 @@ Membership::AddCredentialResult Network::addCredential(const Address &sentFrom,c
outp.append((uint16_t)1); // one revocation!
rev.serialize(outp);
outp.append((uint16_t)0); // no certificates of ownership
RR->sw->send(outp,true);
RR->sw->send(tPtr,outp,true);
}
}
}
@@ -1495,7 +1497,7 @@ void Network::_externalConfig(ZT_VirtualNetworkConfig *ec) const
}
}
void Network::_sendUpdatesToMembers(const MulticastGroup *const newMulticastGroup)
void Network::_sendUpdatesToMembers(void *tPtr,const MulticastGroup *const newMulticastGroup)
{
// Assumes _lock is locked
const uint64_t now = RR->node->now();
@@ -1517,9 +1519,13 @@ void Network::_sendUpdatesToMembers(const MulticastGroup *const newMulticastGrou
Packet outp(*a,RR->identity.address(),Packet::VERB_NETWORK_CREDENTIALS);
_config.com.serialize(outp);
outp.append((uint8_t)0x00);
RR->sw->send(outp,true);
outp.append((uint16_t)0); // no capabilities
outp.append((uint16_t)0); // no tags
outp.append((uint16_t)0); // no revocations
outp.append((uint16_t)0); // no certificates of ownership
RR->sw->send(tPtr,outp,true);
}
_announceMulticastGroupsTo(*a,groups);
_announceMulticastGroupsTo(tPtr,*a,groups);
}
// Also announce to controller, and send COM to simplify and generalize behavior even though in theory it does not need it
@@ -1529,9 +1535,13 @@ void Network::_sendUpdatesToMembers(const MulticastGroup *const newMulticastGrou
Packet outp(c,RR->identity.address(),Packet::VERB_NETWORK_CREDENTIALS);
_config.com.serialize(outp);
outp.append((uint8_t)0x00);
RR->sw->send(outp,true);
outp.append((uint16_t)0); // no capabilities
outp.append((uint16_t)0); // no tags
outp.append((uint16_t)0); // no revocations
outp.append((uint16_t)0); // no certificates of ownership
RR->sw->send(tPtr,outp,true);
}
_announceMulticastGroupsTo(c,groups);
_announceMulticastGroupsTo(tPtr,c,groups);
}
}
@@ -1548,17 +1558,17 @@ void Network::_sendUpdatesToMembers(const MulticastGroup *const newMulticastGrou
Membership *m = (Membership *)0;
Hashtable<Address,Membership>::Iterator i(_memberships);
while (i.next(a,m)) {
m->pushCredentials(RR,now,*a,_config,-1,false);
m->pushCredentials(RR,tPtr,now,*a,_config,-1,false);
if ( ((newMulticastGroup)||(m->shouldLikeMulticasts(now))) && (m->isAllowedOnNetwork(_config)) ) {
if (!newMulticastGroup)
m->likingMulticasts(now);
_announceMulticastGroupsTo(*a,groups);
_announceMulticastGroupsTo(tPtr,*a,groups);
}
}
}
}
void Network::_announceMulticastGroupsTo(const Address &peer,const std::vector<MulticastGroup> &allMulticastGroups)
void Network::_announceMulticastGroupsTo(void *tPtr,const Address &peer,const std::vector<MulticastGroup> &allMulticastGroups)
{
// Assumes _lock is locked
Packet outp(peer,RR->identity.address(),Packet::VERB_MULTICAST_LIKE);
@@ -1566,7 +1576,7 @@ void Network::_announceMulticastGroupsTo(const Address &peer,const std::vector<M
for(std::vector<MulticastGroup>::const_iterator mg(allMulticastGroups.begin());mg!=allMulticastGroups.end();++mg) {
if ((outp.size() + 24) >= ZT_PROTO_MAX_PACKET_LENGTH) {
outp.compress();
RR->sw->send(outp,true);
RR->sw->send(tPtr,outp,true);
outp.reset(peer,RR->identity.address(),Packet::VERB_MULTICAST_LIKE);
}
@@ -1578,7 +1588,7 @@ void Network::_announceMulticastGroupsTo(const Address &peer,const std::vector<M
if (outp.size() > ZT_PROTO_MIN_PACKET_LENGTH) {
outp.compress();
RR->sw->send(outp,true);
RR->sw->send(tPtr,outp,true);
}
}

View File

@@ -77,10 +77,11 @@ public:
* constructed to actually configure the port.
*
* @param renv Runtime environment
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param nwid Network ID
* @param uptr Arbitrary pointer used by externally-facing API (for user use)
*/
Network(const RuntimeEnvironment *renv,uint64_t nwid,void *uptr);
Network(const RuntimeEnvironment *renv,void *tPtr,uint64_t nwid,void *uptr);
~Network();
@@ -101,6 +102,7 @@ public:
* such as TEE may be taken, and credentials may be pushed, so this is not
* side-effect-free. It's basically step one in sending something over VL2.
*
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param noTee If true, do not TEE anything anywhere (for two-pass filtering as done with multicast and bridging)
* @param ztSource Source ZeroTier address
* @param ztDest Destination ZeroTier address
@@ -113,6 +115,7 @@ public:
* @return True if packet should be sent, false if dropped or redirected
*/
bool filterOutgoingPacket(
void *tPtr,
const bool noTee,
const Address &ztSource,
const Address &ztDest,
@@ -131,6 +134,7 @@ public:
* a match certain actions may be taken such as sending a copy of the packet
* to a TEE or REDIRECT target.
*
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param sourcePeer Source Peer
* @param ztDest Destination ZeroTier address
* @param macSource Ethernet layer source address
@@ -142,6 +146,7 @@ public:
* @return 0 == drop, 1 == accept, 2 == accept even if bridged
*/
int filterIncomingPacket(
void *tPtr,
const SharedPtr<Peer> &sourcePeer,
const Address &ztDest,
const MAC &macSource,
@@ -163,9 +168,10 @@ public:
/**
* Subscribe to a multicast group
*
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param mg New multicast group
*/
void multicastSubscribe(const MulticastGroup &mg);
void multicastSubscribe(void *tPtr,const MulticastGroup &mg);
/**
* Unsubscribe from a multicast group
@@ -181,22 +187,24 @@ public:
* chunks via OK(NETWORK_CONFIG_REQUEST) or NETWORK_CONFIG. It verifies
* each chunk and once assembled applies the configuration.
*
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param packetId Packet ID or 0 if none (e.g. via cluster path)
* @param source Address of sender of chunk or NULL if none (e.g. via cluster path)
* @param chunk Buffer containing chunk
* @param ptr Index of chunk and related fields in packet
* @return Update ID if update was fully assembled and accepted or 0 otherwise
*/
uint64_t handleConfigChunk(const uint64_t packetId,const Address &source,const Buffer<ZT_PROTO_MAX_PACKET_LENGTH> &chunk,unsigned int ptr);
uint64_t handleConfigChunk(void *tPtr,const uint64_t packetId,const Address &source,const Buffer<ZT_PROTO_MAX_PACKET_LENGTH> &chunk,unsigned int ptr);
/**
* Set network configuration
*
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param nconf Network configuration
* @param saveToDisk Save to disk? Used during loading, should usually be true otherwise.
* @return 0 == bad, 1 == accepted but duplicate/unchanged, 2 == accepted and new
*/
int setConfiguration(const NetworkConfig &nconf,bool saveToDisk);
int setConfiguration(void *tPtr,const NetworkConfig &nconf,bool saveToDisk);
/**
* Set netconf failure to 'access denied' -- called in IncomingPacket when controller reports this
@@ -218,13 +226,18 @@ public:
/**
* Causes this network to request an updated configuration from its master node now
*
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
*/
void requestConfiguration();
void requestConfiguration(void *tPtr);
/**
* Determine whether this peer is permitted to communicate on this network
*
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param peer Peer to check
*/
bool gate(const SharedPtr<Peer> &peer);
bool gate(void *tPtr,const SharedPtr<Peer> &peer);
/**
* Do periodic cleanup and housekeeping tasks
@@ -233,11 +246,13 @@ public:
/**
* Push state to members such as multicast group memberships and latest COM (if needed)
*
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
*/
inline void sendUpdatesToMembers()
inline void sendUpdatesToMembers(void *tPtr)
{
Mutex::Lock _l(_lock);
_sendUpdatesToMembers((const MulticastGroup *)0);
_sendUpdatesToMembers(tPtr,(const MulticastGroup *)0);
}
/**
@@ -264,64 +279,66 @@ public:
/**
* Learn a multicast group that is bridged to our tap device
*
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param mg Multicast group
* @param now Current time
*/
void learnBridgedMulticastGroup(const MulticastGroup &mg,uint64_t now);
void learnBridgedMulticastGroup(void *tPtr,const MulticastGroup &mg,uint64_t now);
/**
* Validate a credential and learn it if it passes certificate and other checks
*/
Membership::AddCredentialResult addCredential(const CertificateOfMembership &com);
Membership::AddCredentialResult addCredential(void *tPtr,const CertificateOfMembership &com);
/**
* Validate a credential and learn it if it passes certificate and other checks
*/
inline Membership::AddCredentialResult addCredential(const Capability &cap)
inline Membership::AddCredentialResult addCredential(void *tPtr,const Capability &cap)
{
if (cap.networkId() != _id)
return Membership::ADD_REJECTED;
Mutex::Lock _l(_lock);
return _membership(cap.issuedTo()).addCredential(RR,_config,cap);
return _membership(cap.issuedTo()).addCredential(RR,tPtr,_config,cap);
}
/**
* Validate a credential and learn it if it passes certificate and other checks
*/
inline Membership::AddCredentialResult addCredential(const Tag &tag)
inline Membership::AddCredentialResult addCredential(void *tPtr,const Tag &tag)
{
if (tag.networkId() != _id)
return Membership::ADD_REJECTED;
Mutex::Lock _l(_lock);
return _membership(tag.issuedTo()).addCredential(RR,_config,tag);
return _membership(tag.issuedTo()).addCredential(RR,tPtr,_config,tag);
}
/**
* Validate a credential and learn it if it passes certificate and other checks
*/
Membership::AddCredentialResult addCredential(const Address &sentFrom,const Revocation &rev);
Membership::AddCredentialResult addCredential(void *tPtr,const Address &sentFrom,const Revocation &rev);
/**
* Validate a credential and learn it if it passes certificate and other checks
*/
inline Membership::AddCredentialResult addCredential(const CertificateOfOwnership &coo)
inline Membership::AddCredentialResult addCredential(void *tPtr,const CertificateOfOwnership &coo)
{
if (coo.networkId() != _id)
return Membership::ADD_REJECTED;
Mutex::Lock _l(_lock);
return _membership(coo.issuedTo()).addCredential(RR,_config,coo);
return _membership(coo.issuedTo()).addCredential(RR,tPtr,_config,coo);
}
/**
* Force push credentials (COM, etc.) to a peer now
*
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param to Destination peer address
* @param now Current time
*/
inline void pushCredentialsNow(const Address &to,const uint64_t now)
inline void pushCredentialsNow(void *tPtr,const Address &to,const uint64_t now)
{
Mutex::Lock _l(_lock);
_membership(to).pushCredentials(RR,now,to,_config,-1,true);
_membership(to).pushCredentials(RR,tPtr,now,to,_config,-1,true);
}
/**
@@ -353,8 +370,8 @@ private:
ZT_VirtualNetworkStatus _status() const;
void _externalConfig(ZT_VirtualNetworkConfig *ec) const; // assumes _lock is locked
bool _gate(const SharedPtr<Peer> &peer);
void _sendUpdatesToMembers(const MulticastGroup *const newMulticastGroup);
void _announceMulticastGroupsTo(const Address &peer,const std::vector<MulticastGroup> &allMulticastGroups);
void _sendUpdatesToMembers(void *tPtr,const MulticastGroup *const newMulticastGroup);
void _announceMulticastGroupsTo(void *tPtr,const Address &peer,const std::vector<MulticastGroup> &allMulticastGroups);
std::vector<MulticastGroup> _allMulticastGroups() const;
Membership &_membership(const Address &a);
@@ -374,6 +391,7 @@ private:
struct _IncomingConfigChunk
{
_IncomingConfigChunk() { memset(this,0,sizeof(_IncomingConfigChunk)); }
uint64_t ts;
uint64_t updateId;
uint64_t haveChunkIds[ZT_NETWORK_MAX_UPDATE_CHUNKS];

View File

@@ -46,7 +46,7 @@ namespace ZeroTier {
/* Public Node interface (C++, exposed via CAPI bindings) */
/****************************************************************************/
Node::Node(void *uptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now) :
Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now) :
_RR(this),
RR(&_RR),
_uPtr(uptr),
@@ -72,26 +72,26 @@ Node::Node(void *uptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now) :
memset(_prngStream,0,sizeof(_prngStream));
_prng.crypt12(_prngStream,_prngStream,sizeof(_prngStream));
std::string idtmp(dataStoreGet("identity.secret"));
std::string idtmp(dataStoreGet(tptr,"identity.secret"));
if ((!idtmp.length())||(!RR->identity.fromString(idtmp))||(!RR->identity.hasPrivate())) {
TRACE("identity.secret not found, generating...");
RR->identity.generate();
idtmp = RR->identity.toString(true);
if (!dataStorePut("identity.secret",idtmp,true))
if (!dataStorePut(tptr,"identity.secret",idtmp,true))
throw std::runtime_error("unable to write identity.secret");
}
RR->publicIdentityStr = RR->identity.toString(false);
RR->secretIdentityStr = RR->identity.toString(true);
idtmp = dataStoreGet("identity.public");
idtmp = dataStoreGet(tptr,"identity.public");
if (idtmp != RR->publicIdentityStr) {
if (!dataStorePut("identity.public",RR->publicIdentityStr,false))
if (!dataStorePut(tptr,"identity.public",RR->publicIdentityStr,false))
throw std::runtime_error("unable to write identity.public");
}
try {
RR->sw = new Switch(RR);
RR->mc = new Multicaster(RR);
RR->topology = new Topology(RR);
RR->topology = new Topology(RR,tptr);
RR->sa = new SelfAwareness(RR);
} catch ( ... ) {
delete RR->sa;
@@ -101,7 +101,7 @@ Node::Node(void *uptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now) :
throw;
}
postEvent(ZT_EVENT_UP);
postEvent(tptr,ZT_EVENT_UP);
}
Node::~Node()
@@ -121,6 +121,7 @@ Node::~Node()
}
ZT_ResultCode Node::processWirePacket(
void *tptr,
uint64_t now,
const struct sockaddr_storage *localAddress,
const struct sockaddr_storage *remoteAddress,
@@ -129,11 +130,12 @@ ZT_ResultCode Node::processWirePacket(
volatile uint64_t *nextBackgroundTaskDeadline)
{
_now = now;
RR->sw->onRemotePacket(*(reinterpret_cast<const InetAddress *>(localAddress)),*(reinterpret_cast<const InetAddress *>(remoteAddress)),packetData,packetLength);
RR->sw->onRemotePacket(tptr,*(reinterpret_cast<const InetAddress *>(localAddress)),*(reinterpret_cast<const InetAddress *>(remoteAddress)),packetData,packetLength);
return ZT_RESULT_OK;
}
ZT_ResultCode Node::processVirtualNetworkFrame(
void *tptr,
uint64_t now,
uint64_t nwid,
uint64_t sourceMac,
@@ -147,7 +149,7 @@ ZT_ResultCode Node::processVirtualNetworkFrame(
_now = now;
SharedPtr<Network> nw(this->network(nwid));
if (nw) {
RR->sw->onLocalEthernet(nw,MAC(sourceMac),MAC(destMac),etherType,vlanId,frameData,frameLength);
RR->sw->onLocalEthernet(tptr,nw,MAC(sourceMac),MAC(destMac),etherType,vlanId,frameData,frameLength);
return ZT_RESULT_OK;
} else return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
}
@@ -156,9 +158,10 @@ ZT_ResultCode Node::processVirtualNetworkFrame(
class _PingPeersThatNeedPing
{
public:
_PingPeersThatNeedPing(const RuntimeEnvironment *renv,Hashtable< Address,std::vector<InetAddress> > &upstreamsToContact,uint64_t now) :
_PingPeersThatNeedPing(const RuntimeEnvironment *renv,void *tPtr,Hashtable< Address,std::vector<InetAddress> > &upstreamsToContact,uint64_t now) :
lastReceiveFromUpstream(0),
RR(renv),
_tPtr(tPtr),
_upstreamsToContact(upstreamsToContact),
_now(now),
_bestCurrentUpstream(RR->topology->getUpstreamPeer())
@@ -176,21 +179,21 @@ public:
// Upstreams must be pinged constantly over both IPv4 and IPv6 to allow
// them to perform three way handshake introductions for both stacks.
if (!p->doPingAndKeepalive(_now,AF_INET)) {
if (!p->doPingAndKeepalive(_tPtr,_now,AF_INET)) {
for(unsigned long k=0,ptr=(unsigned long)RR->node->prng();k<(unsigned long)upstreamStableEndpoints->size();++k) {
const InetAddress &addr = (*upstreamStableEndpoints)[ptr++ % upstreamStableEndpoints->size()];
if (addr.ss_family == AF_INET) {
p->sendHELLO(InetAddress(),addr,_now,0);
p->sendHELLO(_tPtr,InetAddress(),addr,_now,0);
contacted = true;
break;
}
}
} else contacted = true;
if (!p->doPingAndKeepalive(_now,AF_INET6)) {
if (!p->doPingAndKeepalive(_tPtr,_now,AF_INET6)) {
for(unsigned long k=0,ptr=(unsigned long)RR->node->prng();k<(unsigned long)upstreamStableEndpoints->size();++k) {
const InetAddress &addr = (*upstreamStableEndpoints)[ptr++ % upstreamStableEndpoints->size()];
if (addr.ss_family == AF_INET6) {
p->sendHELLO(InetAddress(),addr,_now,0);
p->sendHELLO(_tPtr,InetAddress(),addr,_now,0);
contacted = true;
break;
}
@@ -200,24 +203,25 @@ public:
if ((!contacted)&&(_bestCurrentUpstream)) {
const SharedPtr<Path> up(_bestCurrentUpstream->getBestPath(_now,true));
if (up)
p->sendHELLO(up->localAddress(),up->address(),_now,up->nextOutgoingCounter());
p->sendHELLO(_tPtr,up->localAddress(),up->address(),_now,up->nextOutgoingCounter());
}
lastReceiveFromUpstream = std::max(p->lastReceive(),lastReceiveFromUpstream);
_upstreamsToContact.erase(p->address()); // erase from upstreams to contact so that we can WHOIS those that remain
} else if (p->isActive(_now)) {
p->doPingAndKeepalive(_now,-1);
p->doPingAndKeepalive(_tPtr,_now,-1);
}
}
private:
const RuntimeEnvironment *RR;
void *_tPtr;
Hashtable< Address,std::vector<InetAddress> > &_upstreamsToContact;
const uint64_t _now;
const SharedPtr<Peer> _bestCurrentUpstream;
};
ZT_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline)
ZT_ResultCode Node::processBackgroundTasks(void *tptr,uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline)
{
_now = now;
Mutex::Lock bl(_backgroundTasksLock);
@@ -235,16 +239,16 @@ ZT_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *nextB
for(std::vector< std::pair< uint64_t,SharedPtr<Network> > >::const_iterator n(_networks.begin());n!=_networks.end();++n) {
if (((now - n->second->lastConfigUpdate()) >= ZT_NETWORK_AUTOCONF_DELAY)||(!n->second->hasConfig()))
needConfig.push_back(n->second);
n->second->sendUpdatesToMembers();
n->second->sendUpdatesToMembers(tptr);
}
}
for(std::vector< SharedPtr<Network> >::const_iterator n(needConfig.begin());n!=needConfig.end();++n)
(*n)->requestConfiguration();
(*n)->requestConfiguration(tptr);
// Do pings and keepalives
Hashtable< Address,std::vector<InetAddress> > upstreamsToContact;
RR->topology->getUpstreamsToContact(upstreamsToContact);
_PingPeersThatNeedPing pfunc(RR,upstreamsToContact,now);
_PingPeersThatNeedPing pfunc(RR,tptr,upstreamsToContact,now);
RR->topology->eachPeer<_PingPeersThatNeedPing &>(pfunc);
// Run WHOIS to create Peer for any upstreams we could not contact (including pending moon seeds)
@@ -252,13 +256,13 @@ ZT_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *nextB
Address *upstreamAddress = (Address *)0;
std::vector<InetAddress> *upstreamStableEndpoints = (std::vector<InetAddress> *)0;
while (i.next(upstreamAddress,upstreamStableEndpoints))
RR->sw->requestWhois(*upstreamAddress);
RR->sw->requestWhois(tptr,*upstreamAddress);
// Update online status, post status change as event
const bool oldOnline = _online;
_online = (((now - pfunc.lastReceiveFromUpstream) < ZT_PEER_ACTIVITY_TIMEOUT)||(RR->topology->amRoot()));
if (oldOnline != _online)
postEvent(_online ? ZT_EVENT_ONLINE : ZT_EVENT_OFFLINE);
postEvent(tptr,_online ? ZT_EVENT_ONLINE : ZT_EVENT_OFFLINE);
} catch ( ... ) {
return ZT_RESULT_FATAL_ERROR_INTERNAL;
}
@@ -281,12 +285,12 @@ ZT_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *nextB
#ifdef ZT_ENABLE_CLUSTER
// If clustering is enabled we have to call cluster->doPeriodicTasks() very often, so we override normal timer deadline behavior
if (RR->cluster) {
RR->sw->doTimerTasks(now);
RR->sw->doTimerTasks(tptr,now);
RR->cluster->doPeriodicTasks();
*nextBackgroundTaskDeadline = now + ZT_CLUSTER_PERIODIC_TASK_PERIOD; // this is really short so just tick at this rate
} else {
#endif
*nextBackgroundTaskDeadline = now + (uint64_t)std::max(std::min(timeUntilNextPingCheck,RR->sw->doTimerTasks(now)),(unsigned long)ZT_CORE_TIMER_TASK_GRANULARITY);
*nextBackgroundTaskDeadline = now + (uint64_t)std::max(std::min(timeUntilNextPingCheck,RR->sw->doTimerTasks(tptr,now)),(unsigned long)ZT_CORE_TIMER_TASK_GRANULARITY);
#ifdef ZT_ENABLE_CLUSTER
}
#endif
@@ -297,17 +301,17 @@ ZT_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *nextB
return ZT_RESULT_OK;
}
ZT_ResultCode Node::join(uint64_t nwid,void *uptr)
ZT_ResultCode Node::join(uint64_t nwid,void *uptr,void *tptr)
{
Mutex::Lock _l(_networks_m);
SharedPtr<Network> nw = _network(nwid);
if(!nw)
_networks.push_back(std::pair< uint64_t,SharedPtr<Network> >(nwid,SharedPtr<Network>(new Network(RR,nwid,uptr))));
_networks.push_back(std::pair< uint64_t,SharedPtr<Network> >(nwid,SharedPtr<Network>(new Network(RR,tptr,nwid,uptr))));
std::sort(_networks.begin(),_networks.end()); // will sort by nwid since it's the first in a pair<>
return ZT_RESULT_OK;
}
ZT_ResultCode Node::leave(uint64_t nwid,void **uptr)
ZT_ResultCode Node::leave(uint64_t nwid,void **uptr,void *tptr)
{
std::vector< std::pair< uint64_t,SharedPtr<Network> > > newn;
Mutex::Lock _l(_networks_m);
@@ -324,11 +328,11 @@ ZT_ResultCode Node::leave(uint64_t nwid,void **uptr)
return ZT_RESULT_OK;
}
ZT_ResultCode Node::multicastSubscribe(uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi)
ZT_ResultCode Node::multicastSubscribe(void *tptr,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi)
{
SharedPtr<Network> nw(this->network(nwid));
if (nw) {
nw->multicastSubscribe(MulticastGroup(MAC(multicastGroup),(uint32_t)(multicastAdi & 0xffffffff)));
nw->multicastSubscribe(tptr,MulticastGroup(MAC(multicastGroup),(uint32_t)(multicastAdi & 0xffffffff)));
return ZT_RESULT_OK;
} else return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
}
@@ -342,15 +346,15 @@ ZT_ResultCode Node::multicastUnsubscribe(uint64_t nwid,uint64_t multicastGroup,u
} else return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
}
ZT_ResultCode Node::orbit(uint64_t moonWorldId,uint64_t moonSeed)
ZT_ResultCode Node::orbit(void *tptr,uint64_t moonWorldId,uint64_t moonSeed)
{
RR->topology->addMoon(moonWorldId,Address(moonSeed));
RR->topology->addMoon(tptr,moonWorldId,Address(moonSeed));
return ZT_RESULT_OK;
}
ZT_ResultCode Node::deorbit(uint64_t moonWorldId)
ZT_ResultCode Node::deorbit(void *tptr,uint64_t moonWorldId)
{
RR->topology->removeMoon(moonWorldId);
RR->topology->removeMoon(tptr,moonWorldId);
return ZT_RESULT_OK;
}
@@ -465,7 +469,7 @@ void Node::clearLocalInterfaceAddresses()
_directPaths.clear();
}
int Node::sendUserMessage(uint64_t dest,uint64_t typeId,const void *data,unsigned int len)
int Node::sendUserMessage(void *tptr,uint64_t dest,uint64_t typeId,const void *data,unsigned int len)
{
try {
if (RR->identity.address().toInt() != dest) {
@@ -473,7 +477,7 @@ int Node::sendUserMessage(uint64_t dest,uint64_t typeId,const void *data,unsigne
outp.append(typeId);
outp.append(data,len);
outp.compress();
RR->sw->send(outp,true);
RR->sw->send(tptr,outp,true);
return 1;
}
} catch ( ... ) {}
@@ -486,7 +490,7 @@ void Node::setNetconfMaster(void *networkControllerInstance)
RR->localNetworkController->init(RR->identity,this);
}
ZT_ResultCode Node::circuitTestBegin(ZT_CircuitTest *test,void (*reportCallback)(ZT_Node *,ZT_CircuitTest *,const ZT_CircuitTestReport *))
ZT_ResultCode Node::circuitTestBegin(void *tptr,ZT_CircuitTest *test,void (*reportCallback)(ZT_Node *,ZT_CircuitTest *,const ZT_CircuitTestReport *))
{
if (test->hopCount > 0) {
try {
@@ -516,7 +520,7 @@ ZT_ResultCode Node::circuitTestBegin(ZT_CircuitTest *test,void (*reportCallback)
for(unsigned int a=0;a<test->hops[0].breadth;++a) {
outp.newInitializationVector();
outp.setDestination(Address(test->hops[0].addresses[a]));
RR->sw->send(outp,true);
RR->sw->send(tptr,outp,true);
}
} catch ( ... ) {
return ZT_RESULT_FATAL_ERROR_INTERNAL; // probably indicates FIFO too big for packet
@@ -616,13 +620,13 @@ void Node::clusterStatus(ZT_ClusterStatus *cs)
/* Node methods used only within node/ */
/****************************************************************************/
std::string Node::dataStoreGet(const char *name)
std::string Node::dataStoreGet(void *tPtr,const char *name)
{
char buf[1024];
std::string r;
unsigned long olen = 0;
do {
long n = _cb.dataStoreGetFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,name,buf,sizeof(buf),(unsigned long)r.length(),&olen);
long n = _cb.dataStoreGetFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,name,buf,sizeof(buf),(unsigned long)r.length(),&olen);
if (n <= 0)
return std::string();
r.append(buf,n);
@@ -630,7 +634,7 @@ std::string Node::dataStoreGet(const char *name)
return r;
}
bool Node::shouldUsePathForZeroTierTraffic(const Address &ztaddr,const InetAddress &localAddress,const InetAddress &remoteAddress)
bool Node::shouldUsePathForZeroTierTraffic(void *tPtr,const Address &ztaddr,const InetAddress &localAddress,const InetAddress &remoteAddress)
{
if (!Path::isAddressValidForPath(remoteAddress))
return false;
@@ -650,7 +654,7 @@ bool Node::shouldUsePathForZeroTierTraffic(const Address &ztaddr,const InetAddre
}
}
return ( (_cb.pathCheckFunction) ? (_cb.pathCheckFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,ztaddr.toInt(),reinterpret_cast<const struct sockaddr_storage *>(&localAddress),reinterpret_cast<const struct sockaddr_storage *>(&remoteAddress)) != 0) : true);
return ( (_cb.pathCheckFunction) ? (_cb.pathCheckFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,ztaddr.toInt(),reinterpret_cast<const struct sockaddr_storage *>(&localAddress),reinterpret_cast<const struct sockaddr_storage *>(&remoteAddress)) != 0) : true);
}
#ifdef ZT_TRACE
@@ -682,7 +686,7 @@ void Node::postTrace(const char *module,unsigned int line,const char *fmt,...)
tmp2[sizeof(tmp2)-1] = (char)0;
Utils::snprintf(tmp1,sizeof(tmp1),"[%s] %s:%u %s",nowstr,module,line,tmp2);
postEvent(ZT_EVENT_TRACE,tmp1);
postEvent((void *)0,ZT_EVENT_TRACE,tmp1);
}
#endif // ZT_TRACE
@@ -728,7 +732,7 @@ void Node::ncSendConfig(uint64_t nwid,uint64_t requestPacketId,const Address &de
if (destination == RR->identity.address()) {
SharedPtr<Network> n(network(nwid));
if (!n) return;
n->setConfiguration(nc,true);
n->setConfiguration((void *)0,nc,true);
} else {
Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> *dconf = new Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY>();
try {
@@ -762,7 +766,7 @@ void Node::ncSendConfig(uint64_t nwid,uint64_t requestPacketId,const Address &de
outp.append(sig.data,ZT_C25519_SIGNATURE_LEN);
outp.compress();
RR->sw->send(outp,true);
RR->sw->send((void *)0,outp,true);
chunkIndex += chunkLen;
}
}
@@ -779,7 +783,7 @@ void Node::ncSendRevocation(const Address &destination,const Revocation &rev)
if (destination == RR->identity.address()) {
SharedPtr<Network> n(network(rev.networkId()));
if (!n) return;
n->addCredential(RR->identity.address(),rev);
n->addCredential((void *)0,RR->identity.address(),rev);
} else {
Packet outp(destination,RR->identity.address(),Packet::VERB_NETWORK_CREDENTIALS);
outp.append((uint8_t)0x00);
@@ -788,7 +792,7 @@ void Node::ncSendRevocation(const Address &destination,const Revocation &rev)
outp.append((uint16_t)1);
rev.serialize(outp);
outp.append((uint16_t)0);
RR->sw->send(outp,true);
RR->sw->send((void *)0,outp,true);
}
}
@@ -823,7 +827,7 @@ void Node::ncSendError(uint64_t nwid,uint64_t requestPacketId,const Address &des
break;
}
outp.append(nwid);
RR->sw->send(outp,true);
RR->sw->send((void *)0,outp,true);
} // else we can't send an ERROR() in response to nothing, so discard
}
@@ -835,11 +839,11 @@ void Node::ncSendError(uint64_t nwid,uint64_t requestPacketId,const Address &des
extern "C" {
enum ZT_ResultCode ZT_Node_new(ZT_Node **node,void *uptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now)
enum ZT_ResultCode ZT_Node_new(ZT_Node **node,void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now)
{
*node = (ZT_Node *)0;
try {
*node = reinterpret_cast<ZT_Node *>(new ZeroTier::Node(uptr,callbacks,now));
*node = reinterpret_cast<ZT_Node *>(new ZeroTier::Node(uptr,tptr,callbacks,now));
return ZT_RESULT_OK;
} catch (std::bad_alloc &exc) {
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
@@ -859,6 +863,7 @@ void ZT_Node_delete(ZT_Node *node)
enum ZT_ResultCode ZT_Node_processWirePacket(
ZT_Node *node,
void *tptr,
uint64_t now,
const struct sockaddr_storage *localAddress,
const struct sockaddr_storage *remoteAddress,
@@ -867,7 +872,7 @@ enum ZT_ResultCode ZT_Node_processWirePacket(
volatile uint64_t *nextBackgroundTaskDeadline)
{
try {
return reinterpret_cast<ZeroTier::Node *>(node)->processWirePacket(now,localAddress,remoteAddress,packetData,packetLength,nextBackgroundTaskDeadline);
return reinterpret_cast<ZeroTier::Node *>(node)->processWirePacket(tptr,now,localAddress,remoteAddress,packetData,packetLength,nextBackgroundTaskDeadline);
} catch (std::bad_alloc &exc) {
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
} catch ( ... ) {
@@ -877,6 +882,7 @@ enum ZT_ResultCode ZT_Node_processWirePacket(
enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame(
ZT_Node *node,
void *tptr,
uint64_t now,
uint64_t nwid,
uint64_t sourceMac,
@@ -888,7 +894,7 @@ enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame(
volatile uint64_t *nextBackgroundTaskDeadline)
{
try {
return reinterpret_cast<ZeroTier::Node *>(node)->processVirtualNetworkFrame(now,nwid,sourceMac,destMac,etherType,vlanId,frameData,frameLength,nextBackgroundTaskDeadline);
return reinterpret_cast<ZeroTier::Node *>(node)->processVirtualNetworkFrame(tptr,now,nwid,sourceMac,destMac,etherType,vlanId,frameData,frameLength,nextBackgroundTaskDeadline);
} catch (std::bad_alloc &exc) {
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
} catch ( ... ) {
@@ -896,10 +902,10 @@ enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame(
}
}
enum ZT_ResultCode ZT_Node_processBackgroundTasks(ZT_Node *node,uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline)
enum ZT_ResultCode ZT_Node_processBackgroundTasks(ZT_Node *node,void *tptr,uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline)
{
try {
return reinterpret_cast<ZeroTier::Node *>(node)->processBackgroundTasks(now,nextBackgroundTaskDeadline);
return reinterpret_cast<ZeroTier::Node *>(node)->processBackgroundTasks(tptr,now,nextBackgroundTaskDeadline);
} catch (std::bad_alloc &exc) {
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
} catch ( ... ) {
@@ -907,10 +913,10 @@ enum ZT_ResultCode ZT_Node_processBackgroundTasks(ZT_Node *node,uint64_t now,vol
}
}
enum ZT_ResultCode ZT_Node_join(ZT_Node *node,uint64_t nwid,void *uptr)
enum ZT_ResultCode ZT_Node_join(ZT_Node *node,uint64_t nwid,void *uptr,void *tptr)
{
try {
return reinterpret_cast<ZeroTier::Node *>(node)->join(nwid,uptr);
return reinterpret_cast<ZeroTier::Node *>(node)->join(nwid,uptr,tptr);
} catch (std::bad_alloc &exc) {
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
} catch ( ... ) {
@@ -918,10 +924,10 @@ enum ZT_ResultCode ZT_Node_join(ZT_Node *node,uint64_t nwid,void *uptr)
}
}
enum ZT_ResultCode ZT_Node_leave(ZT_Node *node,uint64_t nwid,void **uptr)
enum ZT_ResultCode ZT_Node_leave(ZT_Node *node,uint64_t nwid,void **uptr,void *tptr)
{
try {
return reinterpret_cast<ZeroTier::Node *>(node)->leave(nwid,uptr);
return reinterpret_cast<ZeroTier::Node *>(node)->leave(nwid,uptr,tptr);
} catch (std::bad_alloc &exc) {
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
} catch ( ... ) {
@@ -929,10 +935,10 @@ enum ZT_ResultCode ZT_Node_leave(ZT_Node *node,uint64_t nwid,void **uptr)
}
}
enum ZT_ResultCode ZT_Node_multicastSubscribe(ZT_Node *node,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi)
enum ZT_ResultCode ZT_Node_multicastSubscribe(ZT_Node *node,void *tptr,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi)
{
try {
return reinterpret_cast<ZeroTier::Node *>(node)->multicastSubscribe(nwid,multicastGroup,multicastAdi);
return reinterpret_cast<ZeroTier::Node *>(node)->multicastSubscribe(tptr,nwid,multicastGroup,multicastAdi);
} catch (std::bad_alloc &exc) {
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
} catch ( ... ) {
@@ -951,19 +957,19 @@ enum ZT_ResultCode ZT_Node_multicastUnsubscribe(ZT_Node *node,uint64_t nwid,uint
}
}
enum ZT_ResultCode ZT_Node_orbit(ZT_Node *node,uint64_t moonWorldId,uint64_t moonSeed)
enum ZT_ResultCode ZT_Node_orbit(ZT_Node *node,void *tptr,uint64_t moonWorldId,uint64_t moonSeed)
{
try {
return reinterpret_cast<ZeroTier::Node *>(node)->orbit(moonWorldId,moonSeed);
return reinterpret_cast<ZeroTier::Node *>(node)->orbit(tptr,moonWorldId,moonSeed);
} catch ( ... ) {
return ZT_RESULT_FATAL_ERROR_INTERNAL;
}
}
ZT_ResultCode ZT_Node_deorbit(ZT_Node *node,uint64_t moonWorldId)
ZT_ResultCode ZT_Node_deorbit(ZT_Node *node,void *tptr,uint64_t moonWorldId)
{
try {
return reinterpret_cast<ZeroTier::Node *>(node)->deorbit(moonWorldId);
return reinterpret_cast<ZeroTier::Node *>(node)->deorbit(tptr,moonWorldId);
} catch ( ... ) {
return ZT_RESULT_FATAL_ERROR_INTERNAL;
}
@@ -1031,10 +1037,10 @@ void ZT_Node_clearLocalInterfaceAddresses(ZT_Node *node)
} catch ( ... ) {}
}
int ZT_Node_sendUserMessage(ZT_Node *node,uint64_t dest,uint64_t typeId,const void *data,unsigned int len)
int ZT_Node_sendUserMessage(ZT_Node *node,void *tptr,uint64_t dest,uint64_t typeId,const void *data,unsigned int len)
{
try {
return reinterpret_cast<ZeroTier::Node *>(node)->sendUserMessage(dest,typeId,data,len);
return reinterpret_cast<ZeroTier::Node *>(node)->sendUserMessage(tptr,dest,typeId,data,len);
} catch ( ... ) {
return 0;
}
@@ -1047,10 +1053,10 @@ void ZT_Node_setNetconfMaster(ZT_Node *node,void *networkControllerInstance)
} catch ( ... ) {}
}
enum ZT_ResultCode ZT_Node_circuitTestBegin(ZT_Node *node,ZT_CircuitTest *test,void (*reportCallback)(ZT_Node *,ZT_CircuitTest *,const ZT_CircuitTestReport *))
enum ZT_ResultCode ZT_Node_circuitTestBegin(ZT_Node *node,void *tptr,ZT_CircuitTest *test,void (*reportCallback)(ZT_Node *,ZT_CircuitTest *,const ZT_CircuitTestReport *))
{
try {
return reinterpret_cast<ZeroTier::Node *>(node)->circuitTestBegin(test,reportCallback);
return reinterpret_cast<ZeroTier::Node *>(node)->circuitTestBegin(tptr,test,reportCallback);
} catch ( ... ) {
return ZT_RESULT_FATAL_ERROR_INTERNAL;
}

View File

@@ -65,7 +65,7 @@ class World;
class Node : public NetworkController::Sender
{
public:
Node(void *uptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now);
Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now);
virtual ~Node();
// Get rid of alignment warnings on 32-bit Windows and possibly improve performance
@@ -77,6 +77,7 @@ public:
// Public API Functions ----------------------------------------------------
ZT_ResultCode processWirePacket(
void *tptr,
uint64_t now,
const struct sockaddr_storage *localAddress,
const struct sockaddr_storage *remoteAddress,
@@ -84,6 +85,7 @@ public:
unsigned int packetLength,
volatile uint64_t *nextBackgroundTaskDeadline);
ZT_ResultCode processVirtualNetworkFrame(
void *tptr,
uint64_t now,
uint64_t nwid,
uint64_t sourceMac,
@@ -93,13 +95,13 @@ public:
const void *frameData,
unsigned int frameLength,
volatile uint64_t *nextBackgroundTaskDeadline);
ZT_ResultCode processBackgroundTasks(uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline);
ZT_ResultCode join(uint64_t nwid,void *uptr);
ZT_ResultCode leave(uint64_t nwid,void **uptr);
ZT_ResultCode multicastSubscribe(uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi);
ZT_ResultCode processBackgroundTasks(void *tptr,uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline);
ZT_ResultCode join(uint64_t nwid,void *uptr,void *tptr);
ZT_ResultCode leave(uint64_t nwid,void **uptr,void *tptr);
ZT_ResultCode multicastSubscribe(void *tptr,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi);
ZT_ResultCode multicastUnsubscribe(uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi);
ZT_ResultCode orbit(uint64_t moonWorldId,uint64_t moonSeed);
ZT_ResultCode deorbit(uint64_t moonWorldId);
ZT_ResultCode orbit(void *tptr,uint64_t moonWorldId,uint64_t moonSeed);
ZT_ResultCode deorbit(void *tptr,uint64_t moonWorldId);
uint64_t address() const;
void status(ZT_NodeStatus *status) const;
ZT_PeerList *peers() const;
@@ -108,9 +110,9 @@ public:
void freeQueryResult(void *qr);
int addLocalInterfaceAddress(const struct sockaddr_storage *addr);
void clearLocalInterfaceAddresses();
int sendUserMessage(uint64_t dest,uint64_t typeId,const void *data,unsigned int len);
int sendUserMessage(void *tptr,uint64_t dest,uint64_t typeId,const void *data,unsigned int len);
void setNetconfMaster(void *networkControllerInstance);
ZT_ResultCode circuitTestBegin(ZT_CircuitTest *test,void (*reportCallback)(ZT_Node *,ZT_CircuitTest *,const ZT_CircuitTestReport *));
ZT_ResultCode circuitTestBegin(void *tptr,ZT_CircuitTest *test,void (*reportCallback)(ZT_Node *,ZT_CircuitTest *,const ZT_CircuitTestReport *));
void circuitTestEnd(ZT_CircuitTest *test);
ZT_ResultCode clusterInit(
unsigned int myId,
@@ -132,11 +134,12 @@ public:
inline uint64_t now() const throw() { return _now; }
inline bool putPacket(const InetAddress &localAddress,const InetAddress &addr,const void *data,unsigned int len,unsigned int ttl = 0)
inline bool putPacket(void *tPtr,const InetAddress &localAddress,const InetAddress &addr,const void *data,unsigned int len,unsigned int ttl = 0)
{
return (_cb.wirePacketSendFunction(
reinterpret_cast<ZT_Node *>(this),
_uPtr,
tPtr,
reinterpret_cast<const struct sockaddr_storage *>(&localAddress),
reinterpret_cast<const struct sockaddr_storage *>(&addr),
data,
@@ -144,11 +147,12 @@ public:
ttl) == 0);
}
inline void putFrame(uint64_t nwid,void **nuptr,const MAC &source,const MAC &dest,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len)
inline void putFrame(void *tPtr,uint64_t nwid,void **nuptr,const MAC &source,const MAC &dest,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len)
{
_cb.virtualNetworkFrameFunction(
reinterpret_cast<ZT_Node *>(this),
_uPtr,
tPtr,
nwid,
nuptr,
source.toInt(),
@@ -191,14 +195,14 @@ public:
return _directPaths;
}
inline bool dataStorePut(const char *name,const void *data,unsigned int len,bool secure) { return (_cb.dataStorePutFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,name,data,len,(int)secure) == 0); }
inline bool dataStorePut(const char *name,const std::string &data,bool secure) { return dataStorePut(name,(const void *)data.data(),(unsigned int)data.length(),secure); }
inline void dataStoreDelete(const char *name) { _cb.dataStorePutFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,name,(const void *)0,0,0); }
std::string dataStoreGet(const char *name);
inline bool dataStorePut(void *tPtr,const char *name,const void *data,unsigned int len,bool secure) { return (_cb.dataStorePutFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,name,data,len,(int)secure) == 0); }
inline bool dataStorePut(void *tPtr,const char *name,const std::string &data,bool secure) { return dataStorePut(tPtr,name,(const void *)data.data(),(unsigned int)data.length(),secure); }
inline void dataStoreDelete(void *tPtr,const char *name) { _cb.dataStorePutFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,name,(const void *)0,0,0); }
std::string dataStoreGet(void *tPtr,const char *name);
inline void postEvent(ZT_Event ev,const void *md = (const void *)0) { _cb.eventCallback(reinterpret_cast<ZT_Node *>(this),_uPtr,ev,md); }
inline void postEvent(void *tPtr,ZT_Event ev,const void *md = (const void *)0) { _cb.eventCallback(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,ev,md); }
inline int configureVirtualNetworkPort(uint64_t nwid,void **nuptr,ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nc) { return _cb.virtualNetworkConfigFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,nwid,nuptr,op,nc); }
inline int configureVirtualNetworkPort(void *tPtr,uint64_t nwid,void **nuptr,ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nc) { return _cb.virtualNetworkConfigFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,nwid,nuptr,op,nc); }
inline bool online() const throw() { return _online; }
@@ -206,8 +210,8 @@ public:
void postTrace(const char *module,unsigned int line,const char *fmt,...);
#endif
bool shouldUsePathForZeroTierTraffic(const Address &ztaddr,const InetAddress &localAddress,const InetAddress &remoteAddress);
inline bool externalPathLookup(const Address &ztaddr,int family,InetAddress &addr) { return ( (_cb.pathLookupFunction) ? (_cb.pathLookupFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,ztaddr.toInt(),family,reinterpret_cast<struct sockaddr_storage *>(&addr)) != 0) : false ); }
bool shouldUsePathForZeroTierTraffic(void *tPtr,const Address &ztaddr,const InetAddress &localAddress,const InetAddress &remoteAddress);
inline bool externalPathLookup(void *tPtr,const Address &ztaddr,int family,InetAddress &addr) { return ( (_cb.pathLookupFunction) ? (_cb.pathLookupFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,ztaddr.toInt(),family,reinterpret_cast<struct sockaddr_storage *>(&addr)) != 0) : false ); }
uint64_t prng();
void postCircuitTestReport(const ZT_CircuitTestReport *report);

View File

@@ -85,16 +85,18 @@ void OutboundMulticast::init(
memcpy(_frameData,payload,_frameLen);
}
void OutboundMulticast::sendOnly(const RuntimeEnvironment *RR,const Address &toAddr)
void OutboundMulticast::sendOnly(const RuntimeEnvironment *RR,void *tPtr,const Address &toAddr)
{
const SharedPtr<Network> nw(RR->node->network(_nwid));
const Address toAddr2(toAddr);
if ((nw)&&(nw->filterOutgoingPacket(true,RR->identity.address(),toAddr2,_macSrc,_macDest,_frameData,_frameLen,_etherType,0))) {
if ((nw)&&(nw->filterOutgoingPacket(tPtr,true,RR->identity.address(),toAddr2,_macSrc,_macDest,_frameData,_frameLen,_etherType,0))) {
//TRACE(">>MC %.16llx -> %s",(unsigned long long)this,toAddr.toString().c_str());
_packet.newInitializationVector();
_packet.setDestination(toAddr2);
RR->node->expectReplyTo(_packet.packetId());
RR->sw->send(_packet,true);
Packet tmp(_packet); // make a copy of packet so as not to garble the original -- GitHub issue #461
RR->sw->send(tPtr,tmp,true);
}
}

View File

@@ -99,33 +99,36 @@ public:
* Just send without checking log
*
* @param RR Runtime environment
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param toAddr Destination address
*/
void sendOnly(const RuntimeEnvironment *RR,const Address &toAddr);
void sendOnly(const RuntimeEnvironment *RR,void *tPtr,const Address &toAddr);
/**
* Just send and log but do not check sent log
*
* @param RR Runtime environment
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param toAddr Destination address
*/
inline void sendAndLog(const RuntimeEnvironment *RR,const Address &toAddr)
inline void sendAndLog(const RuntimeEnvironment *RR,void *tPtr,const Address &toAddr)
{
_alreadySentTo.push_back(toAddr);
sendOnly(RR,toAddr);
sendOnly(RR,tPtr,toAddr);
}
/**
* Try to send this to a given peer if it hasn't been sent to them already
*
* @param RR Runtime environment
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param toAddr Destination address
* @return True if address is new and packet was sent to switch, false if duplicate
*/
inline bool sendIfNew(const RuntimeEnvironment *RR,const Address &toAddr)
inline bool sendIfNew(const RuntimeEnvironment *RR,void *tPtr,const Address &toAddr)
{
if (std::find(_alreadySentTo.begin(),_alreadySentTo.end(),toAddr) == _alreadySentTo.end()) {
sendAndLog(RR,toAddr);
sendAndLog(RR,tPtr,toAddr);
return true;
} else {
return false;

File diff suppressed because it is too large Load Diff

View File

@@ -1322,7 +1322,7 @@ public:
/**
* @return Value of link quality counter extracted from this packet's ID, range 0 to 7 (3 bits)
*/
inline unsigned int linkQualityCounter() const { return (unsigned int)(reinterpret_cast<const uint8_t *>(data())[7] & 7); }
inline unsigned int linkQualityCounter() const { return (unsigned int)(reinterpret_cast<const uint8_t *>(data())[7] & 0x07); }
/**
* Set packet verb

View File

@@ -22,9 +22,9 @@
namespace ZeroTier {
bool Path::send(const RuntimeEnvironment *RR,const void *data,unsigned int len,uint64_t now)
bool Path::send(const RuntimeEnvironment *RR,void *tPtr,const void *data,unsigned int len,uint64_t now)
{
if (RR->node->putPacket(_localAddress,address(),data,len)) {
if (RR->node->putPacket(tPtr,_localAddress,address(),data,len)) {
_lastOut = now;
return true;
}

View File

@@ -186,12 +186,13 @@ public:
* Send a packet via this path (last out time is also updated)
*
* @param RR Runtime environment
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param data Packet data
* @param len Packet length
* @param now Current time
* @return True if transport reported success
*/
bool send(const RuntimeEnvironment *RR,const void *data,unsigned int len,uint64_t now);
bool send(const RuntimeEnvironment *RR,void *tPtr,const void *data,unsigned int len,uint64_t now);
/**
* Manually update last sent time

View File

@@ -68,6 +68,7 @@ Peer::Peer(const RuntimeEnvironment *renv,const Identity &myIdentity,const Ident
}
void Peer::received(
void *tPtr,
const SharedPtr<Path> &path,
const unsigned int hops,
const uint64_t packetId,
@@ -102,7 +103,7 @@ void Peer::received(
}
outp.append((uint16_t)redirectTo.port());
outp.armor(_key,true,path->nextOutgoingCounter());
path->send(RR,outp.data(),outp.size(),now);
path->send(RR,tPtr,outp.data(),outp.size(),now);
} else {
// For older peers we use RENDEZVOUS to coax them into contacting us elsewhere.
Packet outp(_id.address(),RR->identity.address(),Packet::VERB_RENDEZVOUS);
@@ -117,7 +118,7 @@ void Peer::received(
outp.append(redirectTo.rawIpData(),16);
}
outp.armor(_key,true,path->nextOutgoingCounter());
path->send(RR,outp.data(),outp.size(),now);
path->send(RR,tPtr,outp.data(),outp.size(),now);
}
suboptimalPath = true;
}
@@ -161,7 +162,7 @@ void Peer::received(
}
}
if ( (!pathIsConfirmed) && (RR->node->shouldUsePathForZeroTierTraffic(_id.address(),path->localAddress(),path->address())) ) {
if ( (!pathIsConfirmed) && (RR->node->shouldUsePathForZeroTierTraffic(tPtr,_id.address(),path->localAddress(),path->address())) ) {
if (verb == Packet::VERB_OK) {
Mutex::Lock _l(_paths_m);
@@ -206,7 +207,7 @@ void Peer::received(
#endif
} else {
TRACE("got %s via unknown path %s(%s), confirming...",Packet::verbString(verb),_id.address().toString().c_str(),path->address().toString().c_str());
attemptToContactAt(path->localAddress(),path->address(),now,true,path->nextOutgoingCounter());
attemptToContactAt(tPtr,path->localAddress(),path->address(),now,true,path->nextOutgoingCounter());
path->sent(now);
}
}
@@ -281,7 +282,7 @@ void Peer::received(
if (count) {
outp.setAt(ZT_PACKET_IDX_PAYLOAD,(uint16_t)count);
outp.armor(_key,true,path->nextOutgoingCounter());
path->send(RR,outp.data(),outp.size(),now);
path->send(RR,tPtr,outp.data(),outp.size(),now);
}
}
}
@@ -299,7 +300,7 @@ bool Peer::hasActivePathTo(uint64_t now,const InetAddress &addr) const
return false;
}
bool Peer::sendDirect(const void *data,unsigned int len,uint64_t now,bool forceEvenIfDead)
bool Peer::sendDirect(void *tPtr,const void *data,unsigned int len,uint64_t now,bool forceEvenIfDead)
{
Mutex::Lock _l(_paths_m);
@@ -316,7 +317,7 @@ bool Peer::sendDirect(const void *data,unsigned int len,uint64_t now,bool forceE
}
if (bestp >= 0) {
return _paths[bestp].path->send(RR,data,len,now);
return _paths[bestp].path->send(RR,tPtr,data,len,now);
} else {
return false;
}
@@ -345,7 +346,7 @@ SharedPtr<Path> Peer::getBestPath(uint64_t now,bool includeExpired)
}
}
void Peer::sendHELLO(const InetAddress &localAddr,const InetAddress &atAddress,uint64_t now,unsigned int counter)
void Peer::sendHELLO(void *tPtr,const InetAddress &localAddr,const InetAddress &atAddress,uint64_t now,unsigned int counter)
{
Packet outp(_id.address(),RR->identity.address(),Packet::VERB_HELLO);
@@ -387,35 +388,35 @@ void Peer::sendHELLO(const InetAddress &localAddr,const InetAddress &atAddress,u
if (atAddress) {
outp.armor(_key,false,counter); // false == don't encrypt full payload, but add MAC
RR->node->putPacket(localAddr,atAddress,outp.data(),outp.size());
RR->node->putPacket(tPtr,localAddr,atAddress,outp.data(),outp.size());
} else {
RR->sw->send(outp,false); // false == don't encrypt full payload, but add MAC
RR->sw->send(tPtr,outp,false); // false == don't encrypt full payload, but add MAC
}
}
void Peer::attemptToContactAt(const InetAddress &localAddr,const InetAddress &atAddress,uint64_t now,bool sendFullHello,unsigned int counter)
void Peer::attemptToContactAt(void *tPtr,const InetAddress &localAddr,const InetAddress &atAddress,uint64_t now,bool sendFullHello,unsigned int counter)
{
if ( (!sendFullHello) && (_vProto >= 5) && (!((_vMajor == 1)&&(_vMinor == 1)&&(_vRevision == 0))) ) {
Packet outp(_id.address(),RR->identity.address(),Packet::VERB_ECHO);
RR->node->expectReplyTo(outp.packetId());
outp.armor(_key,true,counter);
RR->node->putPacket(localAddr,atAddress,outp.data(),outp.size());
RR->node->putPacket(tPtr,localAddr,atAddress,outp.data(),outp.size());
} else {
sendHELLO(localAddr,atAddress,now,counter);
sendHELLO(tPtr,localAddr,atAddress,now,counter);
}
}
void Peer::tryMemorizedPath(uint64_t now)
void Peer::tryMemorizedPath(void *tPtr,uint64_t now)
{
if ((now - _lastTriedMemorizedPath) >= ZT_TRY_MEMORIZED_PATH_INTERVAL) {
_lastTriedMemorizedPath = now;
InetAddress mp;
if (RR->node->externalPathLookup(_id.address(),-1,mp))
attemptToContactAt(InetAddress(),mp,now,true,0);
if (RR->node->externalPathLookup(tPtr,_id.address(),-1,mp))
attemptToContactAt(tPtr,InetAddress(),mp,now,true,0);
}
}
bool Peer::doPingAndKeepalive(uint64_t now,int inetAddressFamily)
bool Peer::doPingAndKeepalive(void *tPtr,uint64_t now,int inetAddressFamily)
{
Mutex::Lock _l(_paths_m);
@@ -433,7 +434,7 @@ bool Peer::doPingAndKeepalive(uint64_t now,int inetAddressFamily)
if (bestp >= 0) {
if ( ((now - _paths[bestp].lastReceive) >= ZT_PEER_PING_PERIOD) || (_paths[bestp].path->needsHeartbeat(now)) ) {
attemptToContactAt(_paths[bestp].path->localAddress(),_paths[bestp].path->address(),now,false,_paths[bestp].path->nextOutgoingCounter());
attemptToContactAt(tPtr,_paths[bestp].path->localAddress(),_paths[bestp].path->address(),now,false,_paths[bestp].path->nextOutgoingCounter());
_paths[bestp].path->sent(now);
}
return true;
@@ -452,12 +453,12 @@ bool Peer::hasActiveDirectPath(uint64_t now) const
return false;
}
void Peer::resetWithinScope(InetAddress::IpScope scope,int inetAddressFamily,uint64_t now)
void Peer::resetWithinScope(void *tPtr,InetAddress::IpScope scope,int inetAddressFamily,uint64_t now)
{
Mutex::Lock _l(_paths_m);
for(unsigned int p=0;p<_numPaths;++p) {
if ( (_paths[p].path->address().ss_family == inetAddressFamily) && (_paths[p].path->address().ipScope() == scope) ) {
attemptToContactAt(_paths[p].path->localAddress(),_paths[p].path->address(),now,false,_paths[p].path->nextOutgoingCounter());
attemptToContactAt(tPtr,_paths[p].path->localAddress(),_paths[p].path->address(),now,false,_paths[p].path->nextOutgoingCounter());
_paths[p].path->sent(now);
_paths[p].lastReceive = 0; // path will not be used unless it speaks again
}

View File

@@ -84,6 +84,7 @@ public:
* This is called by the decode pipe when a packet is proven to be authentic
* and appears to be valid.
*
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param path Path over which packet was received
* @param hops ZeroTier (not IP) hops
* @param packetId Packet ID
@@ -93,6 +94,7 @@ public:
* @param trustEstablished If true, some form of non-trivial trust (like allowed in network) has been established
*/
void received(
void *tPtr,
const SharedPtr<Path> &path,
const unsigned int hops,
const uint64_t packetId,
@@ -125,13 +127,14 @@ public:
/**
* Send via best direct path
*
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param data Packet data
* @param len Packet length
* @param now Current time
* @param forceEvenIfDead If true, send even if the path is not 'alive'
* @return True if we actually sent something
*/
bool sendDirect(const void *data,unsigned int len,uint64_t now,bool forceEvenIfDead);
bool sendDirect(void *tPtr,const void *data,unsigned int len,uint64_t now,bool forceEvenIfDead);
/**
* Get the best current direct path
@@ -147,41 +150,47 @@ public:
*
* No statistics or sent times are updated here.
*
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param localAddr Local address
* @param atAddress Destination address
* @param now Current time
* @param counter Outgoing packet counter
*/
void sendHELLO(const InetAddress &localAddr,const InetAddress &atAddress,uint64_t now,unsigned int counter);
void sendHELLO(void *tPtr,const InetAddress &localAddr,const InetAddress &atAddress,uint64_t now,unsigned int counter);
/**
* Send ECHO (or HELLO for older peers) to this peer at the given address
*
* No statistics or sent times are updated here.
*
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param localAddr Local address
* @param atAddress Destination address
* @param now Current time
* @param sendFullHello If true, always send a full HELLO instead of just an ECHO
* @param counter Outgoing packet counter
*/
void attemptToContactAt(const InetAddress &localAddr,const InetAddress &atAddress,uint64_t now,bool sendFullHello,unsigned int counter);
void attemptToContactAt(void *tPtr,const InetAddress &localAddr,const InetAddress &atAddress,uint64_t now,bool sendFullHello,unsigned int counter);
/**
* Try a memorized or statically defined path if any are known
*
* Under the hood this is done periodically based on ZT_TRY_MEMORIZED_PATH_INTERVAL.
*
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param now Current time
*/
void tryMemorizedPath(uint64_t now);
void tryMemorizedPath(void *tPtr,uint64_t now);
/**
* Send pings or keepalives depending on configured timeouts
*
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param now Current time
* @param inetAddressFamily Keep this address family alive, or -1 for any
* @return True if we have at least one direct path of the given family (or any if family is -1)
*/
bool doPingAndKeepalive(uint64_t now,int inetAddressFamily);
bool doPingAndKeepalive(void *tPtr,uint64_t now,int inetAddressFamily);
/**
* @param now Current time
@@ -195,11 +204,12 @@ public:
* Resetting a path involves sending an ECHO to it and then deactivating
* it until or unless it responds.
*
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param scope IP scope
* @param inetAddressFamily Family e.g. AF_INET
* @param now Current time
*/
void resetWithinScope(InetAddress::IpScope scope,int inetAddressFamily,uint64_t now);
void resetWithinScope(void *tPtr,InetAddress::IpScope scope,int inetAddressFamily,uint64_t now);
/**
* Get most recently active path addresses for IPv4 and/or IPv6

View File

@@ -25,13 +25,13 @@
namespace ZeroTier {
int Revocation::verify(const RuntimeEnvironment *RR) const
int Revocation::verify(const RuntimeEnvironment *RR,void *tPtr) const
{
if ((!_signedBy)||(_signedBy != Network::controllerFor(_networkId)))
return -1;
const Identity id(RR->topology->getIdentity(_signedBy));
const Identity id(RR->topology->getIdentity(tPtr,_signedBy));
if (!id) {
RR->sw->requestWhois(_signedBy);
RR->sw->requestWhois(tPtr,_signedBy);
return 1;
}
try {

View File

@@ -113,9 +113,10 @@ public:
* Verify this revocation's signature
*
* @param RR Runtime environment to provide for peer lookup, etc.
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @return 0 == OK, 1 == waiting for WHOIS, -1 == BAD signature or chain
*/
int verify(const RuntimeEnvironment *RR) const;
int verify(const RuntimeEnvironment *RR,void *tPtr) const;
template<unsigned int C>
inline void serialize(Buffer<C> &b,const bool forSign = false) const

View File

@@ -40,15 +40,17 @@ namespace ZeroTier {
class _ResetWithinScope
{
public:
_ResetWithinScope(uint64_t now,int inetAddressFamily,InetAddress::IpScope scope) :
_ResetWithinScope(void *tPtr,uint64_t now,int inetAddressFamily,InetAddress::IpScope scope) :
_now(now),
_tPtr(tPtr),
_family(inetAddressFamily),
_scope(scope) {}
inline void operator()(Topology &t,const SharedPtr<Peer> &p) { p->resetWithinScope(_scope,_family,_now); }
inline void operator()(Topology &t,const SharedPtr<Peer> &p) { p->resetWithinScope(_tPtr,_scope,_family,_now); }
private:
uint64_t _now;
void *_tPtr;
int _family;
InetAddress::IpScope _scope;
};
@@ -59,7 +61,7 @@ SelfAwareness::SelfAwareness(const RuntimeEnvironment *renv) :
{
}
void SelfAwareness::iam(const Address &reporter,const InetAddress &receivedOnLocalAddress,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,bool trusted,uint64_t now)
void SelfAwareness::iam(void *tPtr,const Address &reporter,const InetAddress &receivedOnLocalAddress,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,bool trusted,uint64_t now)
{
const InetAddress::IpScope scope = myPhysicalAddress.ipScope();
@@ -91,7 +93,7 @@ void SelfAwareness::iam(const Address &reporter,const InetAddress &receivedOnLoc
}
// Reset all paths within this scope and address family
_ResetWithinScope rset(now,myPhysicalAddress.ss_family,(InetAddress::IpScope)scope);
_ResetWithinScope rset(tPtr,now,myPhysicalAddress.ss_family,(InetAddress::IpScope)scope);
RR->topology->eachPeer<_ResetWithinScope &>(rset);
} else {
// Otherwise just update DB to use to determine external surface info

View File

@@ -47,7 +47,7 @@ public:
* @param trusted True if this peer is trusted as an authority to inform us of external address changes
* @param now Current time
*/
void iam(const Address &reporter,const InetAddress &receivedOnLocalAddress,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,bool trusted,uint64_t now);
void iam(void *tPtr,const Address &reporter,const InetAddress &receivedOnLocalAddress,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,bool trusted,uint64_t now);
/**
* Clean up database periodically

View File

@@ -64,7 +64,7 @@ Switch::Switch(const RuntimeEnvironment *renv) :
{
}
void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &fromAddr,const void *data,unsigned int len)
void Switch::onRemotePacket(void *tPtr,const InetAddress &localAddr,const InetAddress &fromAddr,const void *data,unsigned int len)
{
try {
const uint64_t now = RR->node->now();
@@ -81,15 +81,15 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from
const Address beaconAddr(reinterpret_cast<const char *>(data) + 8,5);
if (beaconAddr == RR->identity.address())
return;
if (!RR->node->shouldUsePathForZeroTierTraffic(beaconAddr,localAddr,fromAddr))
if (!RR->node->shouldUsePathForZeroTierTraffic(tPtr,beaconAddr,localAddr,fromAddr))
return;
const SharedPtr<Peer> peer(RR->topology->getPeer(beaconAddr));
const SharedPtr<Peer> peer(RR->topology->getPeer(tPtr,beaconAddr));
if (peer) { // we'll only respond to beacons from known peers
if ((now - _lastBeaconResponse) >= 2500) { // limit rate of responses
_lastBeaconResponse = now;
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_NOP);
outp.armor(peer->key(),true,path->nextOutgoingCounter());
path->send(RR,outp.data(),outp.size(),now);
path->send(RR,tPtr,outp.data(),outp.size(),now);
}
}
@@ -115,8 +115,8 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from
// Note: we don't bother initiating NAT-t for fragments, since heads will set that off.
// It wouldn't hurt anything, just redundant and unnecessary.
SharedPtr<Peer> relayTo = RR->topology->getPeer(destination);
if ((!relayTo)||(!relayTo->sendDirect(fragment.data(),fragment.size(),now,false))) {
SharedPtr<Peer> relayTo = RR->topology->getPeer(tPtr,destination);
if ((!relayTo)||(!relayTo->sendDirect(tPtr,fragment.data(),fragment.size(),now,false))) {
#ifdef ZT_ENABLE_CLUSTER
if ((RR->cluster)&&(!isClusterFrontplane)) {
RR->cluster->relayViaCluster(Address(),destination,fragment.data(),fragment.size(),false);
@@ -127,7 +127,7 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from
// Don't know peer or no direct path -- so relay via someone upstream
relayTo = RR->topology->getUpstreamPeer();
if (relayTo)
relayTo->sendDirect(fragment.data(),fragment.size(),now,true);
relayTo->sendDirect(tPtr,fragment.data(),fragment.size(),now,true);
}
} else {
TRACE("dropped relay [fragment](%s) -> %s, max hops exceeded",fromAddr.toString().c_str(),destination.toString().c_str());
@@ -171,7 +171,7 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from
for(unsigned int f=1;f<totalFragments;++f)
rq->frag0.append(rq->frags[f - 1].payload(),rq->frags[f - 1].payloadLength());
if (rq->frag0.tryDecode(RR)) {
if (rq->frag0.tryDecode(RR,tPtr)) {
rq->timestamp = 0; // packet decoded, free entry
} else {
rq->complete = true; // set complete flag but leave entry since it probably needs WHOIS or something
@@ -212,8 +212,8 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from
packet.incrementHops();
#endif
SharedPtr<Peer> relayTo = RR->topology->getPeer(destination);
if ((relayTo)&&(relayTo->sendDirect(packet.data(),packet.size(),now,false))) {
SharedPtr<Peer> relayTo = RR->topology->getPeer(tPtr,destination);
if ((relayTo)&&(relayTo->sendDirect(tPtr,packet.data(),packet.size(),now,false))) {
if ((source != RR->identity.address())&&(_shouldUnite(now,source,destination))) { // don't send RENDEZVOUS for cluster frontplane relays
const InetAddress *hintToSource = (InetAddress *)0;
const InetAddress *hintToDest = (InetAddress *)0;
@@ -222,7 +222,7 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from
InetAddress sourceV4,sourceV6;
relayTo->getRendezvousAddresses(now,destV4,destV6);
const SharedPtr<Peer> sourcePeer(RR->topology->getPeer(source));
const SharedPtr<Peer> sourcePeer(RR->topology->getPeer(tPtr,source));
if (sourcePeer) {
sourcePeer->getRendezvousAddresses(now,sourceV4,sourceV6);
if ((destV6)&&(sourceV6)) {
@@ -249,7 +249,7 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from
outp.append((uint8_t)4);
outp.append(hintToSource->rawIpData(),4);
}
send(outp,true);
send(tPtr,outp,true);
} else {
Packet outp(destination,RR->identity.address(),Packet::VERB_RENDEZVOUS);
outp.append((uint8_t)0);
@@ -262,7 +262,7 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from
outp.append((uint8_t)4);
outp.append(hintToDest->rawIpData(),4);
}
send(outp,true);
send(tPtr,outp,true);
}
++alt;
}
@@ -278,7 +278,7 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from
#endif
relayTo = RR->topology->getUpstreamPeer(&source,1,true);
if (relayTo)
relayTo->sendDirect(packet.data(),packet.size(),now,true);
relayTo->sendDirect(tPtr,packet.data(),packet.size(),now,true);
}
} else {
TRACE("dropped relay %s(%s) -> %s, max hops exceeded",packet.source().toString().c_str(),fromAddr.toString().c_str(),destination.toString().c_str());
@@ -321,7 +321,7 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from
for(unsigned int f=1;f<rq->totalFragments;++f)
rq->frag0.append(rq->frags[f - 1].payload(),rq->frags[f - 1].payloadLength());
if (rq->frag0.tryDecode(RR)) {
if (rq->frag0.tryDecode(RR,tPtr)) {
rq->timestamp = 0; // packet decoded, free entry
} else {
rq->complete = true; // set complete flag but leave entry since it probably needs WHOIS or something
@@ -334,7 +334,7 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from
} else {
// Packet is unfragmented, so just process it
IncomingPacket packet(data,len,path,now);
if (!packet.tryDecode(RR)) {
if (!packet.tryDecode(RR,tPtr)) {
Mutex::Lock _l(_rxQueue_m);
RXQueueEntry *rq = &(_rxQueue[ZT_RX_QUEUE_SIZE - 1]);
unsigned long i = ZT_RX_QUEUE_SIZE - 1;
@@ -362,7 +362,7 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from
}
}
void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,const MAC &to,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len)
void Switch::onLocalEthernet(void *tPtr,const SharedPtr<Network> &network,const MAC &from,const MAC &to,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len)
{
if (!network->hasConfig())
return;
@@ -474,7 +474,7 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
adv[42] = (checksum >> 8) & 0xff;
adv[43] = checksum & 0xff;
RR->node->putFrame(network->id(),network->userPtr(),peerMac,from,ZT_ETHERTYPE_IPV6,0,adv,72);
RR->node->putFrame(tPtr,network->id(),network->userPtr(),peerMac,from,ZT_ETHERTYPE_IPV6,0,adv,72);
return; // NDP emulation done. We have forged a "fake" reply, so no need to send actual NDP query.
} // else no NDP emulation
} // else no NDP emulation
@@ -491,17 +491,18 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
* multicast addresses on bridge interfaces and subscribing each slave.
* But in that case this does no harm, as the sets are just merged. */
if (fromBridged)
network->learnBridgedMulticastGroup(multicastGroup,RR->node->now());
network->learnBridgedMulticastGroup(tPtr,multicastGroup,RR->node->now());
//TRACE("%.16llx: MULTICAST %s -> %s %s %u",network->id(),from.toString().c_str(),multicastGroup.toString().c_str(),etherTypeName(etherType),len);
// First pass sets noTee to false, but noTee is set to true in OutboundMulticast to prevent duplicates.
if (!network->filterOutgoingPacket(false,RR->identity.address(),Address(),from,to,(const uint8_t *)data,len,etherType,vlanId)) {
if (!network->filterOutgoingPacket(tPtr,false,RR->identity.address(),Address(),from,to,(const uint8_t *)data,len,etherType,vlanId)) {
TRACE("%.16llx: %s -> %s %s packet not sent: filterOutgoingPacket() returned false",network->id(),from.toString().c_str(),to.toString().c_str(),etherTypeName(etherType));
return;
}
RR->mc->send(
tPtr,
network->config().multicastLimit,
RR->node->now(),
network->id(),
@@ -514,14 +515,14 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
len);
} else if (to == network->mac()) {
// Destination is this node, so just reinject it
RR->node->putFrame(network->id(),network->userPtr(),from,to,etherType,vlanId,data,len);
RR->node->putFrame(tPtr,network->id(),network->userPtr(),from,to,etherType,vlanId,data,len);
} else if (to[0] == MAC::firstOctetForNetwork(network->id())) {
// Destination is another ZeroTier peer on the same network
Address toZT(to.toAddress(network->id())); // since in-network MACs are derived from addresses and network IDs, we can reverse this
SharedPtr<Peer> toPeer(RR->topology->getPeer(toZT));
SharedPtr<Peer> toPeer(RR->topology->getPeer(tPtr,toZT));
if (!network->filterOutgoingPacket(false,RR->identity.address(),toZT,from,to,(const uint8_t *)data,len,etherType,vlanId)) {
if (!network->filterOutgoingPacket(tPtr,false,RR->identity.address(),toZT,from,to,(const uint8_t *)data,len,etherType,vlanId)) {
TRACE("%.16llx: %s -> %s %s packet not sent: filterOutgoingPacket() returned false",network->id(),from.toString().c_str(),to.toString().c_str(),etherTypeName(etherType));
return;
}
@@ -536,7 +537,7 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
outp.append(data,len);
if (!network->config().disableCompression())
outp.compress();
send(outp,true);
send(tPtr,outp,true);
} else {
Packet outp(toZT,RR->identity.address(),Packet::VERB_FRAME);
outp.append(network->id());
@@ -544,7 +545,7 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
outp.append(data,len);
if (!network->config().disableCompression())
outp.compress();
send(outp,true);
send(tPtr,outp,true);
}
//TRACE("%.16llx: UNICAST: %s -> %s etherType==%s(%.4x) vlanId==%u len==%u fromBridged==%d includeCom==%d",network->id(),from.toString().c_str(),to.toString().c_str(),etherTypeName(etherType),etherType,vlanId,len,(int)fromBridged,(int)includeCom);
@@ -554,7 +555,7 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
// We filter with a NULL destination ZeroTier address first. Filtrations
// for each ZT destination are also done below. This is the same rationale
// and design as for multicast.
if (!network->filterOutgoingPacket(false,RR->identity.address(),Address(),from,to,(const uint8_t *)data,len,etherType,vlanId)) {
if (!network->filterOutgoingPacket(tPtr,false,RR->identity.address(),Address(),from,to,(const uint8_t *)data,len,etherType,vlanId)) {
TRACE("%.16llx: %s -> %s %s packet not sent: filterOutgoingPacket() returned false",network->id(),from.toString().c_str(),to.toString().c_str(),etherTypeName(etherType));
return;
}
@@ -592,7 +593,7 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
}
for(unsigned int b=0;b<numBridges;++b) {
if (network->filterOutgoingPacket(true,RR->identity.address(),bridges[b],from,to,(const uint8_t *)data,len,etherType,vlanId)) {
if (network->filterOutgoingPacket(tPtr,true,RR->identity.address(),bridges[b],from,to,(const uint8_t *)data,len,etherType,vlanId)) {
Packet outp(bridges[b],RR->identity.address(),Packet::VERB_EXT_FRAME);
outp.append(network->id());
outp.append((uint8_t)0x00);
@@ -602,7 +603,7 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
outp.append(data,len);
if (!network->config().disableCompression())
outp.compress();
send(outp,true);
send(tPtr,outp,true);
} else {
TRACE("%.16llx: %s -> %s %s packet not sent: filterOutgoingPacket() returned false",network->id(),from.toString().c_str(),to.toString().c_str(),etherTypeName(etherType));
}
@@ -610,21 +611,28 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
}
}
void Switch::send(Packet &packet,bool encrypt)
void Switch::send(void *tPtr,Packet &packet,bool encrypt)
{
if (packet.destination() == RR->identity.address()) {
TRACE("BUG: caught attempt to send() to self, ignored");
return;
}
if (!_trySend(packet,encrypt)) {
if (!_trySend(tPtr,packet,encrypt)) {
Mutex::Lock _l(_txQueue_m);
_txQueue.push_back(TXQueueEntry(packet.destination(),RR->node->now(),packet,encrypt));
}
}
void Switch::requestWhois(const Address &addr)
void Switch::requestWhois(void *tPtr,const Address &addr)
{
#ifdef ZT_TRACE
if (addr == RR->identity.address()) {
fprintf(stderr,"FATAL BUG: Switch::requestWhois() caught attempt to WHOIS self" ZT_EOL_S);
abort();
}
#endif
bool inserted = false;
{
Mutex::Lock _l(_outstandingWhoisRequests_m);
@@ -637,10 +645,10 @@ void Switch::requestWhois(const Address &addr)
}
}
if (inserted)
_sendWhoisRequest(addr,(const Address *)0,0);
_sendWhoisRequest(tPtr,addr,(const Address *)0,0);
}
void Switch::doAnythingWaitingForPeer(const SharedPtr<Peer> &peer)
void Switch::doAnythingWaitingForPeer(void *tPtr,const SharedPtr<Peer> &peer)
{
{ // cancel pending WHOIS since we now know this peer
Mutex::Lock _l(_outstandingWhoisRequests_m);
@@ -653,7 +661,7 @@ void Switch::doAnythingWaitingForPeer(const SharedPtr<Peer> &peer)
while (i) {
RXQueueEntry *rq = &(_rxQueue[--i]);
if ((rq->timestamp)&&(rq->complete)) {
if (rq->frag0.tryDecode(RR))
if (rq->frag0.tryDecode(RR,tPtr))
rq->timestamp = 0;
}
}
@@ -663,7 +671,7 @@ void Switch::doAnythingWaitingForPeer(const SharedPtr<Peer> &peer)
Mutex::Lock _l(_txQueue_m);
for(std::list< TXQueueEntry >::iterator txi(_txQueue.begin());txi!=_txQueue.end();) {
if (txi->dest == peer->address()) {
if (_trySend(txi->packet,txi->encrypt))
if (_trySend(tPtr,txi->packet,txi->encrypt))
_txQueue.erase(txi++);
else ++txi;
} else ++txi;
@@ -671,7 +679,7 @@ void Switch::doAnythingWaitingForPeer(const SharedPtr<Peer> &peer)
}
}
unsigned long Switch::doTimerTasks(uint64_t now)
unsigned long Switch::doTimerTasks(void *tPtr,uint64_t now)
{
unsigned long nextDelay = 0xffffffff; // ceiling delay, caller will cap to minimum
@@ -688,7 +696,7 @@ unsigned long Switch::doTimerTasks(uint64_t now)
_outstandingWhoisRequests.erase(*a);
} else {
r->lastSent = now;
r->peersConsulted[r->retries] = _sendWhoisRequest(*a,r->peersConsulted,(r->retries > 1) ? r->retries : 0);
r->peersConsulted[r->retries] = _sendWhoisRequest(tPtr,*a,r->peersConsulted,(r->retries > 1) ? r->retries : 0);
TRACE("WHOIS %s (retry %u)",a->toString().c_str(),r->retries);
++r->retries;
nextDelay = std::min(nextDelay,(unsigned long)ZT_WHOIS_RETRY_DELAY);
@@ -702,7 +710,7 @@ unsigned long Switch::doTimerTasks(uint64_t now)
{ // Time out TX queue packets that never got WHOIS lookups or other info.
Mutex::Lock _l(_txQueue_m);
for(std::list< TXQueueEntry >::iterator txi(_txQueue.begin());txi!=_txQueue.end();) {
if (_trySend(txi->packet,txi->encrypt))
if (_trySend(tPtr,txi->packet,txi->encrypt))
_txQueue.erase(txi++);
else if ((now - txi->creationTime) > ZT_TRANSMIT_QUEUE_TIMEOUT) {
TRACE("TX %s -> %s timed out",txi->packet.source().toString().c_str(),txi->packet.destination().toString().c_str());
@@ -736,19 +744,19 @@ bool Switch::_shouldUnite(const uint64_t now,const Address &source,const Address
return false;
}
Address Switch::_sendWhoisRequest(const Address &addr,const Address *peersAlreadyConsulted,unsigned int numPeersAlreadyConsulted)
Address Switch::_sendWhoisRequest(void *tPtr,const Address &addr,const Address *peersAlreadyConsulted,unsigned int numPeersAlreadyConsulted)
{
SharedPtr<Peer> upstream(RR->topology->getUpstreamPeer(peersAlreadyConsulted,numPeersAlreadyConsulted,false));
if (upstream) {
Packet outp(upstream->address(),RR->identity.address(),Packet::VERB_WHOIS);
addr.appendTo(outp);
RR->node->expectReplyTo(outp.packetId());
send(outp,true);
send(tPtr,outp,true);
}
return Address();
}
bool Switch::_trySend(Packet &packet,bool encrypt)
bool Switch::_trySend(void *tPtr,Packet &packet,bool encrypt)
{
SharedPtr<Path> viaPath;
const uint64_t now = RR->node->now();
@@ -762,7 +770,7 @@ bool Switch::_trySend(Packet &packet,bool encrypt)
clusterMostRecentMemberId = RR->cluster->checkSendViaCluster(destination,clusterMostRecentTs,clusterPeerSecret);
#endif
const SharedPtr<Peer> peer(RR->topology->getPeer(destination));
const SharedPtr<Peer> peer(RR->topology->getPeer(tPtr,destination));
if (peer) {
/* First get the best path, and if it's dead (and this is not a root)
* we attempt to re-activate that path but this packet will flow
@@ -777,7 +785,7 @@ bool Switch::_trySend(Packet &packet,bool encrypt)
if ((clusterMostRecentMemberId < 0)||(viaPath->lastIn() > clusterMostRecentTs)) {
#endif
if ((now - viaPath->lastOut()) > std::max((now - viaPath->lastIn()) * 4,(uint64_t)ZT_PATH_MIN_REACTIVATE_INTERVAL)) {
peer->attemptToContactAt(viaPath->localAddress(),viaPath->address(),now,false,viaPath->nextOutgoingCounter());
peer->attemptToContactAt(tPtr,viaPath->localAddress(),viaPath->address(),now,false,viaPath->nextOutgoingCounter());
viaPath->sent(now);
}
#ifdef ZT_ENABLE_CLUSTER
@@ -794,7 +802,7 @@ bool Switch::_trySend(Packet &packet,bool encrypt)
#else
if (!viaPath) {
#endif
peer->tryMemorizedPath(now); // periodically attempt memorized or statically defined paths, if any are known
peer->tryMemorizedPath(tPtr,now); // periodically attempt memorized or statically defined paths, if any are known
const SharedPtr<Peer> relay(RR->topology->getUpstreamPeer());
if ( (!relay) || (!(viaPath = relay->getBestPath(now,false))) ) {
if (!(viaPath = peer->getBestPath(now,true)))
@@ -809,7 +817,7 @@ bool Switch::_trySend(Packet &packet,bool encrypt)
#ifdef ZT_ENABLE_CLUSTER
if (clusterMostRecentMemberId < 0) {
#else
requestWhois(destination);
requestWhois(tPtr,destination);
return false; // if we are not in cluster mode, there is no way we can send without knowing the peer directly
#endif
#ifdef ZT_ENABLE_CLUSTER
@@ -837,9 +845,9 @@ bool Switch::_trySend(Packet &packet,bool encrypt)
#endif
#ifdef ZT_ENABLE_CLUSTER
if ( ((viaPath)&&(viaPath->send(RR,packet.data(),chunkSize,now))) || ((clusterMostRecentMemberId >= 0)&&(RR->cluster->sendViaCluster(clusterMostRecentMemberId,destination,packet.data(),chunkSize))) ) {
if ( ((viaPath)&&(viaPath->send(RR,tPtr,packet.data(),chunkSize,now))) || ((clusterMostRecentMemberId >= 0)&&(RR->cluster->sendViaCluster(clusterMostRecentMemberId,destination,packet.data(),chunkSize))) ) {
#else
if (viaPath->send(RR,packet.data(),chunkSize,now)) {
if (viaPath->send(RR,tPtr,packet.data(),chunkSize,now)) {
#endif
if (chunkSize < packet.size()) {
// Too big for one packet, fragment the rest
@@ -855,11 +863,11 @@ bool Switch::_trySend(Packet &packet,bool encrypt)
Packet::Fragment frag(packet,fragStart,chunkSize,fno,totalFragments);
#ifdef ZT_ENABLE_CLUSTER
if (viaPath)
viaPath->send(RR,frag.data(),frag.size(),now);
viaPath->send(RR,tPtr,frag.data(),frag.size(),now);
else if (clusterMostRecentMemberId >= 0)
RR->cluster->sendViaCluster(clusterMostRecentMemberId,destination,frag.data(),frag.size());
#else
viaPath->send(RR,frag.data(),frag.size(),now);
viaPath->send(RR,tPtr,frag.data(),frag.size(),now);
#endif
fragStart += chunkSize;
remaining -= chunkSize;

View File

@@ -59,16 +59,18 @@ public:
/**
* Called when a packet is received from the real network
*
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param localAddr Local interface address
* @param fromAddr Internet IP address of origin
* @param data Packet data
* @param len Packet length
*/
void onRemotePacket(const InetAddress &localAddr,const InetAddress &fromAddr,const void *data,unsigned int len);
void onRemotePacket(void *tPtr,const InetAddress &localAddr,const InetAddress &fromAddr,const void *data,unsigned int len);
/**
* Called when a packet comes from a local Ethernet tap
*
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param network Which network's TAP did this packet come from?
* @param from Originating MAC address
* @param to Destination MAC address
@@ -77,7 +79,7 @@ public:
* @param data Ethernet payload
* @param len Frame length
*/
void onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,const MAC &to,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len);
void onLocalEthernet(void *tPtr,const SharedPtr<Network> &network,const MAC &from,const MAC &to,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len);
/**
* Send a packet to a ZeroTier address (destination in packet)
@@ -91,26 +93,29 @@ public:
* Needless to say, the packet's source must be this node. Otherwise it
* won't be encrypted right. (This is not used for relaying.)
*
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param packet Packet to send (buffer may be modified)
* @param encrypt Encrypt packet payload? (always true except for HELLO)
*/
void send(Packet &packet,bool encrypt);
void send(void *tPtr,Packet &packet,bool encrypt);
/**
* Request WHOIS on a given address
*
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param addr Address to look up
*/
void requestWhois(const Address &addr);
void requestWhois(void *tPtr,const Address &addr);
/**
* Run any processes that are waiting for this peer's identity
*
* Called when we learn of a peer's identity from HELLO, OK(WHOIS), etc.
*
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param peer New peer
*/
void doAnythingWaitingForPeer(const SharedPtr<Peer> &peer);
void doAnythingWaitingForPeer(void *tPtr,const SharedPtr<Peer> &peer);
/**
* Perform retries and other periodic timer tasks
@@ -118,15 +123,16 @@ public:
* This can return a very long delay if there are no pending timer
* tasks. The caller should cap this comparatively vs. other values.
*
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param now Current time
* @return Number of milliseconds until doTimerTasks() should be run again
*/
unsigned long doTimerTasks(uint64_t now);
unsigned long doTimerTasks(void *tPtr,uint64_t now);
private:
bool _shouldUnite(const uint64_t now,const Address &source,const Address &destination);
Address _sendWhoisRequest(const Address &addr,const Address *peersAlreadyConsulted,unsigned int numPeersAlreadyConsulted);
bool _trySend(Packet &packet,bool encrypt); // packet is modified if return is true
Address _sendWhoisRequest(void *tPtr,const Address &addr,const Address *peersAlreadyConsulted,unsigned int numPeersAlreadyConsulted);
bool _trySend(void *tPtr,Packet &packet,bool encrypt); // packet is modified if return is true
const RuntimeEnvironment *const RR;
uint64_t _lastBeaconResponse;

View File

@@ -25,13 +25,13 @@
namespace ZeroTier {
int Tag::verify(const RuntimeEnvironment *RR) const
int Tag::verify(const RuntimeEnvironment *RR,void *tPtr) const
{
if ((!_signedBy)||(_signedBy != Network::controllerFor(_networkId)))
return -1;
const Identity id(RR->topology->getIdentity(_signedBy));
const Identity id(RR->topology->getIdentity(tPtr,_signedBy));
if (!id) {
RR->sw->requestWhois(_signedBy);
RR->sw->requestWhois(tPtr,_signedBy);
return 1;
}
try {

View File

@@ -105,9 +105,10 @@ public:
* Check this tag's signature
*
* @param RR Runtime environment to allow identity lookup for signedBy
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @return 0 == OK, 1 == waiting for WHOIS, -1 == BAD signature or tag
*/
int verify(const RuntimeEnvironment *RR) const;
int verify(const RuntimeEnvironment *RR,void *tPtr) const;
template<unsigned int C>
inline void serialize(Buffer<C> &b,const bool forSign = false) const

View File

@@ -55,19 +55,19 @@ namespace ZeroTier {
#define ZT_DEFAULT_WORLD_LENGTH 634
static const unsigned char ZT_DEFAULT_WORLD[ZT_DEFAULT_WORLD_LENGTH] = {0x01,0x00,0x00,0x00,0x00,0x08,0xea,0xc9,0x0a,0x00,0x00,0x01,0x52,0x3c,0x32,0x50,0x1a,0xb8,0xb3,0x88,0xa4,0x69,0x22,0x14,0x91,0xaa,0x9a,0xcd,0x66,0xcc,0x76,0x4c,0xde,0xfd,0x56,0x03,0x9f,0x10,0x67,0xae,0x15,0xe6,0x9c,0x6f,0xb4,0x2d,0x7b,0x55,0x33,0x0e,0x3f,0xda,0xac,0x52,0x9c,0x07,0x92,0xfd,0x73,0x40,0xa6,0xaa,0x21,0xab,0xa8,0xa4,0x89,0xfd,0xae,0xa4,0x4a,0x39,0xbf,0x2d,0x00,0x65,0x9a,0xc9,0xc8,0x18,0xeb,0x4a,0xf7,0x86,0xa8,0x40,0xd6,0x52,0xea,0xae,0x9e,0x7a,0xbf,0x4c,0x97,0x66,0xab,0x2d,0x6f,0xaf,0xc9,0x2b,0x3a,0xff,0xed,0xd6,0x30,0x3e,0xc4,0x6a,0x65,0xf2,0xbd,0x83,0x52,0xf5,0x40,0xe9,0xcc,0x0d,0x6e,0x89,0x3f,0x9a,0xa0,0xb8,0xdf,0x42,0xd2,0x2f,0x84,0xe6,0x03,0x26,0x0f,0xa8,0xe3,0xcc,0x05,0x05,0x03,0xef,0x12,0x80,0x0d,0xce,0x3e,0xb6,0x58,0x3b,0x1f,0xa8,0xad,0xc7,0x25,0xf9,0x43,0x71,0xa7,0x5c,0x9a,0xc7,0xe1,0xa3,0xb8,0x88,0xd0,0x71,0x6c,0x94,0x99,0x73,0x41,0x0b,0x1b,0x48,0x84,0x02,0x9d,0x21,0x90,0x39,0xf3,0x00,0x01,0xf0,0x92,0x2a,0x98,0xe3,0xb3,0x4e,0xbc,0xbf,0xf3,0x33,0x26,0x9d,0xc2,0x65,0xd7,0xa0,0x20,0xaa,0xb6,0x9d,0x72,0xbe,0x4d,0x4a,0xcc,0x9c,0x8c,0x92,0x94,0x78,0x57,0x71,0x25,0x6c,0xd1,0xd9,0x42,0xa9,0x0d,0x1b,0xd1,0xd2,0xdc,0xa3,0xea,0x84,0xef,0x7d,0x85,0xaf,0xe6,0x61,0x1f,0xb4,0x3f,0xf0,0xb7,0x41,0x26,0xd9,0x0a,0x6e,0x00,0x0c,0x04,0xbc,0xa6,0x5e,0xb1,0x27,0x09,0x06,0x2a,0x03,0xb0,0xc0,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0x7d,0x00,0x01,0x27,0x09,0x04,0x9a,0x42,0xc5,0x21,0x27,0x09,0x06,0x2c,0x0f,0xf8,0x50,0x01,0x54,0x01,0x97,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x27,0x09,0x04,0x9f,0xcb,0x61,0xab,0x27,0x09,0x06,0x26,0x04,0xa8,0x80,0x08,0x00,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,0x54,0x60,0x01,0x27,0x09,0x04,0xa9,0x39,0x8f,0x68,0x27,0x09,0x06,0x26,0x07,0xf0,0xd0,0x1d,0x01,0x00,0x57,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x27,0x09,0x04,0x6b,0xaa,0xc5,0x0e,0x27,0x09,0x06,0x26,0x04,0xa8,0x80,0x00,0x01,0x00,0x20,0x00,0x00,0x00,0x00,0x02,0x00,0xe0,0x01,0x27,0x09,0x04,0x80,0xc7,0xc5,0xd9,0x27,0x09,0x06,0x24,0x00,0x61,0x80,0x00,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0xb7,0x40,0x01,0x27,0x09,0x88,0x41,0x40,0x8a,0x2e,0x00,0xbb,0x1d,0x31,0xf2,0xc3,0x23,0xe2,0x64,0xe9,0xe6,0x41,0x72,0xc1,0xa7,0x4f,0x77,0x89,0x95,0x55,0xed,0x10,0x75,0x1c,0xd5,0x6e,0x86,0x40,0x5c,0xde,0x11,0x8d,0x02,0xdf,0xfe,0x55,0x5d,0x46,0x2c,0xcf,0x6a,0x85,0xb5,0x63,0x1c,0x12,0x35,0x0c,0x8d,0x5d,0xc4,0x09,0xba,0x10,0xb9,0x02,0x5d,0x0f,0x44,0x5c,0xf4,0x49,0xd9,0x2b,0x1c,0x00,0x0c,0x04,0x2d,0x20,0xc6,0x82,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x64,0x00,0x81,0xc3,0x54,0x00,0x00,0xff,0xfe,0x18,0x1d,0x61,0x27,0x09,0x04,0x2e,0x65,0xa0,0xf9,0x27,0x09,0x06,0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0x6a,0x30,0x01,0x27,0x09,0x04,0x6b,0xbf,0x2e,0xd2,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x68,0x00,0x83,0xa4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0x27,0x09,0x04,0x2d,0x20,0xf6,0xb3,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x58,0x00,0x8b,0xf8,0x54,0x00,0x00,0xff,0xfe,0x15,0xb3,0x9a,0x27,0x09,0x04,0x2d,0x20,0xf8,0x57,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x70,0x00,0x9b,0xc9,0x54,0x00,0x00,0xff,0xfe,0x15,0xc4,0xf5,0x27,0x09,0x04,0x9f,0xcb,0x02,0x9a,0x27,0x09,0x06,0x26,0x04,0xa8,0x80,0x0c,0xad,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0x26,0x70,0x01,0x27,0x09};
Topology::Topology(const RuntimeEnvironment *renv) :
Topology::Topology(const RuntimeEnvironment *renv,void *tPtr) :
RR(renv),
_trustedPathCount(0),
_amRoot(false)
{
try {
World cachedPlanet;
std::string buf(RR->node->dataStoreGet("planet"));
std::string buf(RR->node->dataStoreGet(tPtr,"planet"));
if (buf.length() > 0) {
Buffer<ZT_WORLD_MAX_SERIALIZED_LENGTH> dswtmp(buf.data(),(unsigned int)buf.length());
cachedPlanet.deserialize(dswtmp,0);
}
addWorld(cachedPlanet,false);
addWorld(tPtr,cachedPlanet,false);
} catch ( ... ) {}
World defaultPlanet;
@@ -75,10 +75,10 @@ Topology::Topology(const RuntimeEnvironment *renv) :
Buffer<ZT_DEFAULT_WORLD_LENGTH> wtmp(ZT_DEFAULT_WORLD,ZT_DEFAULT_WORLD_LENGTH);
defaultPlanet.deserialize(wtmp,0); // throws on error, which would indicate a bad static variable up top
}
addWorld(defaultPlanet,false);
addWorld(tPtr,defaultPlanet,false);
}
SharedPtr<Peer> Topology::addPeer(const SharedPtr<Peer> &peer)
SharedPtr<Peer> Topology::addPeer(void *tPtr,const SharedPtr<Peer> &peer)
{
#ifdef ZT_TRACE
if ((!peer)||(peer->address() == RR->identity.address())) {
@@ -98,12 +98,12 @@ SharedPtr<Peer> Topology::addPeer(const SharedPtr<Peer> &peer)
np = hp;
}
saveIdentity(np->identity());
saveIdentity(tPtr,np->identity());
return np;
}
SharedPtr<Peer> Topology::getPeer(const Address &zta)
SharedPtr<Peer> Topology::getPeer(void *tPtr,const Address &zta)
{
if (zta == RR->identity.address()) {
TRACE("BUG: ignored attempt to getPeer() for self, returned NULL");
@@ -118,7 +118,7 @@ SharedPtr<Peer> Topology::getPeer(const Address &zta)
}
try {
Identity id(_getIdentity(zta));
Identity id(_getIdentity(tPtr,zta));
if (id) {
SharedPtr<Peer> np(new Peer(RR,RR->identity,id));
{
@@ -134,7 +134,7 @@ SharedPtr<Peer> Topology::getPeer(const Address &zta)
return SharedPtr<Peer>();
}
Identity Topology::getIdentity(const Address &zta)
Identity Topology::getIdentity(void *tPtr,const Address &zta)
{
if (zta == RR->identity.address()) {
return RR->identity;
@@ -144,15 +144,15 @@ Identity Topology::getIdentity(const Address &zta)
if (ap)
return (*ap)->identity();
}
return _getIdentity(zta);
return _getIdentity(tPtr,zta);
}
void Topology::saveIdentity(const Identity &id)
void Topology::saveIdentity(void *tPtr,const Identity &id)
{
if (id) {
char p[128];
Utils::snprintf(p,sizeof(p),"iddb.d/%.10llx",(unsigned long long)id.address().toInt());
RR->node->dataStorePut(p,id.toString(false),false);
RR->node->dataStorePut(tPtr,p,id.toString(false),false);
}
}
@@ -264,7 +264,7 @@ bool Topology::isProhibitedEndpoint(const Address &ztaddr,const InetAddress &ipa
return false;
}
bool Topology::addWorld(const World &newWorld,bool alwaysAcceptNew)
bool Topology::addWorld(void *tPtr,const World &newWorld,bool alwaysAcceptNew)
{
if ((newWorld.type() != World::TYPE_PLANET)&&(newWorld.type() != World::TYPE_MOON))
return false;
@@ -328,29 +328,29 @@ bool Topology::addWorld(const World &newWorld,bool alwaysAcceptNew)
try {
Buffer<ZT_WORLD_MAX_SERIALIZED_LENGTH> dswtmp;
existing->serialize(dswtmp,false);
RR->node->dataStorePut(savePath,dswtmp.data(),dswtmp.size(),false);
RR->node->dataStorePut(tPtr,savePath,dswtmp.data(),dswtmp.size(),false);
} catch ( ... ) {
RR->node->dataStoreDelete(savePath);
RR->node->dataStoreDelete(tPtr,savePath);
}
_memoizeUpstreams();
_memoizeUpstreams(tPtr);
return true;
}
void Topology::addMoon(const uint64_t id,const Address &seed)
void Topology::addMoon(void *tPtr,const uint64_t id,const Address &seed)
{
char savePath[64];
Utils::snprintf(savePath,sizeof(savePath),"moons.d/%.16llx.moon",id);
try {
std::string moonBin(RR->node->dataStoreGet(savePath));
std::string moonBin(RR->node->dataStoreGet(tPtr,savePath));
if (moonBin.length() > 1) {
Buffer<ZT_WORLD_MAX_SERIALIZED_LENGTH> wtmp(moonBin.data(),(unsigned int)moonBin.length());
World w;
w.deserialize(wtmp);
if ((w.type() == World::TYPE_MOON)&&(w.id() == id)) {
addWorld(w,true);
addWorld(tPtr,w,true);
return;
}
}
@@ -363,7 +363,7 @@ void Topology::addMoon(const uint64_t id,const Address &seed)
}
}
void Topology::removeMoon(const uint64_t id)
void Topology::removeMoon(void *tPtr,const uint64_t id)
{
Mutex::Lock _l1(_upstreams_m);
Mutex::Lock _l2(_peers_m);
@@ -375,7 +375,7 @@ void Topology::removeMoon(const uint64_t id)
} else {
char savePath[64];
Utils::snprintf(savePath,sizeof(savePath),"moons.d/%.16llx.moon",id);
RR->node->dataStoreDelete(savePath);
RR->node->dataStoreDelete(tPtr,savePath);
}
}
_moons.swap(nm);
@@ -387,7 +387,7 @@ void Topology::removeMoon(const uint64_t id)
}
_moonSeeds.swap(cm);
_memoizeUpstreams();
_memoizeUpstreams(tPtr);
}
void Topology::clean(uint64_t now)
@@ -415,11 +415,11 @@ void Topology::clean(uint64_t now)
}
}
Identity Topology::_getIdentity(const Address &zta)
Identity Topology::_getIdentity(void *tPtr,const Address &zta)
{
char p[128];
Utils::snprintf(p,sizeof(p),"iddb.d/%.10llx",(unsigned long long)zta.toInt());
std::string ids(RR->node->dataStoreGet(p));
std::string ids(RR->node->dataStoreGet(tPtr,p));
if (ids.length() > 0) {
try {
return Identity(ids);
@@ -428,7 +428,7 @@ Identity Topology::_getIdentity(const Address &zta)
return Identity();
}
void Topology::_memoizeUpstreams()
void Topology::_memoizeUpstreams(void *tPtr)
{
// assumes _upstreams_m and _peers_m are locked
_upstreamAddresses.clear();
@@ -442,7 +442,7 @@ void Topology::_memoizeUpstreams()
SharedPtr<Peer> &hp = _peers[i->identity.address()];
if (!hp) {
hp = new Peer(RR,RR->identity,i->identity);
saveIdentity(i->identity);
saveIdentity(tPtr,i->identity);
}
}
}
@@ -456,7 +456,7 @@ void Topology::_memoizeUpstreams()
SharedPtr<Peer> &hp = _peers[i->identity.address()];
if (!hp) {
hp = new Peer(RR,RR->identity,i->identity);
saveIdentity(i->identity);
saveIdentity(tPtr,i->identity);
}
}
}

View File

@@ -50,7 +50,7 @@ class RuntimeEnvironment;
class Topology
{
public:
Topology(const RuntimeEnvironment *renv);
Topology(const RuntimeEnvironment *renv,void *tPtr);
/**
* Add a peer to database
@@ -58,18 +58,20 @@ public:
* This will not replace existing peers. In that case the existing peer
* record is returned.
*
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param peer Peer to add
* @return New or existing peer (should replace 'peer')
*/
SharedPtr<Peer> addPeer(const SharedPtr<Peer> &peer);
SharedPtr<Peer> addPeer(void *tPtr,const SharedPtr<Peer> &peer);
/**
* Get a peer from its address
*
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param zta ZeroTier address of peer
* @return Peer or NULL if not found
*/
SharedPtr<Peer> getPeer(const Address &zta);
SharedPtr<Peer> getPeer(void *tPtr,const Address &zta);
/**
* Get a peer only if it is presently in memory (no disk cache)
@@ -109,10 +111,11 @@ public:
/**
* Get the identity of a peer
*
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param zta ZeroTier address of peer
* @return Identity or NULL Identity if not found
*/
Identity getIdentity(const Address &zta);
Identity getIdentity(void *tPtr,const Address &zta);
/**
* Cache an identity
@@ -120,9 +123,10 @@ public:
* This is done automatically on addPeer(), and so is only useful for
* cluster identity replication.
*
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param id Identity to cache
*/
void saveIdentity(const Identity &id);
void saveIdentity(void *tPtr,const Identity &id);
/**
* Get the current best upstream peer
@@ -184,14 +188,17 @@ public:
{
Mutex::Lock _l(_upstreams_m);
for(std::vector<World::Root>::const_iterator i(_planet.roots().begin());i!=_planet.roots().end();++i) {
if (i->identity != RR->identity) {
std::vector<InetAddress> &ips = eps[i->identity.address()];
for(std::vector<InetAddress>::const_iterator j(i->stableEndpoints.begin());j!=i->stableEndpoints.end();++j) {
if (std::find(ips.begin(),ips.end(),*j) == ips.end())
ips.push_back(*j);
}
}
}
for(std::vector<World>::const_iterator m(_moons.begin());m!=_moons.end();++m) {
for(std::vector<World::Root>::const_iterator i(m->roots().begin());i!=m->roots().end();++i) {
if (i->identity != RR->identity) {
std::vector<InetAddress> &ips = eps[i->identity.address()];
for(std::vector<InetAddress>::const_iterator j(i->stableEndpoints.begin());j!=i->stableEndpoints.end();++j) {
if (std::find(ips.begin(),ips.end(),*j) == ips.end())
@@ -199,6 +206,7 @@ public:
}
}
}
}
for(std::vector< std::pair<uint64_t,Address> >::const_iterator m(_moonSeeds.begin());m!=_moonSeeds.end();++m)
eps[m->second];
}
@@ -263,11 +271,12 @@ public:
/**
* Validate new world and update if newer and signature is okay
*
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param newWorld A new or updated planet or moon to learn
* @param alwaysAcceptNew If true, always accept new moons even if we're not waiting for one
* @return True if it was valid and newer than current (or totally new for moons)
*/
bool addWorld(const World &newWorld,bool alwaysAcceptNew);
bool addWorld(void *tPtr,const World &newWorld,bool alwaysAcceptNew);
/**
* Add a moon
@@ -278,14 +287,15 @@ public:
* @param id Moon ID
* @param seed If non-NULL, an address of any member of the moon to contact
*/
void addMoon(const uint64_t id,const Address &seed);
void addMoon(void *tPtr,const uint64_t id,const Address &seed);
/**
* Remove a moon
*
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param id Moon's world ID
*/
void removeMoon(const uint64_t id);
void removeMoon(void *tPtr,const uint64_t id);
/**
* Clean and flush database
@@ -416,8 +426,8 @@ public:
}
private:
Identity _getIdentity(const Address &zta);
void _memoizeUpstreams();
Identity _getIdentity(void *tPtr,const Address &zta);
void _memoizeUpstreams(void *tPtr);
const RuntimeEnvironment *const RR;

View File

@@ -72,6 +72,7 @@
#include "osdep/OSUtils.hpp"
#include "osdep/Http.hpp"
#include "osdep/Thread.hpp"
#include "service/OneService.hpp"
@@ -84,7 +85,7 @@ using namespace ZeroTier;
static OneService *volatile zt1Service = (OneService *)0;
#define PROGRAM_NAME "ZeroTier One"
#define COPYRIGHT_NOTICE "Copyright © 20112016 ZeroTier, Inc."
#define COPYRIGHT_NOTICE "Copyright (c) 2011-2017 ZeroTier, Inc."
#define LICENSE_GRANT \
"This is free software: you may copy, modify, and/or distribute this" ZT_EOL_S \
"work under the terms of the GNU General Public License, version 3 or" ZT_EOL_S \
@@ -100,9 +101,10 @@ static OneService *volatile zt1Service = (OneService *)0;
static void cliPrintHelp(const char *pn,FILE *out)
{
fprintf(out,
"%s version %d.%d.%d" ZT_EOL_S,
"%s version %d.%d.%d build %d (platform %d arch %d)" ZT_EOL_S,
PROGRAM_NAME,
ZEROTIER_ONE_VERSION_MAJOR, ZEROTIER_ONE_VERSION_MINOR, ZEROTIER_ONE_VERSION_REVISION);
ZEROTIER_ONE_VERSION_MAJOR, ZEROTIER_ONE_VERSION_MINOR, ZEROTIER_ONE_VERSION_REVISION, ZEROTIER_ONE_VERSION_BUILD,
ZT_BUILD_PLATFORM, ZT_BUILD_ARCHITECTURE);
fprintf(out,
COPYRIGHT_NOTICE ZT_EOL_S
LICENSE_GRANT ZT_EOL_S);
@@ -1208,6 +1210,52 @@ static void printHelp(const char *cn,FILE *out)
fprintf(out," -q - Query API (zerotier-cli)" ZT_EOL_S);
}
class _OneServiceRunner
{
public:
_OneServiceRunner(const char *pn,const std::string &hd,unsigned int p) : progname(pn),returnValue(0),port(p),homeDir(hd) {}
void threadMain()
throw()
{
try {
for(;;) {
zt1Service = OneService::newInstance(homeDir.c_str(),port);
switch(zt1Service->run()) {
case OneService::ONE_STILL_RUNNING: // shouldn't happen, run() won't return until done
case OneService::ONE_NORMAL_TERMINATION:
break;
case OneService::ONE_UNRECOVERABLE_ERROR:
fprintf(stderr,"%s: fatal error: %s" ZT_EOL_S,progname,zt1Service->fatalErrorMessage().c_str());
returnValue = 1;
break;
case OneService::ONE_IDENTITY_COLLISION: {
delete zt1Service;
zt1Service = (OneService *)0;
std::string oldid;
OSUtils::readFile((homeDir + ZT_PATH_SEPARATOR_S + "identity.secret").c_str(),oldid);
if (oldid.length()) {
OSUtils::writeFile((homeDir + ZT_PATH_SEPARATOR_S + "identity.secret.saved_after_collision").c_str(),oldid);
OSUtils::rm((homeDir + ZT_PATH_SEPARATOR_S + "identity.secret").c_str());
OSUtils::rm((homeDir + ZT_PATH_SEPARATOR_S + "identity.public").c_str());
}
} continue; // restart!
}
break; // terminate loop -- normally we don't keep restarting
}
delete zt1Service;
zt1Service = (OneService *)0;
} catch ( ... ) {
fprintf(stderr,"%s: unexpected exception starting main OneService instance" ZT_EOL_S,progname);
returnValue = 1;
}
}
const char *progname;
unsigned int returnValue;
unsigned int port;
const std::string &homeDir;
};
#ifdef __WINDOWS__
int _tmain(int argc, _TCHAR* argv[])
#else
@@ -1420,8 +1468,8 @@ int main(int argc,char **argv)
} else {
// Running from service manager
_winPokeAHole();
ZeroTierOneService zt1Service;
if (CServiceBase::Run(zt1Service) == TRUE) {
ZeroTierOneService zt1WindowsService;
if (CServiceBase::Run(zt1WindowsService) == TRUE) {
return 0;
} else {
fprintf(stderr,"%s: unable to start service (try -h for help)" ZT_EOL_S,argv[0]);
@@ -1431,7 +1479,6 @@ int main(int argc,char **argv)
#endif // __WINDOWS__
#ifdef __UNIX_LIKE__
#ifdef ZT_HAVE_DROP_PRIVILEGES
dropPrivileges(argv[0],homeDir);
#endif
@@ -1447,35 +1494,13 @@ int main(int argc,char **argv)
}
#endif // __UNIX_LIKE__
unsigned int returnValue = 0;
_OneServiceRunner thr(argv[0],homeDir,port);
thr.threadMain();
//Thread::join(Thread::start(&thr));
for(;;) {
zt1Service = OneService::newInstance(homeDir.c_str(),port);
switch(zt1Service->run()) {
case OneService::ONE_STILL_RUNNING: // shouldn't happen, run() won't return until done
case OneService::ONE_NORMAL_TERMINATION:
break;
case OneService::ONE_UNRECOVERABLE_ERROR:
fprintf(stderr,"%s: fatal error: %s" ZT_EOL_S,argv[0],zt1Service->fatalErrorMessage().c_str());
returnValue = 1;
break;
case OneService::ONE_IDENTITY_COLLISION: {
delete zt1Service;
zt1Service = (OneService *)0;
std::string oldid;
OSUtils::readFile((homeDir + ZT_PATH_SEPARATOR_S + "identity.secret").c_str(),oldid);
if (oldid.length()) {
OSUtils::writeFile((homeDir + ZT_PATH_SEPARATOR_S + "identity.secret.saved_after_collision").c_str(),oldid);
OSUtils::rm((homeDir + ZT_PATH_SEPARATOR_S + "identity.secret").c_str());
OSUtils::rm((homeDir + ZT_PATH_SEPARATOR_S + "identity.public").c_str());
}
} continue; // restart!
}
break; // terminate loop -- normally we don't keep restarting
}
#ifdef __UNIX_LIKE__
OSUtils::rm(pidPath.c_str());
#endif
delete zt1Service;
zt1Service = (OneService *)0;
return returnValue;
return thr.returnValue;
}

View File

@@ -71,7 +71,7 @@ BSDEthernetTap::BSDEthernetTap(
unsigned int metric,
uint64_t nwid,
const char *friendlyName,
void (*handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int),
void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int),
void *arg) :
_handler(handler),
_arg(arg),
@@ -460,8 +460,7 @@ void BSDEthernetTap::threadMain()
to.setTo(getBuf,6);
from.setTo(getBuf + 6,6);
unsigned int etherType = ntohs(((const uint16_t *)getBuf)[6]);
// TODO: VLAN support
_handler(_arg,_nwid,from,to,etherType,0,(const void *)(getBuf + 14),r - 14);
_handler(_arg,(void *)0,_nwid,from,to,etherType,0,(const void *)(getBuf + 14),r - 14);
}
r = 0;

View File

@@ -43,7 +43,7 @@ public:
unsigned int metric,
uint64_t nwid,
const char *friendlyName,
void (*handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int),
void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int),
void *arg);
~BSDEthernetTap();
@@ -62,7 +62,7 @@ public:
throw();
private:
void (*_handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int);
void (*_handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int);
void *_arg;
uint64_t _nwid;
Thread _thread;

View File

@@ -62,7 +62,7 @@ LinuxEthernetTap::LinuxEthernetTap(
unsigned int metric,
uint64_t nwid,
const char *friendlyName,
void (*handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int),
void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int),
void *arg) :
_handler(handler),
_arg(arg),
@@ -470,7 +470,7 @@ void LinuxEthernetTap::threadMain()
from.setTo(getBuf + 6,6);
unsigned int etherType = ntohs(((const uint16_t *)getBuf)[6]);
// TODO: VLAN support
_handler(_arg,_nwid,from,to,etherType,0,(const void *)(getBuf + 14),r - 14);
_handler(_arg,(void *)0,_nwid,from,to,etherType,0,(const void *)(getBuf + 14),r - 14);
}
r = 0;

View File

@@ -44,7 +44,7 @@ public:
unsigned int metric,
uint64_t nwid,
const char *friendlyName,
void (*handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int),
void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int),
void *arg);
~LinuxEthernetTap();
@@ -66,7 +66,7 @@ public:
throw();
private:
void (*_handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int);
void (*_handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int);
void *_arg;
uint64_t _nwid;
Thread _thread;

View File

@@ -108,43 +108,6 @@ std::vector<std::string> OSUtils::listDirectory(const char *path)
return r;
}
std::map<std::string,char> OSUtils::listDirectoryFull(const char *path)
{
std::map<std::string,char> r;
#ifdef __WINDOWS__
HANDLE hFind;
WIN32_FIND_DATAA ffd;
if ((hFind = FindFirstFileA((std::string(path) + "\\*").c_str(),&ffd)) != INVALID_HANDLE_VALUE) {
do {
if ((strcmp(ffd.cFileName,"."))&&(strcmp(ffd.cFileName,".."))) {
r[ffd.cFileName] = ((ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) ? 'd' : 'f';
}
} while (FindNextFileA(hFind,&ffd));
FindClose(hFind);
}
#else
struct dirent de;
struct dirent *dptr;
DIR *d = opendir(path);
if (!d)
return r;
dptr = (struct dirent *)0;
for(;;) {
if (readdir_r(d,&de,&dptr))
break;
if (dptr) {
if ((strcmp(dptr->d_name,"."))&&(strcmp(dptr->d_name,".."))) {
r[dptr->d_name] = (dptr->d_type == DT_DIR) ? 'd' : 'f';
}
} else break;
}
closedir(d);
#endif
return r;
}
long OSUtils::cleanDirectory(const char *path,const uint64_t olderThan)
{
long cleaned = 0;
@@ -162,7 +125,7 @@ long OSUtils::cleanDirectory(const char *path,const uint64_t olderThan)
date.LowPart = ffd.ftLastWriteTime.dwLowDateTime;
if (date.QuadPart > 0) {
date.QuadPart -= adjust.QuadPart;
if (((date.QuadPart / 10000000) * 1000) < olderThan) {
if ((uint64_t)((date.QuadPart / 10000000) * 1000) < olderThan) {
Utils::snprintf(tmp, sizeof(tmp), "%s\\%s", path, ffd.cFileName);
if (DeleteFileA(tmp))
++cleaned;

View File

@@ -111,14 +111,6 @@ public:
*/
static std::vector<std::string> listDirectory(const char *path);
/**
* List all contents in a directory
*
* @param path Path to list
* @return Names of things and types, currently just 'f' and 'd'
*/
static std::map<std::string,char> listDirectoryFull(const char *path);
/**
* Clean a directory of files whose last modified time is older than this
*

View File

@@ -314,7 +314,7 @@ OSXEthernetTap::OSXEthernetTap(
unsigned int metric,
uint64_t nwid,
const char *friendlyName,
void (*handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *data,unsigned int len),
void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *data,unsigned int len),
void *arg) :
_handler(handler),
_arg(arg),
@@ -646,7 +646,7 @@ void OSXEthernetTap::threadMain()
from.setTo(getBuf + 6,6);
unsigned int etherType = ntohs(((const uint16_t *)getBuf)[6]);
// TODO: VLAN support
_handler(_arg,_nwid,from,to,etherType,0,(const void *)(getBuf + 14),r - 14);
_handler(_arg,(void *)0,_nwid,from,to,etherType,0,(const void *)(getBuf + 14),r - 14);
}
r = 0;

View File

@@ -48,7 +48,7 @@ public:
unsigned int metric,
uint64_t nwid,
const char *friendlyName,
void (*handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int),
void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int),
void *arg);
~OSXEthernetTap();
@@ -67,7 +67,7 @@ public:
throw();
private:
void (*_handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int);
void (*_handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int);
void *_arg;
uint64_t _nwid;
Thread _thread;

View File

@@ -456,7 +456,7 @@ WindowsEthernetTap::WindowsEthernetTap(
unsigned int metric,
uint64_t nwid,
const char *friendlyName,
void (*handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int),
void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int),
void *arg) :
_handler(handler),
_arg(arg),
@@ -1058,8 +1058,7 @@ void WindowsEthernetTap::threadMain()
MAC from(tapReadBuf + 6,6);
unsigned int etherType = ((((unsigned int)tapReadBuf[12]) & 0xff) << 8) | (((unsigned int)tapReadBuf[13]) & 0xff);
try {
// TODO: decode vlans
_handler(_arg,_nwid,from,to,etherType,0,tapReadBuf + 14,bytesRead - 14);
_handler(_arg,(void *)0,_nwid,from,to,etherType,0,tapReadBuf + 14,bytesRead - 14);
} catch ( ... ) {} // handlers should not throw
}
}

View File

@@ -87,7 +87,7 @@ public:
unsigned int metric,
uint64_t nwid,
const char *friendlyName,
void (*handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int),
void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int),
void *arg);
~WindowsEthernetTap();
@@ -118,7 +118,7 @@ private:
void _setRegistryIPv4Value(const char *regKey,const std::vector<std::string> &value);
void _syncIps();
void (*_handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int);
void (*_handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int);
void *_arg;
MAC _mac;
uint64_t _nwid;

View File

@@ -582,8 +582,34 @@ static int testPacket()
return 0;
}
static void _testExcept(int &depth)
{
if (depth >= 16) {
throw std::runtime_error("LOL!");
} else {
++depth;
_testExcept(depth);
}
}
static int testOther()
{
std::cout << "[other] Testing C++ exceptions... "; std::cout.flush();
int depth = 0;
try {
_testExcept(depth);
} catch (std::runtime_error &e) {
if (depth == 16) {
std::cout << "OK" << std::endl;
} else {
std::cout << "ERROR (depth not 16)" << std::endl;
return -1;
}
} catch ( ... ) {
std::cout << "ERROR (exception not std::runtime_error)" << std::endl;
return -1;
}
std::cout << "[other] Testing Hashtable... "; std::cout.flush();
{
Hashtable<uint64_t,std::string> ht;

View File

@@ -291,21 +291,21 @@ static void _moonToJson(nlohmann::json &mj,const World &world)
class OneServiceImpl;
static int SnodeVirtualNetworkConfigFunction(ZT_Node *node,void *uptr,uint64_t nwid,void **nuptr,enum ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nwconf);
static void SnodeEventCallback(ZT_Node *node,void *uptr,enum ZT_Event event,const void *metaData);
static long SnodeDataStoreGetFunction(ZT_Node *node,void *uptr,const char *name,void *buf,unsigned long bufSize,unsigned long readIndex,unsigned long *totalSize);
static int SnodeDataStorePutFunction(ZT_Node *node,void *uptr,const char *name,const void *data,unsigned long len,int secure);
static int SnodeWirePacketSendFunction(ZT_Node *node,void *uptr,const struct sockaddr_storage *localAddr,const struct sockaddr_storage *addr,const void *data,unsigned int len,unsigned int ttl);
static void SnodeVirtualNetworkFrameFunction(ZT_Node *node,void *uptr,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,uint64_t ztaddr,const struct sockaddr_storage *localAddr,const struct sockaddr_storage *remoteAddr);
static int SnodePathLookupFunction(ZT_Node *node,void *uptr,uint64_t ztaddr,int family,struct sockaddr_storage *result);
static int SnodeVirtualNetworkConfigFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t nwid,void **nuptr,enum ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nwconf);
static void SnodeEventCallback(ZT_Node *node,void *uptr,void *tptr,enum ZT_Event event,const void *metaData);
static long SnodeDataStoreGetFunction(ZT_Node *node,void *uptr,void *tptr,const char *name,void *buf,unsigned long bufSize,unsigned long readIndex,unsigned long *totalSize);
static int SnodeDataStorePutFunction(ZT_Node *node,void *uptr,void *tptr,const char *name,const void *data,unsigned long len,int secure);
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 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 SnodePathLookupFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t ztaddr,int family,struct sockaddr_storage *result);
#ifdef ZT_ENABLE_CLUSTER
static void SclusterSendFunction(void *uptr,unsigned int toMemberId,const void *data,unsigned int len);
static int SclusterGeoIpFunction(void *uptr,const struct sockaddr_storage *addr,int *x,int *y,int *z);
#endif
static void StapFrameHandler(void *uptr,uint64_t nwid,const MAC &from,const MAC &to,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len);
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);
static int ShttpOnMessageBegin(http_parser *parser);
static int ShttpOnUrl(http_parser *parser,const char *ptr,size_t length);
@@ -488,6 +488,8 @@ public:
,_updater((SoftwareUpdater *)0)
,_updateAutoApply(false)
,_primaryPort(port)
,_v4TcpControlSocket((PhySocket *)0)
,_v6TcpControlSocket((PhySocket *)0)
,_lastDirectReceiveFromGlobal(0)
#ifdef ZT_TCP_FALLBACK_RELAY
,_lastSendToGlobalV4(0)
@@ -571,7 +573,7 @@ public:
cb.eventCallback = SnodeEventCallback;
cb.pathCheckFunction = SnodePathCheckFunction;
cb.pathLookupFunction = SnodePathLookupFunction;
_node = new Node(this,&cb,OSUtils::now());
_node = new Node(this,(void *)0,&cb,OSUtils::now());
}
// Read local configuration
@@ -745,14 +747,6 @@ public:
for(int i=0;i<3;++i)
_portsBE[i] = Utils::hton((uint16_t)_ports[i]);
// Check for legacy controller.db and terminate if present to prevent nasty surprises for DIY controller folks
if (OSUtils::fileExists((_homePath + ZT_PATH_SEPARATOR_S "controller.db").c_str())) {
Mutex::Lock _l(_termReason_m);
_termReason = ONE_UNRECOVERABLE_ERROR;
_fatalErrorMessage = "controller.db is present in our home path! run migrate-sqlite to migrate to new controller.d format.";
return _termReason;
}
_controller = new EmbeddedNetworkController(_node,(_homePath + ZT_PATH_SEPARATOR_S ZT_CONTROLLER_DB_PATH).c_str());
_node->setNetconfMaster((void *)_controller);
@@ -810,7 +804,7 @@ public:
for(std::vector<std::string>::iterator f(networksDotD.begin());f!=networksDotD.end();++f) {
std::size_t dot = f->find_last_of('.');
if ((dot == 16)&&(f->substr(16) == ".conf"))
_node->join(Utils::hexStrToU64(f->substr(0,dot).c_str()),(void *)0);
_node->join(Utils::hexStrToU64(f->substr(0,dot).c_str()),(void *)0,(void *)0);
}
}
{ // Load existing moons
@@ -818,7 +812,7 @@ public:
for(std::vector<std::string>::iterator f(moonsDotD.begin());f!=moonsDotD.end();++f) {
std::size_t dot = f->find_last_of('.');
if ((dot == 16)&&(f->substr(16) == ".moon"))
_node->orbit(Utils::hexStrToU64(f->substr(0,dot).c_str()),0);
_node->orbit((void *)0,Utils::hexStrToU64(f->substr(0,dot).c_str()),0);
}
}
@@ -883,7 +877,7 @@ public:
uint64_t dl = _nextBackgroundTaskDeadline;
if (dl <= now) {
_node->processBackgroundTasks(now,&_nextBackgroundTaskDeadline);
_node->processBackgroundTasks((void *)0,now,&_nextBackgroundTaskDeadline);
dl = _nextBackgroundTaskDeadline;
}
@@ -898,7 +892,7 @@ public:
std::vector<MulticastGroup> added,removed;
n->second.tap->scanMulticastGroups(added,removed);
for(std::vector<MulticastGroup>::iterator m(added.begin());m!=added.end();++m)
_node->multicastSubscribe(n->first,m->mac().toInt(),m->adi());
_node->multicastSubscribe((void *)0,n->first,m->mac().toInt(),m->adi());
for(std::vector<MulticastGroup>::iterator m(removed.begin());m!=removed.end();++m)
_node->multicastUnsubscribe(n->first,m->mac().toInt(),m->adi());
}
@@ -989,12 +983,12 @@ public:
#ifdef ZT_SDK
virtual void leave(const char *hp)
{
_node->leave(Utils::hexStrToU64(hp),NULL);
_node->leave(Utils::hexStrToU64(hp),NULL, NULL);
}
virtual void join(const char *hp)
{
_node->join(Utils::hexStrToU64(hp),NULL);
_node->join(Utils::hexStrToU64(hp),NULL, NULL);
}
virtual std::string givenHomePath()
@@ -1178,9 +1172,10 @@ public:
#else
settings["portMappingEnabled"] = false; // not supported in build
#endif
//settings["softwareUpdate"] = OSUtils::jsonString(settings["softwareUpdate"],ZT_SOFTWARE_UPDATE_DEFAULT);
//settings["softwareUpdateChannel"] = OSUtils::jsonString(settings["softwareUpdateChannel"],ZT_SOFTWARE_UPDATE_DEFAULT_CHANNEL);
/*
settings["softwareUpdate"] = OSUtils::jsonString(settings["softwareUpdate"],ZT_SOFTWARE_UPDATE_DEFAULT);
settings["softwareUpdateChannel"] = OSUtils::jsonString(settings["softwareUpdateChannel"],ZT_SOFTWARE_UPDATE_DEFAULT_CHANNEL);
*/
const World planet(_node->planet());
res["planetWorldId"] = planet.id();
res["planetWorldTimestamp"] = planet.timestamp();
@@ -1343,7 +1338,7 @@ public:
res["signature"] = json();
res["updatesMustBeSignedBy"] = json();
res["waiting"] = true;
_node->orbit(id,seed);
_node->orbit((void *)0,id,seed);
scode = 200;
}
@@ -1352,7 +1347,7 @@ public:
if (ps.size() == 2) {
uint64_t wantnw = Utils::hexStrToU64(ps[1].c_str());
_node->join(wantnw,(void *)0); // does nothing if we are a member
_node->join(wantnw,(void *)0,(void *)0); // does nothing if we are a member
ZT_VirtualNetworkList *nws = _node->networks();
if (nws) {
for(unsigned long i=0;i<nws->networkCount;++i) {
@@ -1397,7 +1392,7 @@ public:
if (ps[0] == "moon") {
if (ps.size() == 2) {
_node->deorbit(Utils::hexStrToU64(ps[1].c_str()));
_node->deorbit((void *)0,Utils::hexStrToU64(ps[1].c_str()));
res["result"] = true;
scode = 200;
} // else 404
@@ -1408,7 +1403,7 @@ public:
uint64_t wantnw = Utils::hexStrToU64(ps[1].c_str());
for(unsigned long i=0;i<nws->networkCount;++i) {
if (nws->networks[i].nwid == wantnw) {
_node->leave(wantnw,(void **)0);
_node->leave(wantnw,(void **)0,(void *)0);
res["result"] = true;
scode = 200;
break;
@@ -1730,6 +1725,7 @@ public:
_lastDirectReceiveFromGlobal = OSUtils::now();
const ZT_ResultCode rc = _node->processWirePacket(
(void *)0,
OSUtils::now(),
reinterpret_cast<const struct sockaddr_storage *>(localAddr),
(const struct sockaddr_storage *)from, // Phy<> uses sockaddr_storage, so it'll always be that big
@@ -1882,6 +1878,7 @@ public:
if (from) {
InetAddress fakeTcpLocalInterfaceAddress((uint32_t)0xffffffff,0xffff);
const ZT_ResultCode rc = _node->processWirePacket(
(void *)0,
OSUtils::now(),
reinterpret_cast<struct sockaddr_storage *>(&fakeTcpLocalInterfaceAddress),
reinterpret_cast<struct sockaddr_storage *>(&from),
@@ -1951,6 +1948,7 @@ public:
try {
char friendlyName[128];
Utils::snprintf(friendlyName,sizeof(friendlyName),"ZeroTier One [%.16llx]",nwid);
n.tap = new EthernetTap(
_homePath.c_str(),
MAC(nwc->mac),
@@ -2291,7 +2289,7 @@ public:
inline void tapFrameHandler(uint64_t nwid,const MAC &from,const MAC &to,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len)
{
_node->processVirtualNetworkFrame(OSUtils::now(),nwid,from.toInt(),to.toInt(),etherType,vlanId,data,len,&_nextBackgroundTaskDeadline);
_node->processVirtualNetworkFrame((void *)0,OSUtils::now(),nwid,from.toInt(),to.toInt(),etherType,vlanId,data,len,&_nextBackgroundTaskDeadline);
}
inline void onHttpRequestToServer(TcpConnection *tc)
@@ -2462,21 +2460,21 @@ public:
}
};
static int SnodeVirtualNetworkConfigFunction(ZT_Node *node,void *uptr,uint64_t nwid,void **nuptr,enum ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nwconf)
static int SnodeVirtualNetworkConfigFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t nwid,void **nuptr,enum ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nwconf)
{ return reinterpret_cast<OneServiceImpl *>(uptr)->nodeVirtualNetworkConfigFunction(nwid,nuptr,op,nwconf); }
static void SnodeEventCallback(ZT_Node *node,void *uptr,enum ZT_Event event,const void *metaData)
static void SnodeEventCallback(ZT_Node *node,void *uptr,void *tptr,enum ZT_Event event,const void *metaData)
{ reinterpret_cast<OneServiceImpl *>(uptr)->nodeEventCallback(event,metaData); }
static long SnodeDataStoreGetFunction(ZT_Node *node,void *uptr,const char *name,void *buf,unsigned long bufSize,unsigned long readIndex,unsigned long *totalSize)
static long SnodeDataStoreGetFunction(ZT_Node *node,void *uptr,void *tptr,const char *name,void *buf,unsigned long bufSize,unsigned long readIndex,unsigned long *totalSize)
{ return reinterpret_cast<OneServiceImpl *>(uptr)->nodeDataStoreGetFunction(name,buf,bufSize,readIndex,totalSize); }
static int SnodeDataStorePutFunction(ZT_Node *node,void *uptr,const char *name,const void *data,unsigned long len,int secure)
static int SnodeDataStorePutFunction(ZT_Node *node,void *uptr,void *tptr,const char *name,const void *data,unsigned long len,int secure)
{ return reinterpret_cast<OneServiceImpl *>(uptr)->nodeDataStorePutFunction(name,data,len,secure); }
static int SnodeWirePacketSendFunction(ZT_Node *node,void *uptr,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,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 void SnodeVirtualNetworkFrameFunction(ZT_Node *node,void *uptr,uint64_t nwid,void **nuptr,uint64_t sourceMac,uint64_t destMac,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len)
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,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,const struct sockaddr_storage *localAddr,const struct sockaddr_storage *remoteAddr)
{ return reinterpret_cast<OneServiceImpl *>(uptr)->nodePathCheckFunction(ztaddr,localAddr,remoteAddr); }
static int SnodePathLookupFunction(ZT_Node *node,void *uptr,uint64_t ztaddr,int family,struct sockaddr_storage *result)
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); }
#ifdef ZT_ENABLE_CLUSTER
@@ -2494,7 +2492,7 @@ static int SclusterGeoIpFunction(void *uptr,const struct sockaddr_storage *addr,
}
#endif
static void StapFrameHandler(void *uptr,uint64_t nwid,const MAC &from,const MAC &to,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len)
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)
{ reinterpret_cast<OneServiceImpl *>(uptr)->tapFrameHandler(nwid,from,to,etherType,vlanId,data,len); }
static int ShttpOnMessageBegin(http_parser *parser)

View File

@@ -25,7 +25,7 @@
#include "../node/InetAddress.hpp"
#include "../node/Node.hpp"
// Include the right tap device driver for this platform -- add new platforms here
// Include the right tap device driver for this platform -- add new platforms here
#ifdef ZT_SDK
// In network containers builds, use the virtual netcon endpoint instead of a tun/tap port driver
#include "../src/tap.hpp"
@@ -34,6 +34,7 @@
namespace ZeroTier {
/**
* Local service for ZeroTier One as system VPN/NFV provider
*/

View File

@@ -27,6 +27,7 @@ Settings available in `local.conf` (this is not valid JSON, and JSON does not al
"primaryPort": 0-65535, /* If set, override default port of 9993 and any command line port */
"portMappingEnabled": true|false, /* If true (the default), try to use uPnP or NAT-PMP to map ports */
"softwareUpdate": "apply"|"download"|"disable", /* Automatically apply updates, just download, or disable built-in software updates */
"softwareUpdateChannel": "release"|"beta", /* Software update channel */
"softwareUpdateDist": true|false, /* If true, distribute software updates (only really useful to ZeroTier, Inc. itself, default is false) */
"interfacePrefixBlacklist": [ "XXX",... ], /* Array of interface name prefixes (e.g. eth for eth#) to blacklist for ZT traffic */
"allowManagementFrom": "NETWORK/bits"|null /* If non-NULL, allow JSON/HTTP management from this IP network. Default is 127.0.0.1 only. */
@@ -57,7 +58,8 @@ An example `local.conf`:
}
},
"settings": {
"relayPolicy": "ALWAYS"
"softwareUpdate": "apply",
"softwraeUpdateChannel": "release"
}
}
```

View File

@@ -47,13 +47,6 @@
#include "../osdep/OSUtils.hpp"
#ifndef ZT_BUILD_ARCHITECTURE
#define ZT_BUILD_ARCHITECTURE 0
#endif
#ifndef ZT_BUILD_PLATFORM
#define ZT_BUILD_PLATFORM 0
#endif
namespace ZeroTier {
SoftwareUpdater::SoftwareUpdater(Node &node,const std::string &homePath) :
@@ -65,30 +58,7 @@ SoftwareUpdater::SoftwareUpdater(Node &node,const std::string &homePath) :
_latestValid(false),
_downloadLength(0)
{
// Check for a cached newer update. If there's a cached update that is not newer or looks bad, delete.
try {
std::string buf;
if (OSUtils::readFile((_homePath + ZT_PATH_SEPARATOR_S ZT_SOFTWARE_UPDATE_META_FILENAME).c_str(),buf)) {
nlohmann::json meta = OSUtils::jsonParse(buf);
buf = std::string();
const unsigned int rvMaj = (unsigned int)OSUtils::jsonInt(meta[ZT_SOFTWARE_UPDATE_JSON_VERSION_MAJOR],0);
const unsigned int rvMin = (unsigned int)OSUtils::jsonInt(meta[ZT_SOFTWARE_UPDATE_JSON_VERSION_MINOR],0);
const unsigned int rvRev = (unsigned int)OSUtils::jsonInt(meta[ZT_SOFTWARE_UPDATE_JSON_VERSION_REVISION],0);
const unsigned int rvBld = (unsigned int)OSUtils::jsonInt(meta[ZT_SOFTWARE_UPDATE_JSON_VERSION_BUILD],0);
if ((Utils::compareVersion(rvMaj,rvMin,rvRev,rvBld,ZEROTIER_ONE_VERSION_MAJOR,ZEROTIER_ONE_VERSION_MINOR,ZEROTIER_ONE_VERSION_REVISION,ZEROTIER_ONE_VERSION_BUILD) > 0)&&
(OSUtils::readFile((_homePath + ZT_PATH_SEPARATOR_S ZT_SOFTWARE_UPDATE_BIN_FILENAME).c_str(),buf))) {
if ((uint64_t)buf.length() == OSUtils::jsonInt(meta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_SIZE],0)) {
_latestMeta = meta;
_latestValid = true;
//printf("CACHED UPDATE IS NEWER AND LOOKS GOOD\n");
}
}
}
} catch ( ... ) {} // exceptions indicate invalid cached update
if (!_latestValid) {
OSUtils::rm((_homePath + ZT_PATH_SEPARATOR_S ZT_SOFTWARE_UPDATE_META_FILENAME).c_str());
OSUtils::rm((_homePath + ZT_PATH_SEPARATOR_S ZT_SOFTWARE_UPDATE_BIN_FILENAME).c_str());
}
}
SoftwareUpdater::~SoftwareUpdater()
@@ -173,8 +143,18 @@ void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void
unsigned int bestVRev = rvRev;
unsigned int bestVBld = rvBld;
for(std::map< Array<uint8_t,16>,_D >::const_iterator d(_dist.begin());d!=_dist.end();++d) {
// The arch field in update description .json files can be an array for e.g. multi-arch update files
const nlohmann::json &dvArch2 = d->second.meta[ZT_SOFTWARE_UPDATE_JSON_ARCHITECTURE];
std::vector<unsigned int> dvArch;
if (dvArch2.is_array()) {
for(unsigned long i=0;i<dvArch2.size();++i)
dvArch.push_back((unsigned int)OSUtils::jsonInt(dvArch2[i],0));
} else {
dvArch.push_back((unsigned int)OSUtils::jsonInt(dvArch2,0));
}
if ((OSUtils::jsonInt(d->second.meta[ZT_SOFTWARE_UPDATE_JSON_PLATFORM],0) == rvPlatform)&&
(OSUtils::jsonInt(d->second.meta[ZT_SOFTWARE_UPDATE_JSON_ARCHITECTURE],0) == rvArch)&&
(std::find(dvArch.begin(),dvArch.end(),rvArch) != dvArch.end())&&
(OSUtils::jsonInt(d->second.meta[ZT_SOFTWARE_UPDATE_JSON_VENDOR],0) == rvVendor)&&
(OSUtils::jsonString(d->second.meta[ZT_SOFTWARE_UPDATE_JSON_CHANNEL],"") == rvChannel)&&
(OSUtils::jsonString(d->second.meta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_SIGNED_BY],"") == expectedSigner)) {
@@ -195,7 +175,7 @@ void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void
std::string lj;
lj.push_back((char)VERB_LATEST);
lj.append(OSUtils::jsonDump(*latest));
_node.sendUserMessage(origin,ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE,lj.data(),(unsigned int)lj.length());
_node.sendUserMessage((void *)0,origin,ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE,lj.data(),(unsigned int)lj.length());
if (_distLog) {
fprintf(_distLog,"%.10llx GET_LATEST %u.%u.%u_%u platform %u arch %u vendor %u channel %s -> LATEST %u.%u.%u_%u" ZT_EOL_S,(unsigned long long)origin,rvMaj,rvMin,rvRev,rvBld,rvPlatform,rvArch,rvVendor,rvChannel.c_str(),bestVMaj,bestVMin,bestVRev,bestVBld);
fflush(_distLog);
@@ -214,10 +194,7 @@ void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void
if (_latestMeta != req) {
_latestMeta = req;
_latestValid = false;
OSUtils::rm((_homePath + ZT_PATH_SEPARATOR_S ZT_SOFTWARE_UPDATE_META_FILENAME).c_str());
OSUtils::rm((_homePath + ZT_PATH_SEPARATOR_S ZT_SOFTWARE_UPDATE_BIN_FILENAME).c_str());
_download = std::string();
memcpy(_downloadHashPrefix.data,hash.data(),16);
_downloadLength = len;
@@ -228,7 +205,7 @@ void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void
gd.append((uint8_t)VERB_GET_DATA);
gd.append(_downloadHashPrefix.data,16);
gd.append((uint32_t)_download.length());
_node.sendUserMessage(ZT_SOFTWARE_UPDATE_SERVICE,ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE,gd.data(),gd.size());
_node.sendUserMessage((void *)0,ZT_SOFTWARE_UPDATE_SERVICE,ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE,gd.data(),gd.size());
//printf(">> GET_DATA @%u\n",(unsigned int)_download.length());
}
}
@@ -252,7 +229,7 @@ void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void
buf.append(reinterpret_cast<const uint8_t *>(data) + 1,16);
buf.append((uint32_t)idx);
buf.append(d->second.bin.data() + idx,std::min((unsigned long)ZT_SOFTWARE_UPDATE_CHUNK_SIZE,(unsigned long)(d->second.bin.length() - idx)));
_node.sendUserMessage(origin,ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE,buf.data(),buf.size());
_node.sendUserMessage((void *)0,origin,ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE,buf.data(),buf.size());
//printf(">> DATA @%u\n",(unsigned int)idx);
}
}
@@ -272,7 +249,7 @@ void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void
gd.append((uint8_t)VERB_GET_DATA);
gd.append(_downloadHashPrefix.data,16);
gd.append((uint32_t)_download.length());
_node.sendUserMessage(ZT_SOFTWARE_UPDATE_SERVICE,ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE,gd.data(),gd.size());
_node.sendUserMessage((void *)0,ZT_SOFTWARE_UPDATE_SERVICE,ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE,gd.data(),gd.size());
//printf(">> GET_DATA @%u\n",(unsigned int)_download.length());
}
}
@@ -281,14 +258,14 @@ void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void
default:
if (_distLog) {
fprintf(_distLog,"%.10llx WARNING: bad update message verb==%u length==%u (unrecognized verb)" ZT_EOL_S,origin,(unsigned int)v,len);
fprintf(_distLog,"%.10llx WARNING: bad update message verb==%u length==%u (unrecognized verb)" ZT_EOL_S,(unsigned long long)origin,(unsigned int)v,len);
fflush(_distLog);
}
break;
}
} catch ( ... ) {
if (_distLog) {
fprintf(_distLog,"%.10llx WARNING: bad update message verb==%u length==%u (unexpected exception, likely invalid JSON)" ZT_EOL_S,origin,(unsigned int)v,len);
fprintf(_distLog,"%.10llx WARNING: bad update message verb==%u length==%u (unexpected exception, likely invalid JSON)" ZT_EOL_S,(unsigned long long)origin,(unsigned int)v,len);
fflush(_distLog);
}
}
@@ -319,7 +296,7 @@ bool SoftwareUpdater::check(const uint64_t now)
ZT_BUILD_ARCHITECTURE,
(int)ZT_VENDOR_ZEROTIER,
_channel.c_str());
_node.sendUserMessage(ZT_SOFTWARE_UPDATE_SERVICE,ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE,tmp,len);
_node.sendUserMessage((void *)0,ZT_SOFTWARE_UPDATE_SERVICE,ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE,tmp,len);
//printf(">> GET_LATEST\n");
}
@@ -331,9 +308,7 @@ bool SoftwareUpdater::check(const uint64_t now)
// This is the very important security validation part that makes sure
// this software update doesn't have cooties.
const std::string metaPath(_homePath + ZT_PATH_SEPARATOR_S ZT_SOFTWARE_UPDATE_META_FILENAME);
const std::string binPath(_homePath + ZT_PATH_SEPARATOR_S ZT_SOFTWARE_UPDATE_BIN_FILENAME);
try {
// (1) Check the hash itself to make sure the image is basically okay
uint8_t sha512[ZT_SHA512_DIGEST_LEN];
@@ -343,8 +318,8 @@ bool SoftwareUpdater::check(const uint64_t now)
const std::string sig(OSUtils::jsonBinFromHex(_latestMeta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_SIGNATURE]));
if (Identity(ZT_SOFTWARE_UPDATE_SIGNING_AUTHORITY).verify(_download.data(),(unsigned int)_download.length(),sig.data(),(unsigned int)sig.length())) {
// (3) Try to save file, and if so we are good.
if (OSUtils::writeFile(metaPath.c_str(),OSUtils::jsonDump(_latestMeta)) && OSUtils::writeFile(binPath.c_str(),_download)) {
OSUtils::lockDownFile(metaPath.c_str(),false);
OSUtils::rm(binPath.c_str());
if (OSUtils::writeFile(binPath.c_str(),_download)) {
OSUtils::lockDownFile(binPath.c_str(),false);
_latestValid = true;
//printf("VALID UPDATE\n%s\n",OSUtils::jsonDump(_latestMeta).c_str());
@@ -358,7 +333,6 @@ bool SoftwareUpdater::check(const uint64_t now)
// If we get here, checks failed.
//printf("INVALID UPDATE (!!!)\n%s\n",OSUtils::jsonDump(_latestMeta).c_str());
OSUtils::rm(metaPath.c_str());
OSUtils::rm(binPath.c_str());
_latestMeta = nlohmann::json();
_latestValid = false;
@@ -369,7 +343,7 @@ bool SoftwareUpdater::check(const uint64_t now)
gd.append((uint8_t)VERB_GET_DATA);
gd.append(_downloadHashPrefix.data,16);
gd.append((uint32_t)_download.length());
_node.sendUserMessage(ZT_SOFTWARE_UPDATE_SERVICE,ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE,gd.data(),gd.size());
_node.sendUserMessage((void *)0,ZT_SOFTWARE_UPDATE_SERVICE,ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE,gd.data(),gd.size());
//printf(">> GET_DATA @%u\n",(unsigned int)_download.length());
}
}

View File

@@ -71,11 +71,6 @@
*/
#define ZT_SOFTWARE_UPDATE_DEFAULT_CHANNEL "release"
/**
* Filename for latest update's meta JSON
*/
#define ZT_SOFTWARE_UPDATE_META_FILENAME "latest-update.json"
/**
* Filename for latest update's binary image
*/

View File

@@ -32,7 +32,7 @@
/**
* Revision
*/
#define ZEROTIER_ONE_VERSION_REVISION 0
#define ZEROTIER_ONE_VERSION_REVISION 3
/**
* Build version
@@ -43,4 +43,11 @@
*/
#define ZEROTIER_ONE_VERSION_BUILD 0
#ifndef ZT_BUILD_ARCHITECTURE
#define ZT_BUILD_ARCHITECTURE 0
#endif
#ifndef ZT_BUILD_PLATFORM
#define ZT_BUILD_PLATFORM 0
#endif
#endif

View File

@@ -47,7 +47,7 @@ namespace WinUI
}
}
private static bool initHandler()
private static bool initHandler(bool resetToken = false)
{
String localZtDir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\ZeroTier\\One";
String globalZtDir = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "\\ZeroTier\\One";
@@ -55,6 +55,20 @@ namespace WinUI
String authToken = "";
Int32 port = 9993;
if (resetToken)
{
instance = null;
if (File.Exists(localZtDir + "\\authtoken.secret"))
{
File.Delete(localZtDir + "\\authtoken.secret");
}
if (File.Exists(localZtDir + "\\zerotier-one.port"))
{
File.Delete(localZtDir + "\\zerotier-one.port");
}
}
if (!File.Exists(localZtDir + "\\authtoken.secret") || !File.Exists(localZtDir + "\\zerotier-one.port"))
{
// launch external process to copy file into place
@@ -127,7 +141,7 @@ namespace WinUI
public APIHandler(int port, string authtoken)
{
url = "http://localhost:" + port;
url = "http://127.0.0.1:" + port;
this.authtoken = authtoken;
}
@@ -145,6 +159,8 @@ namespace WinUI
try
{
var httpResponse = (HttpWebResponse)request.GetResponse();
if (httpResponse.StatusCode == HttpStatusCode.OK)
{
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var responseText = streamReader.ReadToEnd();
@@ -161,15 +177,27 @@ namespace WinUI
cb(status);
}
}
else if (httpResponse.StatusCode == HttpStatusCode.Unauthorized)
{
APIHandler.initHandler(true);
}
}
catch (System.Net.Sockets.SocketException)
{
cb(null);
}
catch (System.Net.WebException)
catch (System.Net.WebException e)
{
if (((HttpWebResponse)e.Response).StatusCode == HttpStatusCode.Unauthorized)
{
APIHandler.initHandler(true);
}
else
{
cb(null);
}
}
}
@@ -188,6 +216,9 @@ namespace WinUI
try
{
var httpResponse = (HttpWebResponse)request.GetResponse();
if (httpResponse.StatusCode == HttpStatusCode.OK)
{
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var responseText = streamReader.ReadToEnd();
@@ -209,15 +240,27 @@ namespace WinUI
cb(networkList);
}
}
else if (httpResponse.StatusCode == HttpStatusCode.Unauthorized)
{
APIHandler.initHandler(true);
}
}
catch (System.Net.Sockets.SocketException)
{
cb(null);
}
catch (System.Net.WebException)
catch (System.Net.WebException e)
{
if (((HttpWebResponse)e.Response).StatusCode == HttpStatusCode.Unauthorized)
{
APIHandler.initHandler(true);
}
else
{
cb(null);
}
}
}
public void JoinNetwork(string nwid, bool allowManaged = true, bool allowGlobal = false, bool allowDefault = false)
{
@@ -252,7 +295,11 @@ namespace WinUI
{
var httpResponse = (HttpWebResponse)request.GetResponse();
if (httpResponse.StatusCode != HttpStatusCode.OK)
if (httpResponse.StatusCode == HttpStatusCode.Unauthorized)
{
APIHandler.initHandler(true);
}
else if (httpResponse.StatusCode != HttpStatusCode.OK)
{
Console.WriteLine("Error sending join network message");
}
@@ -261,8 +308,12 @@ namespace WinUI
{
MessageBox.Show("Error Joining Network: Cannot connect to ZeroTier service.");
}
catch (System.Net.WebException)
catch (System.Net.WebException e)
{
if (((HttpWebResponse)e.Response).StatusCode == HttpStatusCode.Unauthorized)
{
APIHandler.initHandler(true);
}
MessageBox.Show("Error Joining Network: Cannot connect to ZeroTier service.");
}
}
@@ -282,7 +333,11 @@ namespace WinUI
{
var httpResponse = (HttpWebResponse)request.GetResponse();
if (httpResponse.StatusCode != HttpStatusCode.OK)
if (httpResponse.StatusCode == HttpStatusCode.Unauthorized)
{
APIHandler.initHandler(true);
}
else if (httpResponse.StatusCode != HttpStatusCode.OK)
{
Console.WriteLine("Error sending leave network message");
}
@@ -291,8 +346,12 @@ namespace WinUI
{
MessageBox.Show("Error Leaving Network: Cannot connect to ZeroTier service.");
}
catch (System.Net.WebException)
catch (System.Net.WebException e)
{
if (((HttpWebResponse)e.Response).StatusCode == HttpStatusCode.Unauthorized)
{
APIHandler.initHandler(true);
}
MessageBox.Show("Error Leaving Network: Cannot connect to ZeroTier service.");
}
catch
@@ -317,6 +376,8 @@ namespace WinUI
try
{
var httpResponse = (HttpWebResponse)request.GetResponse();
if (httpResponse.StatusCode == HttpStatusCode.OK)
{
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var responseText = streamReader.ReadToEnd();
@@ -333,14 +394,26 @@ namespace WinUI
cb(peerList);
}
}
else if (httpResponse.StatusCode == HttpStatusCode.Unauthorized)
{
APIHandler.initHandler(true);
}
}
catch (System.Net.Sockets.SocketException)
{
cb(null);
}
catch (System.Net.WebException)
catch (System.Net.WebException e)
{
if (((HttpWebResponse)e.Response).StatusCode == HttpStatusCode.Unauthorized)
{
APIHandler.initHandler(true);
}
else
{
cb(null);
}
}
}
}
}

View File

@@ -5,96 +5,28 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WinUI"
mc:Ignorable="d"
Title="AboutView" Height="460" Width="300" Icon="ZeroTierIcon.ico">
Title="AboutView" Height="368.267" Width="300" Icon="ZeroTierIcon.ico">
<Grid>
<Image x:Name="image" HorizontalAlignment="Center" Height="100" Margin="0,10,0,0" VerticalAlignment="Top" Width="100" Source="ZeroTierIcon.ico"/>
<RichTextBox x:Name="richTextBox" HorizontalAlignment="Left" Height="307" Margin="10,115,0,0" VerticalAlignment="Top" Width="275" IsReadOnly="True" IsDocumentEnabled="True" BorderThickness="0">
<RichTextBox x:Name="richTextBox" HorizontalAlignment="Left" Height="209" Margin="10,123,0,0" VerticalAlignment="Top" Width="275" IsReadOnly="True" IsDocumentEnabled="True" BorderThickness="0" FontSize="18" RenderTransformOrigin="0.506,0.63">
<RichTextBox.Resources>
<Style TargetType="Hyperlink">
<Setter Property="Cursor" Value="Hand" />
</Style>
</RichTextBox.Resources>
<FlowDocument>
<Paragraph>
<Span FontWeight="Bold" FontSize="18" FontFamily="HelveticaNeue">
<Run Text="Getting Started"/>
</Span>
<Span FontWeight="Bold" FontSize="12" FontFamily="HelveticaNeue">
<LineBreak/>
</Span>
<Span FontSize="12" FontFamily="HelveticaNeue">
<Run/>
</Span>
<Paragraph TextAlignment="Center">
<Run Text="ZeroTier One"/>
</Paragraph>
<Paragraph>
<Span FontSize="12" FontFamily="HelveticaNeue">
<Run Text="Getting started is simple. Simply click "/>
</Span>
<Span FontSize="12" FontFamily="Menlo-Regular">
<Run Text="Join Network"/>
</Span>
<Span FontSize="12" FontFamily="HelveticaNeue">
<Run Text=" from the ZeroTier status bar menu. To join the public network &quot;Earth&quot;, enter "/>
</Span>
<Span FontSize="12" FontFamily="Menlo-Regular">
<Run Text="8056c2e21c000001"/>
</Span>
<Span FontSize="12" FontFamily="HelveticaNeue">
<Run Text=" and click the Join button. Once connected, you'll be able to navigate to "/>
</Span>
<Hyperlink NavigateUri="http://earth.zerotier.net/" RequestNavigate="Hyperlink_MouseLeftButtonDown">
<Span Foreground="#FF0000E9" FontSize="12" FontFamily="HelveticaNeue">
<Run Text="earth.zerotier.net"/>
</Span>
</Hyperlink>
<Span FontSize="12" FontFamily="HelveticaNeue">
<Run Text="."/>
</Span>
</Paragraph>
<Paragraph>
<Span FontSize="12" FontFamily="HelveticaNeue">
<Run/>
<Paragraph TextAlignment="Center">
<Run FontSize="14" Text="Version 1.2.2"/>
<LineBreak/>
</Span>
<Span FontWeight="Bold" FontSize="18" FontFamily="HelveticaNeue">
<Run Text="Create a Network"/>
</Span>
<Span FontWeight="Bold" FontSize="12" FontFamily="HelveticaNeue">
<Run FontSize="14" Text="(c) 2011-2017 ZeroTier, Inc."/>
<LineBreak/>
</Span>
<Span FontSize="12" FontFamily="HelveticaNeue">
<Run/>
</Span>
<Run FontSize="14" Text="www.zerotier.com"/>
</Paragraph>
<Paragraph>
<Span FontSize="12" FontFamily="HelveticaNeue">
<Run Text="Visit "/>
</Span>
<Hyperlink NavigateUri="http://my.zerotier.com/" RequestNavigate="Hyperlink_MouseLeftButtonDown">
<Span Foreground="#FF0000E9" FontSize="12" FontFamily="HelveticaNeue">
<Run Text="my.zerotier.com"/>
</Span>
</Hyperlink>
<Span FontSize="12" FontFamily="HelveticaNeue">
<Run Text=" to create and manage your own virtual networks."/>
</Span>
<Span FontSize="12" FontFamily="HelveticaNeue">
<LineBreak/>
<Run/>
</Span>
</Paragraph>
<Paragraph>
<Span FontSize="12" FontFamily="HelveticaNeue">
<Run Text="For more information, visit "/>
</Span>
<Hyperlink NavigateUri="http://www.zerotier.com/" RequestNavigate="Hyperlink_MouseLeftButtonDown">
<Span Foreground="#FF0000E9" FontSize="12" FontFamily="HelveticaNeue">
<Run Text="zerotier.com"/>
</Span>
</Hyperlink>
<Span FontSize="12" FontFamily="HelveticaNeue">
<Run Text="."/>
</Span>
<Paragraph TextAlignment="Center">
<Run FontSize="14" Text="ZeroTier One allows your computer to join virtual networks. Just select &quot;join&quot; and enter a network's 16-digit ID. Each network appears on your computer as a new network port."/>
</Paragraph>
</FlowDocument>
</RichTextBox>

View File

@@ -1,5 +1,5 @@
Name: zerotier-one
Version: 1.2.0
Version: 1.2.2
Release: 1%{?dist}
Summary: ZeroTier One network virtualization service
@@ -145,6 +145,12 @@ esac
%endif
%changelog
* Fri Mar 17 2017 Adam Ierymenko <adam.ierymenko@zerotier.com> - 1.2.2-0.1
- see https://github.com/zerotier/ZeroTierOne for release notes
* Tue Mar 14 2017 Adam Ierymenko <adam.ierymenko@zerotier.com> - 1.2.0-0.1
- see https://github.com/zerotier/ZeroTierOne for release notes
* Tue Jul 12 2016 Adam Ierymenko <adam.ierymenko@zerotier.com> - 1.1.10-0.1
- see https://github.com/zerotier/ZeroTierOne for release notes