Updated core for tptr support
This commit is contained in:
@@ -357,7 +357,7 @@ namespace ZeroTier {
|
|||||||
src_mac.setTo(ethhdr->saddr, 6);
|
src_mac.setTo(ethhdr->saddr, 6);
|
||||||
dest_mac.setTo(ethhdr->daddr, 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));
|
Utils::ntoh((uint16_t)ethhdr->proto),0, ((char*)buf) + sizeof(struct pico_eth_hdr),len - sizeof(struct pico_eth_hdr));
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ NetconEthernetTap::NetconEthernetTap(
|
|||||||
unsigned int metric,
|
unsigned int metric,
|
||||||
uint64_t nwid,
|
uint64_t nwid,
|
||||||
const char *friendlyName,
|
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) :
|
void *arg) :
|
||||||
_homePath(homePath),
|
_homePath(homePath),
|
||||||
_mac(mac),
|
_mac(mac),
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ namespace ZeroTier {
|
|||||||
unsigned int metric,
|
unsigned int metric,
|
||||||
uint64_t nwid,
|
uint64_t nwid,
|
||||||
const char *friendlyName,
|
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);
|
void *arg);
|
||||||
|
|
||||||
~NetconEthernetTap();
|
~NetconEthernetTap();
|
||||||
@@ -149,7 +149,7 @@ namespace ZeroTier {
|
|||||||
MAC _mac;
|
MAC _mac;
|
||||||
unsigned int _mtu;
|
unsigned int _mtu;
|
||||||
uint64_t _nwid;
|
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;
|
void *_arg;
|
||||||
Phy<NetconEthernetTap *> _phy;
|
Phy<NetconEthernetTap *> _phy;
|
||||||
PhySocket *_unixListenSocket;
|
PhySocket *_unixListenSocket;
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ ifeq ($(OSTYPE),Linux)
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(OSTYPE),FreeBSD)
|
ifeq ($(OSTYPE),FreeBSD)
|
||||||
CC=gcc
|
CC=clang
|
||||||
CXX=g++
|
CXX=clang++
|
||||||
ZT_BUILD_PLATFORM=7
|
ZT_BUILD_PLATFORM=7
|
||||||
include make-bsd.mk
|
include make-bsd.mk
|
||||||
endif
|
endif
|
||||||
|
|||||||
@@ -1,32 +1,40 @@
|
|||||||
ZeroTier Release Notes
|
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 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.
|
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.
|
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
|
### 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:
|
Federated roots achieve a number of things:
|
||||||
|
|
||||||
* You can deploy your own infrastructure to reduce dependency on ours.
|
* 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.)
|
* 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.
|
* 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).
|
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
|
### 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)
|
### 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
|
## Major Bug Fixes in 1.2.0
|
||||||
|
|
||||||
* **The Windows HyperV 100% CPU bug**
|
* **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.
|
||||||
* 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.
|
||||||
* **Segmenation Faults on musl-libc based Linux Systems**
|
* **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.
|
||||||
* 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.
|
* **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.
|
||||||
* **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.
|
## Other Improvements in 1.2.0
|
||||||
* **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.
|
* **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.
|
||||||
|
|||||||
@@ -61,9 +61,6 @@ using json = nlohmann::json;
|
|||||||
// Nodes are considered active if they've queried in less than this long
|
// Nodes are considered active if they've queried in less than this long
|
||||||
#define ZT_NETCONF_NODE_ACTIVE_THRESHOLD (ZT_NETWORK_AUTOCONF_DELAY * 2)
|
#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 {
|
namespace ZeroTier {
|
||||||
|
|
||||||
static json _renderRule(ZT_VirtualNetworkRule &rule)
|
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) :
|
EmbeddedNetworkController::EmbeddedNetworkController(Node *node,const char *dbPath) :
|
||||||
|
_startTime(OSUtils::now()),
|
||||||
_threadsStarted(false),
|
_threadsStarted(false),
|
||||||
_db(dbPath),
|
_db(dbPath),
|
||||||
_node(node)
|
_node(node)
|
||||||
@@ -503,7 +501,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET(
|
|||||||
json network;
|
json network;
|
||||||
{
|
{
|
||||||
Mutex::Lock _l(_db_m);
|
Mutex::Lock _l(_db_m);
|
||||||
network = _db.get("network",nwids,ZT_NETCONF_DB_CACHE_TTL);
|
network = _db.get("network",nwids);
|
||||||
}
|
}
|
||||||
if (!network.size())
|
if (!network.size())
|
||||||
return 404;
|
return 404;
|
||||||
@@ -518,7 +516,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET(
|
|||||||
json member;
|
json member;
|
||||||
{
|
{
|
||||||
Mutex::Lock _l(_db_m);
|
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())
|
if (!member.size())
|
||||||
return 404;
|
return 404;
|
||||||
@@ -533,11 +531,10 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET(
|
|||||||
Mutex::Lock _l(_db_m);
|
Mutex::Lock _l(_db_m);
|
||||||
|
|
||||||
responseBody = "{";
|
responseBody = "{";
|
||||||
std::string pfx(std::string("network/") + nwids + "member/");
|
_db.filter((std::string("network/") + nwids + "/member/"),[&responseBody](const std::string &n,const json &member) {
|
||||||
_db.filter(pfx,ZT_NETCONF_DB_CACHE_TTL,[&responseBody](const std::string &n,const json &member) {
|
if ((member.is_object())&&(member.size() > 0)) {
|
||||||
if (member.size() > 0) {
|
|
||||||
responseBody.append((responseBody.length() == 1) ? "\"" : ",\"");
|
responseBody.append((responseBody.length() == 1) ? "\"" : ",\"");
|
||||||
responseBody.append(OSUtils::jsonString(member["id"],""));
|
responseBody.append(OSUtils::jsonString(member["id"],"0"));
|
||||||
responseBody.append("\":");
|
responseBody.append("\":");
|
||||||
responseBody.append(OSUtils::jsonString(member["revision"],"0"));
|
responseBody.append(OSUtils::jsonString(member["revision"],"0"));
|
||||||
}
|
}
|
||||||
@@ -567,7 +564,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET(
|
|||||||
std::set<std::string> networkIds;
|
std::set<std::string> networkIds;
|
||||||
{
|
{
|
||||||
Mutex::Lock _l(_db_m);
|
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))
|
if (n.length() == (16 + 8))
|
||||||
networkIds.insert(n.substr(8));
|
networkIds.insert(n.substr(8));
|
||||||
return true; // do not delete
|
return true; // do not delete
|
||||||
@@ -642,7 +639,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST(
|
|||||||
json member;
|
json member;
|
||||||
{
|
{
|
||||||
Mutex::Lock _l(_db_m);
|
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
|
json origMember(member); // for detecting changes
|
||||||
_initMember(member);
|
_initMember(member);
|
||||||
@@ -793,7 +790,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST(
|
|||||||
test->timestamp = OSUtils::now();
|
test->timestamp = OSUtils::now();
|
||||||
|
|
||||||
if (_node) {
|
if (_node) {
|
||||||
_node->circuitTestBegin(test,&(EmbeddedNetworkController::_circuitTestCallback));
|
_node->circuitTestBegin((void *)0,test,&(EmbeddedNetworkController::_circuitTestCallback));
|
||||||
} else {
|
} else {
|
||||||
_tests.pop_back();
|
_tests.pop_back();
|
||||||
return 500;
|
return 500;
|
||||||
@@ -825,7 +822,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST(
|
|||||||
uint64_t tryNwid = nwidPrefix | (nwidPostfix & 0xffffffULL);
|
uint64_t tryNwid = nwidPrefix | (nwidPostfix & 0xffffffULL);
|
||||||
if ((tryNwid & 0xffffffULL) == 0ULL) tryNwid |= 1ULL;
|
if ((tryNwid & 0xffffffULL) == 0ULL) tryNwid |= 1ULL;
|
||||||
Utils::snprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)tryNwid);
|
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;
|
nwid = tryNwid;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -834,7 +831,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST(
|
|||||||
return 503;
|
return 503;
|
||||||
}
|
}
|
||||||
|
|
||||||
network = _db.get("network",nwids,ZT_NETCONF_DB_CACHE_TTL);
|
network = _db.get("network",nwids);
|
||||||
}
|
}
|
||||||
json origNetwork(network); // for detecting changes
|
json origNetwork(network); // for detecting changes
|
||||||
_initNetwork(network);
|
_initNetwork(network);
|
||||||
@@ -1054,7 +1051,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Send an update to all members of the network
|
// 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);
|
_pushMemberUpdate(now,nwid,obj);
|
||||||
return true; // do not delete
|
return true; // do not delete
|
||||||
});
|
});
|
||||||
@@ -1071,7 +1068,15 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST(
|
|||||||
|
|
||||||
} // else 404
|
} // 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;
|
return 404;
|
||||||
}
|
}
|
||||||
@@ -1096,7 +1101,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpDELETE(
|
|||||||
json network;
|
json network;
|
||||||
{
|
{
|
||||||
Mutex::Lock _l(_db_m);
|
Mutex::Lock _l(_db_m);
|
||||||
network = _db.get("network",nwids,ZT_NETCONF_DB_CACHE_TTL);
|
network = _db.get("network",nwids);
|
||||||
}
|
}
|
||||||
if (!network.size())
|
if (!network.size())
|
||||||
return 404;
|
return 404;
|
||||||
@@ -1107,7 +1112,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpDELETE(
|
|||||||
|
|
||||||
Mutex::Lock _l(_db_m);
|
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());
|
_db.erase("network",nwids,"member",Address(address).toString());
|
||||||
|
|
||||||
if (!member.size())
|
if (!member.size())
|
||||||
@@ -1120,7 +1125,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpDELETE(
|
|||||||
Mutex::Lock _l(_db_m);
|
Mutex::Lock _l(_db_m);
|
||||||
|
|
||||||
std::string pfx("network/"); pfx.append(nwids);
|
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
|
return false; // delete
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1247,8 +1252,8 @@ void EmbeddedNetworkController::_request(
|
|||||||
json member;
|
json member;
|
||||||
{
|
{
|
||||||
Mutex::Lock _l(_db_m);
|
Mutex::Lock _l(_db_m);
|
||||||
network = _db.get("network",nwids,ZT_NETCONF_DB_CACHE_TTL);
|
network = _db.get("network",nwids);
|
||||||
member = _db.get("network",nwids,"member",identity.address().toString(),ZT_NETCONF_DB_CACHE_TTL);
|
member = _db.get("network",nwids,"member",identity.address().toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!network.size()) {
|
if (!network.size()) {
|
||||||
@@ -1773,7 +1778,7 @@ void EmbeddedNetworkController::_getNetworkMemberInfo(uint64_t now,uint64_t nwid
|
|||||||
|
|
||||||
{
|
{
|
||||||
Mutex::Lock _l(_db_m);
|
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 {
|
try {
|
||||||
if (OSUtils::jsonBool(member["authorized"],false)) {
|
if (OSUtils::jsonBool(member["authorized"],false)) {
|
||||||
++nmi.authorizedMemberCount;
|
++nmi.authorizedMemberCount;
|
||||||
|
|||||||
@@ -98,14 +98,6 @@ public:
|
|||||||
throw();
|
throw();
|
||||||
|
|
||||||
private:
|
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
|
struct _RQEntry
|
||||||
{
|
{
|
||||||
uint64_t nwid;
|
uint64_t nwid;
|
||||||
@@ -114,11 +106,6 @@ private:
|
|||||||
Identity identity;
|
Identity identity;
|
||||||
Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> metaData;
|
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
|
// Gathers a bunch of statistics about members of a network, IP assignments, etc. that we need in various places
|
||||||
struct _NetworkMemberInfo
|
struct _NetworkMemberInfo
|
||||||
@@ -132,15 +119,11 @@ private:
|
|||||||
uint64_t mostRecentDeauthTime;
|
uint64_t mostRecentDeauthTime;
|
||||||
uint64_t nmiTimestamp; // time this NMI structure was computed
|
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);
|
void _pushMemberUpdate(uint64_t now,uint64_t nwid,const nlohmann::json &member);
|
||||||
|
|
||||||
// These init objects with default and static/informational fields
|
// These init objects with default and static/informational fields
|
||||||
@@ -196,6 +179,16 @@ private:
|
|||||||
member["clock"] = now;
|
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;
|
JSONDB _db;
|
||||||
Mutex _db_m;
|
Mutex _db_m;
|
||||||
|
|
||||||
|
|||||||
@@ -53,52 +53,26 @@ bool JSONDB::put(const std::string &n,const nlohmann::json &obj)
|
|||||||
|
|
||||||
_E &e = _db[n];
|
_E &e = _db[n];
|
||||||
e.obj = obj;
|
e.obj = obj;
|
||||||
e.lastModifiedOnDisk = OSUtils::getLastModified(path.c_str());
|
|
||||||
e.lastCheck = OSUtils::now();
|
|
||||||
|
|
||||||
return true;
|
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))
|
if (!_isValidObjectName(n))
|
||||||
return _EMPTY_JSON;
|
return _EMPTY_JSON;
|
||||||
|
|
||||||
const uint64_t now = OSUtils::now();
|
|
||||||
std::string buf;
|
|
||||||
std::map<std::string,_E>::iterator e(_db.find(n));
|
std::map<std::string,_E>::iterator e(_db.find(n));
|
||||||
|
if (e != _db.end())
|
||||||
if (e != _db.end()) {
|
|
||||||
if ((now - e->second.lastCheck) <= (uint64_t)maxSinceCheck)
|
|
||||||
return e->second.obj;
|
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));
|
const std::string path(_genPath(n,false));
|
||||||
if (!path.length())
|
if (!path.length())
|
||||||
return _EMPTY_JSON;
|
return _EMPTY_JSON;
|
||||||
|
std::string buf;
|
||||||
if (!OSUtils::readFile(path.c_str(),buf))
|
if (!OSUtils::readFile(path.c_str(),buf))
|
||||||
return _EMPTY_JSON;
|
return _EMPTY_JSON;
|
||||||
|
|
||||||
const uint64_t lm = OSUtils::getLastModified(path.c_str());
|
|
||||||
_E &e2 = _db[n];
|
_E &e2 = _db[n];
|
||||||
try {
|
try {
|
||||||
e2.obj = OSUtils::jsonParse(buf);
|
e2.obj = OSUtils::jsonParse(buf);
|
||||||
@@ -106,12 +80,9 @@ const nlohmann::json &JSONDB::get(const std::string &n,unsigned long maxSinceChe
|
|||||||
e2.obj = _EMPTY_JSON;
|
e2.obj = _EMPTY_JSON;
|
||||||
buf = "{}";
|
buf = "{}";
|
||||||
}
|
}
|
||||||
e2.lastModifiedOnDisk = lm;
|
|
||||||
e2.lastCheck = now;
|
|
||||||
|
|
||||||
return e2.obj;
|
return e2.obj;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void JSONDB::erase(const std::string &n)
|
void JSONDB::erase(const std::string &n)
|
||||||
{
|
{
|
||||||
@@ -126,22 +97,14 @@ void JSONDB::erase(const std::string &n)
|
|||||||
_db.erase(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()));
|
std::vector<std::string> dl(OSUtils::listDirectory(p.c_str()));
|
||||||
for(std::map<std::string,char>::iterator li(l.begin());li!=l.end();++li) {
|
for(std::vector<std::string>::const_iterator di(dl.begin());di!=dl.end();++di) {
|
||||||
if (li->second == 'f') {
|
if ((di->length() > 5)&&(di->substr(di->length() - 5) == ".json")) {
|
||||||
// assume p starts with _basePath, which it always does -- will throw otherwise
|
this->get(b + di->substr(0,di->length() - 5));
|
||||||
std::string n(p.substr(_basePath.length()));
|
} else {
|
||||||
while ((n.length() > 0)&&(n[0] == ZT_PATH_SEPARATOR)) n = n.substr(1);
|
this->_reload((p + ZT_PATH_SEPARATOR + *di),(b + *di + ZT_PATH_SEPARATOR));
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,13 +45,13 @@ public:
|
|||||||
JSONDB(const std::string &basePath) :
|
JSONDB(const std::string &basePath) :
|
||||||
_basePath(basePath)
|
_basePath(basePath)
|
||||||
{
|
{
|
||||||
_reload(_basePath);
|
_reload(_basePath,std::string());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void reload()
|
inline void reload()
|
||||||
{
|
{
|
||||||
_db.clear();
|
_db.clear();
|
||||||
_reload(_basePath);
|
_reload(_basePath,std::string());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool writeRaw(const std::string &n,const std::string &obj);
|
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 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); }
|
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) { return this->get((n1 + "/" + n2)); }
|
||||||
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) { 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,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) { 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,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,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);
|
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); }
|
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>
|
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();) {
|
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 ((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;
|
std::map<std::string,_E>::iterator i2(i); ++i2;
|
||||||
this->erase(i->first);
|
this->erase(i->first);
|
||||||
i = i2;
|
i = i2;
|
||||||
@@ -95,16 +95,13 @@ public:
|
|||||||
inline bool operator!=(const JSONDB &db) const { return (!(*this == db)); }
|
inline bool operator!=(const JSONDB &db) const { return (!(*this == db)); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _reload(const std::string &p);
|
void _reload(const std::string &p,const std::string &b);
|
||||||
bool _isValidObjectName(const std::string &n);
|
bool _isValidObjectName(const std::string &n);
|
||||||
std::string _genPath(const std::string &n,bool create);
|
std::string _genPath(const std::string &n,bool create);
|
||||||
|
|
||||||
struct _E
|
struct _E
|
||||||
{
|
{
|
||||||
nlohmann::json obj;
|
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); }
|
||||||
inline bool operator!=(const _E &e) const { return (obj != e.obj); }
|
inline bool operator!=(const _E &e) const { return (obj != e.obj); }
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1408,6 +1408,7 @@ typedef void ZT_Node;
|
|||||||
typedef int (*ZT_VirtualNetworkConfigFunction)(
|
typedef int (*ZT_VirtualNetworkConfigFunction)(
|
||||||
ZT_Node *, /* Node */
|
ZT_Node *, /* Node */
|
||||||
void *, /* User ptr */
|
void *, /* User ptr */
|
||||||
|
void *, /* Thread ptr */
|
||||||
uint64_t, /* Network ID */
|
uint64_t, /* Network ID */
|
||||||
void **, /* Modifiable network user PTR */
|
void **, /* Modifiable network user PTR */
|
||||||
enum ZT_VirtualNetworkConfigOperation, /* Config operation */
|
enum ZT_VirtualNetworkConfigOperation, /* Config operation */
|
||||||
@@ -1423,6 +1424,7 @@ typedef int (*ZT_VirtualNetworkConfigFunction)(
|
|||||||
typedef void (*ZT_VirtualNetworkFrameFunction)(
|
typedef void (*ZT_VirtualNetworkFrameFunction)(
|
||||||
ZT_Node *, /* Node */
|
ZT_Node *, /* Node */
|
||||||
void *, /* User ptr */
|
void *, /* User ptr */
|
||||||
|
void *, /* Thread ptr */
|
||||||
uint64_t, /* Network ID */
|
uint64_t, /* Network ID */
|
||||||
void **, /* Modifiable network user PTR */
|
void **, /* Modifiable network user PTR */
|
||||||
uint64_t, /* Source MAC */
|
uint64_t, /* Source MAC */
|
||||||
@@ -1442,10 +1444,11 @@ typedef void (*ZT_VirtualNetworkFrameFunction)(
|
|||||||
* in the definition of ZT_Event.
|
* in the definition of ZT_Event.
|
||||||
*/
|
*/
|
||||||
typedef void (*ZT_EventCallback)(
|
typedef void (*ZT_EventCallback)(
|
||||||
ZT_Node *,
|
ZT_Node *, /* Node */
|
||||||
void *,
|
void *, /* User ptr */
|
||||||
enum ZT_Event,
|
void *, /* Thread ptr */
|
||||||
const void *);
|
enum ZT_Event, /* Event type */
|
||||||
|
const void *); /* Event payload (if applicable) */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function to get an object from the data store
|
* Function to get an object from the data store
|
||||||
@@ -1468,8 +1471,9 @@ typedef void (*ZT_EventCallback)(
|
|||||||
* object.
|
* object.
|
||||||
*/
|
*/
|
||||||
typedef long (*ZT_DataStoreGetFunction)(
|
typedef long (*ZT_DataStoreGetFunction)(
|
||||||
ZT_Node *,
|
ZT_Node *, /* Node */
|
||||||
void *,
|
void *, /* User ptr */
|
||||||
|
void *, /* Thread ptr */
|
||||||
const char *,
|
const char *,
|
||||||
void *,
|
void *,
|
||||||
unsigned long,
|
unsigned long,
|
||||||
@@ -1495,6 +1499,7 @@ typedef long (*ZT_DataStoreGetFunction)(
|
|||||||
typedef int (*ZT_DataStorePutFunction)(
|
typedef int (*ZT_DataStorePutFunction)(
|
||||||
ZT_Node *,
|
ZT_Node *,
|
||||||
void *,
|
void *,
|
||||||
|
void *, /* Thread ptr */
|
||||||
const char *,
|
const char *,
|
||||||
const void *,
|
const void *,
|
||||||
unsigned long,
|
unsigned long,
|
||||||
@@ -1529,6 +1534,7 @@ typedef int (*ZT_DataStorePutFunction)(
|
|||||||
typedef int (*ZT_WirePacketSendFunction)(
|
typedef int (*ZT_WirePacketSendFunction)(
|
||||||
ZT_Node *, /* Node */
|
ZT_Node *, /* Node */
|
||||||
void *, /* User ptr */
|
void *, /* User ptr */
|
||||||
|
void *, /* Thread ptr */
|
||||||
const struct sockaddr_storage *, /* Local address */
|
const struct sockaddr_storage *, /* Local address */
|
||||||
const struct sockaddr_storage *, /* Remote address */
|
const struct sockaddr_storage *, /* Remote address */
|
||||||
const void *, /* Packet data */
|
const void *, /* Packet data */
|
||||||
@@ -1562,6 +1568,7 @@ typedef int (*ZT_WirePacketSendFunction)(
|
|||||||
typedef int (*ZT_PathCheckFunction)(
|
typedef int (*ZT_PathCheckFunction)(
|
||||||
ZT_Node *, /* Node */
|
ZT_Node *, /* Node */
|
||||||
void *, /* User ptr */
|
void *, /* User ptr */
|
||||||
|
void *, /* Thread ptr */
|
||||||
uint64_t, /* ZeroTier address */
|
uint64_t, /* ZeroTier address */
|
||||||
const struct sockaddr_storage *, /* Local address */
|
const struct sockaddr_storage *, /* Local address */
|
||||||
const struct sockaddr_storage *); /* Remote address */
|
const struct sockaddr_storage *); /* Remote address */
|
||||||
@@ -1584,6 +1591,7 @@ typedef int (*ZT_PathCheckFunction)(
|
|||||||
typedef int (*ZT_PathLookupFunction)(
|
typedef int (*ZT_PathLookupFunction)(
|
||||||
ZT_Node *, /* Node */
|
ZT_Node *, /* Node */
|
||||||
void *, /* User ptr */
|
void *, /* User ptr */
|
||||||
|
void *, /* Thread ptr */
|
||||||
uint64_t, /* ZeroTier address (40 bits) */
|
uint64_t, /* ZeroTier address (40 bits) */
|
||||||
int, /* Desired ss_family or -1 for any */
|
int, /* Desired ss_family or -1 for any */
|
||||||
struct sockaddr_storage *); /* Result buffer */
|
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 node Result: pointer is set to new node instance on success
|
||||||
* @param uptr User pointer to pass to functions/callbacks
|
* @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 callbacks Callback function configuration
|
||||||
* @param now Current clock in milliseconds
|
* @param now Current clock in milliseconds
|
||||||
* @return OK (0) or error code if a fatal error condition has occurred
|
* @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
|
* 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
|
* Process a packet received from the physical wire
|
||||||
*
|
*
|
||||||
* @param node Node instance
|
* @param node Node instance
|
||||||
|
* @param tptr Thread pointer to pass to functions/callbacks resulting from this call
|
||||||
* @param now Current clock in milliseconds
|
* @param now Current clock in milliseconds
|
||||||
* @param localAddress Local address, or point to ZT_SOCKADDR_NULL if unspecified
|
* @param localAddress Local address, or point to ZT_SOCKADDR_NULL if unspecified
|
||||||
* @param remoteAddress Origin of packet
|
* @param remoteAddress Origin of packet
|
||||||
@@ -1684,6 +1694,7 @@ void ZT_Node_delete(ZT_Node *node);
|
|||||||
*/
|
*/
|
||||||
enum ZT_ResultCode ZT_Node_processWirePacket(
|
enum ZT_ResultCode ZT_Node_processWirePacket(
|
||||||
ZT_Node *node,
|
ZT_Node *node,
|
||||||
|
void *tptr,
|
||||||
uint64_t now,
|
uint64_t now,
|
||||||
const struct sockaddr_storage *localAddress,
|
const struct sockaddr_storage *localAddress,
|
||||||
const struct sockaddr_storage *remoteAddress,
|
const struct sockaddr_storage *remoteAddress,
|
||||||
@@ -1695,6 +1706,7 @@ enum ZT_ResultCode ZT_Node_processWirePacket(
|
|||||||
* Process a frame from a virtual network port (tap)
|
* Process a frame from a virtual network port (tap)
|
||||||
*
|
*
|
||||||
* @param node Node instance
|
* @param node Node instance
|
||||||
|
* @param tptr Thread pointer to pass to functions/callbacks resulting from this call
|
||||||
* @param now Current clock in milliseconds
|
* @param now Current clock in milliseconds
|
||||||
* @param nwid ZeroTier 64-bit virtual network ID
|
* @param nwid ZeroTier 64-bit virtual network ID
|
||||||
* @param sourceMac Source MAC address (least significant 48 bits)
|
* @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(
|
enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame(
|
||||||
ZT_Node *node,
|
ZT_Node *node,
|
||||||
|
void *tptr,
|
||||||
uint64_t now,
|
uint64_t now,
|
||||||
uint64_t nwid,
|
uint64_t nwid,
|
||||||
uint64_t sourceMac,
|
uint64_t sourceMac,
|
||||||
@@ -1722,11 +1735,12 @@ enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame(
|
|||||||
* Perform periodic background operations
|
* Perform periodic background operations
|
||||||
*
|
*
|
||||||
* @param node Node instance
|
* @param node Node instance
|
||||||
|
* @param tptr Thread pointer to pass to functions/callbacks resulting from this call
|
||||||
* @param now Current clock in milliseconds
|
* @param now Current clock in milliseconds
|
||||||
* @param nextBackgroundTaskDeadline Value/result: set to deadline for next call to processBackgroundTasks()
|
* @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
|
* @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
|
* 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)
|
* @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
|
* @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
|
* 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)
|
* @param uptr Target pointer is set to uptr (if not NULL)
|
||||||
* @return OK (0) or error code if a fatal error condition has occurred
|
* @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
|
* 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().
|
* This does not generate an update call to networkConfigCallback().
|
||||||
*
|
*
|
||||||
* @param node Node instance
|
* @param node Node instance
|
||||||
|
* @param tptr Thread pointer to pass to functions/callbacks resulting from this call
|
||||||
* @param nwid 64-bit network ID
|
* @param nwid 64-bit network ID
|
||||||
* @param multicastGroup Ethernet multicast or broadcast MAC (least significant 48 bits)
|
* @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)
|
* @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
|
* @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)
|
* 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
|
* across invocations if the contents of moon.d are scanned and orbit is
|
||||||
* called for each on startup.
|
* 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 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 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
|
* @param len Length of moonWorld in bytes
|
||||||
* @return Error if moon was invalid or failed to be added
|
* @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)
|
* Remove a moon (does nothing if not present)
|
||||||
*
|
*
|
||||||
* @param node Node instance
|
* @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
|
* @param moonWorldId World ID of moon to remove
|
||||||
* @return Error if anything bad happened
|
* @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
|
* 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
|
* There is no delivery guarantee here. Failure can occur if the message is
|
||||||
* too large or if dest is not a valid ZeroTier address.
|
* 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 dest Destination ZeroTier address
|
||||||
* @param typeId VERB_USER_MESSAGE type ID
|
* @param typeId VERB_USER_MESSAGE type ID
|
||||||
* @param data Payload data to attach to user message
|
* @param data Payload data to attach to user message
|
||||||
* @param len Length of data in bytes
|
* @param len Length of data in bytes
|
||||||
* @return Boolean: non-zero on success, zero on failure
|
* @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
|
* 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.
|
* for results forever.
|
||||||
*
|
*
|
||||||
* @param node Node instance
|
* @param node Node instance
|
||||||
|
* @param tptr Thread pointer to pass to functions/callbacks resulting from this call
|
||||||
* @param test Test configuration
|
* @param test Test configuration
|
||||||
* @param reportCallback Function to call each time a report is received
|
* @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
|
* @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
|
* Stop listening for results to a given circuit test
|
||||||
|
|||||||
@@ -96,6 +96,18 @@ endif
|
|||||||
ifeq ($(CC_MACH),arm)
|
ifeq ($(CC_MACH),arm)
|
||||||
ZT_ARCHITECTURE=3
|
ZT_ARCHITECTURE=3
|
||||||
endif
|
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)
|
ifeq ($(CC_MACH),arm64)
|
||||||
ZT_ARCHITECTURE=4
|
ZT_ARCHITECTURE=4
|
||||||
endif
|
endif
|
||||||
@@ -104,6 +116,13 @@ ifeq ($(CC_MACH),aarch64)
|
|||||||
endif
|
endif
|
||||||
DEFS+=-DZT_BUILD_PLATFORM=1 -DZT_BUILD_ARCHITECTURE=$(ZT_ARCHITECTURE) -DZT_SOFTWARE_UPDATE_DEFAULT="\"disable\""
|
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
|
# Define this to build a static binary, which is needed to make this runnable on a few ancient Linux distros
|
||||||
ifeq ($(ZT_STATIC),1)
|
ifeq ($(ZT_STATIC),1)
|
||||||
override LDFLAGS+=-static
|
override LDFLAGS+=-static
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
int Capability::verify(const RuntimeEnvironment *RR) const
|
int Capability::verify(const RuntimeEnvironment *RR,void *tPtr) const
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
// There must be at least one entry, and sanity check for bad chain max length
|
// 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
|
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) {
|
||||||
if (!id.verify(tmp.data(),tmp.size(),_custody[c].signature))
|
if (!id.verify(tmp.data(),tmp.size(),_custody[c].signature))
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
RR->sw->requestWhois(_custody[c].from);
|
RR->sw->requestWhois(tPtr,_custody[c].from);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ public:
|
|||||||
* @param RR Runtime environment to provide for peer lookup, etc.
|
* @param RR Runtime environment to provide for peer lookup, etc.
|
||||||
* @return 0 == OK, 1 == waiting for WHOIS, -1 == BAD signature or chain
|
* @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>
|
template<unsigned int C>
|
||||||
static inline void serializeRules(Buffer<C> &b,const ZT_VirtualNetworkRule *rules,unsigned int ruleCount)
|
static inline void serializeRules(Buffer<C> &b,const ZT_VirtualNetworkRule *rules,unsigned int ruleCount)
|
||||||
|
|||||||
@@ -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))
|
if ((!_signedBy)||(_signedBy != Network::controllerFor(networkId()))||(_qualifierCount > ZT_NETWORK_COM_MAX_QUALIFIERS))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
const Identity id(RR->topology->getIdentity(_signedBy));
|
const Identity id(RR->topology->getIdentity(tPtr,_signedBy));
|
||||||
if (!id) {
|
if (!id) {
|
||||||
RR->sw->requestWhois(_signedBy);
|
RR->sw->requestWhois(tPtr,_signedBy);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -250,9 +250,10 @@ public:
|
|||||||
* Verify this COM and its signature
|
* Verify this COM and its signature
|
||||||
*
|
*
|
||||||
* @param RR Runtime environment for looking up peers
|
* @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
|
* @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
|
* @return True if signed
|
||||||
|
|||||||
@@ -25,13 +25,13 @@
|
|||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
int CertificateOfOwnership::verify(const RuntimeEnvironment *RR) const
|
int CertificateOfOwnership::verify(const RuntimeEnvironment *RR,void *tPtr) const
|
||||||
{
|
{
|
||||||
if ((!_signedBy)||(_signedBy != Network::controllerFor(_networkId)))
|
if ((!_signedBy)||(_signedBy != Network::controllerFor(_networkId)))
|
||||||
return -1;
|
return -1;
|
||||||
const Identity id(RR->topology->getIdentity(_signedBy));
|
const Identity id(RR->topology->getIdentity(tPtr,_signedBy));
|
||||||
if (!id) {
|
if (!id) {
|
||||||
RR->sw->requestWhois(_signedBy);
|
RR->sw->requestWhois(tPtr,_signedBy);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -56,12 +56,9 @@ public:
|
|||||||
THING_IPV6_ADDRESS = 3
|
THING_IPV6_ADDRESS = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
CertificateOfOwnership() :
|
CertificateOfOwnership()
|
||||||
_networkId(0),
|
|
||||||
_ts(0),
|
|
||||||
_id(0),
|
|
||||||
_thingCount(0)
|
|
||||||
{
|
{
|
||||||
|
memset(this,0,sizeof(CertificateOfOwnership));
|
||||||
}
|
}
|
||||||
|
|
||||||
CertificateOfOwnership(const uint64_t nwid,const uint64_t ts,const Address &issuedTo,const uint32_t id) :
|
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 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
|
* @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>
|
template<unsigned int C>
|
||||||
inline void serialize(Buffer<C> &b,const bool forSign = false) const
|
inline void serialize(Buffer<C> &b,const bool forSign = false) const
|
||||||
|
|||||||
@@ -346,7 +346,7 @@ void Cluster::handleIncomingStateMessage(const void *msg,unsigned int len)
|
|||||||
Mutex::Lock _l(_remotePeers_m);
|
Mutex::Lock _l(_remotePeers_m);
|
||||||
_RemotePeer &rp = _remotePeers[std::pair<Address,unsigned int>(id.address(),(unsigned int)fromMemberId)];
|
_RemotePeer &rp = _remotePeers[std::pair<Address,unsigned int>(id.address(),(unsigned int)fromMemberId)];
|
||||||
if (!rp.lastHavePeerReceived) {
|
if (!rp.lastHavePeerReceived) {
|
||||||
RR->topology->saveIdentity(id);
|
RR->topology->saveIdentity((void *)0,id);
|
||||||
RR->identity.agree(id,rp.key,ZT_PEER_SECRET_KEY_LENGTH);
|
RR->identity.agree(id,rp.key,ZT_PEER_SECRET_KEY_LENGTH);
|
||||||
}
|
}
|
||||||
rp.lastHavePeerReceived = RR->node->now();
|
rp.lastHavePeerReceived = RR->node->now();
|
||||||
@@ -459,7 +459,7 @@ void Cluster::handleIncomingStateMessage(const void *msg,unsigned int len)
|
|||||||
Mutex::Lock _l2(_members[fromMemberId].lock);
|
Mutex::Lock _l2(_members[fromMemberId].lock);
|
||||||
_send(fromMemberId,CLUSTER_MESSAGE_PROXY_SEND,rendezvousForRemote.data(),rendezvousForRemote.size());
|
_send(fromMemberId,CLUSTER_MESSAGE_PROXY_SEND,rendezvousForRemote.data(),rendezvousForRemote.size());
|
||||||
}
|
}
|
||||||
RR->sw->send(rendezvousForLocal,true);
|
RR->sw->send((void *)0,rendezvousForLocal,true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} break;
|
} 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;
|
const unsigned int len = dmsg.at<uint16_t>(ptr); ptr += 2;
|
||||||
Packet outp(rcpt,RR->identity.address(),verb);
|
Packet outp(rcpt,RR->identity.address(),verb);
|
||||||
outp.append(dmsg.field(ptr,len),len); ptr += len;
|
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);
|
//TRACE("[%u] proxy send %s to %s length %u",(unsigned int)fromMemberId,Packet::verbString(verb),rcpt.toString().c_str(),len);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
@@ -479,7 +479,7 @@ void Cluster::handleIncomingStateMessage(const void *msg,unsigned int len)
|
|||||||
if (network) {
|
if (network) {
|
||||||
// Copy into a Packet just to conform to Network API. Eventually
|
// Copy into a Packet just to conform to Network API. Eventually
|
||||||
// will want to refactor.
|
// 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;
|
} 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) {
|
for(std::vector<InetAddress>::const_iterator i2(_members[mostRecentMemberId].zeroTierPhysicalEndpoints.begin());i2!=_members[mostRecentMemberId].zeroTierPhysicalEndpoints.end();++i2) {
|
||||||
if (i1->ss_family == i2->ss_family) {
|
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());
|
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;
|
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) {
|
for(std::vector<InetAddress>::const_iterator i2(_members[mostRecentMemberId].zeroTierPhysicalEndpoints.begin());i2!=_members[mostRecentMemberId].zeroTierPhysicalEndpoints.end();++i2) {
|
||||||
if (i1->ss_family == i2->ss_family) {
|
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());
|
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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -981,7 +981,7 @@ void Cluster::_flush(uint16_t memberId)
|
|||||||
void Cluster::_doREMOTE_WHOIS(uint64_t fromMemberId,const Packet &remotep)
|
void Cluster::_doREMOTE_WHOIS(uint64_t fromMemberId,const Packet &remotep)
|
||||||
{
|
{
|
||||||
if (remotep.payloadLength() >= ZT_ADDRESS_LENGTH) {
|
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) {
|
if (queried) {
|
||||||
Buffer<1024> routp;
|
Buffer<1024> routp;
|
||||||
remotep.source().appendTo(routp);
|
remotep.source().appendTo(routp);
|
||||||
|
|||||||
@@ -61,15 +61,23 @@ public:
|
|||||||
|
|
||||||
Dictionary(const char *s)
|
Dictionary(const char *s)
|
||||||
{
|
{
|
||||||
|
if (s) {
|
||||||
Utils::scopy(_d,sizeof(_d),s);
|
Utils::scopy(_d,sizeof(_d),s);
|
||||||
|
} else {
|
||||||
|
_d[0] = (char)0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Dictionary(const char *s,unsigned int len)
|
Dictionary(const char *s,unsigned int len)
|
||||||
{
|
{
|
||||||
|
if (s) {
|
||||||
if (len > (C-1))
|
if (len > (C-1))
|
||||||
len = C-1;
|
len = C-1;
|
||||||
memcpy(_d,s,len);
|
memcpy(_d,s,len);
|
||||||
_d[len] = (char)0;
|
_d[len] = (char)0;
|
||||||
|
} else {
|
||||||
|
_d[0] = (char)0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Dictionary(const Dictionary &d)
|
Dictionary(const Dictionary &d)
|
||||||
@@ -91,7 +99,12 @@ public:
|
|||||||
*/
|
*/
|
||||||
inline bool load(const char *s)
|
inline bool load(const char *s)
|
||||||
{
|
{
|
||||||
|
if (s) {
|
||||||
return Utils::scopy(_d,sizeof(_d),s);
|
return Utils::scopy(_d,sizeof(_d),s);
|
||||||
|
} else {
|
||||||
|
_d[0] = (char)0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -44,7 +44,7 @@
|
|||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR)
|
bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR,void *tPtr)
|
||||||
{
|
{
|
||||||
const Address sourceAddress(source());
|
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)) {
|
} 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
|
// 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 (peer) {
|
||||||
if (!trusted) {
|
if (!trusted) {
|
||||||
if (!dearmor(peer->key())) {
|
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());
|
TRACE("dropped packet from %s(%s), MAC authentication failed (size: %u)",sourceAddress.toString().c_str(),_path->address().toString().c_str(),size());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!uncompress()) {
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,30 +89,30 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR)
|
|||||||
switch(v) {
|
switch(v) {
|
||||||
//case Packet::VERB_NOP:
|
//case Packet::VERB_NOP:
|
||||||
default: // ignore unknown verbs, but if they pass auth check they are "received"
|
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;
|
return true;
|
||||||
|
|
||||||
case Packet::VERB_HELLO: return _doHELLO(RR,true);
|
case Packet::VERB_HELLO: return _doHELLO(RR,tPtr,true);
|
||||||
case Packet::VERB_ERROR: return _doERROR(RR,peer);
|
case Packet::VERB_ERROR: return _doERROR(RR,tPtr,peer);
|
||||||
case Packet::VERB_OK: return _doOK(RR,peer);
|
case Packet::VERB_OK: return _doOK(RR,tPtr,peer);
|
||||||
case Packet::VERB_WHOIS: return _doWHOIS(RR,peer);
|
case Packet::VERB_WHOIS: return _doWHOIS(RR,tPtr,peer);
|
||||||
case Packet::VERB_RENDEZVOUS: return _doRENDEZVOUS(RR,peer);
|
case Packet::VERB_RENDEZVOUS: return _doRENDEZVOUS(RR,tPtr,peer);
|
||||||
case Packet::VERB_FRAME: return _doFRAME(RR,peer);
|
case Packet::VERB_FRAME: return _doFRAME(RR,tPtr,peer);
|
||||||
case Packet::VERB_EXT_FRAME: return _doEXT_FRAME(RR,peer);
|
case Packet::VERB_EXT_FRAME: return _doEXT_FRAME(RR,tPtr,peer);
|
||||||
case Packet::VERB_ECHO: return _doECHO(RR,peer);
|
case Packet::VERB_ECHO: return _doECHO(RR,tPtr,peer);
|
||||||
case Packet::VERB_MULTICAST_LIKE: return _doMULTICAST_LIKE(RR,peer);
|
case Packet::VERB_MULTICAST_LIKE: return _doMULTICAST_LIKE(RR,tPtr,peer);
|
||||||
case Packet::VERB_NETWORK_CREDENTIALS: return _doNETWORK_CREDENTIALS(RR,peer);
|
case Packet::VERB_NETWORK_CREDENTIALS: return _doNETWORK_CREDENTIALS(RR,tPtr,peer);
|
||||||
case Packet::VERB_NETWORK_CONFIG_REQUEST: return _doNETWORK_CONFIG_REQUEST(RR,peer);
|
case Packet::VERB_NETWORK_CONFIG_REQUEST: return _doNETWORK_CONFIG_REQUEST(RR,tPtr,peer);
|
||||||
case Packet::VERB_NETWORK_CONFIG: return _doNETWORK_CONFIG(RR,peer);
|
case Packet::VERB_NETWORK_CONFIG: return _doNETWORK_CONFIG(RR,tPtr,peer);
|
||||||
case Packet::VERB_MULTICAST_GATHER: return _doMULTICAST_GATHER(RR,peer);
|
case Packet::VERB_MULTICAST_GATHER: return _doMULTICAST_GATHER(RR,tPtr,peer);
|
||||||
case Packet::VERB_MULTICAST_FRAME: return _doMULTICAST_FRAME(RR,peer);
|
case Packet::VERB_MULTICAST_FRAME: return _doMULTICAST_FRAME(RR,tPtr,peer);
|
||||||
case Packet::VERB_PUSH_DIRECT_PATHS: return _doPUSH_DIRECT_PATHS(RR,peer);
|
case Packet::VERB_PUSH_DIRECT_PATHS: return _doPUSH_DIRECT_PATHS(RR,tPtr,peer);
|
||||||
case Packet::VERB_CIRCUIT_TEST: return _doCIRCUIT_TEST(RR,peer);
|
case Packet::VERB_CIRCUIT_TEST: return _doCIRCUIT_TEST(RR,tPtr,peer);
|
||||||
case Packet::VERB_CIRCUIT_TEST_REPORT: return _doCIRCUIT_TEST_REPORT(RR,peer);
|
case Packet::VERB_CIRCUIT_TEST_REPORT: return _doCIRCUIT_TEST_REPORT(RR,tPtr,peer);
|
||||||
case Packet::VERB_USER_MESSAGE: return _doUSER_MESSAGE(RR,peer);
|
case Packet::VERB_USER_MESSAGE: return _doUSER_MESSAGE(RR,tPtr,peer);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
RR->sw->requestWhois(sourceAddress);
|
RR->sw->requestWhois(tPtr,sourceAddress);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} catch ( ... ) {
|
} 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 {
|
try {
|
||||||
const Packet::Verb inReVerb = (Packet::Verb)(*this)[ZT_PROTO_VERB_ERROR_IDX_IN_RE_VERB];
|
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:
|
case Packet::ERROR_IDENTITY_COLLISION:
|
||||||
// FIXME: for federation this will need a payload with a signature or something.
|
// FIXME: for federation this will need a payload with a signature or something.
|
||||||
if (RR->topology->isUpstream(peer->identity()))
|
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;
|
break;
|
||||||
|
|
||||||
case Packet::ERROR_NEED_MEMBERSHIP_CERTIFICATE: {
|
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 SharedPtr<Network> network(RR->node->network(at<uint64_t>(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD)));
|
||||||
const uint64_t now = RR->node->now();
|
const uint64_t now = RR->node->now();
|
||||||
if ( (network) && (network->config().com) && (peer->rateGateIncomingComRequest(now)) )
|
if ( (network) && (network->config().com) && (peer->rateGateIncomingComRequest(now)) )
|
||||||
network->pushCredentialsNow(peer->address(),now);
|
network->pushCredentialsNow(tPtr,peer->address(),now);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Packet::ERROR_NETWORK_ACCESS_DENIED_: {
|
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
|
// Members of networks can use this error to indicate that they no longer
|
||||||
// want to receive multicasts on a given channel.
|
// want to receive multicasts on a given channel.
|
||||||
const SharedPtr<Network> network(RR->node->network(at<uint64_t>(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD)));
|
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));
|
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());
|
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());
|
RR->mc->remove(network->id(),mg,peer->address());
|
||||||
@@ -193,14 +195,14 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,const SharedPtr<Peer>
|
|||||||
default: break;
|
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 ( ... ) {
|
} catch ( ... ) {
|
||||||
TRACE("dropped ERROR from %s(%s): unexpected exception",peer->address().toString().c_str(),_path->address().toString().c_str());
|
TRACE("dropped ERROR from %s(%s): unexpected exception",peer->address().toString().c_str(),_path->address().toString().c_str());
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,const bool alreadyAuthenticated)
|
bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool alreadyAuthenticated)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
const uint64_t now = RR->node->now();
|
const uint64_t now = RR->node->now();
|
||||||
@@ -224,7 +226,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,const bool alreadyAut
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedPtr<Peer> peer(RR->topology->getPeer(id.address()));
|
SharedPtr<Peer> peer(RR->topology->getPeer(tPtr,id.address()));
|
||||||
if (peer) {
|
if (peer) {
|
||||||
// We already have an identity with this address -- check for collisions
|
// We already have an identity with this address -- check for collisions
|
||||||
if (!alreadyAuthenticated) {
|
if (!alreadyAuthenticated) {
|
||||||
@@ -244,7 +246,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,const bool alreadyAut
|
|||||||
outp.append((uint64_t)pid);
|
outp.append((uint64_t)pid);
|
||||||
outp.append((uint8_t)Packet::ERROR_IDENTITY_COLLISION);
|
outp.append((uint8_t)Packet::ERROR_IDENTITY_COLLISION);
|
||||||
outp.armor(key,true,_path->nextOutgoingCounter());
|
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 {
|
} else {
|
||||||
TRACE("rejected HELLO from %s(%s): packet failed authentication",id.address().toString().c_str(),_path->address().toString().c_str());
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
peer = RR->topology->addPeer(newPeer);
|
peer = RR->topology->addPeer(tPtr,newPeer);
|
||||||
|
|
||||||
// Continue at // VALID
|
// Continue at // VALID
|
||||||
}
|
}
|
||||||
@@ -302,7 +304,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,const bool alreadyAut
|
|||||||
if (ptr < size()) {
|
if (ptr < size()) {
|
||||||
ptr += externalSurfaceAddress.deserialize(*this,ptr);
|
ptr += externalSurfaceAddress.deserialize(*this,ptr);
|
||||||
if ((externalSurfaceAddress)&&(hops() == 0))
|
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
|
// 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.setAt(corSizeAt,(uint16_t)(outp.size() - (corSizeAt + 2)));
|
||||||
|
|
||||||
outp.armor(peer->key(),true,_path->nextOutgoingCounter());
|
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->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 ( ... ) {
|
} catch ( ... ) {
|
||||||
TRACE("dropped HELLO from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
|
TRACE("dropped HELLO from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
|
||||||
}
|
}
|
||||||
return true;
|
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 {
|
try {
|
||||||
const Packet::Verb inReVerb = (Packet::Verb)(*this)[ZT_PROTO_VERB_OK_IDX_IN_RE_VERB];
|
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) {
|
while (ptr < endOfWorlds) {
|
||||||
World w;
|
World w;
|
||||||
ptr += w.deserialize(*this,ptr);
|
ptr += w.deserialize(*this,ptr);
|
||||||
RR->topology->addWorld(w,false);
|
RR->topology->addWorld(tPtr,w,false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ptr += worldsLen;
|
ptr += worldsLen;
|
||||||
@@ -477,27 +479,31 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &p
|
|||||||
} else ptr += 2;
|
} 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())
|
if (!hops())
|
||||||
peer->addDirectLatencyMeasurment((unsigned int)latency);
|
peer->addDirectLatencyMeasurment((unsigned int)latency);
|
||||||
peer->setRemoteVersion(vProto,vMajor,vMinor,vRevision);
|
peer->setRemoteVersion(vProto,vMajor,vMinor,vRevision);
|
||||||
|
|
||||||
if ((externalSurfaceAddress)&&(hops() == 0))
|
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;
|
} break;
|
||||||
|
|
||||||
case Packet::VERB_WHOIS:
|
case Packet::VERB_WHOIS:
|
||||||
if (RR->topology->isUpstream(peer->identity())) {
|
if (RR->topology->isUpstream(peer->identity())) {
|
||||||
const Identity id(*this,ZT_PROTO_VERB_WHOIS__OK__IDX_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;
|
break;
|
||||||
|
|
||||||
case Packet::VERB_NETWORK_CONFIG_REQUEST: {
|
case Packet::VERB_NETWORK_CONFIG_REQUEST: {
|
||||||
const SharedPtr<Network> network(RR->node->network(at<uint64_t>(ZT_PROTO_VERB_OK_IDX_PAYLOAD)));
|
const SharedPtr<Network> network(RR->node->network(at<uint64_t>(ZT_PROTO_VERB_OK_IDX_PAYLOAD)));
|
||||||
if (network)
|
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;
|
} break;
|
||||||
|
|
||||||
case Packet::VERB_MULTICAST_GATHER: {
|
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));
|
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());
|
//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);
|
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;
|
} break;
|
||||||
|
|
||||||
@@ -526,7 +532,7 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &p
|
|||||||
CertificateOfMembership com;
|
CertificateOfMembership com;
|
||||||
offset += com.deserialize(*this,ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_COM_AND_GATHER_RESULTS);
|
offset += com.deserialize(*this,ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_COM_AND_GATHER_RESULTS);
|
||||||
if (com)
|
if (com)
|
||||||
network->addCredential(com);
|
network->addCredential(tPtr,com);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((flags & 0x02) != 0) {
|
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;
|
offset += ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_COM_AND_GATHER_RESULTS;
|
||||||
unsigned int totalKnown = at<uint32_t>(offset); offset += 4;
|
unsigned int totalKnown = at<uint32_t>(offset); offset += 4;
|
||||||
unsigned int count = at<uint16_t>(offset); offset += 2;
|
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;
|
} break;
|
||||||
@@ -542,14 +548,14 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &p
|
|||||||
default: break;
|
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 ( ... ) {
|
} catch ( ... ) {
|
||||||
TRACE("dropped OK from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
|
TRACE("dropped OK from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
|
||||||
}
|
}
|
||||||
return true;
|
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 {
|
try {
|
||||||
if ((!RR->topology->amRoot())&&(!peer->rateGateInboundWhoisRequest(RR->node->now()))) {
|
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);
|
const Address addr(field(ptr,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH);
|
||||||
ptr += ZT_ADDRESS_LENGTH;
|
ptr += ZT_ADDRESS_LENGTH;
|
||||||
|
|
||||||
const Identity id(RR->topology->getIdentity(addr));
|
const Identity id(RR->topology->getIdentity(tPtr,addr));
|
||||||
if (id) {
|
if (id) {
|
||||||
id.serialize(outp,false);
|
id.serialize(outp,false);
|
||||||
++count;
|
++count;
|
||||||
} else {
|
} else {
|
||||||
// Request unknown WHOIS from upstream from us (if we have one)
|
// Request unknown WHOIS from upstream from us (if we have one)
|
||||||
RR->sw->requestWhois(addr);
|
RR->sw->requestWhois(tPtr,addr);
|
||||||
#ifdef ZT_ENABLE_CLUSTER
|
#ifdef ZT_ENABLE_CLUSTER
|
||||||
// Distribute WHOIS queries across a cluster if we do not know the ID.
|
// 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.
|
// 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) {
|
if (count > 0) {
|
||||||
outp.armor(peer->key(),true,_path->nextOutgoingCounter());
|
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 ( ... ) {
|
} catch ( ... ) {
|
||||||
TRACE("dropped WHOIS from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
|
TRACE("dropped WHOIS from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
|
||||||
}
|
}
|
||||||
return true;
|
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 {
|
try {
|
||||||
if (!RR->topology->isUpstream(peer->identity())) {
|
if (!RR->topology->isUpstream(peer->identity())) {
|
||||||
TRACE("RENDEZVOUS from %s ignored since source is not upstream",peer->address().toString().c_str());
|
TRACE("RENDEZVOUS from %s ignored since source is not upstream",peer->address().toString().c_str());
|
||||||
} else {
|
} else {
|
||||||
const Address with(field(ZT_PROTO_VERB_RENDEZVOUS_IDX_ZTADDRESS,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH);
|
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) {
|
if (rendezvousWith) {
|
||||||
const unsigned int port = at<uint16_t>(ZT_PROTO_VERB_RENDEZVOUS_IDX_PORT);
|
const unsigned int port = at<uint16_t>(ZT_PROTO_VERB_RENDEZVOUS_IDX_PORT);
|
||||||
const unsigned int addrlen = (*this)[ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRLEN];
|
const unsigned int addrlen = (*this)[ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRLEN];
|
||||||
if ((port > 0)&&((addrlen == 4)||(addrlen == 16))) {
|
if ((port > 0)&&((addrlen == 4)||(addrlen == 16))) {
|
||||||
const InetAddress atAddr(field(ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRESS,addrlen),addrlen,port);
|
const InetAddress atAddr(field(ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRESS,addrlen),addrlen,port);
|
||||||
if (RR->node->shouldUsePathForZeroTierTraffic(with,_path->localAddress(),atAddr)) {
|
if (RR->node->shouldUsePathForZeroTierTraffic(tPtr,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
|
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(_path->localAddress(),atAddr,RR->node->now(),false,0);
|
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());
|
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 {
|
} 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());
|
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());
|
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 ( ... ) {
|
} catch ( ... ) {
|
||||||
TRACE("dropped RENDEZVOUS from %s(%s): unexpected exception",peer->address().toString().c_str(),_path->address().toString().c_str());
|
TRACE("dropped RENDEZVOUS from %s(%s): unexpected exception",peer->address().toString().c_str(),_path->address().toString().c_str());
|
||||||
}
|
}
|
||||||
return true;
|
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 {
|
try {
|
||||||
const uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID);
|
const uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID);
|
||||||
const SharedPtr<Network> network(RR->node->network(nwid));
|
const SharedPtr<Network> network(RR->node->network(nwid));
|
||||||
bool trustEstablished = false;
|
bool trustEstablished = false;
|
||||||
if (network) {
|
if (network) {
|
||||||
if (network->gate(peer)) {
|
if (network->gate(tPtr,peer)) {
|
||||||
trustEstablished = true;
|
trustEstablished = true;
|
||||||
if (size() > ZT_PROTO_VERB_FRAME_IDX_PAYLOAD) {
|
if (size() > ZT_PROTO_VERB_FRAME_IDX_PAYLOAD) {
|
||||||
const unsigned int etherType = at<uint16_t>(ZT_PROTO_VERB_FRAME_IDX_ETHERTYPE);
|
const unsigned int etherType = at<uint16_t>(ZT_PROTO_VERB_FRAME_IDX_ETHERTYPE);
|
||||||
const MAC sourceMac(peer->address(),nwid);
|
const MAC sourceMac(peer->address(),nwid);
|
||||||
const unsigned int frameLen = size() - ZT_PROTO_VERB_FRAME_IDX_PAYLOAD;
|
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;
|
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)
|
if (network->filterIncomingPacket(tPtr,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);
|
RR->node->putFrame(tPtr,nwid,network->userPtr(),sourceMac,network->mac(),etherType,0,(const void *)frameData,frameLen);
|
||||||
}
|
}
|
||||||
} else {
|
} 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());
|
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 {
|
} 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));
|
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 ( ... ) {
|
} catch ( ... ) {
|
||||||
TRACE("dropped FRAME from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
|
TRACE("dropped FRAME from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
|
||||||
}
|
}
|
||||||
return true;
|
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 {
|
try {
|
||||||
const uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_EXT_FRAME_IDX_NETWORK_ID);
|
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;
|
CertificateOfMembership com;
|
||||||
comLen = com.deserialize(*this,ZT_PROTO_VERB_EXT_FRAME_IDX_COM);
|
comLen = com.deserialize(*this,ZT_PROTO_VERB_EXT_FRAME_IDX_COM);
|
||||||
if (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());
|
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);
|
_sendErrorNeedCredentials(RR,tPtr,peer,nwid);
|
||||||
peer->received(_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,false);
|
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -693,36 +699,36 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,const SharedPtr<P
|
|||||||
|
|
||||||
if ((!from)||(from.isMulticast())||(from == network->mac())) {
|
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());
|
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;
|
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:
|
case 1:
|
||||||
if (from != MAC(peer->address(),nwid)) {
|
if (from != MAC(peer->address(),nwid)) {
|
||||||
if (network->config().permitsBridging(peer->address())) {
|
if (network->config().permitsBridging(peer->address())) {
|
||||||
network->learnBridgeRoute(from,peer->address());
|
network->learnBridgeRoute(from,peer->address());
|
||||||
} else {
|
} 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());
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (to != network->mac()) {
|
} else if (to != network->mac()) {
|
||||||
if (to.isMulticast()) {
|
if (to.isMulticast()) {
|
||||||
if (network->config().multicastLimit == 0) {
|
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());
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (!network->config().permitsBridging(RR->identity.address())) {
|
} 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());
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// fall through -- 2 means accept regardless of bridging checks or other restrictions
|
// fall through -- 2 means accept regardless of bridging checks or other restrictions
|
||||||
case 2:
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -733,14 +739,14 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,const SharedPtr<P
|
|||||||
outp.append((uint64_t)packetId());
|
outp.append((uint64_t)packetId());
|
||||||
outp.append((uint64_t)nwid);
|
outp.append((uint64_t)nwid);
|
||||||
outp.armor(peer->key(),true,_path->nextOutgoingCounter());
|
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 {
|
} 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));
|
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);
|
_sendErrorNeedCredentials(RR,tPtr,peer,nwid);
|
||||||
peer->received(_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,false);
|
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,false);
|
||||||
}
|
}
|
||||||
} catch ( ... ) {
|
} catch ( ... ) {
|
||||||
TRACE("dropped EXT_FRAME from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
|
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;
|
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 {
|
try {
|
||||||
if (!peer->rateGateEchoRequest(RR->node->now())) {
|
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)
|
if (size() > ZT_PACKET_IDX_PAYLOAD)
|
||||||
outp.append(reinterpret_cast<const unsigned char *>(data()) + ZT_PACKET_IDX_PAYLOAD,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());
|
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 ( ... ) {
|
} catch ( ... ) {
|
||||||
TRACE("dropped ECHO from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
|
TRACE("dropped ECHO from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
|
||||||
}
|
}
|
||||||
return true;
|
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 {
|
try {
|
||||||
const uint64_t now = RR->node->now();
|
const uint64_t now = RR->node->now();
|
||||||
@@ -796,9 +802,9 @@ bool IncomingPacket::_doMULTICAST_LIKE(const RuntimeEnvironment *RR,const Shared
|
|||||||
if (!auth) {
|
if (!auth) {
|
||||||
if ((!network)||(network->id() != nwid))
|
if ((!network)||(network->id() != nwid))
|
||||||
network = RR->node->network(nwid);
|
network = RR->node->network(nwid);
|
||||||
const bool authOnNet = ((network)&&(network->gate(peer)));
|
const bool authOnNet = ((network)&&(network->gate(tPtr,peer)));
|
||||||
if (!authOnNet)
|
if (!authOnNet)
|
||||||
_sendErrorNeedCredentials(RR,peer,nwid);
|
_sendErrorNeedCredentials(RR,tPtr,peer,nwid);
|
||||||
trustEstablished |= authOnNet;
|
trustEstablished |= authOnNet;
|
||||||
if (authOnNet||RR->mc->cacheAuthorized(peer->address(),nwid,now)) {
|
if (authOnNet||RR->mc->cacheAuthorized(peer->address(),nwid,now)) {
|
||||||
auth = true;
|
auth = true;
|
||||||
@@ -809,18 +815,18 @@ bool IncomingPacket::_doMULTICAST_LIKE(const RuntimeEnvironment *RR,const Shared
|
|||||||
|
|
||||||
if (auth) {
|
if (auth) {
|
||||||
const MulticastGroup group(MAC(field(ptr + 8,6),6),at<uint32_t>(ptr + 14));
|
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 ( ... ) {
|
} catch ( ... ) {
|
||||||
TRACE("dropped MULTICAST_LIKE from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
|
TRACE("dropped MULTICAST_LIKE from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
|
||||||
}
|
}
|
||||||
return true;
|
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 {
|
try {
|
||||||
if (!peer->rateGateCredentialsReceived(RR->node->now())) {
|
if (!peer->rateGateCredentialsReceived(RR->node->now())) {
|
||||||
@@ -836,12 +842,12 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const S
|
|||||||
bool trustEstablished = false;
|
bool trustEstablished = false;
|
||||||
|
|
||||||
unsigned int p = ZT_PACKET_IDX_PAYLOAD;
|
unsigned int p = ZT_PACKET_IDX_PAYLOAD;
|
||||||
while ((p < size())&&((*this)[p])) {
|
while ((p < size())&&((*this)[p] != 0)) {
|
||||||
p += com.deserialize(*this,p);
|
p += com.deserialize(*this,p);
|
||||||
if (com) {
|
if (com) {
|
||||||
const SharedPtr<Network> network(RR->node->network(com.networkId()));
|
const SharedPtr<Network> network(RR->node->network(com.networkId()));
|
||||||
if (network) {
|
if (network) {
|
||||||
switch (network->addCredential(com)) {
|
switch (network->addCredential(tPtr,com)) {
|
||||||
case Membership::ADD_REJECTED:
|
case Membership::ADD_REJECTED:
|
||||||
break;
|
break;
|
||||||
case Membership::ADD_ACCEPTED_NEW:
|
case Membership::ADD_ACCEPTED_NEW:
|
||||||
@@ -851,7 +857,7 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const S
|
|||||||
case Membership::ADD_DEFERRED_FOR_WHOIS:
|
case Membership::ADD_DEFERRED_FOR_WHOIS:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else RR->mc->addCredential(com,false);
|
} else RR->mc->addCredential(tPtr,com,false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
++p; // skip trailing 0 after COMs if present
|
++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);
|
p += cap.deserialize(*this,p);
|
||||||
const SharedPtr<Network> network(RR->node->network(cap.networkId()));
|
const SharedPtr<Network> network(RR->node->network(cap.networkId()));
|
||||||
if (network) {
|
if (network) {
|
||||||
switch (network->addCredential(cap)) {
|
switch (network->addCredential(tPtr,cap)) {
|
||||||
case Membership::ADD_REJECTED:
|
case Membership::ADD_REJECTED:
|
||||||
break;
|
break;
|
||||||
case Membership::ADD_ACCEPTED_NEW:
|
case Membership::ADD_ACCEPTED_NEW:
|
||||||
@@ -882,7 +888,7 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const S
|
|||||||
p += tag.deserialize(*this,p);
|
p += tag.deserialize(*this,p);
|
||||||
const SharedPtr<Network> network(RR->node->network(tag.networkId()));
|
const SharedPtr<Network> network(RR->node->network(tag.networkId()));
|
||||||
if (network) {
|
if (network) {
|
||||||
switch (network->addCredential(tag)) {
|
switch (network->addCredential(tPtr,tag)) {
|
||||||
case Membership::ADD_REJECTED:
|
case Membership::ADD_REJECTED:
|
||||||
break;
|
break;
|
||||||
case Membership::ADD_ACCEPTED_NEW:
|
case Membership::ADD_ACCEPTED_NEW:
|
||||||
@@ -902,7 +908,7 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const S
|
|||||||
p += revocation.deserialize(*this,p);
|
p += revocation.deserialize(*this,p);
|
||||||
const SharedPtr<Network> network(RR->node->network(revocation.networkId()));
|
const SharedPtr<Network> network(RR->node->network(revocation.networkId()));
|
||||||
if (network) {
|
if (network) {
|
||||||
switch(network->addCredential(peer->address(),revocation)) {
|
switch(network->addCredential(tPtr,peer->address(),revocation)) {
|
||||||
case Membership::ADD_REJECTED:
|
case Membership::ADD_REJECTED:
|
||||||
break;
|
break;
|
||||||
case Membership::ADD_ACCEPTED_NEW:
|
case Membership::ADD_ACCEPTED_NEW:
|
||||||
@@ -922,7 +928,7 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const S
|
|||||||
p += coo.deserialize(*this,p);
|
p += coo.deserialize(*this,p);
|
||||||
const SharedPtr<Network> network(RR->node->network(coo.networkId()));
|
const SharedPtr<Network> network(RR->node->network(coo.networkId()));
|
||||||
if (network) {
|
if (network) {
|
||||||
switch(network->addCredential(coo)) {
|
switch(network->addCredential(tPtr,coo)) {
|
||||||
case Membership::ADD_REJECTED:
|
case Membership::ADD_REJECTED:
|
||||||
break;
|
break;
|
||||||
case Membership::ADD_ACCEPTED_NEW:
|
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) {
|
} 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());
|
TRACE("dropped NETWORK_CREDENTIALS from %s(%s): %s",source().toString().c_str(),_path->address().toString().c_str(),exc.what());
|
||||||
} catch ( ... ) {
|
} 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;
|
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 {
|
try {
|
||||||
const uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_NETWORK_ID);
|
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();
|
const uint64_t requestPacketId = packetId();
|
||||||
|
|
||||||
if (RR->localNetworkController) {
|
if (RR->localNetworkController) {
|
||||||
const unsigned int metaDataLength = at<uint16_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT_LEN);
|
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 = (const char *)field(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT,metaDataLength);
|
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);
|
const Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> metaData(metaDataBytes,metaDataLength);
|
||||||
RR->localNetworkController->request(nwid,(hopCount > 0) ? InetAddress() : _path->address(),requestPacketId,peer->identity(),metaData);
|
RR->localNetworkController->request(nwid,(hopCount > 0) ? InetAddress() : _path->address(),requestPacketId,peer->identity(),metaData);
|
||||||
} else {
|
} else {
|
||||||
@@ -964,26 +972,26 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons
|
|||||||
outp.append((unsigned char)Packet::ERROR_UNSUPPORTED_OPERATION);
|
outp.append((unsigned char)Packet::ERROR_UNSUPPORTED_OPERATION);
|
||||||
outp.append(nwid);
|
outp.append(nwid);
|
||||||
outp.armor(peer->key(),true,_path->nextOutgoingCounter());
|
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) {
|
} 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());
|
TRACE("dropped NETWORK_CONFIG_REQUEST from %s(%s): %s",source().toString().c_str(),_path->address().toString().c_str(),exc.what());
|
||||||
} catch ( ... ) {
|
} 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());
|
TRACE("dropped NETWORK_CONFIG_REQUEST from %s(%s): unknown exception",source().toString().c_str(),_path->address().toString().c_str());
|
||||||
}
|
}
|
||||||
return true;
|
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 {
|
try {
|
||||||
const SharedPtr<Network> network(RR->node->network(at<uint64_t>(ZT_PACKET_IDX_PAYLOAD)));
|
const SharedPtr<Network> network(RR->node->network(at<uint64_t>(ZT_PACKET_IDX_PAYLOAD)));
|
||||||
if (network) {
|
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) {
|
if (configUpdateId) {
|
||||||
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_OK);
|
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_OK);
|
||||||
outp.append((uint8_t)Packet::VERB_ECHO);
|
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)network->id());
|
||||||
outp.append((uint64_t)configUpdateId);
|
outp.append((uint64_t)configUpdateId);
|
||||||
outp.armor(peer->key(),true,_path->nextOutgoingCounter());
|
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 ( ... ) {
|
} catch ( ... ) {
|
||||||
TRACE("dropped NETWORK_CONFIG_REFRESH from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
|
TRACE("dropped NETWORK_CONFIG_REFRESH from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
|
||||||
}
|
}
|
||||||
return true;
|
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 {
|
try {
|
||||||
const uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_MULTICAST_GATHER_IDX_NETWORK_ID);
|
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);
|
com.deserialize(*this,ZT_PROTO_VERB_MULTICAST_GATHER_IDX_COM);
|
||||||
if (com) {
|
if (com) {
|
||||||
if (network)
|
if (network)
|
||||||
network->addCredential(com);
|
network->addCredential(tPtr,com);
|
||||||
else RR->mc->addCredential(com,false);
|
else RR->mc->addCredential(tPtr,com,false);
|
||||||
}
|
}
|
||||||
} catch ( ... ) {
|
} catch ( ... ) {
|
||||||
TRACE("MULTICAST_GATHER from %s(%s): discarded invalid COM",peer->address().toString().c_str(),_path->address().toString().c_str());
|
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)
|
if (!trustEstablished)
|
||||||
_sendErrorNeedCredentials(RR,peer,nwid);
|
_sendErrorNeedCredentials(RR,tPtr,peer,nwid);
|
||||||
if ( ( trustEstablished || RR->mc->cacheAuthorized(peer->address(),nwid,RR->node->now()) ) && (gatherLimit > 0) ) {
|
if ( ( trustEstablished || RR->mc->cacheAuthorized(peer->address(),nwid,RR->node->now()) ) && (gatherLimit > 0) ) {
|
||||||
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_OK);
|
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_OK);
|
||||||
outp.append((unsigned char)Packet::VERB_MULTICAST_GATHER);
|
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);
|
const unsigned int gatheredLocally = RR->mc->gather(peer->address(),nwid,mg,outp,gatherLimit);
|
||||||
if (gatheredLocally > 0) {
|
if (gatheredLocally > 0) {
|
||||||
outp.armor(peer->key(),true,_path->nextOutgoingCounter());
|
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
|
// 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
|
#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 ( ... ) {
|
} catch ( ... ) {
|
||||||
TRACE("dropped MULTICAST_GATHER from %s(%s): unexpected exception",peer->address().toString().c_str(),_path->address().toString().c_str());
|
TRACE("dropped MULTICAST_GATHER from %s(%s): unexpected exception",peer->address().toString().c_str(),_path->address().toString().c_str());
|
||||||
}
|
}
|
||||||
return true;
|
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 {
|
try {
|
||||||
const uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID);
|
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;
|
CertificateOfMembership com;
|
||||||
offset += com.deserialize(*this,ZT_PROTO_VERB_MULTICAST_FRAME_IDX_COM);
|
offset += com.deserialize(*this,ZT_PROTO_VERB_MULTICAST_FRAME_IDX_COM);
|
||||||
if (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());
|
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);
|
_sendErrorNeedCredentials(RR,tPtr,peer,nwid);
|
||||||
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (network->config().multicastLimit == 0) {
|
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());
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1112,12 +1120,12 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,const Share
|
|||||||
if ((frameLen > 0)&&(frameLen <= ZT_IF_MTU)) {
|
if ((frameLen > 0)&&(frameLen <= ZT_IF_MTU)) {
|
||||||
if (!to.mac().isMulticast()) {
|
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());
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
if ((!from)||(from.isMulticast())||(from == network->mac())) {
|
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());
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1126,14 +1134,14 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,const Share
|
|||||||
network->learnBridgeRoute(from,peer->address());
|
network->learnBridgeRoute(from,peer->address());
|
||||||
} else {
|
} 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());
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t *const frameData = (const uint8_t *)field(offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME,frameLen);
|
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) {
|
if (network->filterIncomingPacket(tPtr,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);
|
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
|
outp.append((unsigned char)0x02); // flag 0x02 = contains gather results
|
||||||
if (RR->mc->gather(peer->address(),nwid,to,outp,gatherLimit)) {
|
if (RR->mc->gather(peer->address(),nwid,to,outp,gatherLimit)) {
|
||||||
outp.armor(peer->key(),true,_path->nextOutgoingCounter());
|
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 {
|
} else {
|
||||||
_sendErrorNeedCredentials(RR,peer,nwid);
|
_sendErrorNeedCredentials(RR,tPtr,peer,nwid);
|
||||||
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);
|
||||||
}
|
}
|
||||||
} catch ( ... ) {
|
} catch ( ... ) {
|
||||||
TRACE("dropped MULTICAST_FRAME from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
|
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;
|
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 {
|
try {
|
||||||
const uint64_t now = RR->node->now();
|
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
|
// First, subject this to a rate limit
|
||||||
if (!peer->rateGatePushDirectPaths(now)) {
|
if (!peer->rateGatePushDirectPaths(now)) {
|
||||||
TRACE("dropped PUSH_DIRECT_PATHS from %s(%s): circuit breaker tripped",source().toString().c_str(),_path->address().toString().c_str());
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1201,10 +1209,10 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,const Sha
|
|||||||
redundant = peer->hasActivePathTo(now,a);
|
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) {
|
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());
|
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 {
|
} else {
|
||||||
TRACE("ignoring contact for %s at %s -- too many per scope",peer->address().toString().c_str(),a.toString().c_str());
|
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);
|
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) {
|
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());
|
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 {
|
} else {
|
||||||
TRACE("ignoring contact for %s at %s -- too many per scope",peer->address().toString().c_str(),a.toString().c_str());
|
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;
|
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 ( ... ) {
|
} catch ( ... ) {
|
||||||
TRACE("dropped PUSH_DIRECT_PATHS from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
|
TRACE("dropped PUSH_DIRECT_PATHS from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
|
||||||
}
|
}
|
||||||
return true;
|
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 {
|
try {
|
||||||
const Address originatorAddress(field(ZT_PACKET_IDX_PAYLOAD,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH);
|
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) {
|
if (!originator) {
|
||||||
RR->sw->requestWhois(originatorAddress);
|
RR->sw->requestWhois(tPtr,originatorAddress);
|
||||||
return false;
|
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);
|
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)) {
|
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());
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
vlf += signatureLength;
|
vlf += signatureLength;
|
||||||
@@ -1296,14 +1304,14 @@ bool IncomingPacket::_doCIRCUIT_TEST(const RuntimeEnvironment *RR,const SharedPt
|
|||||||
SharedPtr<Network> network(RR->node->network(originatorCredentialNetworkId));
|
SharedPtr<Network> network(RR->node->network(originatorCredentialNetworkId));
|
||||||
if ((!network)||(!network->config().circuitTestingAllowed(originatorAddress))) {
|
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);
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
if (network->gate(peer))
|
if (network->gate(tPtr,peer))
|
||||||
reportFlags |= ZT_CIRCUIT_TEST_REPORT_FLAGS_UPSTREAM_AUTHORIZED_IN_PATH;
|
reportFlags |= ZT_CIRCUIT_TEST_REPORT_FLAGS_UPSTREAM_AUTHORIZED_IN_PATH;
|
||||||
} else {
|
} 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());
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1319,7 +1327,7 @@ bool IncomingPacket::_doCIRCUIT_TEST(const RuntimeEnvironment *RR,const SharedPt
|
|||||||
for(unsigned int h=0;h<breadth;++h) {
|
for(unsigned int h=0;h<breadth;++h) {
|
||||||
nextHop[h].setTo(field(remainingHopsPtr,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH);
|
nextHop[h].setTo(field(remainingHopsPtr,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH);
|
||||||
remainingHopsPtr += 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) {
|
if (nhp) {
|
||||||
SharedPtr<Path> nhbp(nhp->getBestPath(now,false));
|
SharedPtr<Path> nhbp(nhp->getBestPath(now,false));
|
||||||
if ((nhbp)&&(nhbp->alive(now)))
|
if ((nhbp)&&(nhbp->alive(now)))
|
||||||
@@ -1354,7 +1362,7 @@ bool IncomingPacket::_doCIRCUIT_TEST(const RuntimeEnvironment *RR,const SharedPt
|
|||||||
nextHop[h].appendTo(outp);
|
nextHop[h].appendTo(outp);
|
||||||
nextHopBestPathAddress[h].serialize(outp); // appends 0 if null InetAddress
|
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
|
// 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
|
if (RR->identity.address() != nextHop[h]) { // next hops that loop back to the current hop are not valid
|
||||||
outp.newInitializationVector();
|
outp.newInitializationVector();
|
||||||
outp.setDestination(nextHop[h]);
|
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 ( ... ) {
|
} catch ( ... ) {
|
||||||
TRACE("dropped CIRCUIT_TEST from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
|
TRACE("dropped CIRCUIT_TEST from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
|
||||||
}
|
}
|
||||||
return true;
|
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 {
|
try {
|
||||||
ZT_CircuitTestReport report;
|
ZT_CircuitTestReport report;
|
||||||
@@ -1423,14 +1431,14 @@ bool IncomingPacket::_doCIRCUIT_TEST_REPORT(const RuntimeEnvironment *RR,const S
|
|||||||
|
|
||||||
RR->node->postCircuitTestReport(&report);
|
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 ( ... ) {
|
} catch ( ... ) {
|
||||||
TRACE("dropped CIRCUIT_TEST_REPORT from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
|
TRACE("dropped CIRCUIT_TEST_REPORT from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
|
||||||
}
|
}
|
||||||
return true;
|
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 {
|
try {
|
||||||
if (size() >= (ZT_PACKET_IDX_PAYLOAD + 8)) {
|
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.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.data = reinterpret_cast<const void *>(reinterpret_cast<const uint8_t *>(data()) + ZT_PACKET_IDX_PAYLOAD + 8);
|
||||||
um.length = size() - (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 ( ... ) {
|
} catch ( ... ) {
|
||||||
TRACE("dropped CIRCUIT_TEST_REPORT from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
|
TRACE("dropped CIRCUIT_TEST_REPORT from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
|
||||||
}
|
}
|
||||||
return true;
|
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();
|
const uint64_t now = RR->node->now();
|
||||||
if (peer->rateGateOutgoingComRequest(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((uint8_t)Packet::ERROR_NEED_MEMBERSHIP_CERTIFICATE);
|
||||||
outp.append(nwid);
|
outp.append(nwid);
|
||||||
outp.armor(peer->key(),true,_path->nextOutgoingCounter());
|
outp.armor(peer->key(),true,_path->nextOutgoingCounter());
|
||||||
_path->send(RR,outp.data(),outp.size(),now);
|
_path->send(RR,tPtr,outp.data(),outp.size(),now);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -102,9 +102,10 @@ public:
|
|||||||
* may no longer be valid.
|
* may no longer be valid.
|
||||||
*
|
*
|
||||||
* @param RR Runtime environment
|
* @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
|
* @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
|
* @return Time of packet receipt / start of decode
|
||||||
@@ -114,26 +115,26 @@ public:
|
|||||||
private:
|
private:
|
||||||
// These are called internally to handle packet contents once it has
|
// These are called internally to handle packet contents once it has
|
||||||
// been authenticated, decrypted, decompressed, and classified.
|
// been authenticated, decrypted, decompressed, and classified.
|
||||||
bool _doERROR(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
|
bool _doERROR(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||||
bool _doHELLO(const RuntimeEnvironment *RR,const bool alreadyAuthenticated);
|
bool _doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool alreadyAuthenticated);
|
||||||
bool _doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
|
bool _doOK(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||||
bool _doWHOIS(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
|
bool _doWHOIS(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||||
bool _doRENDEZVOUS(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
|
bool _doRENDEZVOUS(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||||
bool _doFRAME(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
|
bool _doFRAME(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||||
bool _doEXT_FRAME(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
|
bool _doEXT_FRAME(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||||
bool _doECHO(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
|
bool _doECHO(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||||
bool _doMULTICAST_LIKE(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
|
bool _doMULTICAST_LIKE(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||||
bool _doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
|
bool _doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||||
bool _doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
|
bool _doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||||
bool _doNETWORK_CONFIG(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
|
bool _doNETWORK_CONFIG(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||||
bool _doMULTICAST_GATHER(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
|
bool _doMULTICAST_GATHER(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||||
bool _doMULTICAST_FRAME(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
|
bool _doMULTICAST_FRAME(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||||
bool _doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
|
bool _doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||||
bool _doCIRCUIT_TEST(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
|
bool _doCIRCUIT_TEST(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||||
bool _doCIRCUIT_TEST_REPORT(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
|
bool _doCIRCUIT_TEST_REPORT(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||||
bool _doUSER_MESSAGE(const RuntimeEnvironment *RR,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;
|
uint64_t _receiveTime;
|
||||||
SharedPtr<Path> _path;
|
SharedPtr<Path> _path;
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ Membership::Membership() :
|
|||||||
for(unsigned int i=0;i<ZT_MAX_CERTIFICATES_OF_OWNERSHIP;++i) _remoteCoos[i] = &(_cooMem[i]);
|
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) ) );
|
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.setAt(cooCountAt,(uint16_t)thisPacketCooCount);
|
||||||
|
|
||||||
outp.compress();
|
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);
|
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;
|
const uint64_t newts = com.timestamp().first;
|
||||||
if (newts <= _comRevocationThreshold) {
|
if (newts <= _comRevocationThreshold) {
|
||||||
@@ -141,7 +141,7 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
|
|||||||
return ADD_ACCEPTED_REDUNDANT;
|
return ADD_ACCEPTED_REDUNDANT;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(com.verify(RR)) {
|
switch(com.verify(RR,tPtr)) {
|
||||||
default:
|
default:
|
||||||
TRACE("addCredential(CertificateOfMembership) for %s on %.16llx REJECTED (invalid signature or object)",com.issuedTo().toString().c_str(),com.networkId());
|
TRACE("addCredential(CertificateOfMembership) for %s on %.16llx REJECTED (invalid signature or object)",com.issuedTo().toString().c_str(),com.networkId());
|
||||||
return ADD_REJECTED;
|
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> *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;
|
_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:
|
default:
|
||||||
TRACE("addCredential(Tag) for %s on %.16llx REJECTED (invalid)",tag.issuedTo().toString().c_str(),tag.networkId());
|
TRACE("addCredential(Tag) for %s on %.16llx REJECTED (invalid)",tag.issuedTo().toString().c_str(),tag.networkId());
|
||||||
return ADD_REJECTED;
|
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> *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;
|
_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:
|
default:
|
||||||
TRACE("addCredential(Capability) for %s on %.16llx REJECTED (invalid)",cap.issuedTo().toString().c_str(),cap.networkId());
|
TRACE("addCredential(Capability) for %s on %.16llx REJECTED (invalid)",cap.issuedTo().toString().c_str(),cap.networkId());
|
||||||
return ADD_REJECTED;
|
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:
|
default:
|
||||||
return ADD_REJECTED;
|
return ADD_REJECTED;
|
||||||
case 0: {
|
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> *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;
|
_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:
|
default:
|
||||||
TRACE("addCredential(CertificateOfOwnership) for %s on %.16llx REJECTED (invalid)",coo.issuedTo().toString().c_str(),coo.networkId());
|
TRACE("addCredential(CertificateOfOwnership) for %s on %.16llx REJECTED (invalid)",coo.issuedTo().toString().c_str(),coo.networkId());
|
||||||
return ADD_REJECTED;
|
return ADD_REJECTED;
|
||||||
|
|||||||
@@ -158,13 +158,14 @@ public:
|
|||||||
* sends VERB_NETWORK_CREDENTIALS if the recipient might need them.
|
* sends VERB_NETWORK_CREDENTIALS if the recipient might need them.
|
||||||
*
|
*
|
||||||
* @param RR Runtime environment
|
* @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 now Current time
|
||||||
* @param peerAddress Address of member peer (the one that this Membership describes)
|
* @param peerAddress Address of member peer (the one that this Membership describes)
|
||||||
* @param nconf My network config
|
* @param nconf My network config
|
||||||
* @param localCapabilityIndex Index of local capability to include (in nconf.capabilities[]) or -1 if none
|
* @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
|
* @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
|
* 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
|
* 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
|
* 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
|
* 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
|
* 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
|
* 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:
|
private:
|
||||||
_RemoteCredential<Tag> *_newTag(const uint64_t id);
|
_RemoteCredential<Tag> *_newTag(const uint64_t id);
|
||||||
|
|||||||
@@ -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 *p = (const unsigned char *)addresses;
|
||||||
const unsigned char *e = p + (5 * count);
|
const unsigned char *e = p + (5 * count);
|
||||||
Mutex::Lock _l(_groups_m);
|
Mutex::Lock _l(_groups_m);
|
||||||
MulticastGroupStatus &gs = _groups[Multicaster::Key(nwid,mg)];
|
MulticastGroupStatus &gs = _groups[Multicaster::Key(nwid,mg)];
|
||||||
while (p != e) {
|
while (p != e) {
|
||||||
_add(now,nwid,mg,gs,Address(p,5));
|
_add(tPtr,now,nwid,mg,gs,Address(p,5));
|
||||||
p += 5;
|
p += 5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -152,6 +152,7 @@ std::vector<Address> Multicaster::getMembers(uint64_t nwid,const MulticastGroup
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Multicaster::send(
|
void Multicaster::send(
|
||||||
|
void *tPtr,
|
||||||
unsigned int limit,
|
unsigned int limit,
|
||||||
uint64_t now,
|
uint64_t now,
|
||||||
uint64_t nwid,
|
uint64_t nwid,
|
||||||
@@ -207,7 +208,7 @@ void Multicaster::send(
|
|||||||
|
|
||||||
for(std::vector<Address>::const_iterator ast(alwaysSendTo.begin());ast!=alwaysSendTo.end();++ast) {
|
for(std::vector<Address>::const_iterator ast(alwaysSendTo.begin());ast!=alwaysSendTo.end();++ast) {
|
||||||
if (*ast != RR->identity.address()) {
|
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)
|
if (++count >= limit)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -217,7 +218,7 @@ void Multicaster::send(
|
|||||||
while ((count < limit)&&(idx < gs.members.size())) {
|
while ((count < limit)&&(idx < gs.members.size())) {
|
||||||
Address ma(gs.members[indexes[idx++]].address);
|
Address ma(gs.members[indexes[idx++]].address);
|
||||||
if (std::find(alwaysSendTo.begin(),alwaysSendTo.end(),ma) == alwaysSendTo.end()) {
|
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;
|
++count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -256,7 +257,7 @@ void Multicaster::send(
|
|||||||
if (com)
|
if (com)
|
||||||
com->serialize(outp);
|
com->serialize(outp);
|
||||||
RR->node->expectReplyTo(outp.packetId());
|
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) {
|
for(std::vector<Address>::const_iterator ast(alwaysSendTo.begin());ast!=alwaysSendTo.end();++ast) {
|
||||||
if (*ast != RR->identity.address()) {
|
if (*ast != RR->identity.address()) {
|
||||||
out.sendAndLog(RR,*ast);
|
out.sendAndLog(RR,tPtr,*ast);
|
||||||
if (++count >= limit)
|
if (++count >= limit)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -290,7 +291,7 @@ void Multicaster::send(
|
|||||||
while ((count < limit)&&(idx < gs.members.size())) {
|
while ((count < limit)&&(idx < gs.members.size())) {
|
||||||
Address ma(gs.members[indexes[idx++]].address);
|
Address ma(gs.members[indexes[idx++]].address);
|
||||||
if (std::find(alwaysSendTo.begin(),alwaysSendTo.end(),ma) == alwaysSendTo.end()) {
|
if (std::find(alwaysSendTo.begin(),alwaysSendTo.end(),ma) == alwaysSendTo.end()) {
|
||||||
out.sendAndLog(RR,ma);
|
out.sendAndLog(RR,tPtr,ma);
|
||||||
++count;
|
++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);
|
Mutex::Lock _l(_gatherAuth_m);
|
||||||
_gatherAuth[_GatherAuthKey(com.networkId(),com.issuedTo())] = RR->node->now();
|
_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
|
// 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())
|
if (tx->atLimit())
|
||||||
gs.txQueue.erase(tx++);
|
gs.txQueue.erase(tx++);
|
||||||
else {
|
else {
|
||||||
tx->sendIfNew(RR,member);
|
tx->sendIfNew(RR,tPtr,member);
|
||||||
if (tx->atLimit())
|
if (tx->atLimit())
|
||||||
gs.txQueue.erase(tx++);
|
gs.txQueue.erase(tx++);
|
||||||
else ++tx;
|
else ++tx;
|
||||||
|
|||||||
@@ -90,10 +90,10 @@ public:
|
|||||||
* @param mg Multicast group
|
* @param mg Multicast group
|
||||||
* @param member New member address
|
* @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);
|
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.
|
* 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 now Current time
|
||||||
* @param nwid Network ID
|
* @param nwid Network ID
|
||||||
* @param mg Multicast group
|
* @param mg Multicast group
|
||||||
@@ -108,7 +109,7 @@ public:
|
|||||||
* @param count Number of addresses
|
* @param count Number of addresses
|
||||||
* @param totalKnown Total number of known addresses as reported by peer
|
* @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)
|
* Remove a multicast group member (if present)
|
||||||
@@ -150,6 +151,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Send a multicast
|
* 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 limit Multicast limit
|
||||||
* @param now Current time
|
* @param now Current time
|
||||||
* @param nwid Network ID
|
* @param nwid Network ID
|
||||||
@@ -162,6 +164,7 @@ public:
|
|||||||
* @param len Length of packet data
|
* @param len Length of packet data
|
||||||
*/
|
*/
|
||||||
void send(
|
void send(
|
||||||
|
void *tPtr,
|
||||||
unsigned int limit,
|
unsigned int limit,
|
||||||
uint64_t now,
|
uint64_t now,
|
||||||
uint64_t nwid,
|
uint64_t nwid,
|
||||||
@@ -191,7 +194,7 @@ public:
|
|||||||
* @param com Certificate of membership
|
* @param com Certificate of membership
|
||||||
* @param alreadyValidated If true, COM has already been checked and found to be valid and signed
|
* @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
|
* Check authorization for GATHER and LIKE for non-network-members
|
||||||
@@ -209,7 +212,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
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;
|
const RuntimeEnvironment *RR;
|
||||||
|
|
||||||
|
|||||||
@@ -674,7 +674,7 @@ static _doZtFilterResult _doZtFilter(
|
|||||||
|
|
||||||
const ZeroTier::MulticastGroup Network::BROADCAST(ZeroTier::MAC(0xffffffffffffULL),0);
|
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),
|
RR(renv),
|
||||||
_uPtr(uptr),
|
_uPtr(uptr),
|
||||||
_id(nwid),
|
_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>();
|
Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> *dconf = new Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY>();
|
||||||
NetworkConfig *nconf = new NetworkConfig();
|
NetworkConfig *nconf = new NetworkConfig();
|
||||||
try {
|
try {
|
||||||
std::string conf(RR->node->dataStoreGet(confn));
|
std::string conf(RR->node->dataStoreGet(tPtr,confn));
|
||||||
if (conf.length()) {
|
if (conf.length()) {
|
||||||
dconf->load(conf.c_str());
|
dconf->load(conf.c_str());
|
||||||
if (nconf->fromDictionary(*dconf)) {
|
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
|
_lastConfigUpdate = 0; // we still want to re-request a new config from the network
|
||||||
gotConf = true;
|
gotConf = true;
|
||||||
}
|
}
|
||||||
@@ -711,13 +711,13 @@ Network::Network(const RuntimeEnvironment *renv,uint64_t nwid,void *uptr) :
|
|||||||
|
|
||||||
if (!gotConf) {
|
if (!gotConf) {
|
||||||
// Save a one-byte CR to persist membership while we request a real netconf
|
// 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) {
|
if (!_portInitialized) {
|
||||||
ZT_VirtualNetworkConfig ctmp;
|
ZT_VirtualNetworkConfig ctmp;
|
||||||
_externalConfig(&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;
|
_portInitialized = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -729,15 +729,16 @@ Network::~Network()
|
|||||||
|
|
||||||
char n[128];
|
char n[128];
|
||||||
if (_destroyed) {
|
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);
|
Utils::snprintf(n,sizeof(n),"networks.d/%.16llx.conf",_id);
|
||||||
RR->node->dataStoreDelete(n);
|
RR->node->dataStoreDelete((void *)0,n);
|
||||||
} else {
|
} 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(
|
bool Network::filterOutgoingPacket(
|
||||||
|
void *tPtr,
|
||||||
const bool noTee,
|
const bool noTee,
|
||||||
const Address &ztSource,
|
const Address &ztSource,
|
||||||
const Address &ztDest,
|
const Address &ztDest,
|
||||||
@@ -781,7 +782,7 @@ bool Network::filterOutgoingPacket(
|
|||||||
|
|
||||||
if ((!noTee)&&(cc2)) {
|
if ((!noTee)&&(cc2)) {
|
||||||
Membership &m2 = _membership(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);
|
Packet outp(cc2,RR->identity.address(),Packet::VERB_EXT_FRAME);
|
||||||
outp.append(_id);
|
outp.append(_id);
|
||||||
@@ -791,7 +792,7 @@ bool Network::filterOutgoingPacket(
|
|||||||
outp.append((uint16_t)etherType);
|
outp.append((uint16_t)etherType);
|
||||||
outp.append(frameData,ccLength2);
|
outp.append(frameData,ccLength2);
|
||||||
outp.compress();
|
outp.compress();
|
||||||
RR->sw->send(outp,true);
|
RR->sw->send(tPtr,outp,true);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -813,11 +814,11 @@ bool Network::filterOutgoingPacket(
|
|||||||
|
|
||||||
if (accept) {
|
if (accept) {
|
||||||
if (membership)
|
if (membership)
|
||||||
membership->pushCredentials(RR,now,ztDest,_config,localCapabilityIndex,false);
|
membership->pushCredentials(RR,tPtr,now,ztDest,_config,localCapabilityIndex,false);
|
||||||
|
|
||||||
if ((!noTee)&&(cc)) {
|
if ((!noTee)&&(cc)) {
|
||||||
Membership &m2 = _membership(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);
|
Packet outp(cc,RR->identity.address(),Packet::VERB_EXT_FRAME);
|
||||||
outp.append(_id);
|
outp.append(_id);
|
||||||
@@ -827,12 +828,12 @@ bool Network::filterOutgoingPacket(
|
|||||||
outp.append((uint16_t)etherType);
|
outp.append((uint16_t)etherType);
|
||||||
outp.append(frameData,ccLength);
|
outp.append(frameData,ccLength);
|
||||||
outp.compress();
|
outp.compress();
|
||||||
RR->sw->send(outp,true);
|
RR->sw->send(tPtr,outp,true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ztDest != ztFinalDest)&&(ztFinalDest)) {
|
if ((ztDest != ztFinalDest)&&(ztFinalDest)) {
|
||||||
Membership &m2 = _membership(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);
|
Packet outp(ztFinalDest,RR->identity.address(),Packet::VERB_EXT_FRAME);
|
||||||
outp.append(_id);
|
outp.append(_id);
|
||||||
@@ -842,7 +843,7 @@ bool Network::filterOutgoingPacket(
|
|||||||
outp.append((uint16_t)etherType);
|
outp.append((uint16_t)etherType);
|
||||||
outp.append(frameData,frameLen);
|
outp.append(frameData,frameLen);
|
||||||
outp.compress();
|
outp.compress();
|
||||||
RR->sw->send(outp,true);
|
RR->sw->send(tPtr,outp,true);
|
||||||
|
|
||||||
return false; // DROP locally, since we redirected
|
return false; // DROP locally, since we redirected
|
||||||
} else {
|
} else {
|
||||||
@@ -854,6 +855,7 @@ bool Network::filterOutgoingPacket(
|
|||||||
}
|
}
|
||||||
|
|
||||||
int Network::filterIncomingPacket(
|
int Network::filterIncomingPacket(
|
||||||
|
void *tPtr,
|
||||||
const SharedPtr<Peer> &sourcePeer,
|
const SharedPtr<Peer> &sourcePeer,
|
||||||
const Address &ztDest,
|
const Address &ztDest,
|
||||||
const MAC &macSource,
|
const MAC &macSource,
|
||||||
@@ -898,7 +900,7 @@ int Network::filterIncomingPacket(
|
|||||||
|
|
||||||
if (accept) {
|
if (accept) {
|
||||||
if (cc2) {
|
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);
|
Packet outp(cc2,RR->identity.address(),Packet::VERB_EXT_FRAME);
|
||||||
outp.append(_id);
|
outp.append(_id);
|
||||||
@@ -908,7 +910,7 @@ int Network::filterIncomingPacket(
|
|||||||
outp.append((uint16_t)etherType);
|
outp.append((uint16_t)etherType);
|
||||||
outp.append(frameData,ccLength2);
|
outp.append(frameData,ccLength2);
|
||||||
outp.compress();
|
outp.compress();
|
||||||
RR->sw->send(outp,true);
|
RR->sw->send(tPtr,outp,true);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -929,7 +931,7 @@ int Network::filterIncomingPacket(
|
|||||||
|
|
||||||
if (accept) {
|
if (accept) {
|
||||||
if (cc) {
|
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);
|
Packet outp(cc,RR->identity.address(),Packet::VERB_EXT_FRAME);
|
||||||
outp.append(_id);
|
outp.append(_id);
|
||||||
@@ -939,11 +941,11 @@ int Network::filterIncomingPacket(
|
|||||||
outp.append((uint16_t)etherType);
|
outp.append((uint16_t)etherType);
|
||||||
outp.append(frameData,ccLength);
|
outp.append(frameData,ccLength);
|
||||||
outp.compress();
|
outp.compress();
|
||||||
RR->sw->send(outp,true);
|
RR->sw->send(tPtr,outp,true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ztDest != ztFinalDest)&&(ztFinalDest)) {
|
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);
|
Packet outp(ztFinalDest,RR->identity.address(),Packet::VERB_EXT_FRAME);
|
||||||
outp.append(_id);
|
outp.append(_id);
|
||||||
@@ -953,7 +955,7 @@ int Network::filterIncomingPacket(
|
|||||||
outp.append((uint16_t)etherType);
|
outp.append((uint16_t)etherType);
|
||||||
outp.append(frameData,frameLen);
|
outp.append(frameData,frameLen);
|
||||||
outp.compress();
|
outp.compress();
|
||||||
RR->sw->send(outp,true);
|
RR->sw->send(tPtr,outp,true);
|
||||||
|
|
||||||
return 0; // DROP locally, since we redirected
|
return 0; // DROP locally, since we redirected
|
||||||
}
|
}
|
||||||
@@ -972,12 +974,12 @@ bool Network::subscribedToMulticastGroup(const MulticastGroup &mg,bool includeBr
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Network::multicastSubscribe(const MulticastGroup &mg)
|
void Network::multicastSubscribe(void *tPtr,const MulticastGroup &mg)
|
||||||
{
|
{
|
||||||
Mutex::Lock _l(_lock);
|
Mutex::Lock _l(_lock);
|
||||||
if (!std::binary_search(_myMulticastGroups.begin(),_myMulticastGroups.end(),mg)) {
|
if (!std::binary_search(_myMulticastGroups.begin(),_myMulticastGroups.end(),mg)) {
|
||||||
_myMulticastGroups.insert(std::upper_bound(_myMulticastGroups.begin(),_myMulticastGroups.end(),mg),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);
|
_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;
|
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
|
// 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?
|
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());
|
TRACE("unable to verify chunk from %s: don't have controller identity",source.toString().c_str());
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1067,7 +1069,7 @@ uint64_t Network::handleConfigChunk(const uint64_t packetId,const Address &sourc
|
|||||||
if ((*a != source)&&(*a != controller())) {
|
if ((*a != source)&&(*a != controller())) {
|
||||||
Packet outp(*a,RR->identity.address(),Packet::VERB_NETWORK_CONFIG);
|
Packet outp(*a,RR->identity.address(),Packet::VERB_NETWORK_CONFIG);
|
||||||
outp.append(reinterpret_cast<const uint8_t *>(chunk.data()) + start,chunk.size() - start);
|
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) {
|
if (nc) {
|
||||||
this->setConfiguration(*nc,true);
|
this->setConfiguration(tPtr,*nc,true);
|
||||||
delete nc;
|
delete nc;
|
||||||
return configUpdateId;
|
return configUpdateId;
|
||||||
} else {
|
} else {
|
||||||
@@ -1136,7 +1138,7 @@ uint64_t Network::handleConfigChunk(const uint64_t packetId,const Address &sourc
|
|||||||
return 0;
|
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
|
// _lock is NOT locked when this is called
|
||||||
try {
|
try {
|
||||||
@@ -1156,7 +1158,7 @@ int Network::setConfiguration(const NetworkConfig &nconf,bool saveToDisk)
|
|||||||
_portInitialized = true;
|
_portInitialized = true;
|
||||||
_externalConfig(&ctmp);
|
_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) {
|
if (saveToDisk) {
|
||||||
Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> *d = new Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY>();
|
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];
|
char n[64];
|
||||||
Utils::snprintf(n,sizeof(n),"networks.d/%.16llx.conf",_id);
|
Utils::snprintf(n,sizeof(n),"networks.d/%.16llx.conf",_id);
|
||||||
if (nconf.toDictionary(*d,false))
|
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 ( ... ) {}
|
} catch ( ... ) {}
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
@@ -1176,7 +1178,7 @@ int Network::setConfiguration(const NetworkConfig &nconf,bool saveToDisk)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Network::requestConfiguration()
|
void Network::requestConfiguration(void *tPtr)
|
||||||
{
|
{
|
||||||
/* ZeroTier addresses can't begin with 0xff, so this is used to mark controllerless
|
/* 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
|
* 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;
|
nconf->type = ZT_NETWORK_TYPE_PUBLIC;
|
||||||
Utils::snprintf(nconf->name,sizeof(nconf->name),"adhoc-%.04x-%.04x",(int)startPortRange,(int)endPortRange);
|
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;
|
delete nconf;
|
||||||
} else {
|
} else {
|
||||||
this->setNotFound();
|
this->setNotFound();
|
||||||
@@ -1282,12 +1284,12 @@ void Network::requestConfiguration()
|
|||||||
} else {
|
} else {
|
||||||
outp.append((unsigned char)0,16);
|
outp.append((unsigned char)0,16);
|
||||||
}
|
}
|
||||||
RR->node->expectReplyTo(outp.packetId());
|
|
||||||
outp.compress();
|
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();
|
const uint64_t now = RR->node->now();
|
||||||
Mutex::Lock _l(_lock);
|
Mutex::Lock _l(_lock);
|
||||||
@@ -1298,8 +1300,8 @@ bool Network::gate(const SharedPtr<Peer> &peer)
|
|||||||
if (!m)
|
if (!m)
|
||||||
m = &(_membership(peer->address()));
|
m = &(_membership(peer->address()));
|
||||||
if (m->shouldLikeMulticasts(now)) {
|
if (m->shouldLikeMulticasts(now)) {
|
||||||
m->pushCredentials(RR,now,peer->address(),_config,-1,false);
|
m->pushCredentials(RR,tPtr,now,peer->address(),_config,-1,false);
|
||||||
_announceMulticastGroupsTo(peer->address(),_allMulticastGroups());
|
_announceMulticastGroupsTo(tPtr,peer->address(),_allMulticastGroups());
|
||||||
m->likingMulticasts(now);
|
m->likingMulticasts(now);
|
||||||
}
|
}
|
||||||
return true;
|
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);
|
Mutex::Lock _l(_lock);
|
||||||
const unsigned long tmp = (unsigned long)_multicastGroupsBehindMe.size();
|
const unsigned long tmp = (unsigned long)_multicastGroupsBehindMe.size();
|
||||||
_multicastGroupsBehindMe.set(mg,now);
|
_multicastGroupsBehindMe.set(mg,now);
|
||||||
if (tmp != _multicastGroupsBehindMe.size())
|
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)
|
if (com.networkId() != _id)
|
||||||
return Membership::ADD_REJECTED;
|
return Membership::ADD_REJECTED;
|
||||||
const Address a(com.issuedTo());
|
const Address a(com.issuedTo());
|
||||||
Mutex::Lock _l(_lock);
|
Mutex::Lock _l(_lock);
|
||||||
Membership &m = _membership(a);
|
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)) {
|
if ((result == Membership::ADD_ACCEPTED_NEW)||(result == Membership::ADD_ACCEPTED_REDUNDANT)) {
|
||||||
m.pushCredentials(RR,RR->node->now(),a,_config,-1,false);
|
m.pushCredentials(RR,tPtr,RR->node->now(),a,_config,-1,false);
|
||||||
RR->mc->addCredential(com,true);
|
RR->mc->addCredential(tPtr,com,true);
|
||||||
}
|
}
|
||||||
return result;
|
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)
|
if (rev.networkId() != _id)
|
||||||
return Membership::ADD_REJECTED;
|
return Membership::ADD_REJECTED;
|
||||||
@@ -1409,7 +1411,7 @@ Membership::AddCredentialResult Network::addCredential(const Address &sentFrom,c
|
|||||||
Mutex::Lock _l(_lock);
|
Mutex::Lock _l(_lock);
|
||||||
Membership &m = _membership(rev.target());
|
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())) {
|
if ((result == Membership::ADD_ACCEPTED_NEW)&&(rev.fastPropagate())) {
|
||||||
Address *a = (Address *)0;
|
Address *a = (Address *)0;
|
||||||
@@ -1424,7 +1426,7 @@ Membership::AddCredentialResult Network::addCredential(const Address &sentFrom,c
|
|||||||
outp.append((uint16_t)1); // one revocation!
|
outp.append((uint16_t)1); // one revocation!
|
||||||
rev.serialize(outp);
|
rev.serialize(outp);
|
||||||
outp.append((uint16_t)0); // no certificates of ownership
|
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
|
// Assumes _lock is locked
|
||||||
const uint64_t now = RR->node->now();
|
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);
|
Packet outp(*a,RR->identity.address(),Packet::VERB_NETWORK_CREDENTIALS);
|
||||||
_config.com.serialize(outp);
|
_config.com.serialize(outp);
|
||||||
outp.append((uint8_t)0x00);
|
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
|
// 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);
|
Packet outp(c,RR->identity.address(),Packet::VERB_NETWORK_CREDENTIALS);
|
||||||
_config.com.serialize(outp);
|
_config.com.serialize(outp);
|
||||||
outp.append((uint8_t)0x00);
|
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;
|
Membership *m = (Membership *)0;
|
||||||
Hashtable<Address,Membership>::Iterator i(_memberships);
|
Hashtable<Address,Membership>::Iterator i(_memberships);
|
||||||
while (i.next(a,m)) {
|
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->shouldLikeMulticasts(now))) && (m->isAllowedOnNetwork(_config)) ) {
|
||||||
if (!newMulticastGroup)
|
if (!newMulticastGroup)
|
||||||
m->likingMulticasts(now);
|
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
|
// Assumes _lock is locked
|
||||||
Packet outp(peer,RR->identity.address(),Packet::VERB_MULTICAST_LIKE);
|
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) {
|
for(std::vector<MulticastGroup>::const_iterator mg(allMulticastGroups.begin());mg!=allMulticastGroups.end();++mg) {
|
||||||
if ((outp.size() + 24) >= ZT_PROTO_MAX_PACKET_LENGTH) {
|
if ((outp.size() + 24) >= ZT_PROTO_MAX_PACKET_LENGTH) {
|
||||||
outp.compress();
|
outp.compress();
|
||||||
RR->sw->send(outp,true);
|
RR->sw->send(tPtr,outp,true);
|
||||||
outp.reset(peer,RR->identity.address(),Packet::VERB_MULTICAST_LIKE);
|
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) {
|
if (outp.size() > ZT_PROTO_MIN_PACKET_LENGTH) {
|
||||||
outp.compress();
|
outp.compress();
|
||||||
RR->sw->send(outp,true);
|
RR->sw->send(tPtr,outp,true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -77,10 +77,11 @@ public:
|
|||||||
* constructed to actually configure the port.
|
* constructed to actually configure the port.
|
||||||
*
|
*
|
||||||
* @param renv Runtime environment
|
* @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 nwid Network ID
|
||||||
* @param uptr Arbitrary pointer used by externally-facing API (for user use)
|
* @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();
|
~Network();
|
||||||
|
|
||||||
@@ -101,6 +102,7 @@ public:
|
|||||||
* such as TEE may be taken, and credentials may be pushed, so this is not
|
* 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.
|
* 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 noTee If true, do not TEE anything anywhere (for two-pass filtering as done with multicast and bridging)
|
||||||
* @param ztSource Source ZeroTier address
|
* @param ztSource Source ZeroTier address
|
||||||
* @param ztDest Destination ZeroTier address
|
* @param ztDest Destination ZeroTier address
|
||||||
@@ -113,6 +115,7 @@ public:
|
|||||||
* @return True if packet should be sent, false if dropped or redirected
|
* @return True if packet should be sent, false if dropped or redirected
|
||||||
*/
|
*/
|
||||||
bool filterOutgoingPacket(
|
bool filterOutgoingPacket(
|
||||||
|
void *tPtr,
|
||||||
const bool noTee,
|
const bool noTee,
|
||||||
const Address &ztSource,
|
const Address &ztSource,
|
||||||
const Address &ztDest,
|
const Address &ztDest,
|
||||||
@@ -131,6 +134,7 @@ public:
|
|||||||
* a match certain actions may be taken such as sending a copy of the packet
|
* a match certain actions may be taken such as sending a copy of the packet
|
||||||
* to a TEE or REDIRECT target.
|
* 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 sourcePeer Source Peer
|
||||||
* @param ztDest Destination ZeroTier address
|
* @param ztDest Destination ZeroTier address
|
||||||
* @param macSource Ethernet layer source address
|
* @param macSource Ethernet layer source address
|
||||||
@@ -142,6 +146,7 @@ public:
|
|||||||
* @return 0 == drop, 1 == accept, 2 == accept even if bridged
|
* @return 0 == drop, 1 == accept, 2 == accept even if bridged
|
||||||
*/
|
*/
|
||||||
int filterIncomingPacket(
|
int filterIncomingPacket(
|
||||||
|
void *tPtr,
|
||||||
const SharedPtr<Peer> &sourcePeer,
|
const SharedPtr<Peer> &sourcePeer,
|
||||||
const Address &ztDest,
|
const Address &ztDest,
|
||||||
const MAC &macSource,
|
const MAC &macSource,
|
||||||
@@ -163,9 +168,10 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Subscribe to a multicast group
|
* 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
|
* @param mg New multicast group
|
||||||
*/
|
*/
|
||||||
void multicastSubscribe(const MulticastGroup &mg);
|
void multicastSubscribe(void *tPtr,const MulticastGroup &mg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unsubscribe from a multicast group
|
* Unsubscribe from a multicast group
|
||||||
@@ -181,22 +187,24 @@ public:
|
|||||||
* chunks via OK(NETWORK_CONFIG_REQUEST) or NETWORK_CONFIG. It verifies
|
* chunks via OK(NETWORK_CONFIG_REQUEST) or NETWORK_CONFIG. It verifies
|
||||||
* each chunk and once assembled applies the configuration.
|
* 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 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 source Address of sender of chunk or NULL if none (e.g. via cluster path)
|
||||||
* @param chunk Buffer containing chunk
|
* @param chunk Buffer containing chunk
|
||||||
* @param ptr Index of chunk and related fields in packet
|
* @param ptr Index of chunk and related fields in packet
|
||||||
* @return Update ID if update was fully assembled and accepted or 0 otherwise
|
* @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
|
* 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 nconf Network configuration
|
||||||
* @param saveToDisk Save to disk? Used during loading, should usually be true otherwise.
|
* @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
|
* @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
|
* 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
|
* 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
|
* 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
|
* 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)
|
* 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);
|
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
|
* 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 mg Multicast group
|
||||||
* @param now Current time
|
* @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
|
* 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
|
* 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)
|
if (cap.networkId() != _id)
|
||||||
return Membership::ADD_REJECTED;
|
return Membership::ADD_REJECTED;
|
||||||
Mutex::Lock _l(_lock);
|
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
|
* 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)
|
if (tag.networkId() != _id)
|
||||||
return Membership::ADD_REJECTED;
|
return Membership::ADD_REJECTED;
|
||||||
Mutex::Lock _l(_lock);
|
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
|
* 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
|
* 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)
|
if (coo.networkId() != _id)
|
||||||
return Membership::ADD_REJECTED;
|
return Membership::ADD_REJECTED;
|
||||||
Mutex::Lock _l(_lock);
|
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
|
* 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 to Destination peer address
|
||||||
* @param now Current time
|
* @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);
|
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;
|
ZT_VirtualNetworkStatus _status() const;
|
||||||
void _externalConfig(ZT_VirtualNetworkConfig *ec) const; // assumes _lock is locked
|
void _externalConfig(ZT_VirtualNetworkConfig *ec) const; // assumes _lock is locked
|
||||||
bool _gate(const SharedPtr<Peer> &peer);
|
bool _gate(const SharedPtr<Peer> &peer);
|
||||||
void _sendUpdatesToMembers(const MulticastGroup *const newMulticastGroup);
|
void _sendUpdatesToMembers(void *tPtr,const MulticastGroup *const newMulticastGroup);
|
||||||
void _announceMulticastGroupsTo(const Address &peer,const std::vector<MulticastGroup> &allMulticastGroups);
|
void _announceMulticastGroupsTo(void *tPtr,const Address &peer,const std::vector<MulticastGroup> &allMulticastGroups);
|
||||||
std::vector<MulticastGroup> _allMulticastGroups() const;
|
std::vector<MulticastGroup> _allMulticastGroups() const;
|
||||||
Membership &_membership(const Address &a);
|
Membership &_membership(const Address &a);
|
||||||
|
|
||||||
@@ -374,6 +391,7 @@ private:
|
|||||||
|
|
||||||
struct _IncomingConfigChunk
|
struct _IncomingConfigChunk
|
||||||
{
|
{
|
||||||
|
_IncomingConfigChunk() { memset(this,0,sizeof(_IncomingConfigChunk)); }
|
||||||
uint64_t ts;
|
uint64_t ts;
|
||||||
uint64_t updateId;
|
uint64_t updateId;
|
||||||
uint64_t haveChunkIds[ZT_NETWORK_MAX_UPDATE_CHUNKS];
|
uint64_t haveChunkIds[ZT_NETWORK_MAX_UPDATE_CHUNKS];
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ namespace ZeroTier {
|
|||||||
/* Public Node interface (C++, exposed via CAPI bindings) */
|
/* 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(this),
|
||||||
RR(&_RR),
|
RR(&_RR),
|
||||||
_uPtr(uptr),
|
_uPtr(uptr),
|
||||||
@@ -72,26 +72,26 @@ Node::Node(void *uptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now) :
|
|||||||
memset(_prngStream,0,sizeof(_prngStream));
|
memset(_prngStream,0,sizeof(_prngStream));
|
||||||
_prng.crypt12(_prngStream,_prngStream,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())) {
|
if ((!idtmp.length())||(!RR->identity.fromString(idtmp))||(!RR->identity.hasPrivate())) {
|
||||||
TRACE("identity.secret not found, generating...");
|
TRACE("identity.secret not found, generating...");
|
||||||
RR->identity.generate();
|
RR->identity.generate();
|
||||||
idtmp = RR->identity.toString(true);
|
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");
|
throw std::runtime_error("unable to write identity.secret");
|
||||||
}
|
}
|
||||||
RR->publicIdentityStr = RR->identity.toString(false);
|
RR->publicIdentityStr = RR->identity.toString(false);
|
||||||
RR->secretIdentityStr = RR->identity.toString(true);
|
RR->secretIdentityStr = RR->identity.toString(true);
|
||||||
idtmp = dataStoreGet("identity.public");
|
idtmp = dataStoreGet(tptr,"identity.public");
|
||||||
if (idtmp != RR->publicIdentityStr) {
|
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");
|
throw std::runtime_error("unable to write identity.public");
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
RR->sw = new Switch(RR);
|
RR->sw = new Switch(RR);
|
||||||
RR->mc = new Multicaster(RR);
|
RR->mc = new Multicaster(RR);
|
||||||
RR->topology = new Topology(RR);
|
RR->topology = new Topology(RR,tptr);
|
||||||
RR->sa = new SelfAwareness(RR);
|
RR->sa = new SelfAwareness(RR);
|
||||||
} catch ( ... ) {
|
} catch ( ... ) {
|
||||||
delete RR->sa;
|
delete RR->sa;
|
||||||
@@ -101,7 +101,7 @@ Node::Node(void *uptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now) :
|
|||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
postEvent(ZT_EVENT_UP);
|
postEvent(tptr,ZT_EVENT_UP);
|
||||||
}
|
}
|
||||||
|
|
||||||
Node::~Node()
|
Node::~Node()
|
||||||
@@ -121,6 +121,7 @@ Node::~Node()
|
|||||||
}
|
}
|
||||||
|
|
||||||
ZT_ResultCode Node::processWirePacket(
|
ZT_ResultCode Node::processWirePacket(
|
||||||
|
void *tptr,
|
||||||
uint64_t now,
|
uint64_t now,
|
||||||
const struct sockaddr_storage *localAddress,
|
const struct sockaddr_storage *localAddress,
|
||||||
const struct sockaddr_storage *remoteAddress,
|
const struct sockaddr_storage *remoteAddress,
|
||||||
@@ -129,11 +130,12 @@ ZT_ResultCode Node::processWirePacket(
|
|||||||
volatile uint64_t *nextBackgroundTaskDeadline)
|
volatile uint64_t *nextBackgroundTaskDeadline)
|
||||||
{
|
{
|
||||||
_now = now;
|
_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;
|
return ZT_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZT_ResultCode Node::processVirtualNetworkFrame(
|
ZT_ResultCode Node::processVirtualNetworkFrame(
|
||||||
|
void *tptr,
|
||||||
uint64_t now,
|
uint64_t now,
|
||||||
uint64_t nwid,
|
uint64_t nwid,
|
||||||
uint64_t sourceMac,
|
uint64_t sourceMac,
|
||||||
@@ -147,7 +149,7 @@ ZT_ResultCode Node::processVirtualNetworkFrame(
|
|||||||
_now = now;
|
_now = now;
|
||||||
SharedPtr<Network> nw(this->network(nwid));
|
SharedPtr<Network> nw(this->network(nwid));
|
||||||
if (nw) {
|
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;
|
return ZT_RESULT_OK;
|
||||||
} else return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
|
} else return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
|
||||||
}
|
}
|
||||||
@@ -156,9 +158,10 @@ ZT_ResultCode Node::processVirtualNetworkFrame(
|
|||||||
class _PingPeersThatNeedPing
|
class _PingPeersThatNeedPing
|
||||||
{
|
{
|
||||||
public:
|
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),
|
lastReceiveFromUpstream(0),
|
||||||
RR(renv),
|
RR(renv),
|
||||||
|
_tPtr(tPtr),
|
||||||
_upstreamsToContact(upstreamsToContact),
|
_upstreamsToContact(upstreamsToContact),
|
||||||
_now(now),
|
_now(now),
|
||||||
_bestCurrentUpstream(RR->topology->getUpstreamPeer())
|
_bestCurrentUpstream(RR->topology->getUpstreamPeer())
|
||||||
@@ -176,21 +179,21 @@ public:
|
|||||||
// Upstreams must be pinged constantly over both IPv4 and IPv6 to allow
|
// Upstreams must be pinged constantly over both IPv4 and IPv6 to allow
|
||||||
// them to perform three way handshake introductions for both stacks.
|
// 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) {
|
for(unsigned long k=0,ptr=(unsigned long)RR->node->prng();k<(unsigned long)upstreamStableEndpoints->size();++k) {
|
||||||
const InetAddress &addr = (*upstreamStableEndpoints)[ptr++ % upstreamStableEndpoints->size()];
|
const InetAddress &addr = (*upstreamStableEndpoints)[ptr++ % upstreamStableEndpoints->size()];
|
||||||
if (addr.ss_family == AF_INET) {
|
if (addr.ss_family == AF_INET) {
|
||||||
p->sendHELLO(InetAddress(),addr,_now,0);
|
p->sendHELLO(_tPtr,InetAddress(),addr,_now,0);
|
||||||
contacted = true;
|
contacted = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else contacted = true;
|
} 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) {
|
for(unsigned long k=0,ptr=(unsigned long)RR->node->prng();k<(unsigned long)upstreamStableEndpoints->size();++k) {
|
||||||
const InetAddress &addr = (*upstreamStableEndpoints)[ptr++ % upstreamStableEndpoints->size()];
|
const InetAddress &addr = (*upstreamStableEndpoints)[ptr++ % upstreamStableEndpoints->size()];
|
||||||
if (addr.ss_family == AF_INET6) {
|
if (addr.ss_family == AF_INET6) {
|
||||||
p->sendHELLO(InetAddress(),addr,_now,0);
|
p->sendHELLO(_tPtr,InetAddress(),addr,_now,0);
|
||||||
contacted = true;
|
contacted = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -200,24 +203,25 @@ public:
|
|||||||
if ((!contacted)&&(_bestCurrentUpstream)) {
|
if ((!contacted)&&(_bestCurrentUpstream)) {
|
||||||
const SharedPtr<Path> up(_bestCurrentUpstream->getBestPath(_now,true));
|
const SharedPtr<Path> up(_bestCurrentUpstream->getBestPath(_now,true));
|
||||||
if (up)
|
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);
|
lastReceiveFromUpstream = std::max(p->lastReceive(),lastReceiveFromUpstream);
|
||||||
_upstreamsToContact.erase(p->address()); // erase from upstreams to contact so that we can WHOIS those that remain
|
_upstreamsToContact.erase(p->address()); // erase from upstreams to contact so that we can WHOIS those that remain
|
||||||
} else if (p->isActive(_now)) {
|
} else if (p->isActive(_now)) {
|
||||||
p->doPingAndKeepalive(_now,-1);
|
p->doPingAndKeepalive(_tPtr,_now,-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const RuntimeEnvironment *RR;
|
const RuntimeEnvironment *RR;
|
||||||
|
void *_tPtr;
|
||||||
Hashtable< Address,std::vector<InetAddress> > &_upstreamsToContact;
|
Hashtable< Address,std::vector<InetAddress> > &_upstreamsToContact;
|
||||||
const uint64_t _now;
|
const uint64_t _now;
|
||||||
const SharedPtr<Peer> _bestCurrentUpstream;
|
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;
|
_now = now;
|
||||||
Mutex::Lock bl(_backgroundTasksLock);
|
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) {
|
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()))
|
if (((now - n->second->lastConfigUpdate()) >= ZT_NETWORK_AUTOCONF_DELAY)||(!n->second->hasConfig()))
|
||||||
needConfig.push_back(n->second);
|
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)
|
for(std::vector< SharedPtr<Network> >::const_iterator n(needConfig.begin());n!=needConfig.end();++n)
|
||||||
(*n)->requestConfiguration();
|
(*n)->requestConfiguration(tptr);
|
||||||
|
|
||||||
// Do pings and keepalives
|
// Do pings and keepalives
|
||||||
Hashtable< Address,std::vector<InetAddress> > upstreamsToContact;
|
Hashtable< Address,std::vector<InetAddress> > upstreamsToContact;
|
||||||
RR->topology->getUpstreamsToContact(upstreamsToContact);
|
RR->topology->getUpstreamsToContact(upstreamsToContact);
|
||||||
_PingPeersThatNeedPing pfunc(RR,upstreamsToContact,now);
|
_PingPeersThatNeedPing pfunc(RR,tptr,upstreamsToContact,now);
|
||||||
RR->topology->eachPeer<_PingPeersThatNeedPing &>(pfunc);
|
RR->topology->eachPeer<_PingPeersThatNeedPing &>(pfunc);
|
||||||
|
|
||||||
// Run WHOIS to create Peer for any upstreams we could not contact (including pending moon seeds)
|
// 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;
|
Address *upstreamAddress = (Address *)0;
|
||||||
std::vector<InetAddress> *upstreamStableEndpoints = (std::vector<InetAddress> *)0;
|
std::vector<InetAddress> *upstreamStableEndpoints = (std::vector<InetAddress> *)0;
|
||||||
while (i.next(upstreamAddress,upstreamStableEndpoints))
|
while (i.next(upstreamAddress,upstreamStableEndpoints))
|
||||||
RR->sw->requestWhois(*upstreamAddress);
|
RR->sw->requestWhois(tptr,*upstreamAddress);
|
||||||
|
|
||||||
// Update online status, post status change as event
|
// Update online status, post status change as event
|
||||||
const bool oldOnline = _online;
|
const bool oldOnline = _online;
|
||||||
_online = (((now - pfunc.lastReceiveFromUpstream) < ZT_PEER_ACTIVITY_TIMEOUT)||(RR->topology->amRoot()));
|
_online = (((now - pfunc.lastReceiveFromUpstream) < ZT_PEER_ACTIVITY_TIMEOUT)||(RR->topology->amRoot()));
|
||||||
if (oldOnline != _online)
|
if (oldOnline != _online)
|
||||||
postEvent(_online ? ZT_EVENT_ONLINE : ZT_EVENT_OFFLINE);
|
postEvent(tptr,_online ? ZT_EVENT_ONLINE : ZT_EVENT_OFFLINE);
|
||||||
} catch ( ... ) {
|
} catch ( ... ) {
|
||||||
return ZT_RESULT_FATAL_ERROR_INTERNAL;
|
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
|
#ifdef ZT_ENABLE_CLUSTER
|
||||||
// If clustering is enabled we have to call cluster->doPeriodicTasks() very often, so we override normal timer deadline behavior
|
// If clustering is enabled we have to call cluster->doPeriodicTasks() very often, so we override normal timer deadline behavior
|
||||||
if (RR->cluster) {
|
if (RR->cluster) {
|
||||||
RR->sw->doTimerTasks(now);
|
RR->sw->doTimerTasks(tptr,now);
|
||||||
RR->cluster->doPeriodicTasks();
|
RR->cluster->doPeriodicTasks();
|
||||||
*nextBackgroundTaskDeadline = now + ZT_CLUSTER_PERIODIC_TASK_PERIOD; // this is really short so just tick at this rate
|
*nextBackgroundTaskDeadline = now + ZT_CLUSTER_PERIODIC_TASK_PERIOD; // this is really short so just tick at this rate
|
||||||
} else {
|
} else {
|
||||||
#endif
|
#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
|
#ifdef ZT_ENABLE_CLUSTER
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -297,17 +301,17 @@ ZT_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *nextB
|
|||||||
return ZT_RESULT_OK;
|
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);
|
Mutex::Lock _l(_networks_m);
|
||||||
SharedPtr<Network> nw = _network(nwid);
|
SharedPtr<Network> nw = _network(nwid);
|
||||||
if(!nw)
|
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<>
|
std::sort(_networks.begin(),_networks.end()); // will sort by nwid since it's the first in a pair<>
|
||||||
return ZT_RESULT_OK;
|
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;
|
std::vector< std::pair< uint64_t,SharedPtr<Network> > > newn;
|
||||||
Mutex::Lock _l(_networks_m);
|
Mutex::Lock _l(_networks_m);
|
||||||
@@ -324,11 +328,11 @@ ZT_ResultCode Node::leave(uint64_t nwid,void **uptr)
|
|||||||
return ZT_RESULT_OK;
|
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));
|
SharedPtr<Network> nw(this->network(nwid));
|
||||||
if (nw) {
|
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;
|
return ZT_RESULT_OK;
|
||||||
} else return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
|
} 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;
|
} 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;
|
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;
|
return ZT_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -465,7 +469,7 @@ void Node::clearLocalInterfaceAddresses()
|
|||||||
_directPaths.clear();
|
_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 {
|
try {
|
||||||
if (RR->identity.address().toInt() != dest) {
|
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(typeId);
|
||||||
outp.append(data,len);
|
outp.append(data,len);
|
||||||
outp.compress();
|
outp.compress();
|
||||||
RR->sw->send(outp,true);
|
RR->sw->send(tptr,outp,true);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} catch ( ... ) {}
|
} catch ( ... ) {}
|
||||||
@@ -486,7 +490,7 @@ void Node::setNetconfMaster(void *networkControllerInstance)
|
|||||||
RR->localNetworkController->init(RR->identity,this);
|
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) {
|
if (test->hopCount > 0) {
|
||||||
try {
|
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) {
|
for(unsigned int a=0;a<test->hops[0].breadth;++a) {
|
||||||
outp.newInitializationVector();
|
outp.newInitializationVector();
|
||||||
outp.setDestination(Address(test->hops[0].addresses[a]));
|
outp.setDestination(Address(test->hops[0].addresses[a]));
|
||||||
RR->sw->send(outp,true);
|
RR->sw->send(tptr,outp,true);
|
||||||
}
|
}
|
||||||
} catch ( ... ) {
|
} catch ( ... ) {
|
||||||
return ZT_RESULT_FATAL_ERROR_INTERNAL; // probably indicates FIFO too big for packet
|
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/ */
|
/* 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];
|
char buf[1024];
|
||||||
std::string r;
|
std::string r;
|
||||||
unsigned long olen = 0;
|
unsigned long olen = 0;
|
||||||
do {
|
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)
|
if (n <= 0)
|
||||||
return std::string();
|
return std::string();
|
||||||
r.append(buf,n);
|
r.append(buf,n);
|
||||||
@@ -630,7 +634,7 @@ std::string Node::dataStoreGet(const char *name)
|
|||||||
return r;
|
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))
|
if (!Path::isAddressValidForPath(remoteAddress))
|
||||||
return false;
|
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
|
#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;
|
tmp2[sizeof(tmp2)-1] = (char)0;
|
||||||
|
|
||||||
Utils::snprintf(tmp1,sizeof(tmp1),"[%s] %s:%u %s",nowstr,module,line,tmp2);
|
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
|
#endif // ZT_TRACE
|
||||||
|
|
||||||
@@ -728,7 +732,7 @@ void Node::ncSendConfig(uint64_t nwid,uint64_t requestPacketId,const Address &de
|
|||||||
if (destination == RR->identity.address()) {
|
if (destination == RR->identity.address()) {
|
||||||
SharedPtr<Network> n(network(nwid));
|
SharedPtr<Network> n(network(nwid));
|
||||||
if (!n) return;
|
if (!n) return;
|
||||||
n->setConfiguration(nc,true);
|
n->setConfiguration((void *)0,nc,true);
|
||||||
} else {
|
} else {
|
||||||
Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> *dconf = new Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY>();
|
Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> *dconf = new Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY>();
|
||||||
try {
|
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.append(sig.data,ZT_C25519_SIGNATURE_LEN);
|
||||||
|
|
||||||
outp.compress();
|
outp.compress();
|
||||||
RR->sw->send(outp,true);
|
RR->sw->send((void *)0,outp,true);
|
||||||
chunkIndex += chunkLen;
|
chunkIndex += chunkLen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -779,7 +783,7 @@ void Node::ncSendRevocation(const Address &destination,const Revocation &rev)
|
|||||||
if (destination == RR->identity.address()) {
|
if (destination == RR->identity.address()) {
|
||||||
SharedPtr<Network> n(network(rev.networkId()));
|
SharedPtr<Network> n(network(rev.networkId()));
|
||||||
if (!n) return;
|
if (!n) return;
|
||||||
n->addCredential(RR->identity.address(),rev);
|
n->addCredential((void *)0,RR->identity.address(),rev);
|
||||||
} else {
|
} else {
|
||||||
Packet outp(destination,RR->identity.address(),Packet::VERB_NETWORK_CREDENTIALS);
|
Packet outp(destination,RR->identity.address(),Packet::VERB_NETWORK_CREDENTIALS);
|
||||||
outp.append((uint8_t)0x00);
|
outp.append((uint8_t)0x00);
|
||||||
@@ -788,7 +792,7 @@ void Node::ncSendRevocation(const Address &destination,const Revocation &rev)
|
|||||||
outp.append((uint16_t)1);
|
outp.append((uint16_t)1);
|
||||||
rev.serialize(outp);
|
rev.serialize(outp);
|
||||||
outp.append((uint16_t)0);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
outp.append(nwid);
|
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
|
} // 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" {
|
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;
|
*node = (ZT_Node *)0;
|
||||||
try {
|
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;
|
return ZT_RESULT_OK;
|
||||||
} catch (std::bad_alloc &exc) {
|
} catch (std::bad_alloc &exc) {
|
||||||
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
|
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(
|
enum ZT_ResultCode ZT_Node_processWirePacket(
|
||||||
ZT_Node *node,
|
ZT_Node *node,
|
||||||
|
void *tptr,
|
||||||
uint64_t now,
|
uint64_t now,
|
||||||
const struct sockaddr_storage *localAddress,
|
const struct sockaddr_storage *localAddress,
|
||||||
const struct sockaddr_storage *remoteAddress,
|
const struct sockaddr_storage *remoteAddress,
|
||||||
@@ -867,7 +872,7 @@ enum ZT_ResultCode ZT_Node_processWirePacket(
|
|||||||
volatile uint64_t *nextBackgroundTaskDeadline)
|
volatile uint64_t *nextBackgroundTaskDeadline)
|
||||||
{
|
{
|
||||||
try {
|
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) {
|
} catch (std::bad_alloc &exc) {
|
||||||
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
|
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
|
||||||
} catch ( ... ) {
|
} catch ( ... ) {
|
||||||
@@ -877,6 +882,7 @@ enum ZT_ResultCode ZT_Node_processWirePacket(
|
|||||||
|
|
||||||
enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame(
|
enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame(
|
||||||
ZT_Node *node,
|
ZT_Node *node,
|
||||||
|
void *tptr,
|
||||||
uint64_t now,
|
uint64_t now,
|
||||||
uint64_t nwid,
|
uint64_t nwid,
|
||||||
uint64_t sourceMac,
|
uint64_t sourceMac,
|
||||||
@@ -888,7 +894,7 @@ enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame(
|
|||||||
volatile uint64_t *nextBackgroundTaskDeadline)
|
volatile uint64_t *nextBackgroundTaskDeadline)
|
||||||
{
|
{
|
||||||
try {
|
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) {
|
} catch (std::bad_alloc &exc) {
|
||||||
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
|
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
|
||||||
} catch ( ... ) {
|
} 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 {
|
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) {
|
} catch (std::bad_alloc &exc) {
|
||||||
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
|
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
|
||||||
} catch ( ... ) {
|
} 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 {
|
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) {
|
} catch (std::bad_alloc &exc) {
|
||||||
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
|
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
|
||||||
} catch ( ... ) {
|
} 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 {
|
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) {
|
} catch (std::bad_alloc &exc) {
|
||||||
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
|
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
|
||||||
} catch ( ... ) {
|
} 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 {
|
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) {
|
} catch (std::bad_alloc &exc) {
|
||||||
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
|
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
|
||||||
} catch ( ... ) {
|
} 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 {
|
try {
|
||||||
return reinterpret_cast<ZeroTier::Node *>(node)->orbit(moonWorldId,moonSeed);
|
return reinterpret_cast<ZeroTier::Node *>(node)->orbit(tptr,moonWorldId,moonSeed);
|
||||||
} catch ( ... ) {
|
} catch ( ... ) {
|
||||||
return ZT_RESULT_FATAL_ERROR_INTERNAL;
|
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 {
|
try {
|
||||||
return reinterpret_cast<ZeroTier::Node *>(node)->deorbit(moonWorldId);
|
return reinterpret_cast<ZeroTier::Node *>(node)->deorbit(tptr,moonWorldId);
|
||||||
} catch ( ... ) {
|
} catch ( ... ) {
|
||||||
return ZT_RESULT_FATAL_ERROR_INTERNAL;
|
return ZT_RESULT_FATAL_ERROR_INTERNAL;
|
||||||
}
|
}
|
||||||
@@ -1031,10 +1037,10 @@ void ZT_Node_clearLocalInterfaceAddresses(ZT_Node *node)
|
|||||||
} catch ( ... ) {}
|
} 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 {
|
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 ( ... ) {
|
} catch ( ... ) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1047,10 +1053,10 @@ void ZT_Node_setNetconfMaster(ZT_Node *node,void *networkControllerInstance)
|
|||||||
} catch ( ... ) {}
|
} 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 {
|
try {
|
||||||
return reinterpret_cast<ZeroTier::Node *>(node)->circuitTestBegin(test,reportCallback);
|
return reinterpret_cast<ZeroTier::Node *>(node)->circuitTestBegin(tptr,test,reportCallback);
|
||||||
} catch ( ... ) {
|
} catch ( ... ) {
|
||||||
return ZT_RESULT_FATAL_ERROR_INTERNAL;
|
return ZT_RESULT_FATAL_ERROR_INTERNAL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ class World;
|
|||||||
class Node : public NetworkController::Sender
|
class Node : public NetworkController::Sender
|
||||||
{
|
{
|
||||||
public:
|
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();
|
virtual ~Node();
|
||||||
|
|
||||||
// Get rid of alignment warnings on 32-bit Windows and possibly improve performance
|
// Get rid of alignment warnings on 32-bit Windows and possibly improve performance
|
||||||
@@ -77,6 +77,7 @@ public:
|
|||||||
// Public API Functions ----------------------------------------------------
|
// Public API Functions ----------------------------------------------------
|
||||||
|
|
||||||
ZT_ResultCode processWirePacket(
|
ZT_ResultCode processWirePacket(
|
||||||
|
void *tptr,
|
||||||
uint64_t now,
|
uint64_t now,
|
||||||
const struct sockaddr_storage *localAddress,
|
const struct sockaddr_storage *localAddress,
|
||||||
const struct sockaddr_storage *remoteAddress,
|
const struct sockaddr_storage *remoteAddress,
|
||||||
@@ -84,6 +85,7 @@ public:
|
|||||||
unsigned int packetLength,
|
unsigned int packetLength,
|
||||||
volatile uint64_t *nextBackgroundTaskDeadline);
|
volatile uint64_t *nextBackgroundTaskDeadline);
|
||||||
ZT_ResultCode processVirtualNetworkFrame(
|
ZT_ResultCode processVirtualNetworkFrame(
|
||||||
|
void *tptr,
|
||||||
uint64_t now,
|
uint64_t now,
|
||||||
uint64_t nwid,
|
uint64_t nwid,
|
||||||
uint64_t sourceMac,
|
uint64_t sourceMac,
|
||||||
@@ -93,13 +95,13 @@ public:
|
|||||||
const void *frameData,
|
const void *frameData,
|
||||||
unsigned int frameLength,
|
unsigned int frameLength,
|
||||||
volatile uint64_t *nextBackgroundTaskDeadline);
|
volatile uint64_t *nextBackgroundTaskDeadline);
|
||||||
ZT_ResultCode processBackgroundTasks(uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline);
|
ZT_ResultCode processBackgroundTasks(void *tptr,uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline);
|
||||||
ZT_ResultCode join(uint64_t nwid,void *uptr);
|
ZT_ResultCode join(uint64_t nwid,void *uptr,void *tptr);
|
||||||
ZT_ResultCode leave(uint64_t nwid,void **uptr);
|
ZT_ResultCode leave(uint64_t nwid,void **uptr,void *tptr);
|
||||||
ZT_ResultCode multicastSubscribe(uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi);
|
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 multicastUnsubscribe(uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi);
|
||||||
ZT_ResultCode orbit(uint64_t moonWorldId,uint64_t moonSeed);
|
ZT_ResultCode orbit(void *tptr,uint64_t moonWorldId,uint64_t moonSeed);
|
||||||
ZT_ResultCode deorbit(uint64_t moonWorldId);
|
ZT_ResultCode deorbit(void *tptr,uint64_t moonWorldId);
|
||||||
uint64_t address() const;
|
uint64_t address() const;
|
||||||
void status(ZT_NodeStatus *status) const;
|
void status(ZT_NodeStatus *status) const;
|
||||||
ZT_PeerList *peers() const;
|
ZT_PeerList *peers() const;
|
||||||
@@ -108,9 +110,9 @@ public:
|
|||||||
void freeQueryResult(void *qr);
|
void freeQueryResult(void *qr);
|
||||||
int addLocalInterfaceAddress(const struct sockaddr_storage *addr);
|
int addLocalInterfaceAddress(const struct sockaddr_storage *addr);
|
||||||
void clearLocalInterfaceAddresses();
|
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);
|
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);
|
void circuitTestEnd(ZT_CircuitTest *test);
|
||||||
ZT_ResultCode clusterInit(
|
ZT_ResultCode clusterInit(
|
||||||
unsigned int myId,
|
unsigned int myId,
|
||||||
@@ -132,11 +134,12 @@ public:
|
|||||||
|
|
||||||
inline uint64_t now() const throw() { return _now; }
|
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(
|
return (_cb.wirePacketSendFunction(
|
||||||
reinterpret_cast<ZT_Node *>(this),
|
reinterpret_cast<ZT_Node *>(this),
|
||||||
_uPtr,
|
_uPtr,
|
||||||
|
tPtr,
|
||||||
reinterpret_cast<const struct sockaddr_storage *>(&localAddress),
|
reinterpret_cast<const struct sockaddr_storage *>(&localAddress),
|
||||||
reinterpret_cast<const struct sockaddr_storage *>(&addr),
|
reinterpret_cast<const struct sockaddr_storage *>(&addr),
|
||||||
data,
|
data,
|
||||||
@@ -144,11 +147,12 @@ public:
|
|||||||
ttl) == 0);
|
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(
|
_cb.virtualNetworkFrameFunction(
|
||||||
reinterpret_cast<ZT_Node *>(this),
|
reinterpret_cast<ZT_Node *>(this),
|
||||||
_uPtr,
|
_uPtr,
|
||||||
|
tPtr,
|
||||||
nwid,
|
nwid,
|
||||||
nuptr,
|
nuptr,
|
||||||
source.toInt(),
|
source.toInt(),
|
||||||
@@ -191,14 +195,14 @@ public:
|
|||||||
return _directPaths;
|
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(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(const char *name,const std::string &data,bool secure) { return dataStorePut(name,(const void *)data.data(),(unsigned int)data.length(),secure); }
|
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(const char *name) { _cb.dataStorePutFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,name,(const void *)0,0,0); }
|
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(const char *name);
|
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; }
|
inline bool online() const throw() { return _online; }
|
||||||
|
|
||||||
@@ -206,8 +210,8 @@ public:
|
|||||||
void postTrace(const char *module,unsigned int line,const char *fmt,...);
|
void postTrace(const char *module,unsigned int line,const char *fmt,...);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool shouldUsePathForZeroTierTraffic(const Address &ztaddr,const InetAddress &localAddress,const InetAddress &remoteAddress);
|
bool shouldUsePathForZeroTierTraffic(void *tPtr,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 ); }
|
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();
|
uint64_t prng();
|
||||||
void postCircuitTestReport(const ZT_CircuitTestReport *report);
|
void postCircuitTestReport(const ZT_CircuitTestReport *report);
|
||||||
|
|||||||
@@ -85,16 +85,18 @@ void OutboundMulticast::init(
|
|||||||
memcpy(_frameData,payload,_frameLen);
|
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 SharedPtr<Network> nw(RR->node->network(_nwid));
|
||||||
const Address toAddr2(toAddr);
|
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());
|
//TRACE(">>MC %.16llx -> %s",(unsigned long long)this,toAddr.toString().c_str());
|
||||||
_packet.newInitializationVector();
|
_packet.newInitializationVector();
|
||||||
_packet.setDestination(toAddr2);
|
_packet.setDestination(toAddr2);
|
||||||
RR->node->expectReplyTo(_packet.packetId());
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -99,33 +99,36 @@ public:
|
|||||||
* Just send without checking log
|
* Just send without checking log
|
||||||
*
|
*
|
||||||
* @param RR Runtime environment
|
* @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
|
* @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
|
* Just send and log but do not check sent log
|
||||||
*
|
*
|
||||||
* @param RR Runtime environment
|
* @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
|
* @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);
|
_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
|
* Try to send this to a given peer if it hasn't been sent to them already
|
||||||
*
|
*
|
||||||
* @param RR Runtime environment
|
* @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
|
* @param toAddr Destination address
|
||||||
* @return True if address is new and packet was sent to switch, false if duplicate
|
* @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()) {
|
if (std::find(_alreadySentTo.begin(),_alreadySentTo.end(),toAddr) == _alreadySentTo.end()) {
|
||||||
sendAndLog(RR,toAddr);
|
sendAndLog(RR,tPtr,toAddr);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
1005
zto/node/Packet.cpp
1005
zto/node/Packet.cpp
File diff suppressed because it is too large
Load Diff
@@ -1322,7 +1322,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* @return Value of link quality counter extracted from this packet's ID, range 0 to 7 (3 bits)
|
* @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
|
* Set packet verb
|
||||||
|
|||||||
@@ -22,9 +22,9 @@
|
|||||||
|
|
||||||
namespace ZeroTier {
|
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;
|
_lastOut = now;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -186,12 +186,13 @@ public:
|
|||||||
* Send a packet via this path (last out time is also updated)
|
* Send a packet via this path (last out time is also updated)
|
||||||
*
|
*
|
||||||
* @param RR Runtime environment
|
* @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 data Packet data
|
||||||
* @param len Packet length
|
* @param len Packet length
|
||||||
* @param now Current time
|
* @param now Current time
|
||||||
* @return True if transport reported success
|
* @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
|
* Manually update last sent time
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ Peer::Peer(const RuntimeEnvironment *renv,const Identity &myIdentity,const Ident
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Peer::received(
|
void Peer::received(
|
||||||
|
void *tPtr,
|
||||||
const SharedPtr<Path> &path,
|
const SharedPtr<Path> &path,
|
||||||
const unsigned int hops,
|
const unsigned int hops,
|
||||||
const uint64_t packetId,
|
const uint64_t packetId,
|
||||||
@@ -102,7 +103,7 @@ void Peer::received(
|
|||||||
}
|
}
|
||||||
outp.append((uint16_t)redirectTo.port());
|
outp.append((uint16_t)redirectTo.port());
|
||||||
outp.armor(_key,true,path->nextOutgoingCounter());
|
outp.armor(_key,true,path->nextOutgoingCounter());
|
||||||
path->send(RR,outp.data(),outp.size(),now);
|
path->send(RR,tPtr,outp.data(),outp.size(),now);
|
||||||
} else {
|
} else {
|
||||||
// For older peers we use RENDEZVOUS to coax them into contacting us elsewhere.
|
// For older peers we use RENDEZVOUS to coax them into contacting us elsewhere.
|
||||||
Packet outp(_id.address(),RR->identity.address(),Packet::VERB_RENDEZVOUS);
|
Packet outp(_id.address(),RR->identity.address(),Packet::VERB_RENDEZVOUS);
|
||||||
@@ -117,7 +118,7 @@ void Peer::received(
|
|||||||
outp.append(redirectTo.rawIpData(),16);
|
outp.append(redirectTo.rawIpData(),16);
|
||||||
}
|
}
|
||||||
outp.armor(_key,true,path->nextOutgoingCounter());
|
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;
|
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) {
|
if (verb == Packet::VERB_OK) {
|
||||||
Mutex::Lock _l(_paths_m);
|
Mutex::Lock _l(_paths_m);
|
||||||
|
|
||||||
@@ -206,7 +207,7 @@ void Peer::received(
|
|||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
TRACE("got %s via unknown path %s(%s), confirming...",Packet::verbString(verb),_id.address().toString().c_str(),path->address().toString().c_str());
|
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);
|
path->sent(now);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -281,7 +282,7 @@ void Peer::received(
|
|||||||
if (count) {
|
if (count) {
|
||||||
outp.setAt(ZT_PACKET_IDX_PAYLOAD,(uint16_t)count);
|
outp.setAt(ZT_PACKET_IDX_PAYLOAD,(uint16_t)count);
|
||||||
outp.armor(_key,true,path->nextOutgoingCounter());
|
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;
|
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);
|
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) {
|
if (bestp >= 0) {
|
||||||
return _paths[bestp].path->send(RR,data,len,now);
|
return _paths[bestp].path->send(RR,tPtr,data,len,now);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
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);
|
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) {
|
if (atAddress) {
|
||||||
outp.armor(_key,false,counter); // false == don't encrypt full payload, but add MAC
|
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 {
|
} 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))) ) {
|
if ( (!sendFullHello) && (_vProto >= 5) && (!((_vMajor == 1)&&(_vMinor == 1)&&(_vRevision == 0))) ) {
|
||||||
Packet outp(_id.address(),RR->identity.address(),Packet::VERB_ECHO);
|
Packet outp(_id.address(),RR->identity.address(),Packet::VERB_ECHO);
|
||||||
RR->node->expectReplyTo(outp.packetId());
|
RR->node->expectReplyTo(outp.packetId());
|
||||||
outp.armor(_key,true,counter);
|
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 {
|
} 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) {
|
if ((now - _lastTriedMemorizedPath) >= ZT_TRY_MEMORIZED_PATH_INTERVAL) {
|
||||||
_lastTriedMemorizedPath = now;
|
_lastTriedMemorizedPath = now;
|
||||||
InetAddress mp;
|
InetAddress mp;
|
||||||
if (RR->node->externalPathLookup(_id.address(),-1,mp))
|
if (RR->node->externalPathLookup(tPtr,_id.address(),-1,mp))
|
||||||
attemptToContactAt(InetAddress(),mp,now,true,0);
|
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);
|
Mutex::Lock _l(_paths_m);
|
||||||
|
|
||||||
@@ -433,7 +434,7 @@ bool Peer::doPingAndKeepalive(uint64_t now,int inetAddressFamily)
|
|||||||
|
|
||||||
if (bestp >= 0) {
|
if (bestp >= 0) {
|
||||||
if ( ((now - _paths[bestp].lastReceive) >= ZT_PEER_PING_PERIOD) || (_paths[bestp].path->needsHeartbeat(now)) ) {
|
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);
|
_paths[bestp].path->sent(now);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -452,12 +453,12 @@ bool Peer::hasActiveDirectPath(uint64_t now) const
|
|||||||
return false;
|
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);
|
Mutex::Lock _l(_paths_m);
|
||||||
for(unsigned int p=0;p<_numPaths;++p) {
|
for(unsigned int p=0;p<_numPaths;++p) {
|
||||||
if ( (_paths[p].path->address().ss_family == inetAddressFamily) && (_paths[p].path->address().ipScope() == scope) ) {
|
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].path->sent(now);
|
||||||
_paths[p].lastReceive = 0; // path will not be used unless it speaks again
|
_paths[p].lastReceive = 0; // path will not be used unless it speaks again
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ public:
|
|||||||
* This is called by the decode pipe when a packet is proven to be authentic
|
* This is called by the decode pipe when a packet is proven to be authentic
|
||||||
* and appears to be valid.
|
* 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 path Path over which packet was received
|
||||||
* @param hops ZeroTier (not IP) hops
|
* @param hops ZeroTier (not IP) hops
|
||||||
* @param packetId Packet ID
|
* @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
|
* @param trustEstablished If true, some form of non-trivial trust (like allowed in network) has been established
|
||||||
*/
|
*/
|
||||||
void received(
|
void received(
|
||||||
|
void *tPtr,
|
||||||
const SharedPtr<Path> &path,
|
const SharedPtr<Path> &path,
|
||||||
const unsigned int hops,
|
const unsigned int hops,
|
||||||
const uint64_t packetId,
|
const uint64_t packetId,
|
||||||
@@ -125,13 +127,14 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Send via best direct path
|
* 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 data Packet data
|
||||||
* @param len Packet length
|
* @param len Packet length
|
||||||
* @param now Current time
|
* @param now Current time
|
||||||
* @param forceEvenIfDead If true, send even if the path is not 'alive'
|
* @param forceEvenIfDead If true, send even if the path is not 'alive'
|
||||||
* @return True if we actually sent something
|
* @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
|
* Get the best current direct path
|
||||||
@@ -147,41 +150,47 @@ public:
|
|||||||
*
|
*
|
||||||
* No statistics or sent times are updated here.
|
* 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 localAddr Local address
|
||||||
* @param atAddress Destination address
|
* @param atAddress Destination address
|
||||||
* @param now Current time
|
* @param now Current time
|
||||||
* @param counter Outgoing packet counter
|
* @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
|
* Send ECHO (or HELLO for older peers) to this peer at the given address
|
||||||
*
|
*
|
||||||
* No statistics or sent times are updated here.
|
* 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 localAddr Local address
|
||||||
* @param atAddress Destination address
|
* @param atAddress Destination address
|
||||||
* @param now Current time
|
* @param now Current time
|
||||||
* @param sendFullHello If true, always send a full HELLO instead of just an ECHO
|
* @param sendFullHello If true, always send a full HELLO instead of just an ECHO
|
||||||
* @param counter Outgoing packet counter
|
* @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
|
* 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.
|
* 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
|
* 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 now Current time
|
||||||
* @param inetAddressFamily Keep this address family alive, or -1 for any
|
* @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)
|
* @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
|
* @param now Current time
|
||||||
@@ -195,11 +204,12 @@ public:
|
|||||||
* Resetting a path involves sending an ECHO to it and then deactivating
|
* Resetting a path involves sending an ECHO to it and then deactivating
|
||||||
* it until or unless it responds.
|
* 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 scope IP scope
|
||||||
* @param inetAddressFamily Family e.g. AF_INET
|
* @param inetAddressFamily Family e.g. AF_INET
|
||||||
* @param now Current time
|
* @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
|
* Get most recently active path addresses for IPv4 and/or IPv6
|
||||||
|
|||||||
@@ -25,13 +25,13 @@
|
|||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
int Revocation::verify(const RuntimeEnvironment *RR) const
|
int Revocation::verify(const RuntimeEnvironment *RR,void *tPtr) const
|
||||||
{
|
{
|
||||||
if ((!_signedBy)||(_signedBy != Network::controllerFor(_networkId)))
|
if ((!_signedBy)||(_signedBy != Network::controllerFor(_networkId)))
|
||||||
return -1;
|
return -1;
|
||||||
const Identity id(RR->topology->getIdentity(_signedBy));
|
const Identity id(RR->topology->getIdentity(tPtr,_signedBy));
|
||||||
if (!id) {
|
if (!id) {
|
||||||
RR->sw->requestWhois(_signedBy);
|
RR->sw->requestWhois(tPtr,_signedBy);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -113,9 +113,10 @@ public:
|
|||||||
* Verify this revocation's signature
|
* Verify this revocation's signature
|
||||||
*
|
*
|
||||||
* @param RR Runtime environment to provide for peer lookup, etc.
|
* @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
|
* @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>
|
template<unsigned int C>
|
||||||
inline void serialize(Buffer<C> &b,const bool forSign = false) const
|
inline void serialize(Buffer<C> &b,const bool forSign = false) const
|
||||||
|
|||||||
@@ -40,15 +40,17 @@ namespace ZeroTier {
|
|||||||
class _ResetWithinScope
|
class _ResetWithinScope
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
_ResetWithinScope(uint64_t now,int inetAddressFamily,InetAddress::IpScope scope) :
|
_ResetWithinScope(void *tPtr,uint64_t now,int inetAddressFamily,InetAddress::IpScope scope) :
|
||||||
_now(now),
|
_now(now),
|
||||||
|
_tPtr(tPtr),
|
||||||
_family(inetAddressFamily),
|
_family(inetAddressFamily),
|
||||||
_scope(scope) {}
|
_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:
|
private:
|
||||||
uint64_t _now;
|
uint64_t _now;
|
||||||
|
void *_tPtr;
|
||||||
int _family;
|
int _family;
|
||||||
InetAddress::IpScope _scope;
|
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();
|
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
|
// 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);
|
RR->topology->eachPeer<_ResetWithinScope &>(rset);
|
||||||
} else {
|
} else {
|
||||||
// Otherwise just update DB to use to determine external surface info
|
// Otherwise just update DB to use to determine external surface info
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public:
|
|||||||
* @param trusted True if this peer is trusted as an authority to inform us of external address changes
|
* @param trusted True if this peer is trusted as an authority to inform us of external address changes
|
||||||
* @param now Current time
|
* @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
|
* Clean up database periodically
|
||||||
|
|||||||
@@ -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 {
|
try {
|
||||||
const uint64_t now = RR->node->now();
|
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);
|
const Address beaconAddr(reinterpret_cast<const char *>(data) + 8,5);
|
||||||
if (beaconAddr == RR->identity.address())
|
if (beaconAddr == RR->identity.address())
|
||||||
return;
|
return;
|
||||||
if (!RR->node->shouldUsePathForZeroTierTraffic(beaconAddr,localAddr,fromAddr))
|
if (!RR->node->shouldUsePathForZeroTierTraffic(tPtr,beaconAddr,localAddr,fromAddr))
|
||||||
return;
|
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 (peer) { // we'll only respond to beacons from known peers
|
||||||
if ((now - _lastBeaconResponse) >= 2500) { // limit rate of responses
|
if ((now - _lastBeaconResponse) >= 2500) { // limit rate of responses
|
||||||
_lastBeaconResponse = now;
|
_lastBeaconResponse = now;
|
||||||
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_NOP);
|
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_NOP);
|
||||||
outp.armor(peer->key(),true,path->nextOutgoingCounter());
|
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.
|
// 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.
|
// It wouldn't hurt anything, just redundant and unnecessary.
|
||||||
SharedPtr<Peer> relayTo = RR->topology->getPeer(destination);
|
SharedPtr<Peer> relayTo = RR->topology->getPeer(tPtr,destination);
|
||||||
if ((!relayTo)||(!relayTo->sendDirect(fragment.data(),fragment.size(),now,false))) {
|
if ((!relayTo)||(!relayTo->sendDirect(tPtr,fragment.data(),fragment.size(),now,false))) {
|
||||||
#ifdef ZT_ENABLE_CLUSTER
|
#ifdef ZT_ENABLE_CLUSTER
|
||||||
if ((RR->cluster)&&(!isClusterFrontplane)) {
|
if ((RR->cluster)&&(!isClusterFrontplane)) {
|
||||||
RR->cluster->relayViaCluster(Address(),destination,fragment.data(),fragment.size(),false);
|
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
|
// Don't know peer or no direct path -- so relay via someone upstream
|
||||||
relayTo = RR->topology->getUpstreamPeer();
|
relayTo = RR->topology->getUpstreamPeer();
|
||||||
if (relayTo)
|
if (relayTo)
|
||||||
relayTo->sendDirect(fragment.data(),fragment.size(),now,true);
|
relayTo->sendDirect(tPtr,fragment.data(),fragment.size(),now,true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
TRACE("dropped relay [fragment](%s) -> %s, max hops exceeded",fromAddr.toString().c_str(),destination.toString().c_str());
|
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)
|
for(unsigned int f=1;f<totalFragments;++f)
|
||||||
rq->frag0.append(rq->frags[f - 1].payload(),rq->frags[f - 1].payloadLength());
|
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
|
rq->timestamp = 0; // packet decoded, free entry
|
||||||
} else {
|
} else {
|
||||||
rq->complete = true; // set complete flag but leave entry since it probably needs WHOIS or something
|
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();
|
packet.incrementHops();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SharedPtr<Peer> relayTo = RR->topology->getPeer(destination);
|
SharedPtr<Peer> relayTo = RR->topology->getPeer(tPtr,destination);
|
||||||
if ((relayTo)&&(relayTo->sendDirect(packet.data(),packet.size(),now,false))) {
|
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
|
if ((source != RR->identity.address())&&(_shouldUnite(now,source,destination))) { // don't send RENDEZVOUS for cluster frontplane relays
|
||||||
const InetAddress *hintToSource = (InetAddress *)0;
|
const InetAddress *hintToSource = (InetAddress *)0;
|
||||||
const InetAddress *hintToDest = (InetAddress *)0;
|
const InetAddress *hintToDest = (InetAddress *)0;
|
||||||
@@ -222,7 +222,7 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from
|
|||||||
InetAddress sourceV4,sourceV6;
|
InetAddress sourceV4,sourceV6;
|
||||||
relayTo->getRendezvousAddresses(now,destV4,destV6);
|
relayTo->getRendezvousAddresses(now,destV4,destV6);
|
||||||
|
|
||||||
const SharedPtr<Peer> sourcePeer(RR->topology->getPeer(source));
|
const SharedPtr<Peer> sourcePeer(RR->topology->getPeer(tPtr,source));
|
||||||
if (sourcePeer) {
|
if (sourcePeer) {
|
||||||
sourcePeer->getRendezvousAddresses(now,sourceV4,sourceV6);
|
sourcePeer->getRendezvousAddresses(now,sourceV4,sourceV6);
|
||||||
if ((destV6)&&(sourceV6)) {
|
if ((destV6)&&(sourceV6)) {
|
||||||
@@ -249,7 +249,7 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from
|
|||||||
outp.append((uint8_t)4);
|
outp.append((uint8_t)4);
|
||||||
outp.append(hintToSource->rawIpData(),4);
|
outp.append(hintToSource->rawIpData(),4);
|
||||||
}
|
}
|
||||||
send(outp,true);
|
send(tPtr,outp,true);
|
||||||
} else {
|
} else {
|
||||||
Packet outp(destination,RR->identity.address(),Packet::VERB_RENDEZVOUS);
|
Packet outp(destination,RR->identity.address(),Packet::VERB_RENDEZVOUS);
|
||||||
outp.append((uint8_t)0);
|
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((uint8_t)4);
|
||||||
outp.append(hintToDest->rawIpData(),4);
|
outp.append(hintToDest->rawIpData(),4);
|
||||||
}
|
}
|
||||||
send(outp,true);
|
send(tPtr,outp,true);
|
||||||
}
|
}
|
||||||
++alt;
|
++alt;
|
||||||
}
|
}
|
||||||
@@ -278,7 +278,7 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from
|
|||||||
#endif
|
#endif
|
||||||
relayTo = RR->topology->getUpstreamPeer(&source,1,true);
|
relayTo = RR->topology->getUpstreamPeer(&source,1,true);
|
||||||
if (relayTo)
|
if (relayTo)
|
||||||
relayTo->sendDirect(packet.data(),packet.size(),now,true);
|
relayTo->sendDirect(tPtr,packet.data(),packet.size(),now,true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
TRACE("dropped relay %s(%s) -> %s, max hops exceeded",packet.source().toString().c_str(),fromAddr.toString().c_str(),destination.toString().c_str());
|
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)
|
for(unsigned int f=1;f<rq->totalFragments;++f)
|
||||||
rq->frag0.append(rq->frags[f - 1].payload(),rq->frags[f - 1].payloadLength());
|
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
|
rq->timestamp = 0; // packet decoded, free entry
|
||||||
} else {
|
} else {
|
||||||
rq->complete = true; // set complete flag but leave entry since it probably needs WHOIS or something
|
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 {
|
} else {
|
||||||
// Packet is unfragmented, so just process it
|
// Packet is unfragmented, so just process it
|
||||||
IncomingPacket packet(data,len,path,now);
|
IncomingPacket packet(data,len,path,now);
|
||||||
if (!packet.tryDecode(RR)) {
|
if (!packet.tryDecode(RR,tPtr)) {
|
||||||
Mutex::Lock _l(_rxQueue_m);
|
Mutex::Lock _l(_rxQueue_m);
|
||||||
RXQueueEntry *rq = &(_rxQueue[ZT_RX_QUEUE_SIZE - 1]);
|
RXQueueEntry *rq = &(_rxQueue[ZT_RX_QUEUE_SIZE - 1]);
|
||||||
unsigned long i = 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())
|
if (!network->hasConfig())
|
||||||
return;
|
return;
|
||||||
@@ -474,7 +474,7 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
|
|||||||
adv[42] = (checksum >> 8) & 0xff;
|
adv[42] = (checksum >> 8) & 0xff;
|
||||||
adv[43] = checksum & 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.
|
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
|
||||||
} // 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.
|
* multicast addresses on bridge interfaces and subscribing each slave.
|
||||||
* But in that case this does no harm, as the sets are just merged. */
|
* But in that case this does no harm, as the sets are just merged. */
|
||||||
if (fromBridged)
|
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);
|
//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.
|
// 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));
|
TRACE("%.16llx: %s -> %s %s packet not sent: filterOutgoingPacket() returned false",network->id(),from.toString().c_str(),to.toString().c_str(),etherTypeName(etherType));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
RR->mc->send(
|
RR->mc->send(
|
||||||
|
tPtr,
|
||||||
network->config().multicastLimit,
|
network->config().multicastLimit,
|
||||||
RR->node->now(),
|
RR->node->now(),
|
||||||
network->id(),
|
network->id(),
|
||||||
@@ -514,14 +515,14 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
|
|||||||
len);
|
len);
|
||||||
} else if (to == network->mac()) {
|
} else if (to == network->mac()) {
|
||||||
// Destination is this node, so just reinject it
|
// 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())) {
|
} else if (to[0] == MAC::firstOctetForNetwork(network->id())) {
|
||||||
// Destination is another ZeroTier peer on the same network
|
// 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
|
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));
|
TRACE("%.16llx: %s -> %s %s packet not sent: filterOutgoingPacket() returned false",network->id(),from.toString().c_str(),to.toString().c_str(),etherTypeName(etherType));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -536,7 +537,7 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
|
|||||||
outp.append(data,len);
|
outp.append(data,len);
|
||||||
if (!network->config().disableCompression())
|
if (!network->config().disableCompression())
|
||||||
outp.compress();
|
outp.compress();
|
||||||
send(outp,true);
|
send(tPtr,outp,true);
|
||||||
} else {
|
} else {
|
||||||
Packet outp(toZT,RR->identity.address(),Packet::VERB_FRAME);
|
Packet outp(toZT,RR->identity.address(),Packet::VERB_FRAME);
|
||||||
outp.append(network->id());
|
outp.append(network->id());
|
||||||
@@ -544,7 +545,7 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
|
|||||||
outp.append(data,len);
|
outp.append(data,len);
|
||||||
if (!network->config().disableCompression())
|
if (!network->config().disableCompression())
|
||||||
outp.compress();
|
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);
|
//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
|
// We filter with a NULL destination ZeroTier address first. Filtrations
|
||||||
// for each ZT destination are also done below. This is the same rationale
|
// for each ZT destination are also done below. This is the same rationale
|
||||||
// and design as for multicast.
|
// 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));
|
TRACE("%.16llx: %s -> %s %s packet not sent: filterOutgoingPacket() returned false",network->id(),from.toString().c_str(),to.toString().c_str(),etherTypeName(etherType));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -592,7 +593,7 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
|
|||||||
}
|
}
|
||||||
|
|
||||||
for(unsigned int b=0;b<numBridges;++b) {
|
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);
|
Packet outp(bridges[b],RR->identity.address(),Packet::VERB_EXT_FRAME);
|
||||||
outp.append(network->id());
|
outp.append(network->id());
|
||||||
outp.append((uint8_t)0x00);
|
outp.append((uint8_t)0x00);
|
||||||
@@ -602,7 +603,7 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
|
|||||||
outp.append(data,len);
|
outp.append(data,len);
|
||||||
if (!network->config().disableCompression())
|
if (!network->config().disableCompression())
|
||||||
outp.compress();
|
outp.compress();
|
||||||
send(outp,true);
|
send(tPtr,outp,true);
|
||||||
} else {
|
} else {
|
||||||
TRACE("%.16llx: %s -> %s %s packet not sent: filterOutgoingPacket() returned false",network->id(),from.toString().c_str(),to.toString().c_str(),etherTypeName(etherType));
|
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()) {
|
if (packet.destination() == RR->identity.address()) {
|
||||||
TRACE("BUG: caught attempt to send() to self, ignored");
|
TRACE("BUG: caught attempt to send() to self, ignored");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_trySend(packet,encrypt)) {
|
if (!_trySend(tPtr,packet,encrypt)) {
|
||||||
Mutex::Lock _l(_txQueue_m);
|
Mutex::Lock _l(_txQueue_m);
|
||||||
_txQueue.push_back(TXQueueEntry(packet.destination(),RR->node->now(),packet,encrypt));
|
_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;
|
bool inserted = false;
|
||||||
{
|
{
|
||||||
Mutex::Lock _l(_outstandingWhoisRequests_m);
|
Mutex::Lock _l(_outstandingWhoisRequests_m);
|
||||||
@@ -637,10 +645,10 @@ void Switch::requestWhois(const Address &addr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (inserted)
|
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
|
{ // cancel pending WHOIS since we now know this peer
|
||||||
Mutex::Lock _l(_outstandingWhoisRequests_m);
|
Mutex::Lock _l(_outstandingWhoisRequests_m);
|
||||||
@@ -653,7 +661,7 @@ void Switch::doAnythingWaitingForPeer(const SharedPtr<Peer> &peer)
|
|||||||
while (i) {
|
while (i) {
|
||||||
RXQueueEntry *rq = &(_rxQueue[--i]);
|
RXQueueEntry *rq = &(_rxQueue[--i]);
|
||||||
if ((rq->timestamp)&&(rq->complete)) {
|
if ((rq->timestamp)&&(rq->complete)) {
|
||||||
if (rq->frag0.tryDecode(RR))
|
if (rq->frag0.tryDecode(RR,tPtr))
|
||||||
rq->timestamp = 0;
|
rq->timestamp = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -663,7 +671,7 @@ void Switch::doAnythingWaitingForPeer(const SharedPtr<Peer> &peer)
|
|||||||
Mutex::Lock _l(_txQueue_m);
|
Mutex::Lock _l(_txQueue_m);
|
||||||
for(std::list< TXQueueEntry >::iterator txi(_txQueue.begin());txi!=_txQueue.end();) {
|
for(std::list< TXQueueEntry >::iterator txi(_txQueue.begin());txi!=_txQueue.end();) {
|
||||||
if (txi->dest == peer->address()) {
|
if (txi->dest == peer->address()) {
|
||||||
if (_trySend(txi->packet,txi->encrypt))
|
if (_trySend(tPtr,txi->packet,txi->encrypt))
|
||||||
_txQueue.erase(txi++);
|
_txQueue.erase(txi++);
|
||||||
else ++txi;
|
else ++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
|
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);
|
_outstandingWhoisRequests.erase(*a);
|
||||||
} else {
|
} else {
|
||||||
r->lastSent = now;
|
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);
|
TRACE("WHOIS %s (retry %u)",a->toString().c_str(),r->retries);
|
||||||
++r->retries;
|
++r->retries;
|
||||||
nextDelay = std::min(nextDelay,(unsigned long)ZT_WHOIS_RETRY_DELAY);
|
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.
|
{ // Time out TX queue packets that never got WHOIS lookups or other info.
|
||||||
Mutex::Lock _l(_txQueue_m);
|
Mutex::Lock _l(_txQueue_m);
|
||||||
for(std::list< TXQueueEntry >::iterator txi(_txQueue.begin());txi!=_txQueue.end();) {
|
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++);
|
_txQueue.erase(txi++);
|
||||||
else if ((now - txi->creationTime) > ZT_TRANSMIT_QUEUE_TIMEOUT) {
|
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());
|
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;
|
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));
|
SharedPtr<Peer> upstream(RR->topology->getUpstreamPeer(peersAlreadyConsulted,numPeersAlreadyConsulted,false));
|
||||||
if (upstream) {
|
if (upstream) {
|
||||||
Packet outp(upstream->address(),RR->identity.address(),Packet::VERB_WHOIS);
|
Packet outp(upstream->address(),RR->identity.address(),Packet::VERB_WHOIS);
|
||||||
addr.appendTo(outp);
|
addr.appendTo(outp);
|
||||||
RR->node->expectReplyTo(outp.packetId());
|
RR->node->expectReplyTo(outp.packetId());
|
||||||
send(outp,true);
|
send(tPtr,outp,true);
|
||||||
}
|
}
|
||||||
return Address();
|
return Address();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Switch::_trySend(Packet &packet,bool encrypt)
|
bool Switch::_trySend(void *tPtr,Packet &packet,bool encrypt)
|
||||||
{
|
{
|
||||||
SharedPtr<Path> viaPath;
|
SharedPtr<Path> viaPath;
|
||||||
const uint64_t now = RR->node->now();
|
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);
|
clusterMostRecentMemberId = RR->cluster->checkSendViaCluster(destination,clusterMostRecentTs,clusterPeerSecret);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const SharedPtr<Peer> peer(RR->topology->getPeer(destination));
|
const SharedPtr<Peer> peer(RR->topology->getPeer(tPtr,destination));
|
||||||
if (peer) {
|
if (peer) {
|
||||||
/* First get the best path, and if it's dead (and this is not a root)
|
/* 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
|
* 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)) {
|
if ((clusterMostRecentMemberId < 0)||(viaPath->lastIn() > clusterMostRecentTs)) {
|
||||||
#endif
|
#endif
|
||||||
if ((now - viaPath->lastOut()) > std::max((now - viaPath->lastIn()) * 4,(uint64_t)ZT_PATH_MIN_REACTIVATE_INTERVAL)) {
|
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);
|
viaPath->sent(now);
|
||||||
}
|
}
|
||||||
#ifdef ZT_ENABLE_CLUSTER
|
#ifdef ZT_ENABLE_CLUSTER
|
||||||
@@ -794,7 +802,7 @@ bool Switch::_trySend(Packet &packet,bool encrypt)
|
|||||||
#else
|
#else
|
||||||
if (!viaPath) {
|
if (!viaPath) {
|
||||||
#endif
|
#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());
|
const SharedPtr<Peer> relay(RR->topology->getUpstreamPeer());
|
||||||
if ( (!relay) || (!(viaPath = relay->getBestPath(now,false))) ) {
|
if ( (!relay) || (!(viaPath = relay->getBestPath(now,false))) ) {
|
||||||
if (!(viaPath = peer->getBestPath(now,true)))
|
if (!(viaPath = peer->getBestPath(now,true)))
|
||||||
@@ -809,7 +817,7 @@ bool Switch::_trySend(Packet &packet,bool encrypt)
|
|||||||
#ifdef ZT_ENABLE_CLUSTER
|
#ifdef ZT_ENABLE_CLUSTER
|
||||||
if (clusterMostRecentMemberId < 0) {
|
if (clusterMostRecentMemberId < 0) {
|
||||||
#else
|
#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
|
return false; // if we are not in cluster mode, there is no way we can send without knowing the peer directly
|
||||||
#endif
|
#endif
|
||||||
#ifdef ZT_ENABLE_CLUSTER
|
#ifdef ZT_ENABLE_CLUSTER
|
||||||
@@ -837,9 +845,9 @@ bool Switch::_trySend(Packet &packet,bool encrypt)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ZT_ENABLE_CLUSTER
|
#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
|
#else
|
||||||
if (viaPath->send(RR,packet.data(),chunkSize,now)) {
|
if (viaPath->send(RR,tPtr,packet.data(),chunkSize,now)) {
|
||||||
#endif
|
#endif
|
||||||
if (chunkSize < packet.size()) {
|
if (chunkSize < packet.size()) {
|
||||||
// Too big for one packet, fragment the rest
|
// 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);
|
Packet::Fragment frag(packet,fragStart,chunkSize,fno,totalFragments);
|
||||||
#ifdef ZT_ENABLE_CLUSTER
|
#ifdef ZT_ENABLE_CLUSTER
|
||||||
if (viaPath)
|
if (viaPath)
|
||||||
viaPath->send(RR,frag.data(),frag.size(),now);
|
viaPath->send(RR,tPtr,frag.data(),frag.size(),now);
|
||||||
else if (clusterMostRecentMemberId >= 0)
|
else if (clusterMostRecentMemberId >= 0)
|
||||||
RR->cluster->sendViaCluster(clusterMostRecentMemberId,destination,frag.data(),frag.size());
|
RR->cluster->sendViaCluster(clusterMostRecentMemberId,destination,frag.data(),frag.size());
|
||||||
#else
|
#else
|
||||||
viaPath->send(RR,frag.data(),frag.size(),now);
|
viaPath->send(RR,tPtr,frag.data(),frag.size(),now);
|
||||||
#endif
|
#endif
|
||||||
fragStart += chunkSize;
|
fragStart += chunkSize;
|
||||||
remaining -= chunkSize;
|
remaining -= chunkSize;
|
||||||
|
|||||||
@@ -59,16 +59,18 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Called when a packet is received from the real network
|
* 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 localAddr Local interface address
|
||||||
* @param fromAddr Internet IP address of origin
|
* @param fromAddr Internet IP address of origin
|
||||||
* @param data Packet data
|
* @param data Packet data
|
||||||
* @param len Packet length
|
* @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
|
* 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 network Which network's TAP did this packet come from?
|
||||||
* @param from Originating MAC address
|
* @param from Originating MAC address
|
||||||
* @param to Destination MAC address
|
* @param to Destination MAC address
|
||||||
@@ -77,7 +79,7 @@ public:
|
|||||||
* @param data Ethernet payload
|
* @param data Ethernet payload
|
||||||
* @param len Frame length
|
* @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)
|
* 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
|
* Needless to say, the packet's source must be this node. Otherwise it
|
||||||
* won't be encrypted right. (This is not used for relaying.)
|
* 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 packet Packet to send (buffer may be modified)
|
||||||
* @param encrypt Encrypt packet payload? (always true except for HELLO)
|
* @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
|
* 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
|
* @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
|
* 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.
|
* 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
|
* @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
|
* 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
|
* This can return a very long delay if there are no pending timer
|
||||||
* tasks. The caller should cap this comparatively vs. other values.
|
* 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
|
* @param now Current time
|
||||||
* @return Number of milliseconds until doTimerTasks() should be run again
|
* @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:
|
private:
|
||||||
bool _shouldUnite(const uint64_t now,const Address &source,const Address &destination);
|
bool _shouldUnite(const uint64_t now,const Address &source,const Address &destination);
|
||||||
Address _sendWhoisRequest(const Address &addr,const Address *peersAlreadyConsulted,unsigned int numPeersAlreadyConsulted);
|
Address _sendWhoisRequest(void *tPtr,const Address &addr,const Address *peersAlreadyConsulted,unsigned int numPeersAlreadyConsulted);
|
||||||
bool _trySend(Packet &packet,bool encrypt); // packet is modified if return is true
|
bool _trySend(void *tPtr,Packet &packet,bool encrypt); // packet is modified if return is true
|
||||||
|
|
||||||
const RuntimeEnvironment *const RR;
|
const RuntimeEnvironment *const RR;
|
||||||
uint64_t _lastBeaconResponse;
|
uint64_t _lastBeaconResponse;
|
||||||
|
|||||||
@@ -25,13 +25,13 @@
|
|||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
int Tag::verify(const RuntimeEnvironment *RR) const
|
int Tag::verify(const RuntimeEnvironment *RR,void *tPtr) const
|
||||||
{
|
{
|
||||||
if ((!_signedBy)||(_signedBy != Network::controllerFor(_networkId)))
|
if ((!_signedBy)||(_signedBy != Network::controllerFor(_networkId)))
|
||||||
return -1;
|
return -1;
|
||||||
const Identity id(RR->topology->getIdentity(_signedBy));
|
const Identity id(RR->topology->getIdentity(tPtr,_signedBy));
|
||||||
if (!id) {
|
if (!id) {
|
||||||
RR->sw->requestWhois(_signedBy);
|
RR->sw->requestWhois(tPtr,_signedBy);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -105,9 +105,10 @@ public:
|
|||||||
* Check this tag's signature
|
* Check this tag's signature
|
||||||
*
|
*
|
||||||
* @param RR Runtime environment to allow identity lookup for signedBy
|
* @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
|
* @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>
|
template<unsigned int C>
|
||||||
inline void serialize(Buffer<C> &b,const bool forSign = false) const
|
inline void serialize(Buffer<C> &b,const bool forSign = false) const
|
||||||
|
|||||||
@@ -55,19 +55,19 @@ namespace ZeroTier {
|
|||||||
#define ZT_DEFAULT_WORLD_LENGTH 634
|
#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};
|
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),
|
RR(renv),
|
||||||
_trustedPathCount(0),
|
_trustedPathCount(0),
|
||||||
_amRoot(false)
|
_amRoot(false)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
World cachedPlanet;
|
World cachedPlanet;
|
||||||
std::string buf(RR->node->dataStoreGet("planet"));
|
std::string buf(RR->node->dataStoreGet(tPtr,"planet"));
|
||||||
if (buf.length() > 0) {
|
if (buf.length() > 0) {
|
||||||
Buffer<ZT_WORLD_MAX_SERIALIZED_LENGTH> dswtmp(buf.data(),(unsigned int)buf.length());
|
Buffer<ZT_WORLD_MAX_SERIALIZED_LENGTH> dswtmp(buf.data(),(unsigned int)buf.length());
|
||||||
cachedPlanet.deserialize(dswtmp,0);
|
cachedPlanet.deserialize(dswtmp,0);
|
||||||
}
|
}
|
||||||
addWorld(cachedPlanet,false);
|
addWorld(tPtr,cachedPlanet,false);
|
||||||
} catch ( ... ) {}
|
} catch ( ... ) {}
|
||||||
|
|
||||||
World defaultPlanet;
|
World defaultPlanet;
|
||||||
@@ -75,10 +75,10 @@ Topology::Topology(const RuntimeEnvironment *renv) :
|
|||||||
Buffer<ZT_DEFAULT_WORLD_LENGTH> wtmp(ZT_DEFAULT_WORLD,ZT_DEFAULT_WORLD_LENGTH);
|
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
|
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
|
#ifdef ZT_TRACE
|
||||||
if ((!peer)||(peer->address() == RR->identity.address())) {
|
if ((!peer)||(peer->address() == RR->identity.address())) {
|
||||||
@@ -98,12 +98,12 @@ SharedPtr<Peer> Topology::addPeer(const SharedPtr<Peer> &peer)
|
|||||||
np = hp;
|
np = hp;
|
||||||
}
|
}
|
||||||
|
|
||||||
saveIdentity(np->identity());
|
saveIdentity(tPtr,np->identity());
|
||||||
|
|
||||||
return np;
|
return np;
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedPtr<Peer> Topology::getPeer(const Address &zta)
|
SharedPtr<Peer> Topology::getPeer(void *tPtr,const Address &zta)
|
||||||
{
|
{
|
||||||
if (zta == RR->identity.address()) {
|
if (zta == RR->identity.address()) {
|
||||||
TRACE("BUG: ignored attempt to getPeer() for self, returned NULL");
|
TRACE("BUG: ignored attempt to getPeer() for self, returned NULL");
|
||||||
@@ -118,7 +118,7 @@ SharedPtr<Peer> Topology::getPeer(const Address &zta)
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Identity id(_getIdentity(zta));
|
Identity id(_getIdentity(tPtr,zta));
|
||||||
if (id) {
|
if (id) {
|
||||||
SharedPtr<Peer> np(new Peer(RR,RR->identity,id));
|
SharedPtr<Peer> np(new Peer(RR,RR->identity,id));
|
||||||
{
|
{
|
||||||
@@ -134,7 +134,7 @@ SharedPtr<Peer> Topology::getPeer(const Address &zta)
|
|||||||
return SharedPtr<Peer>();
|
return SharedPtr<Peer>();
|
||||||
}
|
}
|
||||||
|
|
||||||
Identity Topology::getIdentity(const Address &zta)
|
Identity Topology::getIdentity(void *tPtr,const Address &zta)
|
||||||
{
|
{
|
||||||
if (zta == RR->identity.address()) {
|
if (zta == RR->identity.address()) {
|
||||||
return RR->identity;
|
return RR->identity;
|
||||||
@@ -144,15 +144,15 @@ Identity Topology::getIdentity(const Address &zta)
|
|||||||
if (ap)
|
if (ap)
|
||||||
return (*ap)->identity();
|
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) {
|
if (id) {
|
||||||
char p[128];
|
char p[128];
|
||||||
Utils::snprintf(p,sizeof(p),"iddb.d/%.10llx",(unsigned long long)id.address().toInt());
|
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;
|
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))
|
if ((newWorld.type() != World::TYPE_PLANET)&&(newWorld.type() != World::TYPE_MOON))
|
||||||
return false;
|
return false;
|
||||||
@@ -328,29 +328,29 @@ bool Topology::addWorld(const World &newWorld,bool alwaysAcceptNew)
|
|||||||
try {
|
try {
|
||||||
Buffer<ZT_WORLD_MAX_SERIALIZED_LENGTH> dswtmp;
|
Buffer<ZT_WORLD_MAX_SERIALIZED_LENGTH> dswtmp;
|
||||||
existing->serialize(dswtmp,false);
|
existing->serialize(dswtmp,false);
|
||||||
RR->node->dataStorePut(savePath,dswtmp.data(),dswtmp.size(),false);
|
RR->node->dataStorePut(tPtr,savePath,dswtmp.data(),dswtmp.size(),false);
|
||||||
} catch ( ... ) {
|
} catch ( ... ) {
|
||||||
RR->node->dataStoreDelete(savePath);
|
RR->node->dataStoreDelete(tPtr,savePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
_memoizeUpstreams();
|
_memoizeUpstreams(tPtr);
|
||||||
|
|
||||||
return true;
|
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];
|
char savePath[64];
|
||||||
Utils::snprintf(savePath,sizeof(savePath),"moons.d/%.16llx.moon",id);
|
Utils::snprintf(savePath,sizeof(savePath),"moons.d/%.16llx.moon",id);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
std::string moonBin(RR->node->dataStoreGet(savePath));
|
std::string moonBin(RR->node->dataStoreGet(tPtr,savePath));
|
||||||
if (moonBin.length() > 1) {
|
if (moonBin.length() > 1) {
|
||||||
Buffer<ZT_WORLD_MAX_SERIALIZED_LENGTH> wtmp(moonBin.data(),(unsigned int)moonBin.length());
|
Buffer<ZT_WORLD_MAX_SERIALIZED_LENGTH> wtmp(moonBin.data(),(unsigned int)moonBin.length());
|
||||||
World w;
|
World w;
|
||||||
w.deserialize(wtmp);
|
w.deserialize(wtmp);
|
||||||
if ((w.type() == World::TYPE_MOON)&&(w.id() == id)) {
|
if ((w.type() == World::TYPE_MOON)&&(w.id() == id)) {
|
||||||
addWorld(w,true);
|
addWorld(tPtr,w,true);
|
||||||
return;
|
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 _l1(_upstreams_m);
|
||||||
Mutex::Lock _l2(_peers_m);
|
Mutex::Lock _l2(_peers_m);
|
||||||
@@ -375,7 +375,7 @@ void Topology::removeMoon(const uint64_t id)
|
|||||||
} else {
|
} else {
|
||||||
char savePath[64];
|
char savePath[64];
|
||||||
Utils::snprintf(savePath,sizeof(savePath),"moons.d/%.16llx.moon",id);
|
Utils::snprintf(savePath,sizeof(savePath),"moons.d/%.16llx.moon",id);
|
||||||
RR->node->dataStoreDelete(savePath);
|
RR->node->dataStoreDelete(tPtr,savePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_moons.swap(nm);
|
_moons.swap(nm);
|
||||||
@@ -387,7 +387,7 @@ void Topology::removeMoon(const uint64_t id)
|
|||||||
}
|
}
|
||||||
_moonSeeds.swap(cm);
|
_moonSeeds.swap(cm);
|
||||||
|
|
||||||
_memoizeUpstreams();
|
_memoizeUpstreams(tPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Topology::clean(uint64_t now)
|
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];
|
char p[128];
|
||||||
Utils::snprintf(p,sizeof(p),"iddb.d/%.10llx",(unsigned long long)zta.toInt());
|
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) {
|
if (ids.length() > 0) {
|
||||||
try {
|
try {
|
||||||
return Identity(ids);
|
return Identity(ids);
|
||||||
@@ -428,7 +428,7 @@ Identity Topology::_getIdentity(const Address &zta)
|
|||||||
return Identity();
|
return Identity();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Topology::_memoizeUpstreams()
|
void Topology::_memoizeUpstreams(void *tPtr)
|
||||||
{
|
{
|
||||||
// assumes _upstreams_m and _peers_m are locked
|
// assumes _upstreams_m and _peers_m are locked
|
||||||
_upstreamAddresses.clear();
|
_upstreamAddresses.clear();
|
||||||
@@ -442,7 +442,7 @@ void Topology::_memoizeUpstreams()
|
|||||||
SharedPtr<Peer> &hp = _peers[i->identity.address()];
|
SharedPtr<Peer> &hp = _peers[i->identity.address()];
|
||||||
if (!hp) {
|
if (!hp) {
|
||||||
hp = new Peer(RR,RR->identity,i->identity);
|
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()];
|
SharedPtr<Peer> &hp = _peers[i->identity.address()];
|
||||||
if (!hp) {
|
if (!hp) {
|
||||||
hp = new Peer(RR,RR->identity,i->identity);
|
hp = new Peer(RR,RR->identity,i->identity);
|
||||||
saveIdentity(i->identity);
|
saveIdentity(tPtr,i->identity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ class RuntimeEnvironment;
|
|||||||
class Topology
|
class Topology
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Topology(const RuntimeEnvironment *renv);
|
Topology(const RuntimeEnvironment *renv,void *tPtr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a peer to database
|
* Add a peer to database
|
||||||
@@ -58,18 +58,20 @@ public:
|
|||||||
* This will not replace existing peers. In that case the existing peer
|
* This will not replace existing peers. In that case the existing peer
|
||||||
* record is returned.
|
* 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
|
* @param peer Peer to add
|
||||||
* @return New or existing peer (should replace 'peer')
|
* @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
|
* 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
|
* @param zta ZeroTier address of peer
|
||||||
* @return Peer or NULL if not found
|
* @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)
|
* Get a peer only if it is presently in memory (no disk cache)
|
||||||
@@ -109,10 +111,11 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Get the identity of a peer
|
* 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
|
* @param zta ZeroTier address of peer
|
||||||
* @return Identity or NULL Identity if not found
|
* @return Identity or NULL Identity if not found
|
||||||
*/
|
*/
|
||||||
Identity getIdentity(const Address &zta);
|
Identity getIdentity(void *tPtr,const Address &zta);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cache an identity
|
* Cache an identity
|
||||||
@@ -120,9 +123,10 @@ public:
|
|||||||
* This is done automatically on addPeer(), and so is only useful for
|
* This is done automatically on addPeer(), and so is only useful for
|
||||||
* cluster identity replication.
|
* 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
|
* @param id Identity to cache
|
||||||
*/
|
*/
|
||||||
void saveIdentity(const Identity &id);
|
void saveIdentity(void *tPtr,const Identity &id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current best upstream peer
|
* Get the current best upstream peer
|
||||||
@@ -184,14 +188,17 @@ public:
|
|||||||
{
|
{
|
||||||
Mutex::Lock _l(_upstreams_m);
|
Mutex::Lock _l(_upstreams_m);
|
||||||
for(std::vector<World::Root>::const_iterator i(_planet.roots().begin());i!=_planet.roots().end();++i) {
|
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()];
|
std::vector<InetAddress> &ips = eps[i->identity.address()];
|
||||||
for(std::vector<InetAddress>::const_iterator j(i->stableEndpoints.begin());j!=i->stableEndpoints.end();++j) {
|
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())
|
if (std::find(ips.begin(),ips.end(),*j) == ips.end())
|
||||||
ips.push_back(*j);
|
ips.push_back(*j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
for(std::vector<World>::const_iterator m(_moons.begin());m!=_moons.end();++m) {
|
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) {
|
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()];
|
std::vector<InetAddress> &ips = eps[i->identity.address()];
|
||||||
for(std::vector<InetAddress>::const_iterator j(i->stableEndpoints.begin());j!=i->stableEndpoints.end();++j) {
|
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())
|
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)
|
for(std::vector< std::pair<uint64_t,Address> >::const_iterator m(_moonSeeds.begin());m!=_moonSeeds.end();++m)
|
||||||
eps[m->second];
|
eps[m->second];
|
||||||
}
|
}
|
||||||
@@ -263,11 +271,12 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Validate new world and update if newer and signature is okay
|
* 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 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
|
* @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)
|
* @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
|
* Add a moon
|
||||||
@@ -278,14 +287,15 @@ public:
|
|||||||
* @param id Moon ID
|
* @param id Moon ID
|
||||||
* @param seed If non-NULL, an address of any member of the moon to contact
|
* @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
|
* 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
|
* @param id Moon's world ID
|
||||||
*/
|
*/
|
||||||
void removeMoon(const uint64_t id);
|
void removeMoon(void *tPtr,const uint64_t id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clean and flush database
|
* Clean and flush database
|
||||||
@@ -416,8 +426,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Identity _getIdentity(const Address &zta);
|
Identity _getIdentity(void *tPtr,const Address &zta);
|
||||||
void _memoizeUpstreams();
|
void _memoizeUpstreams(void *tPtr);
|
||||||
|
|
||||||
const RuntimeEnvironment *const RR;
|
const RuntimeEnvironment *const RR;
|
||||||
|
|
||||||
|
|||||||
95
zto/one.cpp
95
zto/one.cpp
@@ -72,6 +72,7 @@
|
|||||||
|
|
||||||
#include "osdep/OSUtils.hpp"
|
#include "osdep/OSUtils.hpp"
|
||||||
#include "osdep/Http.hpp"
|
#include "osdep/Http.hpp"
|
||||||
|
#include "osdep/Thread.hpp"
|
||||||
|
|
||||||
#include "service/OneService.hpp"
|
#include "service/OneService.hpp"
|
||||||
|
|
||||||
@@ -84,7 +85,7 @@ using namespace ZeroTier;
|
|||||||
static OneService *volatile zt1Service = (OneService *)0;
|
static OneService *volatile zt1Service = (OneService *)0;
|
||||||
|
|
||||||
#define PROGRAM_NAME "ZeroTier One"
|
#define PROGRAM_NAME "ZeroTier One"
|
||||||
#define COPYRIGHT_NOTICE "Copyright © 2011–2016 ZeroTier, Inc."
|
#define COPYRIGHT_NOTICE "Copyright (c) 2011-2017 ZeroTier, Inc."
|
||||||
#define LICENSE_GRANT \
|
#define LICENSE_GRANT \
|
||||||
"This is free software: you may copy, modify, and/or distribute this" ZT_EOL_S \
|
"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 \
|
"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)
|
static void cliPrintHelp(const char *pn,FILE *out)
|
||||||
{
|
{
|
||||||
fprintf(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,
|
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,
|
fprintf(out,
|
||||||
COPYRIGHT_NOTICE ZT_EOL_S
|
COPYRIGHT_NOTICE ZT_EOL_S
|
||||||
LICENSE_GRANT 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);
|
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__
|
#ifdef __WINDOWS__
|
||||||
int _tmain(int argc, _TCHAR* argv[])
|
int _tmain(int argc, _TCHAR* argv[])
|
||||||
#else
|
#else
|
||||||
@@ -1420,8 +1468,8 @@ int main(int argc,char **argv)
|
|||||||
} else {
|
} else {
|
||||||
// Running from service manager
|
// Running from service manager
|
||||||
_winPokeAHole();
|
_winPokeAHole();
|
||||||
ZeroTierOneService zt1Service;
|
ZeroTierOneService zt1WindowsService;
|
||||||
if (CServiceBase::Run(zt1Service) == TRUE) {
|
if (CServiceBase::Run(zt1WindowsService) == TRUE) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr,"%s: unable to start service (try -h for help)" ZT_EOL_S,argv[0]);
|
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__
|
#endif // __WINDOWS__
|
||||||
|
|
||||||
#ifdef __UNIX_LIKE__
|
#ifdef __UNIX_LIKE__
|
||||||
|
|
||||||
#ifdef ZT_HAVE_DROP_PRIVILEGES
|
#ifdef ZT_HAVE_DROP_PRIVILEGES
|
||||||
dropPrivileges(argv[0],homeDir);
|
dropPrivileges(argv[0],homeDir);
|
||||||
#endif
|
#endif
|
||||||
@@ -1447,35 +1494,13 @@ int main(int argc,char **argv)
|
|||||||
}
|
}
|
||||||
#endif // __UNIX_LIKE__
|
#endif // __UNIX_LIKE__
|
||||||
|
|
||||||
unsigned int returnValue = 0;
|
_OneServiceRunner thr(argv[0],homeDir,port);
|
||||||
|
thr.threadMain();
|
||||||
|
//Thread::join(Thread::start(&thr));
|
||||||
|
|
||||||
for(;;) {
|
#ifdef __UNIX_LIKE__
|
||||||
zt1Service = OneService::newInstance(homeDir.c_str(),port);
|
OSUtils::rm(pidPath.c_str());
|
||||||
switch(zt1Service->run()) {
|
#endif
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
delete zt1Service;
|
return thr.returnValue;
|
||||||
zt1Service = (OneService *)0;
|
|
||||||
|
|
||||||
return returnValue;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ BSDEthernetTap::BSDEthernetTap(
|
|||||||
unsigned int metric,
|
unsigned int metric,
|
||||||
uint64_t nwid,
|
uint64_t nwid,
|
||||||
const char *friendlyName,
|
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) :
|
void *arg) :
|
||||||
_handler(handler),
|
_handler(handler),
|
||||||
_arg(arg),
|
_arg(arg),
|
||||||
@@ -460,8 +460,7 @@ void BSDEthernetTap::threadMain()
|
|||||||
to.setTo(getBuf,6);
|
to.setTo(getBuf,6);
|
||||||
from.setTo(getBuf + 6,6);
|
from.setTo(getBuf + 6,6);
|
||||||
unsigned int etherType = ntohs(((const uint16_t *)getBuf)[6]);
|
unsigned int etherType = ntohs(((const uint16_t *)getBuf)[6]);
|
||||||
// TODO: VLAN support
|
_handler(_arg,(void *)0,_nwid,from,to,etherType,0,(const void *)(getBuf + 14),r - 14);
|
||||||
_handler(_arg,_nwid,from,to,etherType,0,(const void *)(getBuf + 14),r - 14);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
r = 0;
|
r = 0;
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ public:
|
|||||||
unsigned int metric,
|
unsigned int metric,
|
||||||
uint64_t nwid,
|
uint64_t nwid,
|
||||||
const char *friendlyName,
|
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);
|
void *arg);
|
||||||
|
|
||||||
~BSDEthernetTap();
|
~BSDEthernetTap();
|
||||||
@@ -62,7 +62,7 @@ public:
|
|||||||
throw();
|
throw();
|
||||||
|
|
||||||
private:
|
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;
|
void *_arg;
|
||||||
uint64_t _nwid;
|
uint64_t _nwid;
|
||||||
Thread _thread;
|
Thread _thread;
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ LinuxEthernetTap::LinuxEthernetTap(
|
|||||||
unsigned int metric,
|
unsigned int metric,
|
||||||
uint64_t nwid,
|
uint64_t nwid,
|
||||||
const char *friendlyName,
|
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) :
|
void *arg) :
|
||||||
_handler(handler),
|
_handler(handler),
|
||||||
_arg(arg),
|
_arg(arg),
|
||||||
@@ -470,7 +470,7 @@ void LinuxEthernetTap::threadMain()
|
|||||||
from.setTo(getBuf + 6,6);
|
from.setTo(getBuf + 6,6);
|
||||||
unsigned int etherType = ntohs(((const uint16_t *)getBuf)[6]);
|
unsigned int etherType = ntohs(((const uint16_t *)getBuf)[6]);
|
||||||
// TODO: VLAN support
|
// 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;
|
r = 0;
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ public:
|
|||||||
unsigned int metric,
|
unsigned int metric,
|
||||||
uint64_t nwid,
|
uint64_t nwid,
|
||||||
const char *friendlyName,
|
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);
|
void *arg);
|
||||||
|
|
||||||
~LinuxEthernetTap();
|
~LinuxEthernetTap();
|
||||||
@@ -66,7 +66,7 @@ public:
|
|||||||
throw();
|
throw();
|
||||||
|
|
||||||
private:
|
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;
|
void *_arg;
|
||||||
uint64_t _nwid;
|
uint64_t _nwid;
|
||||||
Thread _thread;
|
Thread _thread;
|
||||||
|
|||||||
@@ -108,43 +108,6 @@ std::vector<std::string> OSUtils::listDirectory(const char *path)
|
|||||||
return r;
|
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 OSUtils::cleanDirectory(const char *path,const uint64_t olderThan)
|
||||||
{
|
{
|
||||||
long cleaned = 0;
|
long cleaned = 0;
|
||||||
@@ -162,7 +125,7 @@ long OSUtils::cleanDirectory(const char *path,const uint64_t olderThan)
|
|||||||
date.LowPart = ffd.ftLastWriteTime.dwLowDateTime;
|
date.LowPart = ffd.ftLastWriteTime.dwLowDateTime;
|
||||||
if (date.QuadPart > 0) {
|
if (date.QuadPart > 0) {
|
||||||
date.QuadPart -= adjust.QuadPart;
|
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);
|
Utils::snprintf(tmp, sizeof(tmp), "%s\\%s", path, ffd.cFileName);
|
||||||
if (DeleteFileA(tmp))
|
if (DeleteFileA(tmp))
|
||||||
++cleaned;
|
++cleaned;
|
||||||
|
|||||||
@@ -111,14 +111,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
static std::vector<std::string> listDirectory(const char *path);
|
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
|
* Clean a directory of files whose last modified time is older than this
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -314,7 +314,7 @@ OSXEthernetTap::OSXEthernetTap(
|
|||||||
unsigned int metric,
|
unsigned int metric,
|
||||||
uint64_t nwid,
|
uint64_t nwid,
|
||||||
const char *friendlyName,
|
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) :
|
void *arg) :
|
||||||
_handler(handler),
|
_handler(handler),
|
||||||
_arg(arg),
|
_arg(arg),
|
||||||
@@ -646,7 +646,7 @@ void OSXEthernetTap::threadMain()
|
|||||||
from.setTo(getBuf + 6,6);
|
from.setTo(getBuf + 6,6);
|
||||||
unsigned int etherType = ntohs(((const uint16_t *)getBuf)[6]);
|
unsigned int etherType = ntohs(((const uint16_t *)getBuf)[6]);
|
||||||
// TODO: VLAN support
|
// 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;
|
r = 0;
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ public:
|
|||||||
unsigned int metric,
|
unsigned int metric,
|
||||||
uint64_t nwid,
|
uint64_t nwid,
|
||||||
const char *friendlyName,
|
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);
|
void *arg);
|
||||||
|
|
||||||
~OSXEthernetTap();
|
~OSXEthernetTap();
|
||||||
@@ -67,7 +67,7 @@ public:
|
|||||||
throw();
|
throw();
|
||||||
|
|
||||||
private:
|
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;
|
void *_arg;
|
||||||
uint64_t _nwid;
|
uint64_t _nwid;
|
||||||
Thread _thread;
|
Thread _thread;
|
||||||
|
|||||||
@@ -456,7 +456,7 @@ WindowsEthernetTap::WindowsEthernetTap(
|
|||||||
unsigned int metric,
|
unsigned int metric,
|
||||||
uint64_t nwid,
|
uint64_t nwid,
|
||||||
const char *friendlyName,
|
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) :
|
void *arg) :
|
||||||
_handler(handler),
|
_handler(handler),
|
||||||
_arg(arg),
|
_arg(arg),
|
||||||
@@ -1058,8 +1058,7 @@ void WindowsEthernetTap::threadMain()
|
|||||||
MAC from(tapReadBuf + 6,6);
|
MAC from(tapReadBuf + 6,6);
|
||||||
unsigned int etherType = ((((unsigned int)tapReadBuf[12]) & 0xff) << 8) | (((unsigned int)tapReadBuf[13]) & 0xff);
|
unsigned int etherType = ((((unsigned int)tapReadBuf[12]) & 0xff) << 8) | (((unsigned int)tapReadBuf[13]) & 0xff);
|
||||||
try {
|
try {
|
||||||
// TODO: decode vlans
|
_handler(_arg,(void *)0,_nwid,from,to,etherType,0,tapReadBuf + 14,bytesRead - 14);
|
||||||
_handler(_arg,_nwid,from,to,etherType,0,tapReadBuf + 14,bytesRead - 14);
|
|
||||||
} catch ( ... ) {} // handlers should not throw
|
} catch ( ... ) {} // handlers should not throw
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ public:
|
|||||||
unsigned int metric,
|
unsigned int metric,
|
||||||
uint64_t nwid,
|
uint64_t nwid,
|
||||||
const char *friendlyName,
|
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);
|
void *arg);
|
||||||
|
|
||||||
~WindowsEthernetTap();
|
~WindowsEthernetTap();
|
||||||
@@ -118,7 +118,7 @@ private:
|
|||||||
void _setRegistryIPv4Value(const char *regKey,const std::vector<std::string> &value);
|
void _setRegistryIPv4Value(const char *regKey,const std::vector<std::string> &value);
|
||||||
void _syncIps();
|
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;
|
void *_arg;
|
||||||
MAC _mac;
|
MAC _mac;
|
||||||
uint64_t _nwid;
|
uint64_t _nwid;
|
||||||
|
|||||||
@@ -582,8 +582,34 @@ static int testPacket()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _testExcept(int &depth)
|
||||||
|
{
|
||||||
|
if (depth >= 16) {
|
||||||
|
throw std::runtime_error("LOL!");
|
||||||
|
} else {
|
||||||
|
++depth;
|
||||||
|
_testExcept(depth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int testOther()
|
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();
|
std::cout << "[other] Testing Hashtable... "; std::cout.flush();
|
||||||
{
|
{
|
||||||
Hashtable<uint64_t,std::string> ht;
|
Hashtable<uint64_t,std::string> ht;
|
||||||
|
|||||||
@@ -291,21 +291,21 @@ static void _moonToJson(nlohmann::json &mj,const World &world)
|
|||||||
|
|
||||||
class OneServiceImpl;
|
class OneServiceImpl;
|
||||||
|
|
||||||
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);
|
||||||
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);
|
||||||
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);
|
||||||
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);
|
||||||
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);
|
||||||
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);
|
||||||
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);
|
||||||
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);
|
||||||
|
|
||||||
#ifdef ZT_ENABLE_CLUSTER
|
#ifdef ZT_ENABLE_CLUSTER
|
||||||
static void SclusterSendFunction(void *uptr,unsigned int toMemberId,const void *data,unsigned int len);
|
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);
|
static int SclusterGeoIpFunction(void *uptr,const struct sockaddr_storage *addr,int *x,int *y,int *z);
|
||||||
#endif
|
#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 ShttpOnMessageBegin(http_parser *parser);
|
||||||
static int ShttpOnUrl(http_parser *parser,const char *ptr,size_t length);
|
static int ShttpOnUrl(http_parser *parser,const char *ptr,size_t length);
|
||||||
@@ -488,6 +488,8 @@ public:
|
|||||||
,_updater((SoftwareUpdater *)0)
|
,_updater((SoftwareUpdater *)0)
|
||||||
,_updateAutoApply(false)
|
,_updateAutoApply(false)
|
||||||
,_primaryPort(port)
|
,_primaryPort(port)
|
||||||
|
,_v4TcpControlSocket((PhySocket *)0)
|
||||||
|
,_v6TcpControlSocket((PhySocket *)0)
|
||||||
,_lastDirectReceiveFromGlobal(0)
|
,_lastDirectReceiveFromGlobal(0)
|
||||||
#ifdef ZT_TCP_FALLBACK_RELAY
|
#ifdef ZT_TCP_FALLBACK_RELAY
|
||||||
,_lastSendToGlobalV4(0)
|
,_lastSendToGlobalV4(0)
|
||||||
@@ -571,7 +573,7 @@ public:
|
|||||||
cb.eventCallback = SnodeEventCallback;
|
cb.eventCallback = SnodeEventCallback;
|
||||||
cb.pathCheckFunction = SnodePathCheckFunction;
|
cb.pathCheckFunction = SnodePathCheckFunction;
|
||||||
cb.pathLookupFunction = SnodePathLookupFunction;
|
cb.pathLookupFunction = SnodePathLookupFunction;
|
||||||
_node = new Node(this,&cb,OSUtils::now());
|
_node = new Node(this,(void *)0,&cb,OSUtils::now());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read local configuration
|
// Read local configuration
|
||||||
@@ -745,14 +747,6 @@ public:
|
|||||||
for(int i=0;i<3;++i)
|
for(int i=0;i<3;++i)
|
||||||
_portsBE[i] = Utils::hton((uint16_t)_ports[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());
|
_controller = new EmbeddedNetworkController(_node,(_homePath + ZT_PATH_SEPARATOR_S ZT_CONTROLLER_DB_PATH).c_str());
|
||||||
_node->setNetconfMaster((void *)_controller);
|
_node->setNetconfMaster((void *)_controller);
|
||||||
|
|
||||||
@@ -810,7 +804,7 @@ public:
|
|||||||
for(std::vector<std::string>::iterator f(networksDotD.begin());f!=networksDotD.end();++f) {
|
for(std::vector<std::string>::iterator f(networksDotD.begin());f!=networksDotD.end();++f) {
|
||||||
std::size_t dot = f->find_last_of('.');
|
std::size_t dot = f->find_last_of('.');
|
||||||
if ((dot == 16)&&(f->substr(16) == ".conf"))
|
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
|
{ // Load existing moons
|
||||||
@@ -818,7 +812,7 @@ public:
|
|||||||
for(std::vector<std::string>::iterator f(moonsDotD.begin());f!=moonsDotD.end();++f) {
|
for(std::vector<std::string>::iterator f(moonsDotD.begin());f!=moonsDotD.end();++f) {
|
||||||
std::size_t dot = f->find_last_of('.');
|
std::size_t dot = f->find_last_of('.');
|
||||||
if ((dot == 16)&&(f->substr(16) == ".moon"))
|
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;
|
uint64_t dl = _nextBackgroundTaskDeadline;
|
||||||
if (dl <= now) {
|
if (dl <= now) {
|
||||||
_node->processBackgroundTasks(now,&_nextBackgroundTaskDeadline);
|
_node->processBackgroundTasks((void *)0,now,&_nextBackgroundTaskDeadline);
|
||||||
dl = _nextBackgroundTaskDeadline;
|
dl = _nextBackgroundTaskDeadline;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -898,7 +892,7 @@ public:
|
|||||||
std::vector<MulticastGroup> added,removed;
|
std::vector<MulticastGroup> added,removed;
|
||||||
n->second.tap->scanMulticastGroups(added,removed);
|
n->second.tap->scanMulticastGroups(added,removed);
|
||||||
for(std::vector<MulticastGroup>::iterator m(added.begin());m!=added.end();++m)
|
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)
|
for(std::vector<MulticastGroup>::iterator m(removed.begin());m!=removed.end();++m)
|
||||||
_node->multicastUnsubscribe(n->first,m->mac().toInt(),m->adi());
|
_node->multicastUnsubscribe(n->first,m->mac().toInt(),m->adi());
|
||||||
}
|
}
|
||||||
@@ -989,12 +983,12 @@ public:
|
|||||||
#ifdef ZT_SDK
|
#ifdef ZT_SDK
|
||||||
virtual void leave(const char *hp)
|
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)
|
virtual void join(const char *hp)
|
||||||
{
|
{
|
||||||
_node->join(Utils::hexStrToU64(hp),NULL);
|
_node->join(Utils::hexStrToU64(hp),NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::string givenHomePath()
|
virtual std::string givenHomePath()
|
||||||
@@ -1178,9 +1172,10 @@ public:
|
|||||||
#else
|
#else
|
||||||
settings["portMappingEnabled"] = false; // not supported in build
|
settings["portMappingEnabled"] = false; // not supported in build
|
||||||
#endif
|
#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());
|
const World planet(_node->planet());
|
||||||
res["planetWorldId"] = planet.id();
|
res["planetWorldId"] = planet.id();
|
||||||
res["planetWorldTimestamp"] = planet.timestamp();
|
res["planetWorldTimestamp"] = planet.timestamp();
|
||||||
@@ -1343,7 +1338,7 @@ public:
|
|||||||
res["signature"] = json();
|
res["signature"] = json();
|
||||||
res["updatesMustBeSignedBy"] = json();
|
res["updatesMustBeSignedBy"] = json();
|
||||||
res["waiting"] = true;
|
res["waiting"] = true;
|
||||||
_node->orbit(id,seed);
|
_node->orbit((void *)0,id,seed);
|
||||||
scode = 200;
|
scode = 200;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1352,7 +1347,7 @@ public:
|
|||||||
if (ps.size() == 2) {
|
if (ps.size() == 2) {
|
||||||
|
|
||||||
uint64_t wantnw = Utils::hexStrToU64(ps[1].c_str());
|
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();
|
ZT_VirtualNetworkList *nws = _node->networks();
|
||||||
if (nws) {
|
if (nws) {
|
||||||
for(unsigned long i=0;i<nws->networkCount;++i) {
|
for(unsigned long i=0;i<nws->networkCount;++i) {
|
||||||
@@ -1397,7 +1392,7 @@ public:
|
|||||||
|
|
||||||
if (ps[0] == "moon") {
|
if (ps[0] == "moon") {
|
||||||
if (ps.size() == 2) {
|
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;
|
res["result"] = true;
|
||||||
scode = 200;
|
scode = 200;
|
||||||
} // else 404
|
} // else 404
|
||||||
@@ -1408,7 +1403,7 @@ public:
|
|||||||
uint64_t wantnw = Utils::hexStrToU64(ps[1].c_str());
|
uint64_t wantnw = Utils::hexStrToU64(ps[1].c_str());
|
||||||
for(unsigned long i=0;i<nws->networkCount;++i) {
|
for(unsigned long i=0;i<nws->networkCount;++i) {
|
||||||
if (nws->networks[i].nwid == wantnw) {
|
if (nws->networks[i].nwid == wantnw) {
|
||||||
_node->leave(wantnw,(void **)0);
|
_node->leave(wantnw,(void **)0,(void *)0);
|
||||||
res["result"] = true;
|
res["result"] = true;
|
||||||
scode = 200;
|
scode = 200;
|
||||||
break;
|
break;
|
||||||
@@ -1730,6 +1725,7 @@ public:
|
|||||||
_lastDirectReceiveFromGlobal = OSUtils::now();
|
_lastDirectReceiveFromGlobal = OSUtils::now();
|
||||||
|
|
||||||
const ZT_ResultCode rc = _node->processWirePacket(
|
const ZT_ResultCode rc = _node->processWirePacket(
|
||||||
|
(void *)0,
|
||||||
OSUtils::now(),
|
OSUtils::now(),
|
||||||
reinterpret_cast<const struct sockaddr_storage *>(localAddr),
|
reinterpret_cast<const struct sockaddr_storage *>(localAddr),
|
||||||
(const struct sockaddr_storage *)from, // Phy<> uses sockaddr_storage, so it'll always be that big
|
(const struct sockaddr_storage *)from, // Phy<> uses sockaddr_storage, so it'll always be that big
|
||||||
@@ -1882,6 +1878,7 @@ public:
|
|||||||
if (from) {
|
if (from) {
|
||||||
InetAddress fakeTcpLocalInterfaceAddress((uint32_t)0xffffffff,0xffff);
|
InetAddress fakeTcpLocalInterfaceAddress((uint32_t)0xffffffff,0xffff);
|
||||||
const ZT_ResultCode rc = _node->processWirePacket(
|
const ZT_ResultCode rc = _node->processWirePacket(
|
||||||
|
(void *)0,
|
||||||
OSUtils::now(),
|
OSUtils::now(),
|
||||||
reinterpret_cast<struct sockaddr_storage *>(&fakeTcpLocalInterfaceAddress),
|
reinterpret_cast<struct sockaddr_storage *>(&fakeTcpLocalInterfaceAddress),
|
||||||
reinterpret_cast<struct sockaddr_storage *>(&from),
|
reinterpret_cast<struct sockaddr_storage *>(&from),
|
||||||
@@ -1951,6 +1948,7 @@ public:
|
|||||||
try {
|
try {
|
||||||
char friendlyName[128];
|
char friendlyName[128];
|
||||||
Utils::snprintf(friendlyName,sizeof(friendlyName),"ZeroTier One [%.16llx]",nwid);
|
Utils::snprintf(friendlyName,sizeof(friendlyName),"ZeroTier One [%.16llx]",nwid);
|
||||||
|
|
||||||
n.tap = new EthernetTap(
|
n.tap = new EthernetTap(
|
||||||
_homePath.c_str(),
|
_homePath.c_str(),
|
||||||
MAC(nwc->mac),
|
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)
|
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)
|
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); }
|
{ 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); }
|
{ 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); }
|
{ 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); }
|
{ 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); }
|
{ 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); }
|
{ 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); }
|
{ 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); }
|
{ return reinterpret_cast<OneServiceImpl *>(uptr)->nodePathLookupFunction(ztaddr,family,result); }
|
||||||
|
|
||||||
#ifdef ZT_ENABLE_CLUSTER
|
#ifdef ZT_ENABLE_CLUSTER
|
||||||
@@ -2494,7 +2492,7 @@ static int SclusterGeoIpFunction(void *uptr,const struct sockaddr_storage *addr,
|
|||||||
}
|
}
|
||||||
#endif
|
#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); }
|
{ reinterpret_cast<OneServiceImpl *>(uptr)->tapFrameHandler(nwid,from,to,etherType,vlanId,data,len); }
|
||||||
|
|
||||||
static int ShttpOnMessageBegin(http_parser *parser)
|
static int ShttpOnMessageBegin(http_parser *parser)
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Local service for ZeroTier One as system VPN/NFV provider
|
* Local service for ZeroTier One as system VPN/NFV provider
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -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 */
|
"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 */
|
"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 */
|
"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) */
|
"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 */
|
"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. */
|
"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": {
|
"settings": {
|
||||||
"relayPolicy": "ALWAYS"
|
"softwareUpdate": "apply",
|
||||||
|
"softwraeUpdateChannel": "release"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -47,13 +47,6 @@
|
|||||||
|
|
||||||
#include "../osdep/OSUtils.hpp"
|
#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 {
|
namespace ZeroTier {
|
||||||
|
|
||||||
SoftwareUpdater::SoftwareUpdater(Node &node,const std::string &homePath) :
|
SoftwareUpdater::SoftwareUpdater(Node &node,const std::string &homePath) :
|
||||||
@@ -65,31 +58,8 @@ SoftwareUpdater::SoftwareUpdater(Node &node,const std::string &homePath) :
|
|||||||
_latestValid(false),
|
_latestValid(false),
|
||||||
_downloadLength(0)
|
_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());
|
OSUtils::rm((_homePath + ZT_PATH_SEPARATOR_S ZT_SOFTWARE_UPDATE_BIN_FILENAME).c_str());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
SoftwareUpdater::~SoftwareUpdater()
|
SoftwareUpdater::~SoftwareUpdater()
|
||||||
{
|
{
|
||||||
@@ -173,8 +143,18 @@ void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void
|
|||||||
unsigned int bestVRev = rvRev;
|
unsigned int bestVRev = rvRev;
|
||||||
unsigned int bestVBld = rvBld;
|
unsigned int bestVBld = rvBld;
|
||||||
for(std::map< Array<uint8_t,16>,_D >::const_iterator d(_dist.begin());d!=_dist.end();++d) {
|
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)&&
|
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::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_CHANNEL],"") == rvChannel)&&
|
||||||
(OSUtils::jsonString(d->second.meta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_SIGNED_BY],"") == expectedSigner)) {
|
(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;
|
std::string lj;
|
||||||
lj.push_back((char)VERB_LATEST);
|
lj.push_back((char)VERB_LATEST);
|
||||||
lj.append(OSUtils::jsonDump(*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) {
|
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);
|
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);
|
fflush(_distLog);
|
||||||
@@ -214,10 +194,7 @@ void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void
|
|||||||
if (_latestMeta != req) {
|
if (_latestMeta != req) {
|
||||||
_latestMeta = req;
|
_latestMeta = req;
|
||||||
_latestValid = false;
|
_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());
|
OSUtils::rm((_homePath + ZT_PATH_SEPARATOR_S ZT_SOFTWARE_UPDATE_BIN_FILENAME).c_str());
|
||||||
|
|
||||||
_download = std::string();
|
_download = std::string();
|
||||||
memcpy(_downloadHashPrefix.data,hash.data(),16);
|
memcpy(_downloadHashPrefix.data,hash.data(),16);
|
||||||
_downloadLength = len;
|
_downloadLength = len;
|
||||||
@@ -228,7 +205,7 @@ void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void
|
|||||||
gd.append((uint8_t)VERB_GET_DATA);
|
gd.append((uint8_t)VERB_GET_DATA);
|
||||||
gd.append(_downloadHashPrefix.data,16);
|
gd.append(_downloadHashPrefix.data,16);
|
||||||
gd.append((uint32_t)_download.length());
|
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());
|
//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(reinterpret_cast<const uint8_t *>(data) + 1,16);
|
||||||
buf.append((uint32_t)idx);
|
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)));
|
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);
|
//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((uint8_t)VERB_GET_DATA);
|
||||||
gd.append(_downloadHashPrefix.data,16);
|
gd.append(_downloadHashPrefix.data,16);
|
||||||
gd.append((uint32_t)_download.length());
|
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());
|
//printf(">> GET_DATA @%u\n",(unsigned int)_download.length());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -281,14 +258,14 @@ void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
if (_distLog) {
|
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);
|
fflush(_distLog);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} catch ( ... ) {
|
} catch ( ... ) {
|
||||||
if (_distLog) {
|
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);
|
fflush(_distLog);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -319,7 +296,7 @@ bool SoftwareUpdater::check(const uint64_t now)
|
|||||||
ZT_BUILD_ARCHITECTURE,
|
ZT_BUILD_ARCHITECTURE,
|
||||||
(int)ZT_VENDOR_ZEROTIER,
|
(int)ZT_VENDOR_ZEROTIER,
|
||||||
_channel.c_str());
|
_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");
|
//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 is the very important security validation part that makes sure
|
||||||
// this software update doesn't have cooties.
|
// 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);
|
const std::string binPath(_homePath + ZT_PATH_SEPARATOR_S ZT_SOFTWARE_UPDATE_BIN_FILENAME);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// (1) Check the hash itself to make sure the image is basically okay
|
// (1) Check the hash itself to make sure the image is basically okay
|
||||||
uint8_t sha512[ZT_SHA512_DIGEST_LEN];
|
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]));
|
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())) {
|
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.
|
// (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::rm(binPath.c_str());
|
||||||
OSUtils::lockDownFile(metaPath.c_str(),false);
|
if (OSUtils::writeFile(binPath.c_str(),_download)) {
|
||||||
OSUtils::lockDownFile(binPath.c_str(),false);
|
OSUtils::lockDownFile(binPath.c_str(),false);
|
||||||
_latestValid = true;
|
_latestValid = true;
|
||||||
//printf("VALID UPDATE\n%s\n",OSUtils::jsonDump(_latestMeta).c_str());
|
//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.
|
// If we get here, checks failed.
|
||||||
//printf("INVALID UPDATE (!!!)\n%s\n",OSUtils::jsonDump(_latestMeta).c_str());
|
//printf("INVALID UPDATE (!!!)\n%s\n",OSUtils::jsonDump(_latestMeta).c_str());
|
||||||
OSUtils::rm(metaPath.c_str());
|
|
||||||
OSUtils::rm(binPath.c_str());
|
OSUtils::rm(binPath.c_str());
|
||||||
_latestMeta = nlohmann::json();
|
_latestMeta = nlohmann::json();
|
||||||
_latestValid = false;
|
_latestValid = false;
|
||||||
@@ -369,7 +343,7 @@ bool SoftwareUpdater::check(const uint64_t now)
|
|||||||
gd.append((uint8_t)VERB_GET_DATA);
|
gd.append((uint8_t)VERB_GET_DATA);
|
||||||
gd.append(_downloadHashPrefix.data,16);
|
gd.append(_downloadHashPrefix.data,16);
|
||||||
gd.append((uint32_t)_download.length());
|
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());
|
//printf(">> GET_DATA @%u\n",(unsigned int)_download.length());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,11 +71,6 @@
|
|||||||
*/
|
*/
|
||||||
#define ZT_SOFTWARE_UPDATE_DEFAULT_CHANNEL "release"
|
#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
|
* Filename for latest update's binary image
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
/**
|
/**
|
||||||
* Revision
|
* Revision
|
||||||
*/
|
*/
|
||||||
#define ZEROTIER_ONE_VERSION_REVISION 0
|
#define ZEROTIER_ONE_VERSION_REVISION 3
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build version
|
* Build version
|
||||||
@@ -43,4 +43,11 @@
|
|||||||
*/
|
*/
|
||||||
#define ZEROTIER_ONE_VERSION_BUILD 0
|
#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
|
#endif
|
||||||
|
|||||||
@@ -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 localZtDir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\ZeroTier\\One";
|
||||||
String globalZtDir = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "\\ZeroTier\\One";
|
String globalZtDir = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "\\ZeroTier\\One";
|
||||||
@@ -55,6 +55,20 @@ namespace WinUI
|
|||||||
String authToken = "";
|
String authToken = "";
|
||||||
Int32 port = 9993;
|
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"))
|
if (!File.Exists(localZtDir + "\\authtoken.secret") || !File.Exists(localZtDir + "\\zerotier-one.port"))
|
||||||
{
|
{
|
||||||
// launch external process to copy file into place
|
// launch external process to copy file into place
|
||||||
@@ -127,7 +141,7 @@ namespace WinUI
|
|||||||
|
|
||||||
public APIHandler(int port, string authtoken)
|
public APIHandler(int port, string authtoken)
|
||||||
{
|
{
|
||||||
url = "http://localhost:" + port;
|
url = "http://127.0.0.1:" + port;
|
||||||
this.authtoken = authtoken;
|
this.authtoken = authtoken;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,6 +159,8 @@ namespace WinUI
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var httpResponse = (HttpWebResponse)request.GetResponse();
|
var httpResponse = (HttpWebResponse)request.GetResponse();
|
||||||
|
if (httpResponse.StatusCode == HttpStatusCode.OK)
|
||||||
|
{
|
||||||
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
|
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
|
||||||
{
|
{
|
||||||
var responseText = streamReader.ReadToEnd();
|
var responseText = streamReader.ReadToEnd();
|
||||||
@@ -161,15 +177,27 @@ namespace WinUI
|
|||||||
cb(status);
|
cb(status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (httpResponse.StatusCode == HttpStatusCode.Unauthorized)
|
||||||
|
{
|
||||||
|
APIHandler.initHandler(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
catch (System.Net.Sockets.SocketException)
|
catch (System.Net.Sockets.SocketException)
|
||||||
{
|
{
|
||||||
cb(null);
|
cb(null);
|
||||||
}
|
}
|
||||||
catch (System.Net.WebException)
|
catch (System.Net.WebException e)
|
||||||
|
{
|
||||||
|
if (((HttpWebResponse)e.Response).StatusCode == HttpStatusCode.Unauthorized)
|
||||||
|
{
|
||||||
|
APIHandler.initHandler(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
cb(null);
|
cb(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -188,6 +216,9 @@ namespace WinUI
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var httpResponse = (HttpWebResponse)request.GetResponse();
|
var httpResponse = (HttpWebResponse)request.GetResponse();
|
||||||
|
|
||||||
|
if (httpResponse.StatusCode == HttpStatusCode.OK)
|
||||||
|
{
|
||||||
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
|
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
|
||||||
{
|
{
|
||||||
var responseText = streamReader.ReadToEnd();
|
var responseText = streamReader.ReadToEnd();
|
||||||
@@ -209,15 +240,27 @@ namespace WinUI
|
|||||||
cb(networkList);
|
cb(networkList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (httpResponse.StatusCode == HttpStatusCode.Unauthorized)
|
||||||
|
{
|
||||||
|
APIHandler.initHandler(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
catch (System.Net.Sockets.SocketException)
|
catch (System.Net.Sockets.SocketException)
|
||||||
{
|
{
|
||||||
cb(null);
|
cb(null);
|
||||||
}
|
}
|
||||||
catch (System.Net.WebException)
|
catch (System.Net.WebException e)
|
||||||
|
{
|
||||||
|
if (((HttpWebResponse)e.Response).StatusCode == HttpStatusCode.Unauthorized)
|
||||||
|
{
|
||||||
|
APIHandler.initHandler(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
cb(null);
|
cb(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void JoinNetwork(string nwid, bool allowManaged = true, bool allowGlobal = false, bool allowDefault = false)
|
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();
|
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");
|
Console.WriteLine("Error sending join network message");
|
||||||
}
|
}
|
||||||
@@ -261,8 +308,12 @@ namespace WinUI
|
|||||||
{
|
{
|
||||||
MessageBox.Show("Error Joining Network: Cannot connect to ZeroTier service.");
|
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.");
|
MessageBox.Show("Error Joining Network: Cannot connect to ZeroTier service.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -282,7 +333,11 @@ namespace WinUI
|
|||||||
{
|
{
|
||||||
var httpResponse = (HttpWebResponse)request.GetResponse();
|
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");
|
Console.WriteLine("Error sending leave network message");
|
||||||
}
|
}
|
||||||
@@ -291,8 +346,12 @@ namespace WinUI
|
|||||||
{
|
{
|
||||||
MessageBox.Show("Error Leaving Network: Cannot connect to ZeroTier service.");
|
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.");
|
MessageBox.Show("Error Leaving Network: Cannot connect to ZeroTier service.");
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
@@ -317,6 +376,8 @@ namespace WinUI
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var httpResponse = (HttpWebResponse)request.GetResponse();
|
var httpResponse = (HttpWebResponse)request.GetResponse();
|
||||||
|
if (httpResponse.StatusCode == HttpStatusCode.OK)
|
||||||
|
{
|
||||||
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
|
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
|
||||||
{
|
{
|
||||||
var responseText = streamReader.ReadToEnd();
|
var responseText = streamReader.ReadToEnd();
|
||||||
@@ -333,14 +394,26 @@ namespace WinUI
|
|||||||
cb(peerList);
|
cb(peerList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (httpResponse.StatusCode == HttpStatusCode.Unauthorized)
|
||||||
|
{
|
||||||
|
APIHandler.initHandler(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
catch (System.Net.Sockets.SocketException)
|
catch (System.Net.Sockets.SocketException)
|
||||||
{
|
{
|
||||||
cb(null);
|
cb(null);
|
||||||
}
|
}
|
||||||
catch (System.Net.WebException)
|
catch (System.Net.WebException e)
|
||||||
|
{
|
||||||
|
if (((HttpWebResponse)e.Response).StatusCode == HttpStatusCode.Unauthorized)
|
||||||
|
{
|
||||||
|
APIHandler.initHandler(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
cb(null);
|
cb(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,96 +5,28 @@
|
|||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:local="clr-namespace:WinUI"
|
xmlns:local="clr-namespace:WinUI"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
Title="AboutView" Height="460" Width="300" Icon="ZeroTierIcon.ico">
|
Title="AboutView" Height="368.267" Width="300" Icon="ZeroTierIcon.ico">
|
||||||
<Grid>
|
<Grid>
|
||||||
<Image x:Name="image" HorizontalAlignment="Center" Height="100" Margin="0,10,0,0" VerticalAlignment="Top" Width="100" Source="ZeroTierIcon.ico"/>
|
<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>
|
<RichTextBox.Resources>
|
||||||
<Style TargetType="Hyperlink">
|
<Style TargetType="Hyperlink">
|
||||||
<Setter Property="Cursor" Value="Hand" />
|
<Setter Property="Cursor" Value="Hand" />
|
||||||
</Style>
|
</Style>
|
||||||
</RichTextBox.Resources>
|
</RichTextBox.Resources>
|
||||||
<FlowDocument>
|
<FlowDocument>
|
||||||
<Paragraph>
|
<Paragraph TextAlignment="Center">
|
||||||
<Span FontWeight="Bold" FontSize="18" FontFamily="HelveticaNeue">
|
<Run Text="ZeroTier One"/>
|
||||||
<Run Text="Getting Started"/>
|
|
||||||
</Span>
|
|
||||||
<Span FontWeight="Bold" FontSize="12" FontFamily="HelveticaNeue">
|
|
||||||
<LineBreak/>
|
|
||||||
</Span>
|
|
||||||
<Span FontSize="12" FontFamily="HelveticaNeue">
|
|
||||||
<Run/>
|
|
||||||
</Span>
|
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
<Paragraph>
|
<Paragraph TextAlignment="Center">
|
||||||
<Span FontSize="12" FontFamily="HelveticaNeue">
|
<Run FontSize="14" Text="Version 1.2.2"/>
|
||||||
<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 "Earth", 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/>
|
|
||||||
<LineBreak/>
|
<LineBreak/>
|
||||||
</Span>
|
<Run FontSize="14" Text="(c) 2011-2017 ZeroTier, Inc."/>
|
||||||
<Span FontWeight="Bold" FontSize="18" FontFamily="HelveticaNeue">
|
|
||||||
<Run Text="Create a Network"/>
|
|
||||||
</Span>
|
|
||||||
<Span FontWeight="Bold" FontSize="12" FontFamily="HelveticaNeue">
|
|
||||||
<LineBreak/>
|
<LineBreak/>
|
||||||
</Span>
|
<Run FontSize="14" Text="www.zerotier.com"/>
|
||||||
<Span FontSize="12" FontFamily="HelveticaNeue">
|
|
||||||
<Run/>
|
|
||||||
</Span>
|
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
<Paragraph>
|
<Paragraph TextAlignment="Center">
|
||||||
<Span FontSize="12" FontFamily="HelveticaNeue">
|
<Run FontSize="14" Text="ZeroTier One allows your computer to join virtual networks. Just select "join" and enter a network's 16-digit ID. Each network appears on your computer as a new network port."/>
|
||||||
<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>
|
</Paragraph>
|
||||||
</FlowDocument>
|
</FlowDocument>
|
||||||
</RichTextBox>
|
</RichTextBox>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
Name: zerotier-one
|
Name: zerotier-one
|
||||||
Version: 1.2.0
|
Version: 1.2.2
|
||||||
Release: 1%{?dist}
|
Release: 1%{?dist}
|
||||||
Summary: ZeroTier One network virtualization service
|
Summary: ZeroTier One network virtualization service
|
||||||
|
|
||||||
@@ -145,6 +145,12 @@ esac
|
|||||||
%endif
|
%endif
|
||||||
|
|
||||||
%changelog
|
%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
|
* Tue Jul 12 2016 Adam Ierymenko <adam.ierymenko@zerotier.com> - 1.1.10-0.1
|
||||||
- see https://github.com/zerotier/ZeroTierOne for release notes
|
- see https://github.com/zerotier/ZeroTierOne for release notes
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user