Merge branch 'dev' into dev-tunnel-report

This commit is contained in:
Sean OMeara 2023-01-12 10:04:58 +01:00 committed by GitHub
commit 5ff990aa7b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 422 additions and 25 deletions

108
.github/workflows/build.yml vendored Normal file
View file

@ -0,0 +1,108 @@
on: [ push, pull_request ]
jobs:
build_ubuntu:
runs-on: ubuntu-latest
steps:
- name: gitconfig
run: |
git config --global core.autocrlf false
git config --global core.eol lf
- name: checkout
uses: actions/checkout@v3
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
target: aarch64-apple-darwin
override: true
components: rustfmt, clippy
- name: Set up cargo cache
uses: actions/cache@v3
continue-on-error: false
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: ${{ runner.os }}-cargo-
- name: make
run: make
- name: selftest
run: |
make selftest
./zerotier-selftest
build_macos:
runs-on: macos-latest
steps:
- name: gitconfig
run: |
git config --global core.autocrlf false
git config --global core.eol lf
- name: checkout
uses: actions/checkout@v3
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
target: aarch64-apple-darwin
override: true
components: rustfmt, clippy
- name: Set up cargo cache
uses: actions/cache@v3
continue-on-error: false
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: ${{ runner.os }}-cargo-
- name: make
run: make
- name: selftest
run: |
make selftest
./zerotier-selftest
build_windows:
runs-on: windows-latest
steps:
- name: gitconfig
run: |
git config --global core.autocrlf false
git config --global core.eol lf
- name: checkout
uses: actions/checkout@v3
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
target: aarch64-apple-darwin
override: true
components: rustfmt, clippy
- name: Set up cargo cache
uses: actions/cache@v3
continue-on-error: false
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: ${{ runner.os }}-cargo-
- name: setup msbuild
uses: microsoft/setup-msbuild@v1.1.3
- name: msbuild
run: |
msbuild windows\ZeroTierOne.sln /m /p:Configuration=Release /property:Platform=x64 /t:ZeroTierOne:Rebuild

View file

@ -384,7 +384,7 @@ enum ZT_ResultCode
*/ */
ZT_RESULT_OK_IGNORED = 1, ZT_RESULT_OK_IGNORED = 1,
// Fatal errors (>100, <1000) // Fatal errors (>=100, <1000)
/** /**
* Ran out of memory * Ran out of memory

View file

@ -43,7 +43,7 @@ jobject createResultObject(JNIEnv *env, ZT_ResultCode code)
resultClass = lookup.findClass("com/zerotier/sdk/ResultCode"); resultClass = lookup.findClass("com/zerotier/sdk/ResultCode");
if(resultClass == NULL) if(resultClass == NULL)
{ {
LOGE("Couldnt find ResultCode class"); LOGE("Couldn't find ResultCode class");
return NULL; // exception thrown return NULL; // exception thrown
} }
@ -1032,4 +1032,3 @@ jobject newVirtualNetworkDNS(JNIEnv *env, const ZT_VirtualNetworkDNS &dns)
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -41,7 +41,7 @@ public enum ResultCode {
*/ */
RESULT_OK(0), RESULT_OK(0),
// Fatal errors (> 0, < 1000) // Fatal errors (>=100, <1000)
/** /**
* Ran out of memory * Ran out of memory
*/ */

View file

