updated ZTO core
This commit is contained in:
82
zto/Jenkinsfile
vendored
82
zto/Jenkinsfile
vendored
@@ -1,82 +0,0 @@
|
||||
#!/usr/bin/env groovy
|
||||
|
||||
node('master') {
|
||||
def changelog = getChangeLog currentBuild
|
||||
|
||||
slackSend "Building ${env.JOB_NAME} #${env.BUILD_NUMBER} \n Change Log: \n ${changelog}"
|
||||
}
|
||||
|
||||
parallel 'centos7': {
|
||||
node('centos7') {
|
||||
try {
|
||||
checkout scm
|
||||
|
||||
stage('Build Centos 7') {
|
||||
sh 'make -f make-linux.mk'
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
currentBuild.result = "FAILURE"
|
||||
slackSend color: '#ff0000', message: "${env.JOB_NAME} broken on Centos 7 (<${env.BUILD_URL}|Open>)"
|
||||
|
||||
throw err
|
||||
}
|
||||
}
|
||||
}, 'android-ndk': {
|
||||
node('android-ndk') {
|
||||
try {
|
||||
checkout scm
|
||||
|
||||
stage('Build Android NDK') {
|
||||
sh "/android/android-ndk-r13b/ndk-build -C $WORKSPACE/java ZT1=${WORKSPACE}"
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
currentBuild.result = "FAILURE"
|
||||
slackSend color: '#ff0000', message: "${env.JOB_NAME} broken on Android NDK (<${env.BUILD_URL}|Open>)"
|
||||
|
||||
throw err
|
||||
}
|
||||
}
|
||||
}, 'macOS': {
|
||||
node('macOS') {
|
||||
try {
|
||||
checkout scm
|
||||
|
||||
stage('Build macOS') {
|
||||
sh 'make -f make-mac.mk'
|
||||
}
|
||||
|
||||
stage('Build macOS UI') {
|
||||
sh 'cd macui && xcodebuild -target "ZeroTier One" -configuration Debug'
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
currentBuild.result = "FAILURE"
|
||||
slackSend color: '#ff0000', message: "${env.JOB_NAME} broken on macOS (<${env.BUILD_URL}|Open>)"
|
||||
|
||||
throw err
|
||||
}
|
||||
}
|
||||
}, 'windows': {
|
||||
node('windows') {
|
||||
try {
|
||||
checkout scm
|
||||
|
||||
stage('Build Windows') {
|
||||
bat '''CALL "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\vcvarsall.bat" amd64
|
||||
git clean -dfx
|
||||
msbuild windows\\ZeroTierOne.sln
|
||||
'''
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
currentBuild.result = "FAILURE"
|
||||
slackSend color: '#ff0000', message: "${env.JOB_NAME} broken on Windows (<${env.BUILD_URL}|Open>)"
|
||||
|
||||
throw err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
slackSend color: "#00ff00", message: "${env.JOB_NAME} #${env.BUILD_NUMBER} Complete (<${env.BUILD_URL}|Show More...>)"
|
||||
@@ -5,7 +5,7 @@ ZeroTier is an enterprise Ethernet switch for planet Earth.
|
||||
|
||||
It erases the LAN/WAN distinction and makes VPNs, tunnels, proxies, and other kludges arising from the inflexible nature of physical networks obsolete. Everything is encrypted end-to-end and traffic takes the most direct (peer to peer) path available.
|
||||
|
||||
Visit [ZeroTier's site](https://www.zerotier.com/) for more information and [pre-built binary packages](https://www.zerotier.com/download.shtml). Apps for Android and iOS are available for free in the Google Play and Apple app stores.
|
||||
Visit [ZeroTier's site](https://www.zerotier.com/?pk_campaign=github_ZeroTierOne) for more information and [pre-built binary packages](https://www.zerotier.com/download.shtml?pk_campaign=github_ZeroTierOne). Apps for Android and iOS are available for free in the Google Play and Apple app stores.
|
||||
|
||||
### Getting Started
|
||||
|
||||
@@ -23,7 +23,7 @@ Now wait about 30 seconds and check your system with `ip addr list` or `ifconfig
|
||||
|
||||
The *zt* interface will disappear. You're no longer on the network.
|
||||
|
||||
To create networks of your own, you'll need a network controller. ZeroTier One (for desktops and servers) includes controller functionality in its default build that can be configured via its JSON API (see [README.md in controller/](controller/)). ZeroTier provides a hosted solution with a nice web UI and SaaS add-ons at [my.zerotier.com](https://my.zerotier.com/). Basic controller functionality is free for up to 100 devices.
|
||||
To create networks of your own, you'll need a network controller. ZeroTier One (for desktops and servers) includes controller functionality in its default build that can be configured via its JSON API (see [README.md in controller/](controller/)). ZeroTier provides a hosted solution with a nice web UI and SaaS add-ons at [my.zerotier.com](https://my.zerotier.com/?pk_campaign=github_ZeroTierOne). Basic controller functionality is free for up to 100 devices.
|
||||
|
||||
### Project Layout
|
||||
|
||||
@@ -112,7 +112,7 @@ ZeroTier One peers will automatically locate each other and communicate directly
|
||||
|
||||
Users behind certain types of firewalls and "symmetric" NAT devices may not able able to connect to external peers directly at all. ZeroTier has limited support for port prediction and will *attempt* to traverse symmetric NATs, but this doesn't always work. If P2P connectivity fails you'll be bouncing UDP packets off our relay servers resulting in slower performance. Some NAT router(s) have a configurable NAT mode, and setting this to "full cone" will eliminate this problem. If you do this you may also see a magical improvement for things like VoIP phones, Skype, BitTorrent, WebRTC, certain games, etc., since all of these use NAT traversal techniques similar to ours.
|
||||
|
||||
If you're interested, there's a [technical deep dive about NAT traversal on our blog](https://www.zerotier.com/blog/?p=226). A troubleshooting tool to help you diagnose NAT issues is planned for the future as are uPnP/IGD/NAT-PMP and IPv6 transport.
|
||||
If you're interested, there's a [technical deep dive about NAT traversal on our blog](https://www.zerotier.com/blog/?p=226?pk_campaign=github_ZeroTierOne). A troubleshooting tool to help you diagnose NAT issues is planned for the future as are uPnP/IGD/NAT-PMP and IPv6 transport.
|
||||
|
||||
If a firewall between you and the Internet blocks ZeroTier's UDP traffic, you will fall back to last-resort TCP tunneling to rootservers over port 443 (https impersonation). This will work almost anywhere but is *very slow* compared to UDP or direct peer to peer connectivity.
|
||||
|
||||
|
||||
@@ -487,9 +487,6 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET(
|
||||
|
||||
if ((path.size() >= 2)&&(path[1].length() == 16)) {
|
||||
const uint64_t nwid = Utils::hexStrToU64(path[1].c_str());
|
||||
char nwids[24];
|
||||
Utils::snprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)nwid);
|
||||
|
||||
json network;
|
||||
if (!_db.getNetwork(nwid,network))
|
||||
return 404;
|
||||
@@ -499,6 +496,8 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET(
|
||||
if (path[2] == "member") {
|
||||
|
||||
if (path.size() >= 4) {
|
||||
// Get member
|
||||
|
||||
const uint64_t address = Utils::hexStrToU64(path[3].c_str());
|
||||
json member;
|
||||
if (!_db.getNetworkMember(nwid,address,member))
|
||||
@@ -506,24 +505,29 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET(
|
||||
_addMemberNonPersistedFields(nwid,address,member,OSUtils::now());
|
||||
responseBody = OSUtils::jsonDump(member);
|
||||
responseContentType = "application/json";
|
||||
|
||||
} else {
|
||||
// List members and their revisions
|
||||
|
||||
responseBody = "{";
|
||||
responseBody.reserve((_db.memberCount(nwid) + 1) * 32);
|
||||
_db.eachMember(nwid,[&responseBody](uint64_t networkId,uint64_t nodeId,const json &member) {
|
||||
if ((member.is_object())&&(member.size() > 0)) {
|
||||
responseBody.append((responseBody.length() == 1) ? "\"" : ",\"");
|
||||
responseBody.append(OSUtils::jsonString(member["id"],"0"));
|
||||
responseBody.append("\":");
|
||||
responseBody.append(OSUtils::jsonString(member["revision"],"0"));
|
||||
char tmp[128];
|
||||
Utils::snprintf(tmp,sizeof(tmp),"%s%.10llx\":%llu",(responseBody.length() > 1) ? ",\"" : "\"",(unsigned long long)nodeId,(unsigned long long)OSUtils::jsonInt(member["revision"],0));
|
||||
responseBody.append(tmp);
|
||||
}
|
||||
});
|
||||
responseBody.push_back('}');
|
||||
responseContentType = "application/json";
|
||||
|
||||
}
|
||||
return 200;
|
||||
|
||||
} // else 404
|
||||
|
||||
} else {
|
||||
// Get network
|
||||
|
||||
const uint64_t now = OSUtils::now();
|
||||
JSONDB::NetworkSummaryInfo ns;
|
||||
@@ -535,12 +539,12 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET(
|
||||
|
||||
}
|
||||
} else if (path.size() == 1) {
|
||||
// List networks
|
||||
|
||||
std::vector<uint64_t> networkIds(_db.networkIds());
|
||||
std::sort(networkIds.begin(),networkIds.end());
|
||||
|
||||
char tmp[64];
|
||||
responseBody.push_back('[');
|
||||
responseBody = "[";
|
||||
responseBody.reserve((networkIds.size() + 1) * 24);
|
||||
for(std::vector<uint64_t>::const_iterator i(networkIds.begin());i!=networkIds.end();++i) {
|
||||
if (responseBody.length() > 1)
|
||||
responseBody.push_back(',');
|
||||
@@ -555,6 +559,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET(
|
||||
} // else 404
|
||||
|
||||
} else {
|
||||
// Controller status
|
||||
|
||||
char tmp[4096];
|
||||
Utils::snprintf(tmp,sizeof(tmp),"{\n\t\"controller\": true,\n\t\"apiVersion\": %d,\n\t\"clock\": %llu\n}\n",ZT_NETCONF_CONTROLLER_API_VERSION,(unsigned long long)OSUtils::now());
|
||||
@@ -721,59 +726,6 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST(
|
||||
responseContentType = "application/json";
|
||||
|
||||
return 200;
|
||||
} else if ((path.size() == 3)&&(path[2] == "test")) {
|
||||
|
||||
Mutex::Lock _l(_tests_m);
|
||||
|
||||
_tests.push_back(ZT_CircuitTest());
|
||||
ZT_CircuitTest *const test = &(_tests.back());
|
||||
memset(test,0,sizeof(ZT_CircuitTest));
|
||||
|
||||
Utils::getSecureRandom(&(test->testId),sizeof(test->testId));
|
||||
test->credentialNetworkId = nwid;
|
||||
test->ptr = (void *)this;
|
||||
json hops = b["hops"];
|
||||
if (hops.is_array()) {
|
||||
for(unsigned long i=0;i<hops.size();++i) {
|
||||
json &hops2 = hops[i];
|
||||
if (hops2.is_array()) {
|
||||
for(unsigned long j=0;j<hops2.size();++j) {
|
||||
std::string s = hops2[j];
|
||||
test->hops[test->hopCount].addresses[test->hops[test->hopCount].breadth++] = Utils::hexStrToU64(s.c_str()) & 0xffffffffffULL;
|
||||
}
|
||||
++test->hopCount;
|
||||
} else if (hops2.is_string()) {
|
||||
std::string s = hops2;
|
||||
test->hops[test->hopCount].addresses[test->hops[test->hopCount].breadth++] = Utils::hexStrToU64(s.c_str()) & 0xffffffffffULL;
|
||||
++test->hopCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
test->reportAtEveryHop = (OSUtils::jsonBool(b["reportAtEveryHop"],true) ? 1 : 0);
|
||||
|
||||
if (!test->hopCount) {
|
||||
_tests.pop_back();
|
||||
responseBody = "{ \"message\": \"a test must contain at least one hop\" }";
|
||||
responseContentType = "application/json";
|
||||
return 400;
|
||||
}
|
||||
|
||||
test->timestamp = OSUtils::now();
|
||||
|
||||
if (_node) {
|
||||
_node->circuitTestBegin((void *)0,test,&(EmbeddedNetworkController::_circuitTestCallback));
|
||||
} else {
|
||||
_tests.pop_back();
|
||||
return 500;
|
||||
}
|
||||
|
||||
char json[512];
|
||||
Utils::snprintf(json,sizeof(json),"{\"testId\":\"%.16llx\",\"timestamp\":%llu}",test->testId,test->timestamp);
|
||||
responseBody = json;
|
||||
responseContentType = "application/json";
|
||||
|
||||
return 200;
|
||||
|
||||
} // else 404
|
||||
|
||||
} else {
|
||||
@@ -809,6 +761,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST(
|
||||
if (b.count("enableBroadcast")) network["enableBroadcast"] = OSUtils::jsonBool(b["enableBroadcast"],false);
|
||||
if (b.count("allowPassiveBridging")) network["allowPassiveBridging"] = OSUtils::jsonBool(b["allowPassiveBridging"],false);
|
||||
if (b.count("multicastLimit")) network["multicastLimit"] = OSUtils::jsonInt(b["multicastLimit"],32ULL);
|
||||
if (b.count("mtu")) network["mtu"] = std::max(std::min((unsigned int)OSUtils::jsonInt(b["mtu"],ZT_DEFAULT_MTU),(unsigned int)ZT_MAX_MTU),(unsigned int)ZT_MIN_MTU);
|
||||
|
||||
if (b.count("v4AssignMode")) {
|
||||
json nv4m;
|
||||
@@ -1112,7 +1065,6 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpDELETE(
|
||||
void EmbeddedNetworkController::threadMain()
|
||||
throw()
|
||||
{
|
||||
uint64_t lastCircuitTestCheck = 0;
|
||||
_RQEntry *qe = (_RQEntry *)0;
|
||||
while ((_running)&&(_queue.get(qe))) {
|
||||
try {
|
||||
@@ -1124,7 +1076,7 @@ void EmbeddedNetworkController::threadMain()
|
||||
std::string pong("{\"memberStatus\":{");
|
||||
{
|
||||
Mutex::Lock _l(_memberStatus_m);
|
||||
pong.reserve(64 * _memberStatus.size());
|
||||
pong.reserve(48 * (_memberStatus.size() + 1));
|
||||
_db.eachId([this,&pong,&now,&first](uint64_t networkId,uint64_t nodeId) {
|
||||
char tmp[64];
|
||||
uint64_t lrt = 0ULL;
|
||||
@@ -1147,80 +1099,9 @@ void EmbeddedNetworkController::threadMain()
|
||||
}
|
||||
} catch ( ... ) {}
|
||||
delete qe;
|
||||
|
||||
if (_running) {
|
||||
uint64_t now = OSUtils::now();
|
||||
if ((now - lastCircuitTestCheck) > ZT_EMBEDDEDNETWORKCONTROLLER_CIRCUIT_TEST_EXPIRATION) {
|
||||
lastCircuitTestCheck = now;
|
||||
Mutex::Lock _l(_tests_m);
|
||||
for(std::list< ZT_CircuitTest >::iterator i(_tests.begin());i!=_tests.end();) {
|
||||
if ((now - i->timestamp) > ZT_EMBEDDEDNETWORKCONTROLLER_CIRCUIT_TEST_EXPIRATION) {
|
||||
_node->circuitTestEnd(&(*i));
|
||||
_tests.erase(i++);
|
||||
} else ++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EmbeddedNetworkController::_circuitTestCallback(ZT_Node *node,ZT_CircuitTest *test,const ZT_CircuitTestReport *report)
|
||||
{
|
||||
char tmp[2048],id[128];
|
||||
EmbeddedNetworkController *const self = reinterpret_cast<EmbeddedNetworkController *>(test->ptr);
|
||||
|
||||
if ((!test)||(!report)||(!test->credentialNetworkId)) return; // sanity check
|
||||
|
||||
const uint64_t now = OSUtils::now();
|
||||
Utils::snprintf(id,sizeof(id),"network/%.16llx/test/%.16llx-%.16llx-%.10llx-%.10llx",test->credentialNetworkId,test->testId,now,report->upstream,report->current);
|
||||
Utils::snprintf(tmp,sizeof(tmp),
|
||||
"{\"id\": \"%s\","
|
||||
"\"objtype\": \"circuit_test\","
|
||||
"\"timestamp\": %llu,"
|
||||
"\"networkId\": \"%.16llx\","
|
||||
"\"testId\": \"%.16llx\","
|
||||
"\"upstream\": \"%.10llx\","
|
||||
"\"current\": \"%.10llx\","
|
||||
"\"receivedTimestamp\": %llu,"
|
||||
"\"sourcePacketId\": \"%.16llx\","
|
||||
"\"flags\": %llu,"
|
||||
"\"sourcePacketHopCount\": %u,"
|
||||
"\"errorCode\": %u,"
|
||||
"\"vendor\": %d,"
|
||||
"\"protocolVersion\": %u,"
|
||||
"\"majorVersion\": %u,"
|
||||
"\"minorVersion\": %u,"
|
||||
"\"revision\": %u,"
|
||||
"\"platform\": %d,"
|
||||
"\"architecture\": %d,"
|
||||
"\"receivedOnLocalAddress\": \"%s\","
|
||||
"\"receivedFromRemoteAddress\": \"%s\","
|
||||
"\"receivedFromLinkQuality\": %f}",
|
||||
id + 30, // last bit only, not leading path
|
||||
(unsigned long long)test->timestamp,
|
||||
(unsigned long long)test->credentialNetworkId,
|
||||
(unsigned long long)test->testId,
|
||||
(unsigned long long)report->upstream,
|
||||
(unsigned long long)report->current,
|
||||
(unsigned long long)now,
|
||||
(unsigned long long)report->sourcePacketId,
|
||||
(unsigned long long)report->flags,
|
||||
report->sourcePacketHopCount,
|
||||
report->errorCode,
|
||||
(int)report->vendor,
|
||||
report->protocolVersion,
|
||||
report->majorVersion,
|
||||
report->minorVersion,
|
||||
report->revision,
|
||||
(int)report->platform,
|
||||
(int)report->architecture,
|
||||
reinterpret_cast<const InetAddress *>(&(report->receivedOnLocalAddress))->toString().c_str(),
|
||||
reinterpret_cast<const InetAddress *>(&(report->receivedFromRemoteAddress))->toString().c_str(),
|
||||
((double)report->receivedFromLinkQuality / (double)ZT_PATH_LINK_QUALITY_MAX));
|
||||
|
||||
self->_db.writeRaw(id,std::string(tmp));
|
||||
}
|
||||
|
||||
void EmbeddedNetworkController::_request(
|
||||
uint64_t nwid,
|
||||
const InetAddress &fromAddr,
|
||||
@@ -1424,6 +1305,7 @@ void EmbeddedNetworkController::_request(
|
||||
if (OSUtils::jsonBool(network["enableBroadcast"],true)) nc->flags |= ZT_NETWORKCONFIG_FLAG_ENABLE_BROADCAST;
|
||||
if (OSUtils::jsonBool(network["allowPassiveBridging"],false)) nc->flags |= ZT_NETWORKCONFIG_FLAG_ALLOW_PASSIVE_BRIDGING;
|
||||
Utils::scopy(nc->name,sizeof(nc->name),OSUtils::jsonString(network["name"],"").c_str());
|
||||
nc->mtu = std::max(std::min((unsigned int)OSUtils::jsonInt(network["mtu"],ZT_DEFAULT_MTU),(unsigned int)ZT_MAX_MTU),(unsigned int)ZT_MIN_MTU);
|
||||
nc->multicastLimit = (unsigned int)OSUtils::jsonInt(network["multicastLimit"],32ULL);
|
||||
|
||||
for(std::vector<Address>::const_iterator ab(ns.activeBridges.begin());ab!=ns.activeBridges.end();++ab)
|
||||
|
||||
@@ -45,9 +45,6 @@
|
||||
|
||||
#include "JSONDB.hpp"
|
||||
|
||||
// TTL for circuit tests
|
||||
#define ZT_EMBEDDEDNETWORKCONTROLLER_CIRCUIT_TEST_EXPIRATION 120000
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
class Node;
|
||||
@@ -110,7 +107,6 @@ private:
|
||||
} type;
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
inline void _startThreads()
|
||||
@@ -162,6 +158,7 @@ private:
|
||||
if (!network.count("tags")) network["tags"] = nlohmann::json::array();
|
||||
if (!network.count("routes")) network["routes"] = nlohmann::json::array();
|
||||
if (!network.count("ipAssignmentPools")) network["ipAssignmentPools"] = nlohmann::json::array();
|
||||
if (!network.count("mtu")) network["mtu"] = ZT_DEFAULT_MTU;
|
||||
if (!network.count("rules")) {
|
||||
// If unspecified, rules are set to allow anything and behave like a flat L2 segment
|
||||
network["rules"] = {{
|
||||
@@ -218,9 +215,6 @@ private:
|
||||
NetworkController::Sender *_sender;
|
||||
Identity _signingId;
|
||||
|
||||
std::list< ZT_CircuitTest > _tests;
|
||||
Mutex _tests_m;
|
||||
|
||||
struct _MemberStatusKey
|
||||
{
|
||||
_MemberStatusKey() : networkId(0),nodeId(0) {}
|
||||
|
||||
@@ -392,14 +392,14 @@ bool JSONDB::_load(const std::string &p)
|
||||
std::string objtype(OSUtils::jsonString(j["objtype"],""));
|
||||
|
||||
if ((id.length() == 16)&&(objtype == "network")) {
|
||||
const uint64_t nwid = Utils::strToU64(id.c_str());
|
||||
const uint64_t nwid = Utils::hexStrToU64(id.c_str());
|
||||
if (nwid) {
|
||||
Mutex::Lock _l(_networks_m);
|
||||
_networks[nwid].config = nlohmann::json::to_msgpack(j);
|
||||
}
|
||||
} else if ((id.length() == 10)&&(objtype == "member")) {
|
||||
const uint64_t mid = Utils::strToU64(id.c_str());
|
||||
const uint64_t nwid = Utils::strToU64(OSUtils::jsonString(j["nwid"],"0").c_str());
|
||||
const uint64_t mid = Utils::hexStrToU64(id.c_str());
|
||||
const uint64_t nwid = Utils::hexStrToU64(OSUtils::jsonString(j["nwid"],"0").c_str());
|
||||
if ((mid)&&(nwid)) {
|
||||
Mutex::Lock _l(_networks_m);
|
||||
_networks[nwid].members[mid] = nlohmann::json::to_msgpack(j);
|
||||
|
||||
@@ -93,6 +93,15 @@ public:
|
||||
return r;
|
||||
}
|
||||
|
||||
inline unsigned long memberCount(const uint64_t networkId)
|
||||
{
|
||||
Mutex::Lock _l(_networks_m);
|
||||
std::unordered_map<uint64_t,_NW>::const_iterator i(_networks.find(networkId));
|
||||
if (i != _networks.end())
|
||||
return (unsigned long)i->second.members.size();
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
inline void eachMember(const uint64_t networkId,F func)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
FROM alpine:latest
|
||||
MAINTAINER Adam Ierymenko <adam.ierymenko@zerotier.com>
|
||||
|
||||
LABEL version="1.1.14"
|
||||
LABEL version="1.2.4"
|
||||
LABEL description="Containerized ZeroTier One for use on CoreOS or other Docker-only Linux hosts."
|
||||
|
||||
# Uncomment to build in container
|
||||
|
||||
@@ -60,29 +60,14 @@ extern "C" {
|
||||
#define ZT_DEFAULT_PORT 9993
|
||||
|
||||
/**
|
||||
* Maximum MTU for ZeroTier virtual networks
|
||||
*
|
||||
* This is pretty much an unchangeable global constant. To make it change
|
||||
* across nodes would require logic to send ICMP packet too big messages,
|
||||
* which would complicate things. 1500 has been good enough on most LANs
|
||||
* for ages, so a larger MTU should be fine for the forseeable future. This
|
||||
* typically results in two UDP packets per single large frame. Experimental
|
||||
* results seem to show that this is good. Larger MTUs resulting in more
|
||||
* fragments seemed too brittle on slow/crummy links for no benefit.
|
||||
*
|
||||
* If this does change, also change it in tap.h in the tuntaposx code under
|
||||
* mac-tap.
|
||||
*
|
||||
* Overhead for a normal frame split into two packets:
|
||||
*
|
||||
* 1414 = 1444 (typical UDP MTU) - 28 (packet header) - 2 (ethertype)
|
||||
* 1428 = 1444 (typical UDP MTU) - 16 (fragment header)
|
||||
* SUM: 2842
|
||||
*
|
||||
* We use 2800, which leaves some room for other payload in other types of
|
||||
* messages such as multicast propagation or future support for bridging.
|
||||
* Minimum MTU, which is the minimum allowed by IPv6 and several specs
|
||||
*/
|
||||
#define ZT_MAX_MTU 2800
|
||||
#define ZT_MIN_MTU 1280
|
||||
|
||||
/**
|
||||
* Maximum MTU for ZeroTier virtual networks
|
||||
*/
|
||||
#define ZT_MAX_MTU 10000
|
||||
|
||||
/**
|
||||
* Maximum length of network short name
|
||||
@@ -775,7 +760,6 @@ typedef struct
|
||||
*/
|
||||
uint64_t expiration;
|
||||
|
||||
|
||||
struct {
|
||||
uint64_t from;
|
||||
uint64_t to;
|
||||
@@ -1120,197 +1104,6 @@ typedef struct
|
||||
unsigned long peerCount;
|
||||
} ZT_PeerList;
|
||||
|
||||
/**
|
||||
* ZeroTier circuit test configuration and path
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* Test ID -- an arbitrary 64-bit identifier
|
||||
*/
|
||||
uint64_t testId;
|
||||
|
||||
/**
|
||||
* Timestamp -- sent with test and echoed back by each reporter
|
||||
*/
|
||||
uint64_t timestamp;
|
||||
|
||||
/**
|
||||
* Originator credential: network ID
|
||||
*
|
||||
* If this is nonzero, a network ID will be set for this test and
|
||||
* the originator must be its primary network controller. This is
|
||||
* currently the only authorization method available, so it must
|
||||
* be set to run a test.
|
||||
*/
|
||||
uint64_t credentialNetworkId;
|
||||
|
||||
/**
|
||||
* Hops in circuit test (a.k.a. FIFO for graph traversal)
|
||||
*/
|
||||
struct {
|
||||
/**
|
||||
* Hop flags (currently unused, must be zero)
|
||||
*/
|
||||
unsigned int flags;
|
||||
|
||||
/**
|
||||
* Number of addresses in this hop (max: ZT_CIRCUIT_TEST_MAX_HOP_BREADTH)
|
||||
*/
|
||||
unsigned int breadth;
|
||||
|
||||
/**
|
||||
* 40-bit ZeroTier addresses (most significant 24 bits ignored)
|
||||
*/
|
||||
uint64_t addresses[ZT_CIRCUIT_TEST_MAX_HOP_BREADTH];
|
||||
} hops[ZT_CIRCUIT_TEST_MAX_HOPS];
|
||||
|
||||
/**
|
||||
* Number of hops (max: ZT_CIRCUIT_TEST_MAX_HOPS)
|
||||
*/
|
||||
unsigned int hopCount;
|
||||
|
||||
/**
|
||||
* If non-zero, circuit test will report back at every hop
|
||||
*/
|
||||
int reportAtEveryHop;
|
||||
|
||||
/**
|
||||
* An arbitrary user-settable pointer
|
||||
*/
|
||||
void *ptr;
|
||||
|
||||
/**
|
||||
* Pointer for internal use -- initialize to zero and do not modify
|
||||
*/
|
||||
void *_internalPtr;
|
||||
} ZT_CircuitTest;
|
||||
|
||||
/**
|
||||
* Circuit test result report
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* Sender of report (current hop)
|
||||
*/
|
||||
uint64_t current;
|
||||
|
||||
/**
|
||||
* Previous hop
|
||||
*/
|
||||
uint64_t upstream;
|
||||
|
||||
/**
|
||||
* 64-bit test ID
|
||||
*/
|
||||
uint64_t testId;
|
||||
|
||||
/**
|
||||
* Timestamp from original test (echoed back at each hop)
|
||||
*/
|
||||
uint64_t timestamp;
|
||||
|
||||
/**
|
||||
* 64-bit packet ID of packet received by the reporting device
|
||||
*/
|
||||
uint64_t sourcePacketId;
|
||||
|
||||
/**
|
||||
* Flags
|
||||
*/
|
||||
uint64_t flags;
|
||||
|
||||
/**
|
||||
* ZeroTier protocol-level hop count of packet received by reporting device (>0 indicates relayed)
|
||||
*/
|
||||
unsigned int sourcePacketHopCount;
|
||||
|
||||
/**
|
||||
* Error code (currently unused, will be zero)
|
||||
*/
|
||||
unsigned int errorCode;
|
||||
|
||||
/**
|
||||
* Remote device vendor ID
|
||||
*/
|
||||
enum ZT_Vendor vendor;
|
||||
|
||||
/**
|
||||
* Remote device protocol compliance version
|
||||
*/
|
||||
unsigned int protocolVersion;
|
||||
|
||||
/**
|
||||
* Software major version
|
||||
*/
|
||||
unsigned int majorVersion;
|
||||
|
||||
/**
|
||||
* Software minor version
|
||||
*/
|
||||
unsigned int minorVersion;
|
||||
|
||||
/**
|
||||
* Software revision
|
||||
*/
|
||||
unsigned int revision;
|
||||
|
||||
/**
|
||||
* Platform / OS
|
||||
*/
|
||||
enum ZT_Platform platform;
|
||||
|
||||
/**
|
||||
* System architecture
|
||||
*/
|
||||
enum ZT_Architecture architecture;
|
||||
|
||||
/**
|
||||
* Local device address on which packet was received by reporting device
|
||||
*
|
||||
* This may have ss_family equal to zero (null address) if unspecified.
|
||||
*/
|
||||
struct sockaddr_storage receivedOnLocalAddress;
|
||||
|
||||
/**
|
||||
* Remote address from which reporter received the test packet
|
||||
*
|
||||
* This may have ss_family set to zero (null address) if unspecified.
|
||||
*/
|
||||
struct sockaddr_storage receivedFromRemoteAddress;
|
||||
|
||||
/**
|
||||
* Path link quality of physical path over which test was received
|
||||
*/
|
||||
int receivedFromLinkQuality;
|
||||
|
||||
/**
|
||||
* Next hops to which packets are being or will be sent by the reporter
|
||||
*
|
||||
* In addition to reporting back, the reporter may send the test on if
|
||||
* there are more recipients in the FIFO. If it does this, it can report
|
||||
* back the address(es) that make up the next hop and the physical address
|
||||
* for each if it has one. The physical address being null/unspecified
|
||||
* typically indicates that no direct path exists and the next packet
|
||||
* will be relayed.
|
||||
*/
|
||||
struct {
|
||||
/**
|
||||
* 40-bit ZeroTier address
|
||||
*/
|
||||
uint64_t address;
|
||||
|
||||
/**
|
||||
* Physical address or null address (ss_family == 0) if unspecified or unknown
|
||||
*/
|
||||
struct sockaddr_storage physicalAddress;
|
||||
} nextHops[ZT_CIRCUIT_TEST_MAX_HOP_BREADTH];
|
||||
|
||||
/**
|
||||
* Number of next hops reported in nextHops[]
|
||||
*/
|
||||
unsigned int nextHopCount;
|
||||
} ZT_CircuitTestReport;
|
||||
|
||||
/**
|
||||
* A cluster member's status
|
||||
*/
|
||||
@@ -1972,40 +1765,6 @@ int ZT_Node_sendUserMessage(ZT_Node *node,void *tptr,uint64_t dest,uint64_t type
|
||||
*/
|
||||
void ZT_Node_setNetconfMaster(ZT_Node *node,void *networkConfigMasterInstance);
|
||||
|
||||
/**
|
||||
* Initiate a VL1 circuit test
|
||||
*
|
||||
* This sends an initial VERB_CIRCUIT_TEST and reports results back to the
|
||||
* supplied callback until circuitTestEnd() is called. The supplied
|
||||
* ZT_CircuitTest structure should be initially zeroed and then filled
|
||||
* in with settings and hops.
|
||||
*
|
||||
* It is the caller's responsibility to call circuitTestEnd() and then
|
||||
* to dispose of the test structure. Otherwise this node will listen
|
||||
* for results forever.
|
||||
*
|
||||
* @param node Node instance
|
||||
* @param tptr Thread pointer to pass to functions/callbacks resulting from this call
|
||||
* @param test Test configuration
|
||||
* @param reportCallback Function to call each time a report is received
|
||||
* @return OK or error if, for example, test is too big for a packet or support isn't compiled in
|
||||
*/
|
||||
enum ZT_ResultCode ZT_Node_circuitTestBegin(ZT_Node *node,void *tptr,ZT_CircuitTest *test,void (*reportCallback)(ZT_Node *, ZT_CircuitTest *,const ZT_CircuitTestReport *));
|
||||
|
||||
/**
|
||||
* Stop listening for results to a given circuit test
|
||||
*
|
||||
* This does not free the 'test' structure. The caller may do that
|
||||
* after calling this method to unregister it.
|
||||
*
|
||||
* Any reports that are received for a given test ID after it is
|
||||
* terminated are ignored.
|
||||
*
|
||||
* @param node Node instance
|
||||
* @param test Test configuration to unregister
|
||||
*/
|
||||
void ZT_Node_circuitTestEnd(ZT_Node *node,ZT_CircuitTest *test);
|
||||
|
||||
/**
|
||||
* Initialize cluster operation
|
||||
*
|
||||
|
||||
@@ -5,7 +5,7 @@ DEFS=
|
||||
LIBS=
|
||||
|
||||
include objects.mk
|
||||
OBJS+=osdep/BSDEthernetTap.o ext/http-parser/http_parser.o
|
||||
ONE_OBJS+=osdep/BSDEthernetTap.o ext/http-parser/http_parser.o
|
||||
|
||||
# Build with ZT_ENABLE_CLUSTER=1 to build with cluster support
|
||||
ifeq ($(ZT_ENABLE_CLUSTER),1)
|
||||
@@ -14,10 +14,10 @@ endif
|
||||
|
||||
# "make debug" is a shortcut for this
|
||||
ifeq ($(ZT_DEBUG),1)
|
||||
DEFS+=-DZT_TRACE
|
||||
CFLAGS+=-Wall -g -pthread $(INCLUDES) $(DEFS)
|
||||
CFLAGS+=-Wall -Werror -g -pthread $(INCLUDES) $(DEFS)
|
||||
LDFLAGS+=
|
||||
STRIP=echo
|
||||
ZT_TRACE=1
|
||||
# The following line enables optimization for the crypto code, since
|
||||
# C25519 in particular is almost UNUSABLE in heavy testing without it.
|
||||
node/Salsa20.o node/SHA512.o node/C25519.o node/Poly1305.o: CFLAGS = -Wall -O2 -g -pthread $(INCLUDES) $(DEFS)
|
||||
@@ -28,80 +28,84 @@ else
|
||||
STRIP=strip --strip-all
|
||||
endif
|
||||
|
||||
ifeq ($(ZT_TRACE),1)
|
||||
DEFS+=-DZT_TRACE
|
||||
endif
|
||||
|
||||
# Determine system build architecture from compiler target
|
||||
CC_MACH=$(shell $(CC) -dumpmachine | cut -d '-' -f 1)
|
||||
ZT_ARCHITECTURE=999
|
||||
ifeq ($(CC_MACH),x86_64)
|
||||
ZT_ARCHITECTURE=2
|
||||
ZT_ARCHITECTURE=2
|
||||
ZT_USE_X64_ASM_SALSA2012=1
|
||||
endif
|
||||
ifeq ($(CC_MACH),amd64)
|
||||
ZT_ARCHITECTURE=2
|
||||
ZT_ARCHITECTURE=2
|
||||
ZT_USE_X64_ASM_SALSA2012=1
|
||||
endif
|
||||
ifeq ($(CC_MACH),i386)
|
||||
ZT_ARCHITECTURE=1
|
||||
ZT_ARCHITECTURE=1
|
||||
endif
|
||||
ifeq ($(CC_MACH),i686)
|
||||
ZT_ARCHITECTURE=1
|
||||
ZT_ARCHITECTURE=1
|
||||
endif
|
||||
ifeq ($(CC_MACH),arm)
|
||||
ZT_ARCHITECTURE=3
|
||||
ZT_ARCHITECTURE=3
|
||||
override DEFS+=-DZT_NO_TYPE_PUNNING
|
||||
ZT_USE_ARM32_NEON_ASM_SALSA2012=1
|
||||
endif
|
||||
ifeq ($(CC_MACH),armel)
|
||||
ZT_ARCHITECTURE=3
|
||||
ZT_ARCHITECTURE=3
|
||||
override DEFS+=-DZT_NO_TYPE_PUNNING
|
||||
ZT_USE_ARM32_NEON_ASM_SALSA2012=1
|
||||
endif
|
||||
ifeq ($(CC_MACH),armhf)
|
||||
ZT_ARCHITECTURE=3
|
||||
ZT_ARCHITECTURE=3
|
||||
override DEFS+=-DZT_NO_TYPE_PUNNING
|
||||
ZT_USE_ARM32_NEON_ASM_SALSA2012=1
|
||||
endif
|
||||
ifeq ($(CC_MACH),armv6)
|
||||
ZT_ARCHITECTURE=3
|
||||
ZT_ARCHITECTURE=3
|
||||
override DEFS+=-DZT_NO_TYPE_PUNNING
|
||||
ZT_USE_ARM32_NEON_ASM_SALSA2012=1
|
||||
endif
|
||||
ifeq ($(CC_MACH),armv6zk)
|
||||
ZT_ARCHITECTURE=3
|
||||
ZT_ARCHITECTURE=3
|
||||
override DEFS+=-DZT_NO_TYPE_PUNNING
|
||||
ZT_USE_ARM32_NEON_ASM_SALSA2012=1
|
||||
endif
|
||||
ifeq ($(CC_MACH),armv6kz)
|
||||
ZT_ARCHITECTURE=3
|
||||
ZT_ARCHITECTURE=3
|
||||
override DEFS+=-DZT_NO_TYPE_PUNNING
|
||||
ZT_USE_ARM32_NEON_ASM_SALSA2012=1
|
||||
endif
|
||||
ifeq ($(CC_MACH),armv7)
|
||||
ZT_ARCHITECTURE=3
|
||||
ZT_ARCHITECTURE=3
|
||||
override DEFS+=-DZT_NO_TYPE_PUNNING
|
||||
ZT_USE_ARM32_NEON_ASM_SALSA2012=1
|
||||
endif
|
||||
ifeq ($(CC_MACH),arm64)
|
||||
ZT_ARCHITECTURE=4
|
||||
ZT_ARCHITECTURE=4
|
||||
override DEFS+=-DZT_NO_TYPE_PUNNING
|
||||
endif
|
||||
ifeq ($(CC_MACH),aarch64)
|
||||
ZT_ARCHITECTURE=4
|
||||
ZT_ARCHITECTURE=4
|
||||
override DEFS+=-DZT_NO_TYPE_PUNNING
|
||||
endif
|
||||
ifeq ($(CC_MACH),mipsel)
|
||||
ZT_ARCHITECTURE=5
|
||||
ZT_ARCHITECTURE=5
|
||||
override DEFS+=-DZT_NO_TYPE_PUNNING
|
||||
endif
|
||||
ifeq ($(CC_MACH),mips)
|
||||
ZT_ARCHITECTURE=5
|
||||
ZT_ARCHITECTURE=5
|
||||
override DEFS+=-DZT_NO_TYPE_PUNNING
|
||||
endif
|
||||
ifeq ($(CC_MACH),mips64)
|
||||
ZT_ARCHITECTURE=6
|
||||
ZT_ARCHITECTURE=6
|
||||
override DEFS+=-DZT_NO_TYPE_PUNNING
|
||||
endif
|
||||
ifeq ($(CC_MACH),mips64el)
|
||||
ZT_ARCHITECTURE=6
|
||||
ZT_ARCHITECTURE=6
|
||||
override DEFS+=-DZT_NO_TYPE_PUNNING
|
||||
endif
|
||||
|
||||
@@ -115,11 +119,11 @@ endif
|
||||
# Build faster crypto on some targets
|
||||
ifeq ($(ZT_USE_X64_ASM_SALSA2012),1)
|
||||
override DEFS+=-DZT_USE_X64_ASM_SALSA2012
|
||||
override OBJS+=ext/x64-salsa2012-asm/salsa2012.o
|
||||
override CORE_OBJS+=ext/x64-salsa2012-asm/salsa2012.o
|
||||
endif
|
||||
ifeq ($(ZT_USE_ARM32_NEON_ASM_SALSA2012),1)
|
||||
override DEFS+=-DZT_USE_ARM32_NEON_ASM_SALSA2012
|
||||
override OBJS+=ext/arm32-neon-salsa2012-asm/salsa2012.o
|
||||
override CORE_OBJS+=ext/arm32-neon-salsa2012-asm/salsa2012.o
|
||||
endif
|
||||
|
||||
override DEFS+=-DZT_BUILD_PLATFORM=$(ZT_BUILD_PLATFORM) -DZT_BUILD_ARCHITECTURE=$(ZT_ARCHITECTURE) -DZT_SOFTWARE_UPDATE_DEFAULT="\"disable\""
|
||||
@@ -128,18 +132,32 @@ CXXFLAGS+=$(CFLAGS) -fno-rtti -std=c++11 #-D_GLIBCXX_USE_C99 -D_GLIBCXX_USE_C99_
|
||||
|
||||
all: one
|
||||
|
||||
one: $(OBJS) service/OneService.o one.o
|
||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o zerotier-one $(OBJS) service/OneService.o one.o $(LIBS)
|
||||
one: $(CORE_OBJS) $(ONE_OBJS) one.o
|
||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o zerotier-one $(CORE_OBJS) $(ONE_OBJS) one.o $(LIBS)
|
||||
$(STRIP) zerotier-one
|
||||
ln -sf zerotier-one zerotier-idtool
|
||||
ln -sf zerotier-one zerotier-cli
|
||||
|
||||
selftest: $(OBJS) selftest.o
|
||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o zerotier-selftest selftest.o $(OBJS) $(LIBS)
|
||||
zerotier-one: one
|
||||
|
||||
zerotier-idtool: one
|
||||
|
||||
zerotier-cli: one
|
||||
|
||||
libzerotiercore.a: $(CORE_OBJS)
|
||||
ar rcs libzerotiercore.a $(CORE_OBJS)
|
||||
ranlib libzerotiercore.a
|
||||
|
||||
core: libzerotiercore.a
|
||||
|
||||
selftest: $(CORE_OBJS) $(ONE_OBJS) selftest.o
|
||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o zerotier-selftest selftest.o $(CORE_OBJS) $(ONE_OBJS) $(LIBS)
|
||||
$(STRIP) zerotier-selftest
|
||||
|
||||
zerotier-selftest: selftest
|
||||
|
||||
clean:
|
||||
rm -rf *.o node/*.o controller/*.o osdep/*.o service/*.o ext/http-parser/*.o build-* zerotier-one zerotier-idtool zerotier-selftest zerotier-cli ZeroTierOneInstaller-* $(OBJS)
|
||||
rm -rf *.a *.o node/*.o controller/*.o osdep/*.o service/*.o ext/http-parser/*.o build-* zerotier-one zerotier-idtool zerotier-selftest zerotier-cli $(ONE_OBJS) $(CORE_OBJS)
|
||||
|
||||
debug: FORCE
|
||||
make -j 4 ZT_DEBUG=1
|
||||
|
||||
@@ -13,14 +13,11 @@ LDLIBS?=
|
||||
DESTDIR?=
|
||||
|
||||
include objects.mk
|
||||
|
||||
# Use bundled http-parser since distribution versions are NOT API-stable or compatible!
|
||||
# Trying to use dynamically linked libhttp-parser causes tons of compatibility problems.
|
||||
OBJS+=ext/http-parser/http_parser.o
|
||||
ONE_OBJS+=osdep/LinuxEthernetTap.o
|
||||
|
||||
# Auto-detect miniupnpc and nat-pmp as well and use system libs if present,
|
||||
# otherwise build into binary as done on Mac and Windows.
|
||||
OBJS+=osdep/PortMapper.o
|
||||
ONE_OBJS+=osdep/PortMapper.o
|
||||
DEFS+=-DZT_USE_MINIUPNPC
|
||||
MINIUPNPC_IS_NEW_ENOUGH=$(shell grep -sqr '.*define.*MINIUPNPC_VERSION.*"2.."' /usr/include/miniupnpc/miniupnpc.h && echo 1)
|
||||
ifeq ($(MINIUPNPC_IS_NEW_ENOUGH),1)
|
||||
@@ -28,15 +25,19 @@ ifeq ($(MINIUPNPC_IS_NEW_ENOUGH),1)
|
||||
LDLIBS+=-lminiupnpc
|
||||
else
|
||||
DEFS+=-DMINIUPNP_STATICLIB -DMINIUPNPC_SET_SOCKET_TIMEOUT -DMINIUPNPC_GET_SRC_ADDR -D_BSD_SOURCE -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -DOS_STRING=\"Linux\" -DMINIUPNPC_VERSION_STRING=\"2.0\" -DUPNP_VERSION_STRING=\"UPnP/1.1\" -DENABLE_STRNATPMPERR
|
||||
OBJS+=ext/miniupnpc/connecthostport.o ext/miniupnpc/igd_desc_parse.o ext/miniupnpc/minisoap.o ext/miniupnpc/minissdpc.o ext/miniupnpc/miniupnpc.o ext/miniupnpc/miniwget.o ext/miniupnpc/minixml.o ext/miniupnpc/portlistingparse.o ext/miniupnpc/receivedata.o ext/miniupnpc/upnpcommands.o ext/miniupnpc/upnpdev.o ext/miniupnpc/upnperrors.o ext/miniupnpc/upnpreplyparse.o
|
||||
ONE_OBJS+=ext/miniupnpc/connecthostport.o ext/miniupnpc/igd_desc_parse.o ext/miniupnpc/minisoap.o ext/miniupnpc/minissdpc.o ext/miniupnpc/miniupnpc.o ext/miniupnpc/miniwget.o ext/miniupnpc/minixml.o ext/miniupnpc/portlistingparse.o ext/miniupnpc/receivedata.o ext/miniupnpc/upnpcommands.o ext/miniupnpc/upnpdev.o ext/miniupnpc/upnperrors.o ext/miniupnpc/upnpreplyparse.o
|
||||
endif
|
||||
ifeq ($(wildcard /usr/include/natpmp.h),)
|
||||
OBJS+=ext/libnatpmp/natpmp.o ext/libnatpmp/getgateway.o
|
||||
ONE_OBJS+=ext/libnatpmp/natpmp.o ext/libnatpmp/getgateway.o
|
||||
else
|
||||
LDLIBS+=-lnatpmp
|
||||
DEFS+=-DZT_USE_SYSTEM_NATPMP
|
||||
endif
|
||||
|
||||
# Use bundled http-parser since distribution versions are NOT API-stable or compatible!
|
||||
# Trying to use dynamically linked libhttp-parser causes tons of compatibility problems.
|
||||
ONE_OBJS+=ext/http-parser/http_parser.o
|
||||
|
||||
ifeq ($(ZT_ENABLE_CLUSTER),1)
|
||||
DEFS+=-DZT_ENABLE_CLUSTER
|
||||
endif
|
||||
@@ -54,10 +55,10 @@ ifeq ($(ZT_RULES_ENGINE_DEBUGGING),1)
|
||||
endif
|
||||
|
||||
ifeq ($(ZT_DEBUG),1)
|
||||
override DEFS+=-DZT_TRACE
|
||||
override CFLAGS+=-Wall -g -pthread $(INCLUDES) $(DEFS)
|
||||
override CXXFLAGS+=-Wall -g -std=c++11 -pthread $(INCLUDES) $(DEFS)
|
||||
override CFLAGS+=-Wall -Wno-deprecated -Werror -g -pthread $(INCLUDES) $(DEFS)
|
||||
override CXXFLAGS+=-Wall -Wno-deprecated -Werror -g -std=c++11 -pthread $(INCLUDES) $(DEFS)
|
||||
override LDFLAGS+=
|
||||
ZT_TRACE=1
|
||||
STRIP?=echo
|
||||
# The following line enables optimization for the crypto code, since
|
||||
# C25519 in particular is almost UNUSABLE in -O0 even on a 3ghz box!
|
||||
@@ -65,14 +66,18 @@ node/Salsa20.o node/SHA512.o node/C25519.o node/Poly1305.o: CXXFLAGS=-Wall -O2 -
|
||||
else
|
||||
override DEFS+=-D_FORTIFY_SOURCE=2
|
||||
CFLAGS?=-O3 -fstack-protector
|
||||
override CFLAGS+=-Wall -fPIE -pthread $(INCLUDES) -DNDEBUG $(DEFS)
|
||||
override CFLAGS+=-Wall -Wno-deprecated -fPIE -pthread $(INCLUDES) -DNDEBUG $(DEFS)
|
||||
CXXFLAGS?=-O3 -fstack-protector
|
||||
override CXXFLAGS+=-Wall -Wno-unused-result -Wreorder -fPIE -std=c++11 -pthread $(INCLUDES) -DNDEBUG $(DEFS)
|
||||
override CXXFLAGS+=-Wall -Wno-deprecated -Wno-unused-result -Wreorder -fPIE -std=c++11 -pthread $(INCLUDES) -DNDEBUG $(DEFS)
|
||||
override LDFLAGS+=-pie -Wl,-z,relro,-z,now
|
||||
STRIP?=strip
|
||||
STRIP+=--strip-all
|
||||
endif
|
||||
|
||||
ifeq ($(ZT_TRACE),1)
|
||||
override DEFS+=-DZT_TRACE
|
||||
endif
|
||||
|
||||
ifeq ($(ZT_USE_TEST_TAP),1)
|
||||
override DEFS+=-DZT_USE_TEST_TAP
|
||||
endif
|
||||
@@ -87,82 +92,82 @@ endif
|
||||
CC_MACH=$(shell $(CC) -dumpmachine | cut -d '-' -f 1)
|
||||
ZT_ARCHITECTURE=999
|
||||
ifeq ($(CC_MACH),x86_64)
|
||||
ZT_ARCHITECTURE=2
|
||||
ZT_ARCHITECTURE=2
|
||||
ZT_USE_X64_ASM_SALSA2012=1
|
||||
endif
|
||||
ifeq ($(CC_MACH),amd64)
|
||||
ZT_ARCHITECTURE=2
|
||||
ZT_ARCHITECTURE=2
|
||||
ZT_USE_X64_ASM_SALSA2012=1
|
||||
endif
|
||||
ifeq ($(CC_MACH),i386)
|
||||
ZT_ARCHITECTURE=1
|
||||
ZT_ARCHITECTURE=1
|
||||
endif
|
||||
ifeq ($(CC_MACH),i486)
|
||||
ZT_ARCHITECTURE=1
|
||||
ZT_ARCHITECTURE=1
|
||||
endif
|
||||
ifeq ($(CC_MACH),i586)
|
||||
ZT_ARCHITECTURE=1
|
||||
ZT_ARCHITECTURE=1
|
||||
endif
|
||||
ifeq ($(CC_MACH),i686)
|
||||
ZT_ARCHITECTURE=1
|
||||
ZT_ARCHITECTURE=1
|
||||
endif
|
||||
ifeq ($(CC_MACH),arm)
|
||||
ZT_ARCHITECTURE=3
|
||||
ZT_ARCHITECTURE=3
|
||||
override DEFS+=-DZT_NO_TYPE_PUNNING
|
||||
ZT_USE_ARM32_NEON_ASM_SALSA2012=1
|
||||
endif
|
||||
ifeq ($(CC_MACH),armel)
|
||||
ZT_ARCHITECTURE=3
|
||||
ZT_ARCHITECTURE=3
|
||||
override DEFS+=-DZT_NO_TYPE_PUNNING
|
||||
ZT_USE_ARM32_NEON_ASM_SALSA2012=1
|
||||
endif
|
||||
ifeq ($(CC_MACH),armhf)
|
||||
ZT_ARCHITECTURE=3
|
||||
ZT_ARCHITECTURE=3
|
||||
override DEFS+=-DZT_NO_TYPE_PUNNING
|
||||
ZT_USE_ARM32_NEON_ASM_SALSA2012=1
|
||||
endif
|
||||
ifeq ($(CC_MACH),armv6)
|
||||
ZT_ARCHITECTURE=3
|
||||
ZT_ARCHITECTURE=3
|
||||
override DEFS+=-DZT_NO_TYPE_PUNNING
|
||||
ZT_USE_ARM32_NEON_ASM_SALSA2012=1
|
||||
endif
|
||||
ifeq ($(CC_MACH),armv6zk)
|
||||
ZT_ARCHITECTURE=3
|
||||
ZT_ARCHITECTURE=3
|
||||
override DEFS+=-DZT_NO_TYPE_PUNNING
|
||||
ZT_USE_ARM32_NEON_ASM_SALSA2012=1
|
||||
endif
|
||||
ifeq ($(CC_MACH),armv6kz)
|
||||
ZT_ARCHITECTURE=3
|
||||
ZT_ARCHITECTURE=3
|
||||
override DEFS+=-DZT_NO_TYPE_PUNNING
|
||||
ZT_USE_ARM32_NEON_ASM_SALSA2012=1
|
||||
endif
|
||||
ifeq ($(CC_MACH),armv7)
|
||||
ZT_ARCHITECTURE=3
|
||||
ZT_ARCHITECTURE=3
|
||||
override DEFS+=-DZT_NO_TYPE_PUNNING
|
||||
ZT_USE_ARM32_NEON_ASM_SALSA2012=1
|
||||
endif
|
||||
ifeq ($(CC_MACH),arm64)
|
||||
ZT_ARCHITECTURE=4
|
||||
ZT_ARCHITECTURE=4
|
||||
override DEFS+=-DZT_NO_TYPE_PUNNING
|
||||
endif
|
||||
ifeq ($(CC_MACH),aarch64)
|
||||
ZT_ARCHITECTURE=4
|
||||
ZT_ARCHITECTURE=4
|
||||
override DEFS+=-DZT_NO_TYPE_PUNNING
|
||||
endif
|
||||
ifeq ($(CC_MACH),mipsel)
|
||||
ZT_ARCHITECTURE=5
|
||||
ZT_ARCHITECTURE=5
|
||||
override DEFS+=-DZT_NO_TYPE_PUNNING
|
||||
endif
|
||||
ifeq ($(CC_MACH),mips)
|
||||
ZT_ARCHITECTURE=5
|
||||
ZT_ARCHITECTURE=5
|
||||
override DEFS+=-DZT_NO_TYPE_PUNNING
|
||||
endif
|
||||
ifeq ($(CC_MACH),mips64)
|
||||
ZT_ARCHITECTURE=6
|
||||
ZT_ARCHITECTURE=6
|
||||
override DEFS+=-DZT_NO_TYPE_PUNNING
|
||||
endif
|
||||
ifeq ($(CC_MACH),mips64el)
|
||||
ZT_ARCHITECTURE=6
|
||||
ZT_ARCHITECTURE=6
|
||||
override DEFS+=-DZT_NO_TYPE_PUNNING
|
||||
endif
|
||||
|
||||
@@ -179,48 +184,69 @@ override DEFS+=-DZT_BUILD_PLATFORM=1 -DZT_BUILD_ARCHITECTURE=$(ZT_ARCHITECTURE)
|
||||
# Static builds, which are currently done for a number of Linux targets
|
||||
ifeq ($(ZT_STATIC),1)
|
||||
override LDFLAGS+=-static
|
||||
ifeq ($(ZT_ARCHITECTURE),3)
|
||||
ifeq ($(shell if [ -e /usr/bin/dpkg ]; then dpkg --print-architecture; fi),armel)
|
||||
override CFLAGS+=-march=armv5te -mfloat-abi=soft -msoft-float -mno-unaligned-access -marm
|
||||
override CXXFLAGS+=-march=armv5te -mfloat-abi=soft -msoft-float -mno-unaligned-access -marm
|
||||
ZT_USE_ARM32_NEON_ASM_SALSA2012=0
|
||||
else
|
||||
override CFLAGS+=-march=armv6zk -mcpu=arm1176jzf-s -mfpu=vfp -mfloat-abi=hard -mno-unaligned-access -marm
|
||||
override CXXFLAGS+=-march=armv6zk -mcpu=arm1176jzf-s -mfpu=vfp -mfloat-abi=hard -mno-unaligned-access -marm
|
||||
ZT_USE_ARM32_NEON_ASM_SALSA2012=0
|
||||
endif
|
||||
endif
|
||||
|
||||
# ARM32 hell -- use conservative CFLAGS
|
||||
ifeq ($(ZT_ARCHITECTURE),3)
|
||||
ifeq ($(shell if [ -e /usr/bin/dpkg ]; then dpkg --print-architecture; fi),armel)
|
||||
override CFLAGS+=-march=armv5 -mfloat-abi=soft -msoft-float -mno-unaligned-access -marm
|
||||
override CXXFLAGS+=-march=armv5 -mfloat-abi=soft -msoft-float -mno-unaligned-access -marm
|
||||
ZT_USE_ARM32_NEON_ASM_SALSA2012=0
|
||||
else
|
||||
override CFLAGS+=-march=armv5 -mno-unaligned-access -marm
|
||||
override CXXFLAGS+=-march=armv5 -mno-unaligned-access -marm
|
||||
endif
|
||||
endif
|
||||
|
||||
# Build faster crypto on some targets
|
||||
ifeq ($(ZT_USE_X64_ASM_SALSA2012),1)
|
||||
override DEFS+=-DZT_USE_X64_ASM_SALSA2012
|
||||
override OBJS+=ext/x64-salsa2012-asm/salsa2012.o
|
||||
override CORE_OBJS+=ext/x64-salsa2012-asm/salsa2012.o
|
||||
endif
|
||||
ifeq ($(ZT_USE_ARM32_NEON_ASM_SALSA2012),1)
|
||||
override DEFS+=-DZT_USE_ARM32_NEON_ASM_SALSA2012
|
||||
override OBJS+=ext/arm32-neon-salsa2012-asm/salsa2012.o
|
||||
override CORE_OBJS+=ext/arm32-neon-salsa2012-asm/salsa2012.o
|
||||
endif
|
||||
|
||||
all: one
|
||||
|
||||
one: $(OBJS) service/OneService.o one.o osdep/LinuxEthernetTap.o
|
||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o zerotier-one $(OBJS) service/OneService.o one.o osdep/LinuxEthernetTap.o $(LDLIBS)
|
||||
#ext/x64-salsa2012-asm/salsa2012.o:
|
||||
# $(CC) -c ext/x64-salsa2012-asm/salsa2012.s -o ext/x64-salsa2012-asm/salsa2012.o
|
||||
|
||||
#ext/arm32-neon-salsa2012-asm/salsa2012.o:
|
||||
# $(CC) -c ext/arm32-neon-salsa2012-asm/salsa2012.s -o ext/arm32-neon-salsa2012-asm/salsa2012.o
|
||||
|
||||
one: $(CORE_OBJS) $(ONE_OBJS) one.o
|
||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o zerotier-one $(CORE_OBJS) $(ONE_OBJS) one.o $(LDLIBS)
|
||||
$(STRIP) zerotier-one
|
||||
ln -sf zerotier-one zerotier-idtool
|
||||
ln -sf zerotier-one zerotier-cli
|
||||
|
||||
selftest: $(OBJS) selftest.o
|
||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o zerotier-selftest selftest.o $(OBJS) $(LDLIBS)
|
||||
zerotier-one: one
|
||||
|
||||
zerotier-idtool: one
|
||||
|
||||
zerotier-cli: one
|
||||
|
||||
libzerotiercore.a: $(CORE_OBJS)
|
||||
ar rcs libzerotiercore.a $(CORE_OBJS)
|
||||
ranlib libzerotiercore.a
|
||||
|
||||
core: libzerotiercore.a
|
||||
|
||||
selftest: $(CORE_OBJS) $(ONE_OBJS) selftest.o
|
||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o zerotier-selftest selftest.o $(CORE_OBJS) $(ONE_OBJS $(LDLIBS)
|
||||
$(STRIP) zerotier-selftest
|
||||
|
||||
zerotier-selftest: selftest
|
||||
|
||||
manpages: FORCE
|
||||
cd doc ; ./build.sh
|
||||
|
||||
doc: manpages
|
||||
|
||||
clean: FORCE
|
||||
rm -rf *.so *.o node/*.o controller/*.o osdep/*.o service/*.o ext/http-parser/*.o ext/miniupnpc/*.o ext/libnatpmp/*.o $(OBJS) zerotier-one zerotier-idtool zerotier-cli zerotier-selftest build-* ZeroTierOneInstaller-* *.deb *.rpm .depend debian/files debian/zerotier-one*.debhelper debian/zerotier-one.substvars debian/*.log debian/zerotier-one doc/node_modules
|
||||
rm -rf *.a *.so *.o node/*.o controller/*.o osdep/*.o service/*.o ext/http-parser/*.o ext/miniupnpc/*.o ext/libnatpmp/*.o $(CORE_OBJS) $(ONE_OBJS) zerotier-one zerotier-idtool zerotier-cli zerotier-selftest build-* ZeroTierOneInstaller-* *.deb *.rpm .depend debian/files debian/zerotier-one*.debhelper debian/zerotier-one.substvars debian/*.log debian/zerotier-one doc/node_modules
|
||||
|
||||
distclean: clean
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ ZT_VERSION_BUILD=$(shell cat version.h | grep -F VERSION_BUILD | cut -d ' ' -f 3
|
||||
DEFS+=-DZT_BUILD_PLATFORM=$(ZT_BUILD_PLATFORM) -DZT_BUILD_ARCHITECTURE=$(ZT_BUILD_ARCHITECTURE)
|
||||
|
||||
include objects.mk
|
||||
OBJS+=osdep/OSXEthernetTap.o ext/http-parser/http_parser.o
|
||||
ONE_OBJS+=osdep/OSXEthernetTap.o ext/http-parser/http_parser.o
|
||||
|
||||
# Official releases are signed with our Apple cert and apply software updates by default
|
||||
ifeq ($(ZT_OFFICIAL_RELEASE),1)
|
||||
@@ -39,26 +39,30 @@ endif
|
||||
|
||||
# Use fast ASM Salsa20/12 for x64 processors
|
||||
DEFS+=-DZT_USE_X64_ASM_SALSA2012
|
||||
OBJS+=ext/x64-salsa2012-asm/salsa2012.o
|
||||
CORE_OBJS+=ext/x64-salsa2012-asm/salsa2012.o
|
||||
|
||||
# Build miniupnpc and nat-pmp as included libraries -- extra defs are required for these sources
|
||||
DEFS+=-DMACOSX -DZT_USE_MINIUPNPC -DMINIUPNP_STATICLIB -D_DARWIN_C_SOURCE -DMINIUPNPC_SET_SOCKET_TIMEOUT -DMINIUPNPC_GET_SRC_ADDR -D_BSD_SOURCE -D_DEFAULT_SOURCE -DOS_STRING=\"Darwin/15.0.0\" -DMINIUPNPC_VERSION_STRING=\"2.0\" -DUPNP_VERSION_STRING=\"UPnP/1.1\" -DENABLE_STRNATPMPERR
|
||||
OBJS+=ext/libnatpmp/natpmp.o ext/libnatpmp/getgateway.o ext/miniupnpc/connecthostport.o ext/miniupnpc/igd_desc_parse.o ext/miniupnpc/minisoap.o ext/miniupnpc/minissdpc.o ext/miniupnpc/miniupnpc.o ext/miniupnpc/miniwget.o ext/miniupnpc/minixml.o ext/miniupnpc/portlistingparse.o ext/miniupnpc/receivedata.o ext/miniupnpc/upnpcommands.o ext/miniupnpc/upnpdev.o ext/miniupnpc/upnperrors.o ext/miniupnpc/upnpreplyparse.o osdep/PortMapper.o
|
||||
ONE_OBJS+=ext/libnatpmp/natpmp.o ext/libnatpmp/getgateway.o ext/miniupnpc/connecthostport.o ext/miniupnpc/igd_desc_parse.o ext/miniupnpc/minisoap.o ext/miniupnpc/minissdpc.o ext/miniupnpc/miniupnpc.o ext/miniupnpc/miniwget.o ext/miniupnpc/minixml.o ext/miniupnpc/portlistingparse.o ext/miniupnpc/receivedata.o ext/miniupnpc/upnpcommands.o ext/miniupnpc/upnpdev.o ext/miniupnpc/upnperrors.o ext/miniupnpc/upnpreplyparse.o osdep/PortMapper.o
|
||||
|
||||
# Debug mode -- dump trace output, build binary with -g
|
||||
ifeq ($(ZT_DEBUG),1)
|
||||
DEFS+=-DZT_TRACE
|
||||
CFLAGS+=-Wall -g -pthread $(INCLUDES) $(DEFS)
|
||||
ZT_TRACE=1
|
||||
CFLAGS+=-Wall -Werror -g $(INCLUDES) $(DEFS)
|
||||
STRIP=echo
|
||||
# The following line enables optimization for the crypto code, since
|
||||
# C25519 in particular is almost UNUSABLE in heavy testing without it.
|
||||
node/Salsa20.o node/SHA512.o node/C25519.o node/Poly1305.o: CFLAGS = -Wall -O2 -g -pthread $(INCLUDES) $(DEFS)
|
||||
node/Salsa20.o node/SHA512.o node/C25519.o node/Poly1305.o: CFLAGS = -Wall -O2 -g $(INCLUDES) $(DEFS)
|
||||
else
|
||||
CFLAGS?=-Ofast -fstack-protector-strong
|
||||
CFLAGS+=$(ARCH_FLAGS) -Wall -flto -fPIE -pthread -mmacosx-version-min=10.7 -DNDEBUG -Wno-unused-private-field $(INCLUDES) $(DEFS)
|
||||
CFLAGS+=$(ARCH_FLAGS) -Wall -Werror -flto -fPIE -mmacosx-version-min=10.7 -DNDEBUG -Wno-unused-private-field $(INCLUDES) $(DEFS)
|
||||
STRIP=strip
|
||||
endif
|
||||
|
||||
ifeq ($(ZT_TRACE),1)
|
||||
DEFS+=-DZT_TRACE
|
||||
endif
|
||||
|
||||
CXXFLAGS=$(CFLAGS) -std=c++11 -stdlib=libc++
|
||||
|
||||
all: one macui
|
||||
@@ -66,13 +70,25 @@ all: one macui
|
||||
ext/x64-salsa2012-asm/salsa2012.o:
|
||||
$(CC) $(CFLAGS) -c ext/x64-salsa2012-asm/salsa2012.s -o ext/x64-salsa2012-asm/salsa2012.o
|
||||
|
||||
one: $(OBJS) service/OneService.o one.o
|
||||
$(CXX) $(CXXFLAGS) -o zerotier-one $(OBJS) service/OneService.o one.o $(LIBS)
|
||||
one: $(CORE_OBJS) $(ONE_OBJS) one.o
|
||||
$(CXX) $(CXXFLAGS) -o zerotier-one $(CORE_OBJS) $(ONE_OBJS) one.o $(LIBS)
|
||||
$(STRIP) zerotier-one
|
||||
ln -sf zerotier-one zerotier-idtool
|
||||
ln -sf zerotier-one zerotier-cli
|
||||
$(CODESIGN) -f -s $(CODESIGN_APP_CERT) zerotier-one
|
||||
|
||||
zerotier-one: one
|
||||
|
||||
zerotier-idtool: one
|
||||
|
||||
zerotier-cli: one
|
||||
|
||||
libzerotiercore.a: $(CORE_OBJS)
|
||||
ar rcs libzerotiercore.a $(CORE_OBJS)
|
||||
ranlib libzerotiercore.a
|
||||
|
||||
core: libzerotiercore.a
|
||||
|
||||
macui: FORCE
|
||||
cd macui && xcodebuild -target "ZeroTier One" -configuration Release
|
||||
$(CODESIGN) -f -s $(CODESIGN_APP_CERT) "macui/build/Release/ZeroTier One.app"
|
||||
@@ -81,10 +97,12 @@ macui: FORCE
|
||||
# $(CXX) $(CXXFLAGS) -o zerotier cli/zerotier.cpp osdep/OSUtils.cpp node/InetAddress.cpp node/Utils.cpp node/Salsa20.cpp node/Identity.cpp node/SHA512.cpp node/C25519.cpp -lcurl
|
||||
# $(STRIP) zerotier
|
||||
|
||||
selftest: $(OBJS) selftest.o
|
||||
$(CXX) $(CXXFLAGS) -o zerotier-selftest selftest.o $(OBJS) $(LIBS)
|
||||
selftest: $(CORE_OBJS) $(ONE_OBJS) selftest.o
|
||||
$(CXX) $(CXXFLAGS) -o zerotier-selftest selftest.o $(CORE_OBJS) $(ONE_OBJS) $(LIBS)
|
||||
$(STRIP) zerotier-selftest
|
||||
|
||||
zerotier-selftest: selftest
|
||||
|
||||
# Requires Packages: http://s.sudre.free.fr/Software/Packages/about.html
|
||||
mac-dist-pkg: FORCE
|
||||
packagesbuild "ext/installfiles/mac/ZeroTier One.pkgproj"
|
||||
@@ -102,7 +120,7 @@ official: FORCE
|
||||
make ZT_OFFICIAL_RELEASE=1 mac-dist-pkg
|
||||
|
||||
clean:
|
||||
rm -rf *.dSYM build-* *.pkg *.dmg *.o node/*.o controller/*.o service/*.o osdep/*.o ext/http-parser/*.o $(OBJS) zerotier-one zerotier-idtool zerotier-selftest zerotier-cli zerotier mkworld doc/node_modules macui/build zt1_update_$(ZT_BUILD_PLATFORM)_$(ZT_BUILD_ARCHITECTURE)_*
|
||||
rm -rf *.dSYM build-* *.a *.pkg *.dmg *.o node/*.o controller/*.o service/*.o osdep/*.o ext/http-parser/*.o $(CORE_OBJS) $(ONE_OBJS) zerotier-one zerotier-idtool zerotier-selftest zerotier-cli zerotier doc/node_modules macui/build zt1_update_$(ZT_BUILD_PLATFORM)_$(ZT_BUILD_ARCHITECTURE)_*
|
||||
|
||||
distclean: clean
|
||||
|
||||
|
||||
@@ -123,7 +123,7 @@ public:
|
||||
inline Buffer &operator=(const Buffer<C2> &b)
|
||||
throw(std::out_of_range)
|
||||
{
|
||||
if (b._l > C)
|
||||
if (unlikely(b._l > C))
|
||||
throw std::out_of_range("Buffer: assignment from buffer larger than capacity");
|
||||
memcpy(_b,b._b,_l = b._l);
|
||||
return *this;
|
||||
@@ -139,7 +139,7 @@ public:
|
||||
inline void copyFrom(const void *b,unsigned int l)
|
||||
throw(std::out_of_range)
|
||||
{
|
||||
if (l > C)
|
||||
if (unlikely(l > C))
|
||||
throw std::out_of_range("Buffer: set from C array larger than capacity");
|
||||
_l = l;
|
||||
memcpy(_b,b,l);
|
||||
@@ -148,7 +148,7 @@ public:
|
||||
unsigned char operator[](const unsigned int i) const
|
||||
throw(std::out_of_range)
|
||||
{
|
||||
if (i >= _l)
|
||||
if (unlikely(i >= _l))
|
||||
throw std::out_of_range("Buffer: [] beyond end of data");
|
||||
return (unsigned char)_b[i];
|
||||
}
|
||||
@@ -156,7 +156,7 @@ public:
|
||||
unsigned char &operator[](const unsigned int i)
|
||||
throw(std::out_of_range)
|
||||
{
|
||||
if (i >= _l)
|
||||
if (unlikely(i >= _l))
|
||||
throw std::out_of_range("Buffer: [] beyond end of data");
|
||||
return ((unsigned char *)_b)[i];
|
||||
}
|
||||
@@ -177,14 +177,14 @@ public:
|
||||
unsigned char *field(unsigned int i,unsigned int l)
|
||||
throw(std::out_of_range)
|
||||
{
|
||||
if ((i + l) > _l)
|
||||
if (unlikely((i + l) > _l))
|
||||
throw std::out_of_range("Buffer: field() beyond end of data");
|
||||
return (unsigned char *)(_b + i);
|
||||
}
|
||||
const unsigned char *field(unsigned int i,unsigned int l) const
|
||||
throw(std::out_of_range)
|
||||
{
|
||||
if ((i + l) > _l)
|
||||
if (unlikely((i + l) > _l))
|
||||
throw std::out_of_range("Buffer: field() beyond end of data");
|
||||
return (const unsigned char *)(_b + i);
|
||||
}
|
||||
@@ -200,7 +200,7 @@ public:
|
||||
inline void setAt(unsigned int i,const T v)
|
||||
throw(std::out_of_range)
|
||||
{
|
||||
if ((i + sizeof(T)) > _l)
|
||||
if (unlikely((i + sizeof(T)) > _l))
|
||||
throw std::out_of_range("Buffer: setAt() beyond end of data");
|
||||
#ifdef ZT_NO_TYPE_PUNNING
|
||||
uint8_t *p = reinterpret_cast<uint8_t *>(_b + i);
|
||||
@@ -223,7 +223,7 @@ public:
|
||||
inline T at(unsigned int i) const
|
||||
throw(std::out_of_range)
|
||||
{
|
||||
if ((i + sizeof(T)) > _l)
|
||||
if (unlikely((i + sizeof(T)) > _l))
|
||||
throw std::out_of_range("Buffer: at() beyond end of data");
|
||||
#ifdef ZT_NO_TYPE_PUNNING
|
||||
T v = 0;
|
||||
@@ -250,7 +250,7 @@ public:
|
||||
inline void append(const T v)
|
||||
throw(std::out_of_range)
|
||||
{
|
||||
if ((_l + sizeof(T)) > C)
|
||||
if (unlikely((_l + sizeof(T)) > C))
|
||||
throw std::out_of_range("Buffer: append beyond capacity");
|
||||
#ifdef ZT_NO_TYPE_PUNNING
|
||||
uint8_t *p = reinterpret_cast<uint8_t *>(_b + _l);
|
||||
@@ -273,7 +273,7 @@ public:
|
||||
inline void append(unsigned char c,unsigned int n)
|
||||
throw(std::out_of_range)
|
||||
{
|
||||
if ((_l + n) > C)
|
||||
if (unlikely((_l + n) > C))
|
||||
throw std::out_of_range("Buffer: append beyond capacity");
|
||||
for(unsigned int i=0;i<n;++i)
|
||||
_b[_l++] = (char)c;
|
||||
@@ -289,7 +289,7 @@ public:
|
||||
inline void append(const void *b,unsigned int l)
|
||||
throw(std::out_of_range)
|
||||
{
|
||||
if ((_l + l) > C)
|
||||
if (unlikely((_l + l) > C))
|
||||
throw std::out_of_range("Buffer: append beyond capacity");
|
||||
memcpy(_b + _l,b,l);
|
||||
_l += l;
|
||||
@@ -317,7 +317,7 @@ public:
|
||||
throw(std::out_of_range)
|
||||
{
|
||||
for(;;) {
|
||||
if (_l >= C)
|
||||
if (unlikely(_l >= C))
|
||||
throw std::out_of_range("Buffer: append beyond capacity");
|
||||
if (!(_b[_l++] = *(s++)))
|
||||
break;
|
||||
@@ -351,7 +351,7 @@ public:
|
||||
inline char *appendField(unsigned int l)
|
||||
throw(std::out_of_range)
|
||||
{
|
||||
if ((_l + l) > C)
|
||||
if (unlikely((_l + l) > C))
|
||||
throw std::out_of_range("Buffer: append beyond capacity");
|
||||
char *r = _b + _l;
|
||||
_l += l;
|
||||
@@ -369,7 +369,7 @@ public:
|
||||
inline void addSize(unsigned int i)
|
||||
throw(std::out_of_range)
|
||||
{
|
||||
if ((i + _l) > C)
|
||||
if (unlikely((i + _l) > C))
|
||||
throw std::out_of_range("Buffer: setSize to larger than capacity");
|
||||
_l += i;
|
||||
}
|
||||
@@ -385,7 +385,7 @@ public:
|
||||
inline void setSize(const unsigned int i)
|
||||
throw(std::out_of_range)
|
||||
{
|
||||
if (i > C)
|
||||
if (unlikely(i > C))
|
||||
throw std::out_of_range("Buffer: setSize to larger than capacity");
|
||||
_l = i;
|
||||
}
|
||||
@@ -401,7 +401,7 @@ public:
|
||||
{
|
||||
if (!at)
|
||||
return;
|
||||
if (at > _l)
|
||||
if (unlikely(at > _l))
|
||||
throw std::out_of_range("Buffer: behead() beyond capacity");
|
||||
::memmove(_b,_b + at,_l -= at);
|
||||
}
|
||||
@@ -417,7 +417,7 @@ public:
|
||||
throw(std::out_of_range)
|
||||
{
|
||||
const unsigned int endr = at + length;
|
||||
if (endr > _l)
|
||||
if (unlikely(endr > _l))
|
||||
throw std::out_of_range("Buffer: erase() range beyond end of buffer");
|
||||
::memmove(_b + at,_b + endr,_l - endr);
|
||||
_l -= length;
|
||||
|
||||
@@ -257,7 +257,7 @@ void Cluster::handleIncomingStateMessage(const void *msg,unsigned int len)
|
||||
memcpy(keytmp,_key,32);
|
||||
for(int i=0;i<8;++i)
|
||||
keytmp[i] ^= reinterpret_cast<const char *>(msg)[i];
|
||||
Salsa20 s20(keytmp,256,reinterpret_cast<const char *>(msg) + 8);
|
||||
Salsa20 s20(keytmp,reinterpret_cast<const char *>(msg) + 8);
|
||||
Utils::burn(keytmp,sizeof(keytmp));
|
||||
|
||||
// One-time-use Poly1305 key from first 32 bytes of Salsa20 keystream (as per DJB/NaCl "standard")
|
||||
@@ -956,7 +956,7 @@ void Cluster::_flush(uint16_t memberId)
|
||||
memcpy(keytmp,m.key,32);
|
||||
for(int i=0;i<8;++i)
|
||||
keytmp[i] ^= m.q[i];
|
||||
Salsa20 s20(keytmp,256,m.q.field(8,8));
|
||||
Salsa20 s20(keytmp,m.q.field(8,8));
|
||||
Utils::burn(keytmp,sizeof(keytmp));
|
||||
|
||||
// One-time-use Poly1305 key from first 32 bytes of Salsa20 keystream (as per DJB/NaCl "standard")
|
||||
|
||||
@@ -60,6 +60,8 @@
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define likely(x) __builtin_expect((x),1)
|
||||
#define unlikely(x) __builtin_expect((x),0)
|
||||
#include <TargetConditionals.h>
|
||||
#ifndef __UNIX_LIKE__
|
||||
#define __UNIX_LIKE__
|
||||
@@ -132,6 +134,22 @@
|
||||
#include <endian.h>
|
||||
#endif
|
||||
|
||||
#if (defined(__GNUC__) && (__GNUC__ >= 3)) || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) || defined(__clang__)
|
||||
#ifndef likely
|
||||
#define likely(x) __builtin_expect((x),1)
|
||||
#endif
|
||||
#ifndef unlikely
|
||||
#define unlikely(x) __builtin_expect((x),0)
|
||||
#endif
|
||||
#else
|
||||
#ifndef likely
|
||||
#define likely(x) (x)
|
||||
#endif
|
||||
#ifndef unlikely
|
||||
#define unlikely(x) (x)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Length of a ZeroTier address in bytes
|
||||
*/
|
||||
@@ -159,15 +177,12 @@
|
||||
/**
|
||||
* Default MTU used for Ethernet tap device
|
||||
*/
|
||||
#define ZT_IF_MTU ZT_MAX_MTU
|
||||
#define ZT_DEFAULT_MTU 2800
|
||||
|
||||
/**
|
||||
* Maximum number of packet fragments we'll support
|
||||
*
|
||||
* The actual spec allows 16, but this is the most we'll support right
|
||||
* now. Packets with more than this many fragments are dropped.
|
||||
* Maximum number of packet fragments we'll support (protocol max: 16)
|
||||
*/
|
||||
#define ZT_MAX_PACKET_FRAGMENTS 4
|
||||
#define ZT_MAX_PACKET_FRAGMENTS 7
|
||||
|
||||
/**
|
||||
* Size of RX queue
|
||||
@@ -372,7 +387,7 @@
|
||||
/**
|
||||
* Time horizon for push direct paths cutoff
|
||||
*/
|
||||
#define ZT_PUSH_DIRECT_PATHS_CUTOFF_TIME 60000
|
||||
#define ZT_PUSH_DIRECT_PATHS_CUTOFF_TIME 30000
|
||||
|
||||
/**
|
||||
* Maximum number of direct path pushes within cutoff time
|
||||
@@ -381,12 +396,12 @@
|
||||
* per CUTOFF_TIME milliseconds per peer to prevent this from being
|
||||
* useful for DOS amplification attacks.
|
||||
*/
|
||||
#define ZT_PUSH_DIRECT_PATHS_CUTOFF_LIMIT 5
|
||||
#define ZT_PUSH_DIRECT_PATHS_CUTOFF_LIMIT 8
|
||||
|
||||
/**
|
||||
* Maximum number of paths per IP scope (e.g. global, link-local) and family (e.g. v4/v6)
|
||||
*/
|
||||
#define ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY 4
|
||||
#define ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY 8
|
||||
|
||||
/**
|
||||
* Time horizon for VERB_NETWORK_CREDENTIALS cutoff
|
||||
|
||||
@@ -115,8 +115,6 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR,void *tPtr)
|
||||
case Packet::VERB_MULTICAST_GATHER: return _doMULTICAST_GATHER(RR,tPtr,peer);
|
||||
case Packet::VERB_MULTICAST_FRAME: return _doMULTICAST_FRAME(RR,tPtr,peer);
|
||||
case Packet::VERB_PUSH_DIRECT_PATHS: return _doPUSH_DIRECT_PATHS(RR,tPtr,peer);
|
||||
case Packet::VERB_CIRCUIT_TEST: return _doCIRCUIT_TEST(RR,tPtr,peer);
|
||||
case Packet::VERB_CIRCUIT_TEST_REPORT: return _doCIRCUIT_TEST_REPORT(RR,tPtr,peer);
|
||||
case Packet::VERB_USER_MESSAGE: return _doUSER_MESSAGE(RR,tPtr,peer);
|
||||
}
|
||||
} else {
|
||||
@@ -1125,7 +1123,7 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,void *tPtr,
|
||||
|
||||
//TRACE("<<MC FRAME %.16llx/%s from %s@%s flags %.2x length %u",nwid,to.toString().c_str(),from.toString().c_str(),peer->address().toString().c_str(),flags,frameLen);
|
||||
|
||||
if ((frameLen > 0)&&(frameLen <= ZT_IF_MTU)) {
|
||||
if ((frameLen > 0)&&(frameLen <= ZT_MAX_MTU)) {
|
||||
if (!to.mac().isMulticast()) {
|
||||
TRACE("dropped MULTICAST_FRAME from %s@%s(%s) to %s: destination is unicast, must use FRAME or EXT_FRAME",from.toString().c_str(),peer->address().toString().c_str(),_path->address().toString().c_str(),to.toString().c_str());
|
||||
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay
|
||||
@@ -1185,7 +1183,7 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,void *tPt
|
||||
|
||||
// First, subject this to a rate limit
|
||||
if (!peer->rateGatePushDirectPaths(now)) {
|
||||
TRACE("dropped PUSH_DIRECT_PATHS from %s(%s): circuit breaker tripped",source().toString().c_str(),_path->address().toString().c_str());
|
||||
//TRACE("dropped PUSH_DIRECT_PATHS from %s(%s): circuit breaker tripped",source().toString().c_str(),_path->address().toString().c_str());
|
||||
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_PUSH_DIRECT_PATHS,0,Packet::VERB_NOP,false);
|
||||
return true;
|
||||
}
|
||||
@@ -1220,7 +1218,7 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,void *tPt
|
||||
TRACE("attempting to contact %s at pushed direct path %s",peer->address().toString().c_str(),a.toString().c_str());
|
||||
peer->attemptToContactAt(tPtr,InetAddress(),a,now,false,0);
|
||||
} else {
|
||||
TRACE("ignoring contact for %s at %s -- too many per scope",peer->address().toString().c_str(),a.toString().c_str());
|
||||
//TRACE("ignoring contact for %s at %s -- too many per scope",peer->address().toString().c_str(),a.toString().c_str());
|
||||
}
|
||||
}
|
||||
} break;
|
||||
@@ -1237,7 +1235,7 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,void *tPt
|
||||
TRACE("attempting to contact %s at pushed direct path %s",peer->address().toString().c_str(),a.toString().c_str());
|
||||
peer->attemptToContactAt(tPtr,InetAddress(),a,now,false,0);
|
||||
} else {
|
||||
TRACE("ignoring contact for %s at %s -- too many per scope",peer->address().toString().c_str(),a.toString().c_str());
|
||||
//TRACE("ignoring contact for %s at %s -- too many per scope",peer->address().toString().c_str(),a.toString().c_str());
|
||||
}
|
||||
}
|
||||
} break;
|
||||
@@ -1252,196 +1250,6 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,void *tPt
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IncomingPacket::_doCIRCUIT_TEST(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer)
|
||||
{
|
||||
try {
|
||||
const Address originatorAddress(field(ZT_PACKET_IDX_PAYLOAD,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH);
|
||||
SharedPtr<Peer> originator(RR->topology->getPeer(tPtr,originatorAddress));
|
||||
if (!originator) {
|
||||
RR->sw->requestWhois(tPtr,originatorAddress);
|
||||
return false;
|
||||
}
|
||||
|
||||
const unsigned int flags = at<uint16_t>(ZT_PACKET_IDX_PAYLOAD + 5);
|
||||
const uint64_t timestamp = at<uint64_t>(ZT_PACKET_IDX_PAYLOAD + 7);
|
||||
const uint64_t testId = at<uint64_t>(ZT_PACKET_IDX_PAYLOAD + 15);
|
||||
|
||||
// Tracks total length of variable length fields, initialized to originator credential length below
|
||||
unsigned int vlf;
|
||||
|
||||
// Originator credentials -- right now only a network ID for which the originator is controller or is authorized by controller is allowed
|
||||
const unsigned int originatorCredentialLength = vlf = at<uint16_t>(ZT_PACKET_IDX_PAYLOAD + 23);
|
||||
uint64_t originatorCredentialNetworkId = 0;
|
||||
if (originatorCredentialLength >= 1) {
|
||||
switch((*this)[ZT_PACKET_IDX_PAYLOAD + 25]) {
|
||||
case 0x01: { // 64-bit network ID, originator must be controller
|
||||
if (originatorCredentialLength >= 9)
|
||||
originatorCredentialNetworkId = at<uint64_t>(ZT_PACKET_IDX_PAYLOAD + 26);
|
||||
} break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
// Add length of "additional fields," which are currently unused
|
||||
vlf += at<uint16_t>(ZT_PACKET_IDX_PAYLOAD + 25 + vlf);
|
||||
|
||||
// Verify signature -- only tests signed by their originators are allowed
|
||||
const unsigned int signatureLength = at<uint16_t>(ZT_PACKET_IDX_PAYLOAD + 27 + vlf);
|
||||
if (!originator->identity().verify(field(ZT_PACKET_IDX_PAYLOAD,27 + vlf),27 + vlf,field(ZT_PACKET_IDX_PAYLOAD + 29 + vlf,signatureLength),signatureLength)) {
|
||||
TRACE("dropped CIRCUIT_TEST from %s(%s): signature by originator %s invalid",source().toString().c_str(),_path->address().toString().c_str(),originatorAddress.toString().c_str());
|
||||
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_CIRCUIT_TEST,0,Packet::VERB_NOP,false);
|
||||
return true;
|
||||
}
|
||||
vlf += signatureLength;
|
||||
|
||||
// Save this length so we can copy the immutable parts of this test
|
||||
// into the one we send along to next hops.
|
||||
const unsigned int lengthOfSignedPortionAndSignature = 29 + vlf;
|
||||
|
||||
// Add length of second "additional fields" section.
|
||||
vlf += at<uint16_t>(ZT_PACKET_IDX_PAYLOAD + 29 + vlf);
|
||||
|
||||
uint64_t reportFlags = 0;
|
||||
|
||||
// Check credentials (signature already verified)
|
||||
if (originatorCredentialNetworkId) {
|
||||
SharedPtr<Network> network(RR->node->network(originatorCredentialNetworkId));
|
||||
if ((!network)||(!network->config().circuitTestingAllowed(originatorAddress))) {
|
||||
TRACE("dropped CIRCUIT_TEST from %s(%s): originator %s specified network ID %.16llx as credential, and we don't belong to that network or originator is not allowed'",source().toString().c_str(),_path->address().toString().c_str(),originatorAddress.toString().c_str(),originatorCredentialNetworkId);
|
||||
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_CIRCUIT_TEST,0,Packet::VERB_NOP,false);
|
||||
return true;
|
||||
}
|
||||
if (network->gate(tPtr,peer))
|
||||
reportFlags |= ZT_CIRCUIT_TEST_REPORT_FLAGS_UPSTREAM_AUTHORIZED_IN_PATH;
|
||||
} else {
|
||||
TRACE("dropped CIRCUIT_TEST from %s(%s): originator %s did not specify a credential or credential type",source().toString().c_str(),_path->address().toString().c_str(),originatorAddress.toString().c_str());
|
||||
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_CIRCUIT_TEST,0,Packet::VERB_NOP,false);
|
||||
return true;
|
||||
}
|
||||
|
||||
const uint64_t now = RR->node->now();
|
||||
|
||||
unsigned int breadth = 0;
|
||||
Address nextHop[256]; // breadth is a uin8_t, so this is the max
|
||||
InetAddress nextHopBestPathAddress[256];
|
||||
unsigned int remainingHopsPtr = ZT_PACKET_IDX_PAYLOAD + 33 + vlf;
|
||||
if ((ZT_PACKET_IDX_PAYLOAD + 31 + vlf) < size()) {
|
||||
// unsigned int nextHopFlags = (*this)[ZT_PACKET_IDX_PAYLOAD + 31 + vlf]
|
||||
breadth = (*this)[ZT_PACKET_IDX_PAYLOAD + 32 + vlf];
|
||||
for(unsigned int h=0;h<breadth;++h) {
|
||||
nextHop[h].setTo(field(remainingHopsPtr,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH);
|
||||
remainingHopsPtr += ZT_ADDRESS_LENGTH;
|
||||
SharedPtr<Peer> nhp(RR->topology->getPeer(tPtr,nextHop[h]));
|
||||
if (nhp) {
|
||||
SharedPtr<Path> nhbp(nhp->getBestPath(now,false));
|
||||
if ((nhbp)&&(nhbp->alive(now)))
|
||||
nextHopBestPathAddress[h] = nhbp->address();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Report back to originator, depending on flags and whether we are last hop
|
||||
if ( ((flags & 0x01) != 0) || ((breadth == 0)&&((flags & 0x02) != 0)) ) {
|
||||
Packet outp(originatorAddress,RR->identity.address(),Packet::VERB_CIRCUIT_TEST_REPORT);
|
||||
outp.append((uint64_t)timestamp);
|
||||
outp.append((uint64_t)testId);
|
||||
outp.append((uint64_t)0); // field reserved for future use
|
||||
outp.append((uint8_t)ZT_VENDOR_ZEROTIER);
|
||||
outp.append((uint8_t)ZT_PROTO_VERSION);
|
||||
outp.append((uint8_t)ZEROTIER_ONE_VERSION_MAJOR);
|
||||
outp.append((uint8_t)ZEROTIER_ONE_VERSION_MINOR);
|
||||
outp.append((uint16_t)ZEROTIER_ONE_VERSION_REVISION);
|
||||
outp.append((uint16_t)ZT_PLATFORM_UNSPECIFIED);
|
||||
outp.append((uint16_t)ZT_ARCHITECTURE_UNSPECIFIED);
|
||||
outp.append((uint16_t)0); // error code, currently unused
|
||||
outp.append((uint64_t)reportFlags);
|
||||
outp.append((uint64_t)packetId());
|
||||
peer->address().appendTo(outp);
|
||||
outp.append((uint8_t)hops());
|
||||
_path->localAddress().serialize(outp);
|
||||
_path->address().serialize(outp);
|
||||
outp.append((uint16_t)_path->linkQuality());
|
||||
outp.append((uint8_t)breadth);
|
||||
for(unsigned int h=0;h<breadth;++h) {
|
||||
nextHop[h].appendTo(outp);
|
||||
nextHopBestPathAddress[h].serialize(outp); // appends 0 if null InetAddress
|
||||
}
|
||||
RR->sw->send(tPtr,outp,true);
|
||||
}
|
||||
|
||||
// If there are next hops, forward the test along through the graph
|
||||
if (breadth > 0) {
|
||||
Packet outp(Address(),RR->identity.address(),Packet::VERB_CIRCUIT_TEST);
|
||||
outp.append(field(ZT_PACKET_IDX_PAYLOAD,lengthOfSignedPortionAndSignature),lengthOfSignedPortionAndSignature);
|
||||
outp.append((uint16_t)0); // no additional fields
|
||||
if (remainingHopsPtr < size())
|
||||
outp.append(field(remainingHopsPtr,size() - remainingHopsPtr),size() - remainingHopsPtr);
|
||||
|
||||
for(unsigned int h=0;h<breadth;++h) {
|
||||
if (RR->identity.address() != nextHop[h]) { // next hops that loop back to the current hop are not valid
|
||||
outp.newInitializationVector();
|
||||
outp.setDestination(nextHop[h]);
|
||||
RR->sw->send(tPtr,outp,true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_CIRCUIT_TEST,0,Packet::VERB_NOP,false);
|
||||
} catch ( ... ) {
|
||||
TRACE("dropped CIRCUIT_TEST from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IncomingPacket::_doCIRCUIT_TEST_REPORT(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer)
|
||||
{
|
||||
try {
|
||||
ZT_CircuitTestReport report;
|
||||
memset(&report,0,sizeof(report));
|
||||
|
||||
report.current = peer->address().toInt();
|
||||
report.upstream = Address(field(ZT_PACKET_IDX_PAYLOAD + 52,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH).toInt();
|
||||
report.testId = at<uint64_t>(ZT_PACKET_IDX_PAYLOAD + 8);
|
||||
report.timestamp = at<uint64_t>(ZT_PACKET_IDX_PAYLOAD);
|
||||
report.sourcePacketId = at<uint64_t>(ZT_PACKET_IDX_PAYLOAD + 44);
|
||||
report.flags = at<uint64_t>(ZT_PACKET_IDX_PAYLOAD + 36);
|
||||
report.sourcePacketHopCount = (*this)[ZT_PACKET_IDX_PAYLOAD + 57]; // end of fixed length headers: 58
|
||||
report.errorCode = at<uint16_t>(ZT_PACKET_IDX_PAYLOAD + 34);
|
||||
report.vendor = (enum ZT_Vendor)((*this)[ZT_PACKET_IDX_PAYLOAD + 24]);
|
||||
report.protocolVersion = (*this)[ZT_PACKET_IDX_PAYLOAD + 25];
|
||||
report.majorVersion = (*this)[ZT_PACKET_IDX_PAYLOAD + 26];
|
||||
report.minorVersion = (*this)[ZT_PACKET_IDX_PAYLOAD + 27];
|
||||
report.revision = at<uint16_t>(ZT_PACKET_IDX_PAYLOAD + 28);
|
||||
report.platform = (enum ZT_Platform)at<uint16_t>(ZT_PACKET_IDX_PAYLOAD + 30);
|
||||
report.architecture = (enum ZT_Architecture)at<uint16_t>(ZT_PACKET_IDX_PAYLOAD + 32);
|
||||
|
||||
const unsigned int receivedOnLocalAddressLen = reinterpret_cast<InetAddress *>(&(report.receivedOnLocalAddress))->deserialize(*this,ZT_PACKET_IDX_PAYLOAD + 58);
|
||||
const unsigned int receivedFromRemoteAddressLen = reinterpret_cast<InetAddress *>(&(report.receivedFromRemoteAddress))->deserialize(*this,ZT_PACKET_IDX_PAYLOAD + 58 + receivedOnLocalAddressLen);
|
||||
unsigned int ptr = ZT_PACKET_IDX_PAYLOAD + 58 + receivedOnLocalAddressLen + receivedFromRemoteAddressLen;
|
||||
if (report.protocolVersion >= 9) {
|
||||
report.receivedFromLinkQuality = at<uint16_t>(ptr); ptr += 2;
|
||||
} else {
|
||||
report.receivedFromLinkQuality = ZT_PATH_LINK_QUALITY_MAX;
|
||||
ptr += at<uint16_t>(ptr) + 2; // this field was once an 'extended field length' reserved field, which was always set to 0
|
||||
}
|
||||
|
||||
report.nextHopCount = (*this)[ptr++];
|
||||
if (report.nextHopCount > ZT_CIRCUIT_TEST_MAX_HOP_BREADTH) // sanity check, shouldn't be possible
|
||||
report.nextHopCount = ZT_CIRCUIT_TEST_MAX_HOP_BREADTH;
|
||||
for(unsigned int h=0;h<report.nextHopCount;++h) {
|
||||
report.nextHops[h].address = Address(field(ptr,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH).toInt(); ptr += ZT_ADDRESS_LENGTH;
|
||||
ptr += reinterpret_cast<InetAddress *>(&(report.nextHops[h].physicalAddress))->deserialize(*this,ptr);
|
||||
}
|
||||
|
||||
RR->node->postCircuitTestReport(&report);
|
||||
|
||||
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_CIRCUIT_TEST_REPORT,0,Packet::VERB_NOP,false);
|
||||
} catch ( ... ) {
|
||||
TRACE("dropped CIRCUIT_TEST_REPORT from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IncomingPacket::_doUSER_MESSAGE(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer)
|
||||
{
|
||||
try {
|
||||
@@ -1453,9 +1261,9 @@ bool IncomingPacket::_doUSER_MESSAGE(const RuntimeEnvironment *RR,void *tPtr,con
|
||||
um.length = size() - (ZT_PACKET_IDX_PAYLOAD + 8);
|
||||
RR->node->postEvent(tPtr,ZT_EVENT_USER_MESSAGE,reinterpret_cast<const void *>(&um));
|
||||
}
|
||||
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_CIRCUIT_TEST_REPORT,0,Packet::VERB_NOP,false);
|
||||
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_USER_MESSAGE,0,Packet::VERB_NOP,false);
|
||||
} catch ( ... ) {
|
||||
TRACE("dropped CIRCUIT_TEST_REPORT from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
|
||||
TRACE("dropped USER_MESSAGE from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -138,8 +138,6 @@ private:
|
||||
bool _doMULTICAST_GATHER(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||
bool _doMULTICAST_FRAME(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||
bool _doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||
bool _doCIRCUIT_TEST(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||
bool _doCIRCUIT_TEST_REPORT(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||
bool _doUSER_MESSAGE(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||
|
||||
void _sendErrorNeedCredentials(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer,const uint64_t nwid);
|
||||
|
||||
@@ -1225,6 +1225,8 @@ void Network::requestConfiguration(void *tPtr)
|
||||
nconf->revision = 1;
|
||||
nconf->issuedTo = RR->identity.address();
|
||||
nconf->flags = ZT_NETWORKCONFIG_FLAG_ENABLE_IPV6_NDP_EMULATION;
|
||||
nconf->mtu = ZT_DEFAULT_MTU;
|
||||
nconf->multicastLimit = 0;
|
||||
nconf->staticIpCount = 1;
|
||||
nconf->ruleCount = 14;
|
||||
nconf->staticIps[0] = InetAddress::makeIpv66plane(_id,RR->identity.address().toInt());
|
||||
@@ -1495,7 +1497,7 @@ void Network::_externalConfig(ZT_VirtualNetworkConfig *ec) const
|
||||
else ec->name[0] = (char)0;
|
||||
ec->status = _status();
|
||||
ec->type = (_config) ? (_config.isPrivate() ? ZT_NETWORK_TYPE_PRIVATE : ZT_NETWORK_TYPE_PUBLIC) : ZT_NETWORK_TYPE_PRIVATE;
|
||||
ec->mtu = ZT_IF_MTU;
|
||||
ec->mtu = (_config) ? _config.mtu : ZT_DEFAULT_MTU;
|
||||
ec->physicalMtu = ZT_UDP_DEFAULT_PAYLOAD_MTU - (ZT_PACKET_IDX_PAYLOAD + 16);
|
||||
ec->dhcp = 0;
|
||||
std::vector<Address> ab(_config.activeBridges());
|
||||
|
||||
@@ -51,6 +51,7 @@ bool NetworkConfig::toDictionary(Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d,b
|
||||
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT,(uint64_t)this->multicastLimit)) return false;
|
||||
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_TYPE,(uint64_t)this->type)) return false;
|
||||
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_NAME,this->name)) return false;
|
||||
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_MTU,(uint64_t)this->mtu)) return false;
|
||||
|
||||
#ifdef ZT_SUPPORT_OLD_STYLE_NETCONF
|
||||
if (includeLegacy) {
|
||||
@@ -217,6 +218,12 @@ bool NetworkConfig::fromDictionary(const Dictionary<ZT_NETWORKCONFIG_DICT_CAPACI
|
||||
this->multicastLimit = (unsigned int)d.getUI(ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT,0);
|
||||
d.get(ZT_NETWORKCONFIG_DICT_KEY_NAME,this->name,sizeof(this->name));
|
||||
|
||||
this->mtu = (unsigned int)d.getUI(ZT_NETWORKCONFIG_DICT_KEY_MTU,ZT_DEFAULT_MTU);
|
||||
if (this->mtu < 1280)
|
||||
this->mtu = 1280; // minimum MTU allowed by IPv6 standard and others
|
||||
else if (this->mtu > ZT_MAX_MTU)
|
||||
this->mtu = ZT_MAX_MTU;
|
||||
|
||||
if (d.getUI(ZT_NETWORKCONFIG_DICT_KEY_VERSION,0) < 6) {
|
||||
#ifdef ZT_SUPPORT_OLD_STYLE_NETCONF
|
||||
char tmp2[1024];
|
||||
|
||||
@@ -167,6 +167,8 @@ namespace ZeroTier {
|
||||
#define ZT_NETWORKCONFIG_DICT_KEY_TYPE "t"
|
||||
// text
|
||||
#define ZT_NETWORKCONFIG_DICT_KEY_NAME "n"
|
||||
// network MTU
|
||||
#define ZT_NETWORKCONFIG_DICT_KEY_MTU "mtu"
|
||||
// credential time max delta in ms
|
||||
#define ZT_NETWORKCONFIG_DICT_KEY_CREDENTIAL_TIME_MAX_DELTA "ctmd"
|
||||
// binary serialized certificate of membership
|
||||
@@ -465,6 +467,11 @@ public:
|
||||
*/
|
||||
uint64_t flags;
|
||||
|
||||
/**
|
||||
* Network MTU
|
||||
*/
|
||||
unsigned int mtu;
|
||||
|
||||
/**
|
||||
* Maximum number of recipients per multicast (not including active bridges)
|
||||
*/
|
||||
|
||||
@@ -327,6 +327,7 @@ ZT_ResultCode Node::leave(uint64_t nwid,void **uptr,void *tptr)
|
||||
} else {
|
||||
if (uptr)
|
||||
*uptr = *n->second->userPtr();
|
||||
n->second->externalConfig(&ctmp);
|
||||
n->second->destroy();
|
||||
nUserPtr = n->second->userPtr();
|
||||
}
|
||||
@@ -502,64 +503,6 @@ void Node::setNetconfMaster(void *networkControllerInstance)
|
||||
RR->localNetworkController->init(RR->identity,this);
|
||||
}
|
||||
|
||||
ZT_ResultCode Node::circuitTestBegin(void *tptr,ZT_CircuitTest *test,void (*reportCallback)(ZT_Node *,ZT_CircuitTest *,const ZT_CircuitTestReport *))
|
||||
{
|
||||
if (test->hopCount > 0) {
|
||||
try {
|
||||
Packet outp(Address(),RR->identity.address(),Packet::VERB_CIRCUIT_TEST);
|
||||
RR->identity.address().appendTo(outp);
|
||||
outp.append((uint16_t)((test->reportAtEveryHop != 0) ? 0x03 : 0x02));
|
||||
outp.append((uint64_t)test->timestamp);
|
||||
outp.append((uint64_t)test->testId);
|
||||
outp.append((uint16_t)0); // originator credential length, updated later
|
||||
if (test->credentialNetworkId) {
|
||||
outp.append((uint8_t)0x01);
|
||||
outp.append((uint64_t)test->credentialNetworkId);
|
||||
outp.setAt<uint16_t>(ZT_PACKET_IDX_PAYLOAD + 23,(uint16_t)9);
|
||||
}
|
||||
outp.append((uint16_t)0);
|
||||
C25519::Signature sig(RR->identity.sign(reinterpret_cast<const char *>(outp.data()) + ZT_PACKET_IDX_PAYLOAD,outp.size() - ZT_PACKET_IDX_PAYLOAD));
|
||||
outp.append((uint16_t)sig.size());
|
||||
outp.append(sig.data,(unsigned int)sig.size());
|
||||
outp.append((uint16_t)0); // originator doesn't need an extra credential, since it's the originator
|
||||
for(unsigned int h=1;h<test->hopCount;++h) {
|
||||
outp.append((uint8_t)0);
|
||||
outp.append((uint8_t)(test->hops[h].breadth & 0xff));
|
||||
for(unsigned int a=0;a<test->hops[h].breadth;++a)
|
||||
Address(test->hops[h].addresses[a]).appendTo(outp);
|
||||
}
|
||||
|
||||
for(unsigned int a=0;a<test->hops[0].breadth;++a) {
|
||||
outp.newInitializationVector();
|
||||
outp.setDestination(Address(test->hops[0].addresses[a]));
|
||||
RR->sw->send(tptr,outp,true);
|
||||
}
|
||||
} catch ( ... ) {
|
||||
return ZT_RESULT_FATAL_ERROR_INTERNAL; // probably indicates FIFO too big for packet
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
test->_internalPtr = reinterpret_cast<void *>(reportCallback);
|
||||
Mutex::Lock _l(_circuitTests_m);
|
||||
if (std::find(_circuitTests.begin(),_circuitTests.end(),test) == _circuitTests.end())
|
||||
_circuitTests.push_back(test);
|
||||
}
|
||||
|
||||
return ZT_RESULT_OK;
|
||||
}
|
||||
|
||||
void Node::circuitTestEnd(ZT_CircuitTest *test)
|
||||
{
|
||||
Mutex::Lock _l(_circuitTests_m);
|
||||
for(;;) {
|
||||
std::vector< ZT_CircuitTest * >::iterator ct(std::find(_circuitTests.begin(),_circuitTests.end(),test));
|
||||
if (ct == _circuitTests.end())
|
||||
break;
|
||||
else _circuitTests.erase(ct);
|
||||
}
|
||||
}
|
||||
|
||||
ZT_ResultCode Node::clusterInit(
|
||||
unsigned int myId,
|
||||
const struct sockaddr_storage *zeroTierPhysicalEndpoints,
|
||||
@@ -714,20 +657,6 @@ uint64_t Node::prng()
|
||||
return z + y;
|
||||
}
|
||||
|
||||
void Node::postCircuitTestReport(const ZT_CircuitTestReport *report)
|
||||
{
|
||||
std::vector< ZT_CircuitTest * > toNotify;
|
||||
{
|
||||
Mutex::Lock _l(_circuitTests_m);
|
||||
for(std::vector< ZT_CircuitTest * >::iterator i(_circuitTests.begin());i!=_circuitTests.end();++i) {
|
||||
if ((*i)->testId == report->testId)
|
||||
toNotify.push_back(*i);
|
||||
}
|
||||
}
|
||||
for(std::vector< ZT_CircuitTest * >::iterator i(toNotify.begin());i!=toNotify.end();++i)
|
||||
(reinterpret_cast<void (*)(ZT_Node *,ZT_CircuitTest *,const ZT_CircuitTestReport *)>((*i)->_internalPtr))(reinterpret_cast<ZT_Node *>(this),*i,report);
|
||||
}
|
||||
|
||||
void Node::setTrustedPaths(const struct sockaddr_storage *networks,const uint64_t *ids,unsigned int count)
|
||||
{
|
||||
RR->topology->setTrustedPaths(reinterpret_cast<const InetAddress *>(networks),ids,count);
|
||||
@@ -1069,22 +998,6 @@ void ZT_Node_setNetconfMaster(ZT_Node *node,void *networkControllerInstance)
|
||||
} catch ( ... ) {}
|
||||
}
|
||||
|
||||
enum ZT_ResultCode ZT_Node_circuitTestBegin(ZT_Node *node,void *tptr,ZT_CircuitTest *test,void (*reportCallback)(ZT_Node *,ZT_CircuitTest *,const ZT_CircuitTestReport *))
|
||||
{
|
||||
try {
|
||||
return reinterpret_cast<ZeroTier::Node *>(node)->circuitTestBegin(tptr,test,reportCallback);
|
||||
} catch ( ... ) {
|
||||
return ZT_RESULT_FATAL_ERROR_INTERNAL;
|
||||
}
|
||||
}
|
||||
|
||||
void ZT_Node_circuitTestEnd(ZT_Node *node,ZT_CircuitTest *test)
|
||||
{
|
||||
try {
|
||||
reinterpret_cast<ZeroTier::Node *>(node)->circuitTestEnd(test);
|
||||
} catch ( ... ) {}
|
||||
}
|
||||
|
||||
enum ZT_ResultCode ZT_Node_clusterInit(
|
||||
ZT_Node *node,
|
||||
unsigned int myId,
|
||||
|
||||
@@ -117,8 +117,6 @@ public:
|
||||
void clearLocalInterfaceAddresses();
|
||||
int sendUserMessage(void *tptr,uint64_t dest,uint64_t typeId,const void *data,unsigned int len);
|
||||
void setNetconfMaster(void *networkControllerInstance);
|
||||
ZT_ResultCode circuitTestBegin(void *tptr,ZT_CircuitTest *test,void (*reportCallback)(ZT_Node *,ZT_CircuitTest *,const ZT_CircuitTestReport *));
|
||||
void circuitTestEnd(ZT_CircuitTest *test);
|
||||
ZT_ResultCode clusterInit(
|
||||
unsigned int myId,
|
||||
const struct sockaddr_storage *zeroTierPhysicalEndpoints,
|
||||
@@ -219,7 +217,6 @@ public:
|
||||
inline bool externalPathLookup(void *tPtr,const Address &ztaddr,int family,InetAddress &addr) { return ( (_cb.pathLookupFunction) ? (_cb.pathLookupFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,ztaddr.toInt(),family,reinterpret_cast<struct sockaddr_storage *>(&addr)) != 0) : false ); }
|
||||
|
||||
uint64_t prng();
|
||||
void postCircuitTestReport(const ZT_CircuitTestReport *report);
|
||||
void setTrustedPaths(const struct sockaddr_storage *networks,const uint64_t *ids,unsigned int count);
|
||||
|
||||
World planet() const;
|
||||
@@ -309,9 +306,6 @@ private:
|
||||
std::vector< std::pair< uint64_t, SharedPtr<Network> > > _networks;
|
||||
Mutex _networks_m;
|
||||
|
||||
std::vector< ZT_CircuitTest * > _circuitTests;
|
||||
Mutex _circuitTests_m;
|
||||
|
||||
std::vector<InetAddress> _directPaths;
|
||||
Mutex _directPaths_m;
|
||||
|
||||
|
||||
@@ -320,6 +320,7 @@ union LZ4_streamDecode_u {
|
||||
#define FORCE_INLINE static inline
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#if (defined(__GNUC__) && (__GNUC__ >= 3)) || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) || defined(__clang__)
|
||||
# define expect(expr,value) (__builtin_expect ((expr),(value)) )
|
||||
#else
|
||||
@@ -328,6 +329,7 @@ union LZ4_streamDecode_u {
|
||||
|
||||
#define likely(expr) expect((expr) != 0, 1)
|
||||
#define unlikely(expr) expect((expr) != 0, 0)
|
||||
#endif
|
||||
|
||||
/*-************************************
|
||||
* Memory routines
|
||||
@@ -1080,8 +1082,6 @@ const char *Packet::verbString(Verb v)
|
||||
case VERB_MULTICAST_GATHER: return "MULTICAST_GATHER";
|
||||
case VERB_MULTICAST_FRAME: return "MULTICAST_FRAME";
|
||||
case VERB_PUSH_DIRECT_PATHS: return "PUSH_DIRECT_PATHS";
|
||||
case VERB_CIRCUIT_TEST: return "CIRCUIT_TEST";
|
||||
case VERB_CIRCUIT_TEST_REPORT: return "CIRCUIT_TEST_REPORT";
|
||||
case VERB_USER_MESSAGE: return "USER_MESSAGE";
|
||||
}
|
||||
return "(unknown)";
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
* 4 - 0.6.0 ... 1.0.6
|
||||
* + BREAKING CHANGE: New identity format based on hashcash design
|
||||
* 5 - 1.1.0 ... 1.1.5
|
||||
* + Supports circuit test, proof of work, and echo
|
||||
* + Supports echo
|
||||
* + Supports in-band world (root server definition) updates
|
||||
* + Clustering! (Though this will work with protocol v4 clients.)
|
||||
* + Otherwise backward compatible with protocol v4
|
||||
@@ -954,119 +954,7 @@ public:
|
||||
*/
|
||||
VERB_PUSH_DIRECT_PATHS = 0x10,
|
||||
|
||||
/**
|
||||
* Source-routed circuit test message:
|
||||
* <[5] address of originator of circuit test>
|
||||
* <[2] 16-bit flags>
|
||||
* <[8] 64-bit timestamp>
|
||||
* <[8] 64-bit test ID (arbitrary, set by tester)>
|
||||
* <[2] 16-bit originator credential length (includes type)>
|
||||
* [[1] originator credential type (for authorizing test)]
|
||||
* [[...] originator credential]
|
||||
* <[2] 16-bit length of additional fields>
|
||||
* [[...] additional fields]
|
||||
* [ ... end of signed portion of request ... ]
|
||||
* <[2] 16-bit length of signature of request>
|
||||
* <[...] signature of request by originator>
|
||||
* <[2] 16-bit length of additional fields>
|
||||
* [[...] additional fields]
|
||||
* <[...] next hop(s) in path>
|
||||
*
|
||||
* Flags:
|
||||
* 0x01 - Report back to originator at all hops
|
||||
* 0x02 - Report back to originator at last hop
|
||||
*
|
||||
* Originator credential types:
|
||||
* 0x01 - 64-bit network ID for which originator is controller
|
||||
*
|
||||
* Path record format:
|
||||
* <[1] 8-bit flags (unused, must be zero)>
|
||||
* <[1] 8-bit breadth (number of next hops)>
|
||||
* <[...] one or more ZeroTier addresses of next hops>
|
||||
*
|
||||
* The circuit test allows a device to send a message that will traverse
|
||||
* the network along a specified path, with each hop optionally reporting
|
||||
* back to the tester via VERB_CIRCUIT_TEST_REPORT.
|
||||
*
|
||||
* Each circuit test packet includes a digital signature by the originator
|
||||
* of the request, as well as a credential by which that originator claims
|
||||
* authorization to perform the test. Currently this signature is ed25519,
|
||||
* but in the future flags might be used to indicate an alternative
|
||||
* algorithm. For example, the originator might be a network controller.
|
||||
* In this case the test might be authorized if the recipient is a member
|
||||
* of a network controlled by it, and if the previous hop(s) are also
|
||||
* members. Each hop may include its certificate of network membership.
|
||||
*
|
||||
* Circuit test paths consist of a series of records. When a node receives
|
||||
* an authorized circuit test, it:
|
||||
*
|
||||
* (1) Reports back to circuit tester as flags indicate
|
||||
* (2) Reads and removes the next hop from the packet's path
|
||||
* (3) Sends the packet along to next hop(s), if any.
|
||||
*
|
||||
* It is perfectly legal for a path to contain the same hop more than
|
||||
* once. In fact, this can be a very useful test to determine if a hop
|
||||
* can be reached bidirectionally and if so what that connectivity looks
|
||||
* like.
|
||||
*
|
||||
* The breadth field in source-routed path records allows a hop to forward
|
||||
* to more than one recipient, allowing the tester to specify different
|
||||
* forms of graph traversal in a test.
|
||||
*
|
||||
* There is no hard limit to the number of hops in a test, but it is
|
||||
* practically limited by the maximum size of a (possibly fragmented)
|
||||
* ZeroTier packet.
|
||||
*
|
||||
* Support for circuit tests is optional. If they are not supported, the
|
||||
* node should respond with an UNSUPPORTED_OPERATION error. If a circuit
|
||||
* test request is not authorized, it may be ignored or reported as
|
||||
* an INVALID_REQUEST. No OK messages are generated, but TEST_REPORT
|
||||
* messages may be sent (see below).
|
||||
*
|
||||
* ERROR packet format:
|
||||
* <[8] 64-bit timestamp (echoed from original>
|
||||
* <[8] 64-bit test ID (echoed from original)>
|
||||
*/
|
||||
VERB_CIRCUIT_TEST = 0x11,
|
||||
|
||||
/**
|
||||
* Circuit test hop report:
|
||||
* <[8] 64-bit timestamp (echoed from original test)>
|
||||
* <[8] 64-bit test ID (echoed from original test)>
|
||||
* <[8] 64-bit reserved field (set to 0, currently unused)>
|
||||
* <[1] 8-bit vendor ID (set to 0, currently unused)>
|
||||
* <[1] 8-bit reporter protocol version>
|
||||
* <[1] 8-bit reporter software major version>
|
||||
* <[1] 8-bit reporter software minor version>
|
||||
* <[2] 16-bit reporter software revision>
|
||||
* <[2] 16-bit reporter OS/platform or 0 if not specified>
|
||||
* <[2] 16-bit reporter architecture or 0 if not specified>
|
||||
* <[2] 16-bit error code (set to 0, currently unused)>
|
||||
* <[8] 64-bit report flags>
|
||||
* <[8] 64-bit packet ID of received CIRCUIT_TEST packet>
|
||||
* <[5] upstream ZeroTier address from which CIRCUIT_TEST was received>
|
||||
* <[1] 8-bit packet hop count of received CIRCUIT_TEST>
|
||||
* <[...] local wire address on which packet was received>
|
||||
* <[...] remote wire address from which packet was received>
|
||||
* <[2] 16-bit path link quality of path over which packet was received>
|
||||
* <[1] 8-bit number of next hops (breadth)>
|
||||
* <[...] next hop information>
|
||||
*
|
||||
* Next hop information record format:
|
||||
* <[5] ZeroTier address of next hop>
|
||||
* <[...] current best direct path address, if any, 0 if none>
|
||||
*
|
||||
* Report flags:
|
||||
* 0x1 - Upstream peer in circuit test path allowed in path (e.g. network COM valid)
|
||||
*
|
||||
* Circuit test reports can be sent by hops in a circuit test to report
|
||||
* back results. They should include information about the sender as well
|
||||
* as about the paths to which next hops are being sent.
|
||||
*
|
||||
* If a test report is received and no circuit test was sent, it should be
|
||||
* ignored. This message generates no OK or ERROR response.
|
||||
*/
|
||||
VERB_CIRCUIT_TEST_REPORT = 0x12,
|
||||
// 0x11, 0x12 -- deprecated
|
||||
|
||||
/**
|
||||
* A message with arbitrary user-definable content:
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
OBJS=\
|
||||
controller/EmbeddedNetworkController.o \
|
||||
controller/JSONDB.o \
|
||||
CORE_OBJS=\
|
||||
node/C25519.o \
|
||||
node/Capability.o \
|
||||
node/CertificateOfMembership.o \
|
||||
@@ -26,9 +24,15 @@ OBJS=\
|
||||
node/Switch.o \
|
||||
node/Tag.o \
|
||||
node/Topology.o \
|
||||
node/Utils.o \
|
||||
node/Utils.o
|
||||
|
||||
ONE_OBJS=\
|
||||
controller/EmbeddedNetworkController.o \
|
||||
controller/JSONDB.o \
|
||||
osdep/ManagedRoute.o \
|
||||
osdep/Http.o \
|
||||
osdep/OSUtils.o \
|
||||
service/ClusterGeoIpService.o \
|
||||
service/SoftwareUpdater.o
|
||||
service/SoftwareUpdater.o \
|
||||
service/OneService.o
|
||||
|
||||
|
||||
@@ -1488,7 +1488,8 @@ int main(int argc,char **argv)
|
||||
|
||||
#ifdef __UNIX_LIKE__
|
||||
#ifdef ZT_HAVE_DROP_PRIVILEGES
|
||||
dropPrivileges(argv[0],homeDir);
|
||||
if (!skipRootCheck)
|
||||
dropPrivileges(argv[0],homeDir);
|
||||
#endif
|
||||
|
||||
std::string pidPath(homeDir + ZT_PATH_SEPARATOR_S + ZT_PID_PATH);
|
||||
|
||||
@@ -94,9 +94,6 @@ BSDEthernetTap::BSDEthernetTap(
|
||||
|
||||
Mutex::Lock _gl(globalTapCreateLock);
|
||||
|
||||
if (mtu > 2800)
|
||||
throw std::runtime_error("max tap MTU is 2800");
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
/* FreeBSD allows long interface names and interface renaming */
|
||||
|
||||
@@ -321,7 +318,7 @@ std::vector<InetAddress> BSDEthernetTap::ips() const
|
||||
|
||||
void BSDEthernetTap::put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len)
|
||||
{
|
||||
char putBuf[4096];
|
||||
char putBuf[ZT_MAX_MTU + 64];
|
||||
if ((_fd > 0)&&(len <= _mtu)&&(_enabled)) {
|
||||
to.copyTo(putBuf,6);
|
||||
from.copyTo(putBuf + 6,6);
|
||||
@@ -381,49 +378,22 @@ void BSDEthernetTap::scanMulticastGroups(std::vector<MulticastGroup> &added,std:
|
||||
_multicastGroups.swap(newGroups);
|
||||
}
|
||||
|
||||
/*
|
||||
bool BSDEthernetTap::updateMulticastGroups(std::set<MulticastGroup> &groups)
|
||||
void BSDEthernetTap::setMtu(unsigned int mtu)
|
||||
{
|
||||
std::set<MulticastGroup> newGroups;
|
||||
struct ifmaddrs *ifmap = (struct ifmaddrs *)0;
|
||||
if (!getifmaddrs(&ifmap)) {
|
||||
struct ifmaddrs *p = ifmap;
|
||||
while (p) {
|
||||
if (p->ifma_addr->sa_family == AF_LINK) {
|
||||
struct sockaddr_dl *in = (struct sockaddr_dl *)p->ifma_name;
|
||||
struct sockaddr_dl *la = (struct sockaddr_dl *)p->ifma_addr;
|
||||
if ((la->sdl_alen == 6)&&(in->sdl_nlen <= _dev.length())&&(!memcmp(_dev.data(),in->sdl_data,in->sdl_nlen)))
|
||||
newGroups.insert(MulticastGroup(MAC(la->sdl_data + la->sdl_nlen,6),0));
|
||||
}
|
||||
p = p->ifma_next;
|
||||
}
|
||||
freeifmaddrs(ifmap);
|
||||
}
|
||||
|
||||
{
|
||||
std::set<InetAddress> allIps(ips());
|
||||
for(std::set<InetAddress>::const_iterator i(allIps.begin());i!=allIps.end();++i)
|
||||
newGroups.insert(MulticastGroup::deriveMulticastGroupForAddressResolution(*i));
|
||||
}
|
||||
|
||||
bool changed = false;
|
||||
|
||||
for(std::set<MulticastGroup>::iterator mg(newGroups.begin());mg!=newGroups.end();++mg) {
|
||||
if (!groups.count(*mg)) {
|
||||
groups.insert(*mg);
|
||||
changed = true;
|
||||
if (mtu != _mtu) {
|
||||
_mtu = mtu;
|
||||
long cpid = (long)vfork();
|
||||
if (cpid == 0) {
|
||||
char tmp[64];
|
||||
Utils::snprintf(tmp,sizeof(tmp),"%u",mtu);
|
||||
execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"mtu",tmp,(const char *)0);
|
||||
_exit(-1);
|
||||
} else if (cpid > 0) {
|
||||
int exitcode = -1;
|
||||
waitpid(cpid,&exitcode,0);
|
||||
}
|
||||
}
|
||||
for(std::set<MulticastGroup>::iterator mg(groups.begin());mg!=groups.end();) {
|
||||
if ((!newGroups.count(*mg))&&(*mg != _blindWildcardMulticastGroup)) {
|
||||
groups.erase(mg++);
|
||||
changed = true;
|
||||
} else ++mg;
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
*/
|
||||
|
||||
void BSDEthernetTap::threadMain()
|
||||
throw()
|
||||
@@ -431,7 +401,7 @@ void BSDEthernetTap::threadMain()
|
||||
fd_set readfds,nullfds;
|
||||
MAC to,from;
|
||||
int n,nfds,r;
|
||||
char getBuf[8194];
|
||||
char getBuf[ZT_MAX_MTU + 64];
|
||||
|
||||
// Wait for a moment after startup -- wait for Network to finish
|
||||
// constructing itself.
|
||||
|
||||
@@ -65,6 +65,7 @@ public:
|
||||
std::string deviceName() const;
|
||||
void setFriendlyName(const char *friendlyName);
|
||||
void scanMulticastGroups(std::vector<MulticastGroup> &added,std::vector<MulticastGroup> &removed);
|
||||
void setMtu(unsigned int mtu);
|
||||
|
||||
void threadMain()
|
||||
throw();
|
||||
|
||||
@@ -71,12 +71,7 @@
|
||||
*
|
||||
* OneService also does this on detected restarts.
|
||||
*/
|
||||
|
||||
#ifdef ZT_SDK
|
||||
#define ZT_BINDER_REFRESH_PERIOD 5000
|
||||
#else
|
||||
#define ZT_BINDER_REFRESH_PERIOD 30000
|
||||
#endif
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
#include <string>
|
||||
|
||||
#include "../node/Constants.hpp"
|
||||
#include "../node/Utils.hpp"
|
||||
@@ -63,6 +64,19 @@ namespace ZeroTier {
|
||||
|
||||
static Mutex __tapCreateLock;
|
||||
|
||||
static const char _base32_chars[32] = { 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','2','3','4','5','6','7' };
|
||||
static void _base32_5_to_8(const uint8_t *in,char *out)
|
||||
{
|
||||
out[0] = _base32_chars[(in[0]) >> 3];
|
||||
out[1] = _base32_chars[(in[0] & 0x07) << 2 | (in[1] & 0xc0) >> 6];
|
||||
out[2] = _base32_chars[(in[1] & 0x3e) >> 1];
|
||||
out[3] = _base32_chars[(in[1] & 0x01) << 4 | (in[2] & 0xf0) >> 4];
|
||||
out[4] = _base32_chars[(in[2] & 0x0f) << 1 | (in[3] & 0x80) >> 7];
|
||||
out[5] = _base32_chars[(in[3] & 0x7c) >> 2];
|
||||
out[6] = _base32_chars[(in[3] & 0x03) << 3 | (in[4] & 0xe0) >> 5];
|
||||
out[7] = _base32_chars[(in[4] & 0x1f)];
|
||||
}
|
||||
|
||||
LinuxEthernetTap::LinuxEthernetTap(
|
||||
const char *homePath,
|
||||
const MAC &mac,
|
||||
@@ -87,9 +101,6 @@ LinuxEthernetTap::LinuxEthernetTap(
|
||||
|
||||
Mutex::Lock _l(__tapCreateLock); // create only one tap at a time, globally
|
||||
|
||||
if (mtu > 2800)
|
||||
throw std::runtime_error("max tap MTU is 2800");
|
||||
|
||||
_fd = ::open("/dev/net/tun",O_RDWR);
|
||||
if (_fd <= 0) {
|
||||
_fd = ::open("/dev/tun",O_RDWR);
|
||||
@@ -100,7 +111,7 @@ LinuxEthernetTap::LinuxEthernetTap(
|
||||
struct ifreq ifr;
|
||||
memset(&ifr,0,sizeof(ifr));
|
||||
|
||||
// Try to recall our last device name, or pick an unused one if that fails.
|
||||
// Restore device names from legacy devicemap, but for new devices we use a base32-based canonical naming
|
||||
std::map<std::string,std::string> globalDeviceMap;
|
||||
FILE *devmapf = fopen((_homePath + ZT_PATH_SEPARATOR_S + "devicemap").c_str(),"r");
|
||||
if (devmapf) {
|
||||
@@ -126,17 +137,30 @@ LinuxEthernetTap::LinuxEthernetTap(
|
||||
Utils::snprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name);
|
||||
recalledDevice = (stat(procpath,&sbuf) != 0);
|
||||
}
|
||||
|
||||
if (!recalledDevice) {
|
||||
int devno = 0;
|
||||
do {
|
||||
#ifdef __SYNOLOGY__
|
||||
devno+=50; // Arbitrary number to prevent interface name conflicts
|
||||
int devno = 50;
|
||||
do {
|
||||
Utils::snprintf(ifr.ifr_name,sizeof(ifr.ifr_name),"eth%d",devno++);
|
||||
#else
|
||||
Utils::snprintf(ifr.ifr_name,sizeof(ifr.ifr_name),"zt%d",devno++);
|
||||
#endif
|
||||
Utils::snprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name);
|
||||
} while (stat(procpath,&sbuf) == 0); // try zt#++ until we find one that does not exist
|
||||
#else
|
||||
char devno = 0;
|
||||
do {
|
||||
uint64_t tmp2[2];
|
||||
tmp2[0] = Utils::hton(nwid);
|
||||
tmp2[1] = 0;
|
||||
char tmp3[17];
|
||||
tmp3[0] = 'z';
|
||||
tmp3[1] = 't' + (devno++);
|
||||
_base32_5_to_8(reinterpret_cast<const uint8_t *>(tmp2),tmp3 + 2);
|
||||
_base32_5_to_8(reinterpret_cast<const uint8_t *>(tmp2) + 5,tmp3 + 10);
|
||||
tmp3[15] = (char)0;
|
||||
memcpy(ifr.ifr_name,tmp3,16);
|
||||
Utils::snprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name);
|
||||
} while (stat(procpath,&sbuf) == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
|
||||
@@ -199,6 +223,7 @@ LinuxEthernetTap::LinuxEthernetTap(
|
||||
|
||||
(void)::pipe(_shutdownSignalPipe);
|
||||
|
||||
/*
|
||||
globalDeviceMap[nwids] = _dev;
|
||||
devmapf = fopen((_homePath + ZT_PATH_SEPARATOR_S + "devicemap").c_str(),"w");
|
||||
if (devmapf) {
|
||||
@@ -209,6 +234,7 @@ LinuxEthernetTap::LinuxEthernetTap(
|
||||
}
|
||||
fclose(devmapf);
|
||||
}
|
||||
*/
|
||||
|
||||
_thread = Thread::start(this);
|
||||
}
|
||||
@@ -386,7 +412,7 @@ std::vector<InetAddress> LinuxEthernetTap::ips() const
|
||||
|
||||
void LinuxEthernetTap::put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len)
|
||||
{
|
||||
char putBuf[8194];
|
||||
char putBuf[ZT_MAX_MTU + 64];
|
||||
if ((_fd > 0)&&(len <= _mtu)&&(_enabled)) {
|
||||
to.copyTo(putBuf,6);
|
||||
from.copyTo(putBuf + 6,6);
|
||||
@@ -455,13 +481,28 @@ void LinuxEthernetTap::scanMulticastGroups(std::vector<MulticastGroup> &added,st
|
||||
_multicastGroups.swap(newGroups);
|
||||
}
|
||||
|
||||
void LinuxEthernetTap::setMtu(unsigned int mtu)
|
||||
{
|
||||
if (_mtu != mtu) {
|
||||
_mtu = mtu;
|
||||
int sock = socket(AF_INET,SOCK_DGRAM,0);
|
||||
if (sock > 0) {
|
||||
struct ifreq ifr;
|
||||
memset(&ifr,0,sizeof(ifr));
|
||||
ifr.ifr_ifru.ifru_mtu = (int)mtu;
|
||||
ioctl(sock,SIOCSIFMTU,(void *)&ifr);
|
||||
close(sock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LinuxEthernetTap::threadMain()
|
||||
throw()
|
||||
{
|
||||
fd_set readfds,nullfds;
|
||||
MAC to,from;
|
||||
int n,nfds,r;
|
||||
char getBuf[8194];
|
||||
char getBuf[ZT_MAX_MTU + 64];
|
||||
|
||||
Thread::sleep(500);
|
||||
|
||||
|
||||
@@ -69,6 +69,7 @@ public:
|
||||
std::string deviceName() const;
|
||||
void setFriendlyName(const char *friendlyName);
|
||||
void scanMulticastGroups(std::vector<MulticastGroup> &added,std::vector<MulticastGroup> &removed);
|
||||
void setMtu(unsigned int mtu);
|
||||
|
||||
void threadMain()
|
||||
throw();
|
||||
|
||||
@@ -51,6 +51,9 @@
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <arpa/inet.h>
|
||||
#ifdef __LINUX__
|
||||
#include <sys/syscall.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "../ext/json/json.hpp"
|
||||
@@ -185,7 +188,6 @@ public:
|
||||
* @return Current time in milliseconds since epoch
|
||||
*/
|
||||
static inline uint64_t now()
|
||||
throw()
|
||||
{
|
||||
#ifdef __WINDOWS__
|
||||
FILETIME ft;
|
||||
@@ -198,33 +200,15 @@ public:
|
||||
return ( ((tmp.QuadPart - 116444736000000000ULL) / 10000L) + st.wMilliseconds );
|
||||
#else
|
||||
struct timeval tv;
|
||||
#ifdef __LINUX__
|
||||
syscall(SYS_gettimeofday,&tv,0); /* fix for musl libc broken gettimeofday bug */
|
||||
#else
|
||||
gettimeofday(&tv,(struct timezone *)0);
|
||||
#endif
|
||||
return ( (1000ULL * (uint64_t)tv.tv_sec) + (uint64_t)(tv.tv_usec / 1000) );
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* @return Current time in seconds since epoch, to the highest available resolution
|
||||
*/
|
||||
static inline double nowf()
|
||||
throw()
|
||||
{
|
||||
#ifdef __WINDOWS__
|
||||
FILETIME ft;
|
||||
SYSTEMTIME st;
|
||||
ULARGE_INTEGER tmp;
|
||||
GetSystemTime(&st);
|
||||
SystemTimeToFileTime(&st,&ft);
|
||||
tmp.LowPart = ft.dwLowDateTime;
|
||||
tmp.HighPart = ft.dwHighDateTime;
|
||||
return (((double)(tmp.QuadPart - 116444736000000000ULL)) / 10000000.0);
|
||||
#else
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv,(struct timezone *)0);
|
||||
return ( ((double)tv.tv_sec) + (((double)tv.tv_usec) / 1000000.0) );
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the full contents of a file into a string buffer
|
||||
*
|
||||
|
||||
@@ -338,9 +338,6 @@ OSXEthernetTap::OSXEthernetTap(
|
||||
|
||||
Utils::snprintf(nwids,sizeof(nwids),"%.16llx",nwid);
|
||||
|
||||
if (mtu > 2800)
|
||||
throw std::runtime_error("max tap MTU is 2800");
|
||||
|
||||
Mutex::Lock _gl(globalTapCreateLock);
|
||||
|
||||
if (::stat("/dev/zt0",&stattmp)) {
|
||||
@@ -574,7 +571,7 @@ std::vector<InetAddress> OSXEthernetTap::ips() const
|
||||
|
||||
void OSXEthernetTap::put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len)
|
||||
{
|
||||
char putBuf[4096];
|
||||
char putBuf[ZT_MAX_MTU + 64];
|
||||
if ((_fd > 0)&&(len <= _mtu)&&(_enabled)) {
|
||||
to.copyTo(putBuf,6);
|
||||
from.copyTo(putBuf + 6,6);
|
||||
@@ -632,13 +629,30 @@ void OSXEthernetTap::scanMulticastGroups(std::vector<MulticastGroup> &added,std:
|
||||
_multicastGroups.swap(newGroups);
|
||||
}
|
||||
|
||||
void OSXEthernetTap::setMtu(unsigned int mtu)
|
||||
{
|
||||
if (mtu != _mtu) {
|
||||
_mtu = mtu;
|
||||
long cpid = (long)vfork();
|
||||
if (cpid == 0) {
|
||||
char tmp[64];
|
||||
Utils::snprintf(tmp,sizeof(tmp),"%u",mtu);
|
||||
execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"mtu",tmp,(const char *)0);
|
||||
_exit(-1);
|
||||
} else if (cpid > 0) {
|
||||
int exitcode = -1;
|
||||
waitpid(cpid,&exitcode,0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OSXEthernetTap::threadMain()
|
||||
throw()
|
||||
{
|
||||
fd_set readfds,nullfds;
|
||||
MAC to,from;
|
||||
int n,nfds,r;
|
||||
char getBuf[8194];
|
||||
char getBuf[ZT_MAX_MTU + 64];
|
||||
|
||||
Thread::sleep(500);
|
||||
|
||||
|
||||
@@ -70,6 +70,7 @@ public:
|
||||
std::string deviceName() const;
|
||||
void setFriendlyName(const char *friendlyName);
|
||||
void scanMulticastGroups(std::vector<MulticastGroup> &added,std::vector<MulticastGroup> &removed);
|
||||
void setMtu(unsigned int mtu);
|
||||
|
||||
void threadMain()
|
||||
throw();
|
||||
|
||||
@@ -139,6 +139,10 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
inline void setMtu(unsigned int mtu)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
uint64_t _nwid;
|
||||
std::string _dev;
|
||||
|
||||
@@ -470,6 +470,7 @@ WindowsEthernetTap::WindowsEthernetTap(
|
||||
_arg(arg),
|
||||
_mac(mac),
|
||||
_nwid(nwid),
|
||||
_mtu(mtu),
|
||||
_tap(INVALID_HANDLE_VALUE),
|
||||
_injectSemaphore(INVALID_HANDLE_VALUE),
|
||||
_pathToHelpers(hp),
|
||||
@@ -481,10 +482,6 @@ WindowsEthernetTap::WindowsEthernetTap(
|
||||
char subkeyClass[1024];
|
||||
char data[1024];
|
||||
char tag[24];
|
||||
std::string mySubkeyName;
|
||||
|
||||
if (mtu > 2800)
|
||||
throw std::runtime_error("MTU too large.");
|
||||
|
||||
// We "tag" registry entries with the network ID to identify persistent devices
|
||||
Utils::snprintf(tag,sizeof(tag),"%.16llx",(unsigned long long)nwid);
|
||||
@@ -530,7 +527,7 @@ WindowsEthernetTap::WindowsEthernetTap(
|
||||
_netCfgInstanceId = instanceId;
|
||||
_deviceInstanceId = instanceIdPath;
|
||||
|
||||
mySubkeyName = subkeyName;
|
||||
_mySubkeyName = subkeyName;
|
||||
break; // found it!
|
||||
}
|
||||
}
|
||||
@@ -573,7 +570,7 @@ WindowsEthernetTap::WindowsEthernetTap(
|
||||
if (RegGetValueA(nwAdapters,subkeyName,"DeviceInstanceID",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS)
|
||||
_deviceInstanceId.assign(data,dataLen);
|
||||
|
||||
mySubkeyName = subkeyName;
|
||||
_mySubkeyName = subkeyName;
|
||||
|
||||
// Disable DHCP by default on new devices
|
||||
HKEY tcpIpInterfaces;
|
||||
@@ -605,24 +602,24 @@ WindowsEthernetTap::WindowsEthernetTap(
|
||||
if (_netCfgInstanceId.length() > 0) {
|
||||
char tmps[64];
|
||||
unsigned int tmpsl = Utils::snprintf(tmps,sizeof(tmps),"%.2X-%.2X-%.2X-%.2X-%.2X-%.2X",(unsigned int)mac[0],(unsigned int)mac[1],(unsigned int)mac[2],(unsigned int)mac[3],(unsigned int)mac[4],(unsigned int)mac[5]) + 1;
|
||||
RegSetKeyValueA(nwAdapters,mySubkeyName.c_str(),"NetworkAddress",REG_SZ,tmps,tmpsl);
|
||||
RegSetKeyValueA(nwAdapters,mySubkeyName.c_str(),"MAC",REG_SZ,tmps,tmpsl);
|
||||
tmpsl = Utils::snprintf(tmps, sizeof(tmps), "%d", mtu);
|
||||
RegSetKeyValueA(nwAdapters,mySubkeyName.c_str(),"MTU",REG_SZ,tmps,tmpsl);
|
||||
RegSetKeyValueA(nwAdapters,_mySubkeyName.c_str(),"NetworkAddress",REG_SZ,tmps,tmpsl);
|
||||
RegSetKeyValueA(nwAdapters,_mySubkeyName.c_str(),"MAC",REG_SZ,tmps,tmpsl);
|
||||
tmpsl = Utils::snprintf(tmps, sizeof(tmps), "%d", mtu);
|
||||
RegSetKeyValueA(nwAdapters,_mySubkeyName.c_str(),"MTU",REG_SZ,tmps,tmpsl);
|
||||
|
||||
DWORD tmp = 0;
|
||||
RegSetKeyValueA(nwAdapters,mySubkeyName.c_str(),"*NdisDeviceType",REG_DWORD,(LPCVOID)&tmp,sizeof(tmp));
|
||||
RegSetKeyValueA(nwAdapters,_mySubkeyName.c_str(),"*NdisDeviceType",REG_DWORD,(LPCVOID)&tmp,sizeof(tmp));
|
||||
tmp = IF_TYPE_ETHERNET_CSMACD;
|
||||
RegSetKeyValueA(nwAdapters,mySubkeyName.c_str(),"*IfType",REG_DWORD,(LPCVOID)&tmp,sizeof(tmp));
|
||||
RegSetKeyValueA(nwAdapters,_mySubkeyName.c_str(),"*IfType",REG_DWORD,(LPCVOID)&tmp,sizeof(tmp));
|
||||
|
||||
if (creatingNewDevice) {
|
||||
// Vista/2008 does not set this
|
||||
if (newDeviceInstanceId.length() > 0)
|
||||
RegSetKeyValueA(nwAdapters,mySubkeyName.c_str(),"DeviceInstanceID",REG_SZ,newDeviceInstanceId.c_str(),(DWORD)newDeviceInstanceId.length());
|
||||
RegSetKeyValueA(nwAdapters,_mySubkeyName.c_str(),"DeviceInstanceID",REG_SZ,newDeviceInstanceId.c_str(),(DWORD)newDeviceInstanceId.length());
|
||||
|
||||
// Set EnableDHCP to 0 by default on new devices
|
||||
tmp = 0;
|
||||
RegSetKeyValueA(nwAdapters,mySubkeyName.c_str(),"EnableDHCP",REG_DWORD,(LPCVOID)&tmp,sizeof(tmp));
|
||||
RegSetKeyValueA(nwAdapters,_mySubkeyName.c_str(),"EnableDHCP",REG_DWORD,(LPCVOID)&tmp,sizeof(tmp));
|
||||
}
|
||||
RegCloseKey(nwAdapters);
|
||||
} else {
|
||||
@@ -792,11 +789,11 @@ std::vector<InetAddress> WindowsEthernetTap::ips() const
|
||||
|
||||
void WindowsEthernetTap::put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len)
|
||||
{
|
||||
if ((!_initialized)||(!_enabled)||(_tap == INVALID_HANDLE_VALUE)||(len > (ZT_IF_MTU)))
|
||||
if ((!_initialized)||(!_enabled)||(_tap == INVALID_HANDLE_VALUE)||(len > _mtu))
|
||||
return;
|
||||
|
||||
Mutex::Lock _l(_injectPending_m);
|
||||
_injectPending.push( std::pair<Array<char,ZT_IF_MTU + 32>,unsigned int>(Array<char,ZT_IF_MTU + 32>(),len + 14) );
|
||||
_injectPending.push( std::pair<Array<char,ZT_MAX_MTU + 32>,unsigned int>(Array<char,ZT_MAX_MTU + 32>(),len + 14) );
|
||||
char *d = _injectPending.back().first.data;
|
||||
to.copyTo(d,6);
|
||||
from.copyTo(d + 6,6);
|
||||
@@ -875,6 +872,20 @@ void WindowsEthernetTap::scanMulticastGroups(std::vector<MulticastGroup> &added,
|
||||
_multicastGroups.swap(newGroups);
|
||||
}
|
||||
|
||||
void WindowsEthernetTap::setMtu(unsigned int mtu)
|
||||
{
|
||||
if (mtu != _mtu) {
|
||||
_mtu = mtu;
|
||||
HKEY nwAdapters;
|
||||
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}", 0, KEY_READ | KEY_WRITE, &nwAdapters) == ERROR_SUCCESS) {
|
||||
char tmps[64];
|
||||
unsigned int tmpsl = Utils::snprintf(tmps, sizeof(tmps), "%d", mtu);
|
||||
RegSetKeyValueA(nwAdapters, _mySubkeyName.c_str(), "MTU", REG_SZ, tmps, tmpsl);
|
||||
RegCloseKey(nwAdapters);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NET_IFINDEX WindowsEthernetTap::interfaceIndex() const
|
||||
{
|
||||
NET_IFINDEX idx = -1;
|
||||
@@ -886,7 +897,7 @@ NET_IFINDEX WindowsEthernetTap::interfaceIndex() const
|
||||
void WindowsEthernetTap::threadMain()
|
||||
throw()
|
||||
{
|
||||
char tapReadBuf[ZT_IF_MTU + 32];
|
||||
char tapReadBuf[ZT_MAX_MTU + 32];
|
||||
char tapPath[128];
|
||||
HANDLE wait4[3];
|
||||
OVERLAPPED tapOvlRead,tapOvlWrite;
|
||||
@@ -1015,13 +1026,16 @@ void WindowsEthernetTap::threadMain()
|
||||
ReadFile(_tap,tapReadBuf,sizeof(tapReadBuf),NULL,&tapOvlRead);
|
||||
bool writeInProgress = false;
|
||||
ULONGLONG timeOfLastBorkCheck = GetTickCount64();
|
||||
|
||||
|
||||
_initialized = true;
|
||||
_initialized = true;
|
||||
unsigned int oldmtu = _mtu;
|
||||
|
||||
while (_run) {
|
||||
DWORD waitResult = WaitForMultipleObjectsEx(writeInProgress ? 3 : 2,wait4,FALSE,2500,TRUE);
|
||||
if (!_run) break; // will also break outer while(_run)
|
||||
if (!_run) break; // will also break outer while(_run) since _run is false
|
||||
|
||||
// Check for changes in MTU and break to restart tap device to reconfigure in this case
|
||||
if (_mtu != oldmtu)
|
||||
break;
|
||||
|
||||
// Check for issues with adapter and close/reopen if any are detected. This
|
||||
// check fixes a while boatload of Windows adapter 'coma' issues after
|
||||
@@ -1070,7 +1084,7 @@ void WindowsEthernetTap::threadMain()
|
||||
} catch ( ... ) {} // handlers should not throw
|
||||
}
|
||||
}
|
||||
ReadFile(_tap,tapReadBuf,ZT_IF_MTU + 32,NULL,&tapOvlRead);
|
||||
ReadFile(_tap,tapReadBuf,ZT_MAX_MTU + 32,NULL,&tapOvlRead);
|
||||
}
|
||||
|
||||
if (writeInProgress) {
|
||||
|
||||
@@ -109,6 +109,7 @@ public:
|
||||
std::string deviceName() const;
|
||||
void setFriendlyName(const char *friendlyName);
|
||||
void scanMulticastGroups(std::vector<MulticastGroup> &added,std::vector<MulticastGroup> &removed);
|
||||
void setMtu(unsigned int mtu);
|
||||
|
||||
inline const NET_LUID &luid() const { return _deviceLuid; }
|
||||
inline const GUID &guid() const { return _deviceGuid; }
|
||||
@@ -130,6 +131,7 @@ private:
|
||||
void *_arg;
|
||||
MAC _mac;
|
||||
uint64_t _nwid;
|
||||
volatile unsigned int _mtu;
|
||||
Thread _thread;
|
||||
|
||||
volatile HANDLE _tap;
|
||||
@@ -139,13 +141,14 @@ private:
|
||||
NET_LUID _deviceLuid;
|
||||
std::string _netCfgInstanceId;
|
||||
std::string _deviceInstanceId;
|
||||
std::string _mySubkeyName;
|
||||
|
||||
std::vector<InetAddress> _assignedIps; // IPs assigned with addIp
|
||||
Mutex _assignedIps_m;
|
||||
|
||||
std::vector<MulticastGroup> _multicastGroups;
|
||||
|
||||
std::queue< std::pair< Array<char,ZT_IF_MTU + 32>,unsigned int > > _injectPending;
|
||||
std::queue< std::pair< Array<char,ZT_MAX_MTU + 32>,unsigned int > > _injectPending;
|
||||
Mutex _injectPending_m;
|
||||
|
||||
std::string _pathToHelpers;
|
||||
|
||||
@@ -151,8 +151,8 @@ static const C25519TestVector C25519_TEST_VECTORS[ZT_NUM_C25519_TEST_VECTORS] =
|
||||
|
||||
static int testCrypto()
|
||||
{
|
||||
unsigned char buf1[16384];
|
||||
unsigned char buf2[sizeof(buf1)],buf3[sizeof(buf1)];
|
||||
static unsigned char buf1[16384];
|
||||
static unsigned char buf2[sizeof(buf1)],buf3[sizeof(buf1)];
|
||||
|
||||
for(int i=0;i<3;++i) {
|
||||
Utils::getSecureRandom(buf1,64);
|
||||
@@ -1077,6 +1077,7 @@ int main(int argc,char **argv)
|
||||
*/
|
||||
|
||||
std::cout << "[info] sizeof(void *) == " << sizeof(void *) << std::endl;
|
||||
std::cout << "[info] OSUtils::now() == " << OSUtils::now() << std::endl;
|
||||
std::cout << "[info] hardware concurrency == " << std::thread::hardware_concurrency() << std::endl;
|
||||
std::cout << "[info] sizeof(NetworkConfig) == " << sizeof(ZeroTier::NetworkConfig) << std::endl;
|
||||
|
||||
|
||||
@@ -1022,9 +1022,7 @@ public:
|
||||
for(it = _nets.begin(); it != _nets.end(); it++) {
|
||||
if(it->second.tap) {
|
||||
for(int j=0; j<it->second.tap->_ips.size(); j++) {
|
||||
if(it->second.tap->_ips[j].isEqualPrefix(addr)
|
||||
|| it->second.tap->_ips[j].containsAddress(addr)
|
||||
|| it->second.tap->_ips[j].ipsEqual(addr)) {
|
||||
if(it->second.tap->_ips[j].isEqualPrefix(addr) || it->second.tap->_ips[j].ipsEqual(addr)) {
|
||||
return it->second.tap;
|
||||
}
|
||||
}
|
||||
@@ -2084,16 +2082,17 @@ public:
|
||||
memcpy(&(n.config),nwc,sizeof(ZT_VirtualNetworkConfig));
|
||||
if (n.tap) { // sanity check
|
||||
#ifdef __WINDOWS__
|
||||
// wait for up to 5 seconds for the WindowsEthernetTap to actually be initialized
|
||||
//
|
||||
// without WindowsEthernetTap::isInitialized() returning true, the won't actually
|
||||
// be online yet and setting managed routes on it will fail.
|
||||
const int MAX_SLEEP_COUNT = 500;
|
||||
for (int i = 0; !n.tap->isInitialized() && i < MAX_SLEEP_COUNT; i++) {
|
||||
Sleep(10);
|
||||
}
|
||||
// wait for up to 5 seconds for the WindowsEthernetTap to actually be initialized
|
||||
//
|
||||
// without WindowsEthernetTap::isInitialized() returning true, the won't actually
|
||||
// be online yet and setting managed routes on it will fail.
|
||||
const int MAX_SLEEP_COUNT = 500;
|
||||
for (int i = 0; !n.tap->isInitialized() && i < MAX_SLEEP_COUNT; i++) {
|
||||
Sleep(10);
|
||||
}
|
||||
#endif
|
||||
syncManagedStuff(n,true,true);
|
||||
n.tap->setMtu(nwc->mtu);
|
||||
} else {
|
||||
_nets.erase(nwid);
|
||||
return -999; // tap init failed
|
||||
|
||||
@@ -1,173 +0,0 @@
|
||||
Name: zerotier-one
|
||||
Version: 1.2.4
|
||||
Release: 1%{?dist}
|
||||
Summary: ZeroTier One network virtualization service
|
||||
|
||||
License: GPLv3
|
||||
URL: https://www.zerotier.com
|
||||
|
||||
%if 0%{?rhel} >= 7
|
||||
BuildRequires: systemd
|
||||
%endif
|
||||
|
||||
%if 0%{?fedora} >= 21
|
||||
BuildRequires: systemd
|
||||
%endif
|
||||
|
||||
Requires: iproute
|
||||
|
||||
%if 0%{?rhel} >= 7
|
||||
Requires: systemd
|
||||
Requires(pre): /usr/sbin/useradd, /usr/bin/getent
|
||||
%endif
|
||||
|
||||
%if 0%{?rhel} <= 6
|
||||
Requires: chkconfig
|
||||
%endif
|
||||
|
||||
%if 0%{?fedora} >= 21
|
||||
Requires: systemd
|
||||
Requires(pre): /usr/sbin/useradd, /usr/bin/getent
|
||||
%endif
|
||||
|
||||
%description
|
||||
ZeroTier is a software defined networking layer for Earth.
|
||||
|
||||
It can be used for on-premise network virtualization, as a peer to peer VPN
|
||||
for mobile teams, for hybrid or multi-data-center cloud deployments, or just
|
||||
about anywhere else secure software defined virtual networking is useful.
|
||||
|
||||
ZeroTier One is our OS-level client service. It allows Mac, Linux, Windows,
|
||||
FreeBSD, and soon other types of clients to join ZeroTier virtual networks
|
||||
like conventional VPNs or VLANs. It can run on native systems, VMs, or
|
||||
containers (Docker, OpenVZ, etc.).
|
||||
|
||||
%prep
|
||||
#rm -rf *
|
||||
#ln -s %{getenv:PWD} %{name}-%{version}
|
||||
#tar --exclude=%{name}-%{version}/.git --exclude=%{name}-%{version}/%{name}-%{version} -czf %{_sourcedir}/%{name}-%{version}.tar.gz %{name}-%{version}/*
|
||||
#rm -f %{name}-%{version}
|
||||
#cp -a %{getenv:PWD}/* .
|
||||
|
||||
%build
|
||||
#%if 0%{?rhel} <= 7
|
||||
#make CFLAGS="`echo %{optflags} | sed s/stack-protector-strong/stack-protector/`" CXXFLAGS="`echo %{optflags} | sed s/stack-protector-strong/stack-protector/`" ZT_USE_MINIUPNPC=1 %{?_smp_mflags} one manpages selftest
|
||||
#%else
|
||||
#make CFLAGS="%{optflags}" CXXFLAGS="%{optflags}" ZT_USE_MINIUPNPC=1 %{?_smp_mflags} one manpages selftest
|
||||
#%endif
|
||||
|
||||
%pre
|
||||
%if 0%{?rhel} >= 7
|
||||
/usr/bin/getent passwd zerotier-one || /usr/sbin/useradd -r -d /var/lib/zerotier-one -s /sbin/nologin zerotier-one
|
||||
%endif
|
||||
%if 0%{?fedora} >= 21
|
||||
/usr/bin/getent passwd zerotier-one || /usr/sbin/useradd -r -d /var/lib/zerotier-one -s /sbin/nologin zerotier-one
|
||||
%endif
|
||||
|
||||
%install
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
pushd %{getenv:PWD}
|
||||
make install DESTDIR=$RPM_BUILD_ROOT
|
||||
popd
|
||||
%if 0%{?rhel} >= 7
|
||||
mkdir -p $RPM_BUILD_ROOT%{_unitdir}
|
||||
cp %{getenv:PWD}/debian/zerotier-one.service $RPM_BUILD_ROOT%{_unitdir}/%{name}.service
|
||||
%endif
|
||||
%if 0%{?fedora} >= 21
|
||||
mkdir -p $RPM_BUILD_ROOT%{_unitdir}
|
||||
cp ${getenv:PWD}/debian/zerotier-one.service $RPM_BUILD_ROOT%{_unitdir}/%{name}.service
|
||||
%endif
|
||||
%if 0%{?rhel} <= 6
|
||||
mkdir -p $RPM_BUILD_ROOT/etc/init.d
|
||||
cp %{getenv:PWD}/ext/installfiles/linux/zerotier-one.init.rhel6 $RPM_BUILD_ROOT/etc/init.d/zerotier-one
|
||||
chmod 0755 $RPM_BUILD_ROOT/etc/init.d/zerotier-one
|
||||
%endif
|
||||
|
||||
%files
|
||||
%{_sbindir}/*
|
||||
%{_mandir}/*
|
||||
%{_localstatedir}/*
|
||||
%if 0%{?rhel} >= 7
|
||||
%{_unitdir}/%{name}.service
|
||||
%endif
|
||||
%if 0%{?fedora} >= 21
|
||||
%{_unitdir}/%{name}.service
|
||||
%endif
|
||||
%if 0%{?rhel} <= 6
|
||||
/etc/init.d/zerotier-one
|
||||
%endif
|
||||
|
||||
%post
|
||||
%if 0%{?rhel} >= 7
|
||||
%systemd_post zerotier-one.service
|
||||
%endif
|
||||
%if 0%{?fedora} >= 21
|
||||
%systemd_post zerotier-one.service
|
||||
%endif
|
||||
%if 0%{?rhel} <= 6
|
||||
case "$1" in
|
||||
1)
|
||||
chkconfig --add zerotier-one
|
||||
;;
|
||||
2)
|
||||
chkconfig --del newservice
|
||||
chkconfig --add newservice
|
||||
;;
|
||||
esac
|
||||
%endif
|
||||
|
||||
%preun
|
||||
%if 0%{?rhel} >= 7
|
||||
%systemd_preun zerotier-one.service
|
||||
%endif
|
||||
%if 0%{?fedora} >= 21
|
||||
%systemd_preun zerotier-one.service
|
||||
%endif
|
||||
%if 0%{?rhel} <= 6
|
||||
case "$1" in
|
||||
0)
|
||||
service zerotier-one stop
|
||||
chkconfig --del zerotier-one
|
||||
;;
|
||||
1)
|
||||
# This is an upgrade.
|
||||
:
|
||||
;;
|
||||
esac
|
||||
%endif
|
||||
|
||||
%postun
|
||||
%if 0%{?rhel} >= 7
|
||||
%systemd_postun_with_restart zerotier-one.service
|
||||
%endif
|
||||
%if 0%{?fedora} >= 21
|
||||
%systemd_postun_with_restart zerotier-one.service
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Mon Apr 24 2017 Adam Ierymenko <adam.ierymenko@zerotier.com> - 1.2.2-0.1
|
||||
- see https://github.com/zerotier/ZeroTierOne for release notes
|
||||
|
||||
* Fri Mar 17 2017 Adam Ierymenko <adam.ierymenko@zerotier.com> - 1.2.2-0.1
|
||||
- see https://github.com/zerotier/ZeroTierOne for release notes
|
||||
|
||||
* Tue Mar 14 2017 Adam Ierymenko <adam.ierymenko@zerotier.com> - 1.2.0-0.1
|
||||
- see https://github.com/zerotier/ZeroTierOne for release notes
|
||||
|
||||
* Tue Jul 12 2016 Adam Ierymenko <adam.ierymenko@zerotier.com> - 1.1.10-0.1
|
||||
- see https://github.com/zerotier/ZeroTierOne for release notes
|
||||
|
||||
* Fri Jul 08 2016 Adam Ierymenko <adam.ierymenko@zerotier.com> - 1.1.8-0.1
|
||||
- see https://github.com/zerotier/ZeroTierOne for release notes
|
||||
|
||||
* Sat Jun 25 2016 Adam Ierymenko <adam.ierymenko@zerotier.com> - 1.1.6-0.1
|
||||
- now builds on CentOS 6 as well as newer distros, and some cleanup
|
||||
|
||||
* Wed Jun 08 2016 François Kooman <fkooman@tuxed.net> - 1.1.5-0.3
|
||||
- include systemd unit file
|
||||
|
||||
* Wed Jun 08 2016 François Kooman <fkooman@tuxed.net> - 1.1.5-0.2
|
||||
- add libnatpmp as (build)dependency
|
||||
|
||||
* Wed Jun 08 2016 François Kooman <fkooman@tuxed.net> - 1.1.5-0.1
|
||||
- initial package
|
||||
Reference in New Issue
Block a user