@ -184,7 +184,7 @@ SharedPtr<Link> Bond::getLinkBySocket(const std::string& policyAlias, uint64_t l
auto search = _interfaceToLinkMap[policyAlias].find(ifnameStr); auto search = _interfaceToLinkMap[policyAlias].find(ifnameStr);
if (search == _interfaceToLinkMap[policyAlias].end()) { if (search == _interfaceToLinkMap[policyAlias].end()) {
if (createIfNeeded) { if (createIfNeeded) {
SharedPtr<Link> s = new Link(ifnameStr, 0, 0, true, ZT_BOND_SLAVE_MODE_PRIMARY, ""); SharedPtr<Link> s = new Link(ifnameStr, 0, 0, 0, true, ZT_BOND_SLAVE_MODE_PRIMARY, "");
_interfaceToLinkMap[policyAlias].insert(std::pair<std::string, SharedPtr<Link> >(ifnameStr, s)); _interfaceToLinkMap[policyAlias].insert(std::pair<std::string, SharedPtr<Link> >(ifnameStr, s));
return s; return s;
} }
@ -1253,6 +1253,7 @@ void Bond::estimatePathQuality(int64_t now)
if (link) { if (link) {
int linkSpeed = link->capacity(); int linkSpeed = link->capacity();
_paths[i].p->_givenLinkSpeed = linkSpeed; _paths[i].p->_givenLinkSpeed = linkSpeed;
_paths[i].p->_mtu = link->mtu();
maxObservedLinkCap = linkSpeed > maxObservedLinkCap ? linkSpeed : maxObservedLinkCap; maxObservedLinkCap = linkSpeed > maxObservedLinkCap ? linkSpeed : maxObservedLinkCap;
} }
} }

View file

@ -122,9 +122,10 @@ class Link {
* @param mode * @param mode
* @param failoverToLinkStr * @param failoverToLinkStr
*/ */
Link(std::string ifnameStr, uint8_t ipvPref, uint32_t capacity, bool enabled, uint8_t mode, std::string failoverToLinkStr) Link(std::string ifnameStr, uint8_t ipvPref, uint16_t mtu, uint32_t capacity, bool enabled, uint8_t mode, std::string failoverToLinkStr)
: _ifnameStr(ifnameStr) : _ifnameStr(ifnameStr)
, _ipvPref(ipvPref) , _ipvPref(ipvPref)
, _mtu(mtu)
, _capacity(capacity) , _capacity(capacity)
, _relativeCapacity(0.0) , _relativeCapacity(0.0)
, _enabled(enabled) , _enabled(enabled)
@ -226,6 +227,14 @@ class Link {
return _ipvPref; return _ipvPref;
} }
/**
* @return The MTU for this link (as specified by the user.)
*/
inline uint16_t mtu()
{
return _mtu;
}
/** /**
* @return The mode (e.g. primary/spare) for this link (as specified by the user.) * @return The mode (e.g. primary/spare) for this link (as specified by the user.)
*/ */
@ -260,6 +269,11 @@ class Link {
*/ */
uint8_t _ipvPref; uint8_t _ipvPref;
/**
* The physical-layer MTU for this link
*/
uint16_t _mtu;
/** /**
* User-specified capacity of this link * User-specified capacity of this link
*/ */

View file

@ -149,7 +149,7 @@ public:
/** /**
* Get the ZeroTier address for this MAC on this network (assuming no bridging of course, basic unicast) * Get the ZeroTier address for this MAC on this network (assuming no bridging of course, basic unicast)
* *
* This just XORs the next-lest-significant 5 bytes of the network ID again to unmask. * This just XORs the next-least-significant 5 bytes of the network ID again to unmask.
* *
* @param nwid Network ID * @param nwid Network ID
*/ */

View file

@ -268,7 +268,8 @@ void Multicaster::send(
const unsigned int gatherLimit = (limit - (unsigned int)gs.members.size()) + 1; const unsigned int gatherLimit = (limit - (unsigned int)gs.members.size()) + 1;
if ((gs.members.empty())||((now - gs.lastExplicitGather) >= ZT_MULTICAST_EXPLICIT_GATHER_DELAY)) { int timerScale = RR->node->lowBandwidthModeEnabled() ? 3 : 1;
if ((gs.members.empty())||((now - gs.lastExplicitGather) >= (ZT_MULTICAST_EXPLICIT_GATHER_DELAY * timerScale))) {
gs.lastExplicitGather = now; gs.lastExplicitGather = now;
Address explicitGatherPeers[16]; Address explicitGatherPeers[16];

View file

@ -50,7 +50,8 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,int64
_lastPingCheck(0), _lastPingCheck(0),
_lastGratuitousPingCheck(0), _lastGratuitousPingCheck(0),
_lastHousekeepingRun(0), _lastHousekeepingRun(0),
_lastMemoizedTraceSettings(0) _lastMemoizedTraceSettings(0),
_lowBandwidthMode(false)
{ {
if (callbacks->version != 0) if (callbacks->version != 0)
throw ZT_EXCEPTION_INVALID_ARGUMENT; throw ZT_EXCEPTION_INVALID_ARGUMENT;
@ -202,6 +203,14 @@ public:
{ {
const std::vector<InetAddress> *const alwaysContactEndpoints = _alwaysContact.get(p->address()); const std::vector<InetAddress> *const alwaysContactEndpoints = _alwaysContact.get(p->address());
if (alwaysContactEndpoints) { if (alwaysContactEndpoints) {
// Contact upstream peers as infrequently as possible
ZT_PeerRole role = RR->topology->role(p->address());
int roleBasedTimerScale = (role == ZT_PEER_ROLE_LEAF) ? 2 : 16;
if ((RR->node->now() - p->lastSentFullHello()) <= (ZT_PATH_HEARTBEAT_PERIOD * roleBasedTimerScale)) {
return;
}
const unsigned int sent = p->doPingAndKeepalive(_tPtr,_now); const unsigned int sent = p->doPingAndKeepalive(_tPtr,_now);
bool contacted = (sent != 0); bool contacted = (sent != 0);
@ -262,7 +271,7 @@ ZT_ResultCode Node::processBackgroundTasks(void *tptr,int64_t now,volatile int64
} }
} }
unsigned long timeUntilNextPingCheck = ZT_PING_CHECK_INVERVAL; unsigned long timeUntilNextPingCheck = _lowBandwidthMode ? (ZT_PING_CHECK_INVERVAL * 5) : ZT_PING_CHECK_INVERVAL;
const int64_t timeSinceLastPingCheck = now - _lastPingCheck; const int64_t timeSinceLastPingCheck = now - _lastPingCheck;
if (timeSinceLastPingCheck >= timeUntilNextPingCheck) { if (timeSinceLastPingCheck >= timeUntilNextPingCheck) {
try { try {
@ -309,6 +318,7 @@ ZT_ResultCode Node::processBackgroundTasks(void *tptr,int64_t now,volatile int64
// Get peers we should stay connected to according to network configs // Get peers we should stay connected to according to network configs
// Also get networks and whether they need config so we only have to do one pass over networks // Also get networks and whether they need config so we only have to do one pass over networks
int timerScale = _lowBandwidthMode ? 64 : 1;
std::vector< std::pair< SharedPtr<Network>,bool > > networkConfigNeeded; std::vector< std::pair< SharedPtr<Network>,bool > > networkConfigNeeded;
{ {
Mutex::Lock l(_networks_m); Mutex::Lock l(_networks_m);
@ -317,7 +327,7 @@ ZT_ResultCode Node::processBackgroundTasks(void *tptr,int64_t now,volatile int64
SharedPtr<Network> *network = (SharedPtr<Network> *)0; SharedPtr<Network> *network = (SharedPtr<Network> *)0;
while (i.next(nwid,network)) { while (i.next(nwid,network)) {
(*network)->config().alwaysContactAddresses(alwaysContact); (*network)->config().alwaysContactAddresses(alwaysContact);
networkConfigNeeded.push_back( std::pair< SharedPtr<Network>,bool >(*network,(((now - (*network)->lastConfigUpdate()) >= ZT_NETWORK_AUTOCONF_DELAY)||(!(*network)->hasConfig()))) ); networkConfigNeeded.push_back( std::pair< SharedPtr<Network>,bool >(*network,(((now - (*network)->lastConfigUpdate()) >= ZT_NETWORK_AUTOCONF_DELAY * timerScale)||(!(*network)->hasConfig()))) );
} }
} }
@ -336,10 +346,13 @@ ZT_ResultCode Node::processBackgroundTasks(void *tptr,int64_t now,volatile int64
// Refresh network config or broadcast network updates to members as needed // Refresh network config or broadcast network updates to members as needed
for(std::vector< std::pair< SharedPtr<Network>,bool > >::const_iterator n(networkConfigNeeded.begin());n!=networkConfigNeeded.end();++n) { for(std::vector< std::pair< SharedPtr<Network>,bool > >::const_iterator n(networkConfigNeeded.begin());n!=networkConfigNeeded.end();++n) {
if (n->second) if (n->second) {
n->first->requestConfiguration(tptr); n->first->requestConfiguration(tptr);
}
if (! _lowBandwidthMode) {
n->first->sendUpdatesToMembers(tptr); n->first->sendUpdatesToMembers(tptr);
} }
}
// Update online status, post status change as event // Update online status, post status change as event
const bool oldOnline = _online; const bool oldOnline = _online;

View file

@ -269,6 +269,16 @@ public:
_stats.inVerbBytes[v] += (uint64_t)bytes; _stats.inVerbBytes[v] += (uint64_t)bytes;
} }
inline void setLowBandwidthMode(bool isEnabled)
{
_lowBandwidthMode = isEnabled;
}
inline bool lowBandwidthModeEnabled()
{
return _lowBandwidthMode;
}
private: private:
RuntimeEnvironment _RR; RuntimeEnvironment _RR;
RuntimeEnvironment *RR; RuntimeEnvironment *RR;
@ -316,6 +326,7 @@ private:
int64_t _lastMemoizedTraceSettings; int64_t _lastMemoizedTraceSettings;
volatile int64_t _prngState[2]; volatile int64_t _prngState[2];
bool _online; bool _online;
bool _lowBandwidthMode;
}; };
} // namespace ZeroTier } // namespace ZeroTier

View file

@ -92,6 +92,7 @@ public:
_valid(true), _valid(true),
_eligible(false), _eligible(false),
_bonded(false), _bonded(false),
_mtu(0),
_givenLinkSpeed(0), _givenLinkSpeed(0),
_relativeQuality(0), _relativeQuality(0),
_latency(0xffff), _latency(0xffff),
@ -112,6 +113,7 @@ public:
_valid(true), _valid(true),
_eligible(false), _eligible(false),
_bonded(false), _bonded(false),
_mtu(0),
_givenLinkSpeed(0), _givenLinkSpeed(0),
_relativeQuality(0), _relativeQuality(0),
_latency(0xffff), _latency(0xffff),
@ -334,6 +336,11 @@ public:
*/ */
inline unsigned int bonded() const { return _bonded; } inline unsigned int bonded() const { return _bonded; }
/**
* @return Whether the user-specified MTU for this path (determined by MTU for parent link)
*/
inline unsigned int mtu() const { return _mtu; }
/** /**
* @return Given link capacity as reported by the bonding layer * @return Given link capacity as reported by the bonding layer
*/ */
@ -370,6 +377,7 @@ private:
volatile bool _valid; volatile bool _valid;
volatile bool _eligible; volatile bool _eligible;
volatile bool _bonded; volatile bool _bonded;
volatile uint16_t _mtu;
volatile uint32_t _givenLinkSpeed; volatile uint32_t _givenLinkSpeed;
volatile float _relativeQuality; volatile float _relativeQuality;

View file

@ -219,11 +219,15 @@ void Peer::received(
// is done less frequently. // is done less frequently.
if (this->trustEstablished(now)) { if (this->trustEstablished(now)) {
const int64_t sinceLastPush = now - _lastDirectPathPushSent; const int64_t sinceLastPush = now - _lastDirectPathPushSent;
if (sinceLastPush >= ((hops == 0) ? ZT_DIRECT_PATH_PUSH_INTERVAL_HAVEPATH : ZT_DIRECT_PATH_PUSH_INTERVAL)) { bool lowBandwidth = RR->node->lowBandwidthModeEnabled();
int timerScale = lowBandwidth ? 16 : 1;
if (sinceLastPush >= ((hops == 0) ? ZT_DIRECT_PATH_PUSH_INTERVAL_HAVEPATH * timerScale : ZT_DIRECT_PATH_PUSH_INTERVAL)) {
_lastDirectPathPushSent = now; _lastDirectPathPushSent = now;
std::vector<InetAddress> pathsToPush(RR->node->directPaths()); std::vector<InetAddress> pathsToPush(RR->node->directPaths());
if (! lowBandwidth) {
std::vector<InetAddress> ma = RR->sa->whoami(); std::vector<InetAddress> ma = RR->sa->whoami();
pathsToPush.insert(pathsToPush.end(), ma.begin(), ma.end()); pathsToPush.insert(pathsToPush.end(), ma.begin(), ma.end());
}
if (!pathsToPush.empty()) { if (!pathsToPush.empty()) {
std::vector<InetAddress>::const_iterator p(pathsToPush.begin()); std::vector<InetAddress>::const_iterator p(pathsToPush.begin());
while (p != pathsToPush.end()) { while (p != pathsToPush.end()) {
@ -453,7 +457,7 @@ void Peer::sendHELLO(void *tPtr,const int64_t localSocket,const InetAddress &atA
if (atAddress) { if (atAddress) {
outp.armor(_key,false,nullptr); // false == don't encrypt full payload, but add MAC outp.armor(_key,false,nullptr); // false == don't encrypt full payload, but add MAC
RR->node->expectReplyTo(outp.packetId()); RR->node->expectReplyTo(outp.packetId());
RR->node->putPacket(tPtr,-1,atAddress,outp.data(),outp.size()); RR->node->putPacket(tPtr,RR->node->lowBandwidthModeEnabled() ? localSocket : -1,atAddress,outp.data(),outp.size());
} else { } else {
RR->node->expectReplyTo(outp.packetId()); RR->node->expectReplyTo(outp.packetId());
RR->sw->send(tPtr,outp,false); // false == don't encrypt full payload, but add MAC RR->sw->send(tPtr,outp,false); // false == don't encrypt full payload, but add MAC
@ -477,10 +481,11 @@ void Peer::tryMemorizedPath(void *tPtr,int64_t now)
if ((now - _lastTriedMemorizedPath) >= ZT_TRY_MEMORIZED_PATH_INTERVAL) { if ((now - _lastTriedMemorizedPath) >= ZT_TRY_MEMORIZED_PATH_INTERVAL) {
_lastTriedMemorizedPath = now; _lastTriedMemorizedPath = now;
InetAddress mp; InetAddress mp;
if (RR->node->externalPathLookup(tPtr,_id.address(),-1,mp)) if (RR->node->externalPathLookup(tPtr,_id.address(),-1,mp)) {
attemptToContactAt(tPtr,-1,mp,now,true); attemptToContactAt(tPtr,-1,mp,now,true);
} }
} }
}
void Peer::performMultipathStateCheck(void *tPtr, int64_t now) void Peer::performMultipathStateCheck(void *tPtr, int64_t now)
{ {

View file

@ -302,6 +302,8 @@ public:
*/ */
inline int64_t isActive(int64_t now) const { return ((now - _lastNontrivialReceive) < ZT_PEER_ACTIVITY_TIMEOUT); } inline int64_t isActive(int64_t now) const { return ((now - _lastNontrivialReceive) < ZT_PEER_ACTIVITY_TIMEOUT); }
inline int64_t lastSentFullHello() { return _lastSentFullHello; }
/** /**
* @return Latency in milliseconds of best/aggregate path or 0xffff if unknown / no paths * @return Latency in milliseconds of best/aggregate path or 0xffff if unknown / no paths
*/ */

View file

@ -1009,7 +1009,8 @@ bool Switch::_trySend(void *tPtr,Packet &packet,bool encrypt,int32_t flowId)
Mutex::Lock _l(peer->_paths_m); Mutex::Lock _l(peer->_paths_m);
for(int i=0;i<ZT_MAX_PEER_NETWORK_PATHS;++i) { for(int i=0;i<ZT_MAX_PEER_NETWORK_PATHS;++i) {
if (peer->_paths[i].p && peer->_paths[i].p->alive(now)) { if (peer->_paths[i].p && peer->_paths[i].p->alive(now)) {
_sendViaSpecificPath(tPtr,peer,peer->_paths[i].p,now,packet,encrypt,flowId); uint16_t userSpecifiedMtu = peer->_paths[i].p->mtu();
_sendViaSpecificPath(tPtr,peer,peer->_paths[i].p, userSpecifiedMtu,now,packet,encrypt,flowId);
} }
} }
return true; return true;
@ -1025,7 +1026,8 @@ bool Switch::_trySend(void *tPtr,Packet &packet,bool encrypt,int32_t flowId)
} }
} }
if (viaPath) { if (viaPath) {
_sendViaSpecificPath(tPtr,peer,viaPath,now,packet,encrypt,flowId); uint16_t userSpecifiedMtu = viaPath->mtu();
_sendViaSpecificPath(tPtr,peer,viaPath,userSpecifiedMtu,now,packet,encrypt,flowId);
return true; return true;
} }
} }
@ -1033,12 +1035,15 @@ bool Switch::_trySend(void *tPtr,Packet &packet,bool encrypt,int32_t flowId)
return false; return false;
} }
void Switch::_sendViaSpecificPath(void *tPtr,SharedPtr<Peer> peer,SharedPtr<Path> viaPath,int64_t now,Packet &packet,bool encrypt,int32_t flowId) void Switch::_sendViaSpecificPath(void *tPtr,SharedPtr<Peer> peer,SharedPtr<Path> viaPath,uint16_t userSpecifiedMtu, int64_t now,Packet &packet,bool encrypt,int32_t flowId)
{ {
unsigned int mtu = ZT_DEFAULT_PHYSMTU; unsigned int mtu = ZT_DEFAULT_PHYSMTU;
uint64_t trustedPathId = 0; uint64_t trustedPathId = 0;
RR->topology->getOutboundPathInfo(viaPath->address(),mtu,trustedPathId); RR->topology->getOutboundPathInfo(viaPath->address(),mtu,trustedPathId);
if (userSpecifiedMtu > 0) {
mtu = userSpecifiedMtu;
}
unsigned int chunkSize = std::min(packet.size(),mtu); unsigned int chunkSize = std::min(packet.size(),mtu);
packet.setFragmented(chunkSize < packet.size()); packet.setFragmented(chunkSize < packet.size());

View file

@ -207,7 +207,7 @@ public:
private: private:
bool _shouldUnite(const int64_t now,const Address &source,const Address &destination); bool _shouldUnite(const int64_t now,const Address &source,const Address &destination);
bool _trySend(void *tPtr,Packet &packet,bool encrypt,int32_t flowId = ZT_QOS_NO_FLOW); // packet is modified if return is true bool _trySend(void *tPtr,Packet &packet,bool encrypt,int32_t flowId = ZT_QOS_NO_FLOW); // packet is modified if return is true
void _sendViaSpecificPath(void *tPtr,SharedPtr<Peer> peer,SharedPtr<Path> viaPath,int64_t now,Packet &packet,bool encrypt,int32_t flowId); void _sendViaSpecificPath(void *tPtr,SharedPtr<Peer> peer,SharedPtr<Path> viaPath,uint16_t userSpecifiedMtu, int64_t now,Packet &packet,bool encrypt,int32_t flowId);
const RuntimeEnvironment *const RR; const RuntimeEnvironment *const RR;
int64_t _lastBeaconResponse; int64_t _lastBeaconResponse;

View file

@ -477,7 +477,7 @@ bool ManagedRoute::sync()
if ((newSystemVia)&&(!newSystemDevice[0])) { if ((newSystemVia)&&(!newSystemDevice[0])) {
rtes = _getRTEs(newSystemVia,true); rtes = _getRTEs(newSystemVia,true);
for(std::vector<_RTE>::iterator r(rtes.begin());r!=rtes.end();++r) { for(std::vector<_RTE>::iterator r(rtes.begin());r!=rtes.end();++r) {
if ( (r->device[0]) && (strcmp(r->device,_device) != 0) ) { if ( (r->device[0]) && (strcmp(r->device,_device) != 0) && r->target.netmaskBits() != 0) {
Utils::scopy(newSystemDevice,sizeof(newSystemDevice),r->device); Utils::scopy(newSystemDevice,sizeof(newSystemDevice),r->device);
break; break;
} }

172
osdep/WinFWHelper.cpp Normal file
View file

@ -0,0 +1,172 @@
#include "WinFWHelper.hpp"
namespace ZeroTier {
void ZeroTier::WinFWHelper::newICMPRule(const InetAddress& ip, uint64_t nwid)
{
char nwString[32] = { 0 };
char ipbuf[64];
sprintf(nwString, "%.16llx", nwid);
std::string nwString2 = { nwString };
ip.toString(ipbuf);
if (ip.isV4()) {
WinFWHelper::newICMPv4Rule(ipbuf, nwid);
}
else {
WinFWHelper::newICMPv6Rule(ipbuf, nwid);
}
}
void ZeroTier::WinFWHelper::removeICMPRule(const InetAddress& ip, uint64_t nwid)
{
char nwString[32] = { 0 };
char ipbuf[64];
sprintf(nwString, "%.16llx", nwid);
std::string nwString2 = { nwString };
ip.toString(ipbuf);
if (ip.isV4()) {
WinFWHelper::removeICMPv4Rule(ipbuf, nwid);
}
else {
WinFWHelper::removeICMPv6Rule(ipbuf, nwid);
}
}
void WinFWHelper::newICMPv4Rule(std::string address, uint64_t nwid)
{
// allows icmp, scoped to a specific ip address and interface name
char nwString[32] = { 0 };
sprintf(nwString, "%.16llx", nwid);
std::string nwString2 = { nwString };
std::string cmd = R"(C:\Windows\System32\WindowsPowershell\v1.0\powershell.exe "New-NetFirewallRule -DisplayName zerotier-icmpv4-)" + nwString2 + address +
R"( -InterfaceAlias 'ZeroTier One `[)" + nwString2 + R"(`]')" +
" -Protocol ICMPv4 -Action Allow" +
" -LocalAddress " + address + "\"\r\n";
_run(cmd);
}
void WinFWHelper::newICMPv6Rule(std::string address, uint64_t nwid)
{
// allows icmp, scoped to a specific ip address and interface name
char nwString[32] = { 0 };
sprintf(nwString, "%.16llx", nwid);
std::string nwString2 = { nwString };
std::string cmd = R"(C:\Windows\System32\WindowsPowershell\v1.0\powershell.exe "New-NetFirewallRule -DisplayName zerotier-icmpv6-)" + nwString2 + address +
R"( -InterfaceAlias 'ZeroTier One `[)" + nwString2 + R"(`]')" +
" -Protocol ICMPv6 -Action Allow" +
" -LocalAddress " + address + "\"\r\n";
_run(cmd);
}
void WinFWHelper::removeICMPv4Rule(std::string addr, uint64_t nwid)
{
// removes 1 icmp firewall rule
char nwString[32] = { 0 };
sprintf(nwString, "%.16llx", nwid);
std::string nwString2 = { nwString };
std::string cmd = R"(C:\Windows\System32\WindowsPowershell\v1.0\powershell.exe "Remove-NetFirewallRule -DisplayName zerotier-icmpv4-)" + nwString2 + addr +
"\"\r\n";
_run(cmd);
}
void WinFWHelper::removeICMPv6Rule(std::string addr, uint64_t nwid)
{
// removes 1 icmp firewall rule
char nwString[32] = { 0 };
sprintf(nwString, "%.16llx", nwid);
std::string nwString2 = { nwString };
std::string cmd = R"(C:\Windows\System32\WindowsPowershell\v1.0\powershell.exe "Remove-NetFirewallRule -DisplayName zerotier-icmpv6-)" + nwString2 + addr +
"\"\r\n";
_run(cmd);
}
void WinFWHelper::removeICMPv4Rules(uint64_t nwid)
{
// removes all icmp firewall rules for this network id
char nwString[32] = { 0 };
sprintf(nwString, "%.16llx", nwid);
std::string nwString2 = { nwString };
std::string cmd = R"(C:\Windows\System32\WindowsPowershell\v1.0\powershell.exe "Remove-NetFirewallRule -DisplayName zerotier-icmpv4-)" + nwString2 + "*\" \r\n";
_run(cmd);
}
void WinFWHelper::removeICMPv6Rules(uint64_t nwid)
{
// removes all icmp firewall rules for this network id
char nwString[32] = { 0 };
sprintf(nwString, "%.16llx", nwid);
std::string nwString2 = { nwString };
std::string cmd = R"(C:\Windows\System32\WindowsPowershell\v1.0\powershell.exe "Remove-NetFirewallRule -DisplayName zerotier-icmpv6-)" + nwString2 + "*\" \r\n";
_run(cmd);
}
void WinFWHelper::removeICMPRules()
{
// removes all icmp firewall rules for all networks
std::string cmd = R"(C:\Windows\System32\WindowsPowershell\v1.0\powershell.exe "Remove-NetFirewallRule -DisplayName zerotier-icmp*)" + std::string("\r\n");
_run(cmd);
}
void WinFWHelper::removeICMPRules(uint64_t nwid)
{
// removes all icmp firewall rules for this network
WinFWHelper::removeICMPv4Rules(nwid);
WinFWHelper::removeICMPv6Rules(nwid);
}
void WinFWHelper::_run(std::string cmd)
{
#ifdef ZT_DEBUG
fprintf(stderr, cmd.c_str());
#endif
STARTUPINFOA startupInfo;
PROCESS_INFORMATION processInfo;
startupInfo.cb = sizeof(startupInfo);
memset(&startupInfo, 0, sizeof(STARTUPINFOA));
memset(&processInfo, 0, sizeof(PROCESS_INFORMATION));
if (CreateProcessA(NULL, (LPSTR)cmd.c_str(), NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &startupInfo, &processInfo)) {
WaitForSingleObject(processInfo.hProcess, INFINITE);
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
}
}
} // namespace ZeroTier

31
osdep/WinFWHelper.hpp Normal file
View file

@ -0,0 +1,31 @@
#ifndef WIN_FW_HELPER_H_
#define WIN_FW_HELPER_H_
#include "../node/InetAddress.hpp"
#include <cstdint>
#include <vector>
namespace ZeroTier {
class WinFWHelper {
public:
static void newICMPRule(const InetAddress& ip, uint64_t nwid);
static void removeICMPRule(const InetAddress& ip, uint64_t nwid);
static void removeICMPRules(uint64_t nwid);
static void removeICMPRules();
private:
static void _run(std::string cmd);
static void newICMPv4Rule(std::string address, uint64_t nwid);
static void newICMPv6Rule(std::string address, uint64_t nwid);
static void removeICMPv4Rule(std::string address, uint64_t nwid);
static void removeICMPv6Rule(std::string address, uint64_t nwid);
static void removeICMPv4Rules(uint64_t nwid);
static void removeICMPv6Rules(uint64_t nwid);
};
} // namespace ZeroTier
#endif

View file

@ -78,6 +78,7 @@
#include "../osdep/MacDNSHelper.hpp" #include "../osdep/MacDNSHelper.hpp"
#elif defined(__WINDOWS__) #elif defined(__WINDOWS__)
#include "../osdep/WinDNSHelper.hpp" #include "../osdep/WinDNSHelper.hpp"
#include "../osdep/WinFWHelper.hpp"
#endif #endif
#ifdef ZT_USE_SYSTEM_HTTP_PARSER #ifdef ZT_USE_SYSTEM_HTTP_PARSER
@ -850,6 +851,9 @@ public:
virtual ~OneServiceImpl() virtual ~OneServiceImpl()
{ {
#ifdef __WINDOWS__
WinFWHelper::removeICMPRules();
#endif
_binder.closeAll(_phy); _binder.closeAll(_phy);
_phy.close(_localControlSocket4); _phy.close(_localControlSocket4);
_phy.close(_localControlSocket6); _phy.close(_localControlSocket6);
@ -858,6 +862,8 @@ public:
curl_global_cleanup(); curl_global_cleanup();
#endif #endif
#ifdef ZT_USE_MINIUPNPC #ifdef ZT_USE_MINIUPNPC
delete _portMapper; delete _portMapper;
#endif #endif
@ -902,6 +908,7 @@ public:
_node = new Node(this,(void *)0,&cb,OSUtils::now()); _node = new Node(this,(void *)0,&cb,OSUtils::now());
} }
// local.conf // local.conf
readLocalSettings(); readLocalSettings();
applyLocalConfig(); applyLocalConfig();
@ -2068,6 +2075,7 @@ public:
bool enabled = OSUtils::jsonInt(link["enabled"],true); bool enabled = OSUtils::jsonInt(link["enabled"],true);
uint32_t capacity = OSUtils::jsonInt(link["capacity"],0); uint32_t capacity = OSUtils::jsonInt(link["capacity"],0);
uint8_t ipvPref = OSUtils::jsonInt(link["ipvPref"],0); uint8_t ipvPref = OSUtils::jsonInt(link["ipvPref"],0);
uint16_t mtu = OSUtils::jsonInt(link["mtu"],0);
std::string failoverToStr(OSUtils::jsonString(link["failoverTo"],"")); std::string failoverToStr(OSUtils::jsonString(link["failoverTo"],""));
// Mode // Mode
std::string linkModeStr(OSUtils::jsonString(link["mode"],"spare")); std::string linkModeStr(OSUtils::jsonString(link["mode"],"spare"));
@ -2084,7 +2092,7 @@ public:
failoverToStr = ""; failoverToStr = "";
enabled = false; enabled = false;
} }
_node->bondController()->addCustomLink(customPolicyStr, new Link(linkNameStr,ipvPref,capacity,enabled,linkMode,failoverToStr)); _node->bondController()->addCustomLink(customPolicyStr, new Link(linkNameStr,ipvPref,mtu,capacity,enabled,linkMode,failoverToStr));
} }
std::string linkSelectMethodStr(OSUtils::jsonString(customPolicy["activeReselect"],"optimize")); std::string linkSelectMethodStr(OSUtils::jsonString(customPolicy["activeReselect"],"optimize"));
if (linkSelectMethodStr == "always") { if (linkSelectMethodStr == "always") {
@ -2132,6 +2140,7 @@ public:
fprintf(stderr,"WARNING: using manually-specified secondary and/or tertiary ports. This can cause NAT issues." ZT_EOL_S); fprintf(stderr,"WARNING: using manually-specified secondary and/or tertiary ports. This can cause NAT issues." ZT_EOL_S);
} }
_portMappingEnabled = OSUtils::jsonBool(settings["portMappingEnabled"],true); _portMappingEnabled = OSUtils::jsonBool(settings["portMappingEnabled"],true);
_node->setLowBandwidthMode(OSUtils::jsonBool(settings["lowBandwidthMode"],false));
#ifndef ZT_SDK #ifndef ZT_SDK
const std::string up(OSUtils::jsonString(settings["softwareUpdate"],ZT_SOFTWARE_UPDATE_DEFAULT)); const std::string up(OSUtils::jsonString(settings["softwareUpdate"],ZT_SOFTWARE_UPDATE_DEFAULT));
@ -2272,6 +2281,10 @@ public:
if (std::find(newManagedIps.begin(),newManagedIps.end(),*ip) == newManagedIps.end()) { if (std::find(newManagedIps.begin(),newManagedIps.end(),*ip) == newManagedIps.end()) {
if (!n.tap()->removeIp(*ip)) if (!n.tap()->removeIp(*ip))
fprintf(stderr,"ERROR: unable to remove ip address %s" ZT_EOL_S, ip->toString(ipbuf)); fprintf(stderr,"ERROR: unable to remove ip address %s" ZT_EOL_S, ip->toString(ipbuf));
#ifdef __WINDOWS__
WinFWHelper::removeICMPRule(*ip, n.config().nwid);
#endif
} }
} }
@ -2279,6 +2292,10 @@ public:
if (std::find(n.managedIps().begin(),n.managedIps().end(),*ip) == n.managedIps().end()) { if (std::find(n.managedIps().begin(),n.managedIps().end(),*ip) == n.managedIps().end()) {
if (!n.tap()->addIp(*ip)) if (!n.tap()->addIp(*ip))
fprintf(stderr,"ERROR: unable to add ip address %s" ZT_EOL_S, ip->toString(ipbuf)); fprintf(stderr,"ERROR: unable to add ip address %s" ZT_EOL_S, ip->toString(ipbuf));
#ifdef __WINDOWS__
WinFWHelper::newICMPRule(*ip, n.config().nwid);
#endif
} }
} }
@ -2762,8 +2779,10 @@ public:
n.tap().reset(); n.tap().reset();
_nets.erase(nwid); _nets.erase(nwid);
#if defined(__WINDOWS__) && !defined(ZT_SDK) #if defined(__WINDOWS__) && !defined(ZT_SDK)
if ((op == ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY)&&(winInstanceId.length() > 0)) if ((op == ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY) && (winInstanceId.length() > 0)) {
WindowsEthernetTap::deletePersistentTapDevice(winInstanceId.c_str()); WindowsEthernetTap::deletePersistentTapDevice(winInstanceId.c_str());
WinFWHelper::removeICMPRules(nwid);
}
#endif #endif
if (op == ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY) { if (op == ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY) {
char nlcpath[256]; char nlcpath[256];

View file

@ -124,6 +124,7 @@
<ClCompile Include="..\..\osdep\PortMapper.cpp" /> <ClCompile Include="..\..\osdep\PortMapper.cpp" />
<ClCompile Include="..\..\osdep\WinDNSHelper.cpp" /> <ClCompile Include="..\..\osdep\WinDNSHelper.cpp" />
<ClCompile Include="..\..\osdep\WindowsEthernetTap.cpp" /> <ClCompile Include="..\..\osdep\WindowsEthernetTap.cpp" />
<ClCompile Include="..\..\osdep\WinFWHelper.cpp" />
<ClCompile Include="..\..\selftest.cpp"> <ClCompile Include="..\..\selftest.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
@ -241,6 +242,7 @@
<ClInclude Include="..\..\osdep\Thread.hpp" /> <ClInclude Include="..\..\osdep\Thread.hpp" />
<ClInclude Include="..\..\osdep\WinDNSHelper.hpp" /> <ClInclude Include="..\..\osdep\WinDNSHelper.hpp" />
<ClInclude Include="..\..\osdep\WindowsEthernetTap.hpp" /> <ClInclude Include="..\..\osdep\WindowsEthernetTap.hpp" />
<ClInclude Include="..\..\osdep\WinFWHelper.hpp" />
<ClInclude Include="..\..\service\OneService.hpp" /> <ClInclude Include="..\..\service\OneService.hpp" />
<ClInclude Include="..\..\service\SoftwareUpdater.hpp" /> <ClInclude Include="..\..\service\SoftwareUpdater.hpp" />
<ClInclude Include="..\..\version.h" /> <ClInclude Include="..\..\version.h" />

View file

@ -288,6 +288,9 @@
<ClCompile Include="..\..\node\AES_armcrypto.cpp"> <ClCompile Include="..\..\node\AES_armcrypto.cpp">
<Filter>Source Files\node</Filter> <Filter>Source Files\node</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\osdep\WinFWHelper.cpp">
<Filter>Source Files\osdep</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="resource.h"> <ClInclude Include="resource.h">
@ -551,6 +554,9 @@
<ClInclude Include="..\..\osdep\WinDNSHelper.hpp"> <ClInclude Include="..\..\osdep\WinDNSHelper.hpp">
<Filter>Header Files\osdep</Filter> <Filter>Header Files\osdep</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\osdep\WinFWHelper.hpp">
<Filter>Header Files\osdep</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="ZeroTierOne.rc"> <ResourceCompile Include="ZeroTierOne.rc">