|
@@ -49,6 +49,7 @@
|
|
#include "../osdep/Binder.hpp"
|
|
#include "../osdep/Binder.hpp"
|
|
#include "../osdep/ManagedRoute.hpp"
|
|
#include "../osdep/ManagedRoute.hpp"
|
|
#include "../osdep/BlockingQueue.hpp"
|
|
#include "../osdep/BlockingQueue.hpp"
|
|
|
|
+#include "../osdep/Link.hpp"
|
|
|
|
|
|
#include "OneService.hpp"
|
|
#include "OneService.hpp"
|
|
#include "SoftwareUpdater.hpp"
|
|
#include "SoftwareUpdater.hpp"
|
|
@@ -183,7 +184,6 @@ static void _networkToJson(nlohmann::json &nj,const ZT_VirtualNetworkConfig *nc,
|
|
case ZT_NETWORK_STATUS_NOT_FOUND: nstatus = "NOT_FOUND"; break;
|
|
case ZT_NETWORK_STATUS_NOT_FOUND: nstatus = "NOT_FOUND"; break;
|
|
case ZT_NETWORK_STATUS_PORT_ERROR: nstatus = "PORT_ERROR"; break;
|
|
case ZT_NETWORK_STATUS_PORT_ERROR: nstatus = "PORT_ERROR"; break;
|
|
case ZT_NETWORK_STATUS_CLIENT_TOO_OLD: nstatus = "CLIENT_TOO_OLD"; break;
|
|
case ZT_NETWORK_STATUS_CLIENT_TOO_OLD: nstatus = "CLIENT_TOO_OLD"; break;
|
|
- case ZT_NETWORK_STATUS_AUTHENTICATION_REQUIRED: nstatus = "AUTHENTICATION_REQUIRED"; break;
|
|
|
|
}
|
|
}
|
|
switch(nc->type) {
|
|
switch(nc->type) {
|
|
case ZT_NETWORK_TYPE_PRIVATE: ntype = "PRIVATE"; break;
|
|
case ZT_NETWORK_TYPE_PRIVATE: ntype = "PRIVATE"; break;
|
|
@@ -251,9 +251,6 @@ static void _networkToJson(nlohmann::json &nj,const ZT_VirtualNetworkConfig *nc,
|
|
}
|
|
}
|
|
nj["dns"] = m;
|
|
nj["dns"] = m;
|
|
|
|
|
|
- nj["authenticationURL"] = nc->authenticationURL;
|
|
|
|
- nj["authenticationExpiryTime"] = nc->authenticationExpiryTime;
|
|
|
|
- nj["ssoEnabled"] = nc->ssoEnabled;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
static void _peerToJson(nlohmann::json &pj,const ZT_Peer *peer)
|
|
static void _peerToJson(nlohmann::json &pj,const ZT_Peer *peer)
|
|
@@ -303,11 +300,12 @@ static void _peerToJson(nlohmann::json &pj,const ZT_Peer *peer)
|
|
|
|
|
|
static void _bondToJson(nlohmann::json &pj, SharedPtr<Bond> &bond)
|
|
static void _bondToJson(nlohmann::json &pj, SharedPtr<Bond> &bond)
|
|
{
|
|
{
|
|
|
|
+ char tmp[256];
|
|
uint64_t now = OSUtils::now();
|
|
uint64_t now = OSUtils::now();
|
|
|
|
|
|
- int bondingPolicy = bond->policy();
|
|
|
|
- pj["bondingPolicy"] = Bond::getPolicyStrByCode(bondingPolicy);
|
|
|
|
- if (bondingPolicy == ZT_BOND_POLICY_NONE) {
|
|
|
|
|
|
+ int bondingPolicy = bond->getPolicy();
|
|
|
|
+ pj["bondingPolicy"] = BondController::getPolicyStrByCode(bondingPolicy);
|
|
|
|
+ if (bondingPolicy == ZT_BONDING_POLICY_NONE) {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -317,15 +315,15 @@ static void _bondToJson(nlohmann::json &pj, SharedPtr<Bond> &bond)
|
|
pj["failoverInterval"] = bond->getFailoverInterval();
|
|
pj["failoverInterval"] = bond->getFailoverInterval();
|
|
pj["downDelay"] = bond->getDownDelay();
|
|
pj["downDelay"] = bond->getDownDelay();
|
|
pj["upDelay"] = bond->getUpDelay();
|
|
pj["upDelay"] = bond->getUpDelay();
|
|
- if (bondingPolicy == ZT_BOND_POLICY_BALANCE_RR) {
|
|
|
|
|
|
+ if (bondingPolicy == ZT_BONDING_POLICY_BALANCE_RR) {
|
|
pj["packetsPerLink"] = bond->getPacketsPerLink();
|
|
pj["packetsPerLink"] = bond->getPacketsPerLink();
|
|
}
|
|
}
|
|
- if (bondingPolicy == ZT_BOND_POLICY_ACTIVE_BACKUP) {
|
|
|
|
|
|
+ if (bondingPolicy == ZT_BONDING_POLICY_ACTIVE_BACKUP) {
|
|
pj["linkSelectMethod"] = bond->getLinkSelectMethod();
|
|
pj["linkSelectMethod"] = bond->getLinkSelectMethod();
|
|
}
|
|
}
|
|
|
|
|
|
nlohmann::json pa = nlohmann::json::array();
|
|
nlohmann::json pa = nlohmann::json::array();
|
|
- std::vector< SharedPtr<Path> > paths = bond->paths(now);
|
|
|
|
|
|
+ std::vector< SharedPtr<Path> > paths = bond->getPeer()->paths(now);
|
|
|
|
|
|
for(unsigned int i=0;i<paths.size();++i) {
|
|
for(unsigned int i=0;i<paths.size();++i) {
|
|
char pathStr[128];
|
|
char pathStr[128];
|
|
@@ -334,7 +332,6 @@ static void _bondToJson(nlohmann::json &pj, SharedPtr<Bond> &bond)
|
|
nlohmann::json j;
|
|
nlohmann::json j;
|
|
j["ifname"] = bond->getLink(paths[i])->ifname();
|
|
j["ifname"] = bond->getLink(paths[i])->ifname();
|
|
j["path"] = pathStr;
|
|
j["path"] = pathStr;
|
|
- /*
|
|
|
|
j["alive"] = paths[i]->alive(now,true);
|
|
j["alive"] = paths[i]->alive(now,true);
|
|
j["bonded"] = paths[i]->bonded();
|
|
j["bonded"] = paths[i]->bonded();
|
|
j["latencyMean"] = paths[i]->latencyMean();
|
|
j["latencyMean"] = paths[i]->latencyMean();
|
|
@@ -343,7 +340,6 @@ static void _bondToJson(nlohmann::json &pj, SharedPtr<Bond> &bond)
|
|
j["packetErrorRatio"] = paths[i]->packetErrorRatio();
|
|
j["packetErrorRatio"] = paths[i]->packetErrorRatio();
|
|
j["givenLinkSpeed"] = 1000;
|
|
j["givenLinkSpeed"] = 1000;
|
|
j["allocation"] = paths[i]->allocation();
|
|
j["allocation"] = paths[i]->allocation();
|
|
- */
|
|
|
|
pa.push_back(j);
|
|
pa.push_back(j);
|
|
}
|
|
}
|
|
pj["links"] = pa;
|
|
pj["links"] = pa;
|
|
@@ -539,12 +535,6 @@ public:
|
|
memset(&config, 0, sizeof(ZT_VirtualNetworkConfig));
|
|
memset(&config, 0, sizeof(ZT_VirtualNetworkConfig));
|
|
}
|
|
}
|
|
|
|
|
|
- ~NetworkState()
|
|
|
|
- {
|
|
|
|
- this->managedRoutes.clear();
|
|
|
|
- this->tap.reset();
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
std::shared_ptr<EthernetTap> tap;
|
|
std::shared_ptr<EthernetTap> tap;
|
|
ZT_VirtualNetworkConfig config; // memcpy() of raw config from core
|
|
ZT_VirtualNetworkConfig config; // memcpy() of raw config from core
|
|
std::vector<InetAddress> managedIps;
|
|
std::vector<InetAddress> managedIps;
|
|
@@ -583,7 +573,6 @@ public:
|
|
Mutex _run_m;
|
|
Mutex _run_m;
|
|
|
|
|
|
RedisConfig *_rc;
|
|
RedisConfig *_rc;
|
|
- std::string _ssoRedirectURL;
|
|
|
|
|
|
|
|
// end member variables ----------------------------------------------------
|
|
// end member variables ----------------------------------------------------
|
|
|
|
|
|
@@ -621,7 +610,6 @@ public:
|
|
#endif
|
|
#endif
|
|
,_run(true)
|
|
,_run(true)
|
|
,_rc(NULL)
|
|
,_rc(NULL)
|
|
- ,_ssoRedirectURL()
|
|
|
|
{
|
|
{
|
|
_ports[0] = 0;
|
|
_ports[0] = 0;
|
|
_ports[1] = 0;
|
|
_ports[1] = 0;
|
|
@@ -735,22 +723,25 @@ public:
|
|
OSUtils::ztsnprintf(portstr,sizeof(portstr),"%u",_ports[0]);
|
|
OSUtils::ztsnprintf(portstr,sizeof(portstr),"%u",_ports[0]);
|
|
OSUtils::writeFile((_homePath + ZT_PATH_SEPARATOR_S "zerotier-one.port").c_str(),std::string(portstr));
|
|
OSUtils::writeFile((_homePath + ZT_PATH_SEPARATOR_S "zerotier-one.port").c_str(),std::string(portstr));
|
|
|
|
|
|
- // Attempt to bind to a secondary port.
|
|
|
|
|
|
+ // Attempt to bind to a secondary port chosen from our ZeroTier address.
|
|
// This exists because there are buggy NATs out there that fail if more
|
|
// This exists because there are buggy NATs out there that fail if more
|
|
// than one device behind the same NAT tries to use the same internal
|
|
// than one device behind the same NAT tries to use the same internal
|
|
// private address port number. Buggy NATs are a running theme.
|
|
// private address port number. Buggy NATs are a running theme.
|
|
- //
|
|
|
|
- // This used to pick the secondary port based on the node ID until we
|
|
|
|
- // discovered another problem: buggy routers and malicious traffic
|
|
|
|
- // "detection". A lot of routers have such things built in these days
|
|
|
|
- // and mis-detect ZeroTier traffic as malicious and block it resulting
|
|
|
|
- // in a node that appears to be in a coma. Secondary ports are now
|
|
|
|
- // randomized on startup.
|
|
|
|
if (_allowSecondaryPort) {
|
|
if (_allowSecondaryPort) {
|
|
if (_secondaryPort) {
|
|
if (_secondaryPort) {
|
|
_ports[1] = _secondaryPort;
|
|
_ports[1] = _secondaryPort;
|
|
} else {
|
|
} else {
|
|
- _ports[1] = _getRandomPort();
|
|
|
|
|
|
+ _ports[1] = 20000 + ((unsigned int)_node->address() % 45500);
|
|
|
|
+ for(int i=0;;++i) {
|
|
|
|
+ if (i > 1000) {
|
|
|
|
+ _ports[1] = 0;
|
|
|
|
+ break;
|
|
|
|
+ } else if (++_ports[1] >= 65536) {
|
|
|
|
+ _ports[1] = 20000;
|
|
|
|
+ }
|
|
|
|
+ if (_trialBind(_ports[1]))
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#ifdef ZT_USE_MINIUPNPC
|
|
#ifdef ZT_USE_MINIUPNPC
|
|
@@ -762,7 +753,7 @@ public:
|
|
if (_tertiaryPort) {
|
|
if (_tertiaryPort) {
|
|
_ports[2] = _tertiaryPort;
|
|
_ports[2] = _tertiaryPort;
|
|
} else {
|
|
} else {
|
|
- _ports[2] = 20000 + (_ports[0] % 40000);
|
|
|
|
|
|
+ _ports[2] = _ports[1];
|
|
for(int i=0;;++i) {
|
|
for(int i=0;;++i) {
|
|
if (i > 1000) {
|
|
if (i > 1000) {
|
|
_ports[2] = 0;
|
|
_ports[2] = 0;
|
|
@@ -788,9 +779,6 @@ public:
|
|
|
|
|
|
// Network controller is now enabled by default for desktop and server
|
|
// Network controller is now enabled by default for desktop and server
|
|
_controller = new EmbeddedNetworkController(_node,_homePath.c_str(),_controllerDbPath.c_str(),_ports[0], _rc);
|
|
_controller = new EmbeddedNetworkController(_node,_homePath.c_str(),_controllerDbPath.c_str(),_ports[0], _rc);
|
|
- if (!_ssoRedirectURL.empty()) {
|
|
|
|
- _controller->setSSORedirectURL(_ssoRedirectURL);
|
|
|
|
- }
|
|
|
|
_node->setNetconfMaster((void *)_controller);
|
|
_node->setNetconfMaster((void *)_controller);
|
|
|
|
|
|
// Join existing networks in networks.d
|
|
// Join existing networks in networks.d
|
|
@@ -823,7 +811,6 @@ public:
|
|
int64_t lastCleanedPeersDb = 0;
|
|
int64_t lastCleanedPeersDb = 0;
|
|
int64_t lastLocalInterfaceAddressCheck = (clockShouldBe - ZT_LOCAL_INTERFACE_CHECK_INTERVAL) + 15000; // do this in 15s to give portmapper time to configure and other things time to settle
|
|
int64_t lastLocalInterfaceAddressCheck = (clockShouldBe - ZT_LOCAL_INTERFACE_CHECK_INTERVAL) + 15000; // do this in 15s to give portmapper time to configure and other things time to settle
|
|
int64_t lastLocalConfFileCheck = OSUtils::now();
|
|
int64_t lastLocalConfFileCheck = OSUtils::now();
|
|
- int64_t lastOnline = lastLocalConfFileCheck;
|
|
|
|
for(;;) {
|
|
for(;;) {
|
|
_run_m.lock();
|
|
_run_m.lock();
|
|
if (!_run) {
|
|
if (!_run) {
|
|
@@ -865,16 +852,6 @@ public:
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- // If secondary port is not configured to a constant value and we've been offline for a while,
|
|
|
|
- // bind a new secondary port. This is a workaround for a "coma" issue caused by buggy NATs that stop
|
|
|
|
- // working on one port after a while.
|
|
|
|
- if (_node->online()) {
|
|
|
|
- lastOnline = now;
|
|
|
|
- } else if ((_secondaryPort == 0)&&((now - lastOnline) > ZT_PATH_HEARTBEAT_PERIOD)) {
|
|
|
|
- _secondaryPort = _getRandomPort();
|
|
|
|
- lastBindRefresh = 0;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
// Refresh bindings in case device's interfaces have changed, and also sync routes to update any shadow routes (e.g. shadow default)
|
|
// Refresh bindings in case device's interfaces have changed, and also sync routes to update any shadow routes (e.g. shadow default)
|
|
if (((now - lastBindRefresh) >= (_node->bondController()->inUse() ? ZT_BINDER_REFRESH_PERIOD / 4 : ZT_BINDER_REFRESH_PERIOD))||(restarted)) {
|
|
if (((now - lastBindRefresh) >= (_node->bondController()->inUse() ? ZT_BINDER_REFRESH_PERIOD / 4 : ZT_BINDER_REFRESH_PERIOD))||(restarted)) {
|
|
lastBindRefresh = now;
|
|
lastBindRefresh = now;
|
|
@@ -1035,11 +1012,8 @@ public:
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- // Make a copy so lookups don't modify in place;
|
|
|
|
- json lc(_localConfig);
|
|
|
|
-
|
|
|
|
// Get any trusted paths in local.conf (we'll parse the rest of physical[] elsewhere)
|
|
// Get any trusted paths in local.conf (we'll parse the rest of physical[] elsewhere)
|
|
- json &physical = lc["physical"];
|
|
|
|
|
|
+ json &physical = _localConfig["physical"];
|
|
if (physical.is_object()) {
|
|
if (physical.is_object()) {
|
|
for(json::iterator phy(physical.begin());phy!=physical.end();++phy) {
|
|
for(json::iterator phy(physical.begin());phy!=physical.end();++phy) {
|
|
InetAddress net(OSUtils::jsonString(phy.key(),"").c_str());
|
|
InetAddress net(OSUtils::jsonString(phy.key(),"").c_str());
|
|
@@ -1056,22 +1030,20 @@ public:
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- json &settings = lc["settings"];
|
|
|
|
|
|
+ json &settings = _localConfig["settings"];
|
|
if (settings.is_object()) {
|
|
if (settings.is_object()) {
|
|
// Allow controller DB path to be put somewhere else
|
|
// Allow controller DB path to be put somewhere else
|
|
const std::string cdbp(OSUtils::jsonString(settings["controllerDbPath"],""));
|
|
const std::string cdbp(OSUtils::jsonString(settings["controllerDbPath"],""));
|
|
if (cdbp.length() > 0)
|
|
if (cdbp.length() > 0)
|
|
_controllerDbPath = cdbp;
|
|
_controllerDbPath = cdbp;
|
|
|
|
|
|
- _ssoRedirectURL = OSUtils::jsonString(settings["ssoRedirectURL"], "");
|
|
|
|
-
|
|
|
|
#ifdef ZT_CONTROLLER_USE_LIBPQ
|
|
#ifdef ZT_CONTROLLER_USE_LIBPQ
|
|
// TODO: Redis config
|
|
// TODO: Redis config
|
|
json &redis = settings["redis"];
|
|
json &redis = settings["redis"];
|
|
if (redis.is_object() && _rc == NULL) {
|
|
if (redis.is_object() && _rc == NULL) {
|
|
_rc = new RedisConfig;
|
|
_rc = new RedisConfig;
|
|
_rc->hostname = OSUtils::jsonString(redis["hostname"],"");
|
|
_rc->hostname = OSUtils::jsonString(redis["hostname"],"");
|
|
- _rc->port = OSUtils::jsonInt(redis["port"],0);
|
|
|
|
|
|
+ _rc->port = redis["port"];
|
|
_rc->password = OSUtils::jsonString(redis["password"],"");
|
|
_rc->password = OSUtils::jsonString(redis["password"],"");
|
|
_rc->clusterMode = OSUtils::jsonBool(redis["clusterMode"], false);
|
|
_rc->clusterMode = OSUtils::jsonBool(redis["clusterMode"], false);
|
|
}
|
|
}
|
|
@@ -1287,7 +1259,7 @@ public:
|
|
_bondToJson(res,bond);
|
|
_bondToJson(res,bond);
|
|
scode = 200;
|
|
scode = 200;
|
|
} else {
|
|
} else {
|
|
- fprintf(stderr, "unable to find bond to peer %llx\n", (unsigned long long)id);
|
|
|
|
|
|
+ fprintf(stderr, "unable to find bond to peer %llx\n", id);
|
|
scode = 400;
|
|
scode = 400;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -1299,11 +1271,8 @@ public:
|
|
} else {
|
|
} else {
|
|
scode = 400; /* bond controller is not enabled */
|
|
scode = 400; /* bond controller is not enabled */
|
|
}
|
|
}
|
|
- } else if (ps[0] == "config") {
|
|
|
|
- Mutex::Lock lc(_localConfig_m);
|
|
|
|
- res = _localConfig;
|
|
|
|
- scode = 200;
|
|
|
|
- } else if (ps[0] == "status") {
|
|
|
|
|
|
+ }
|
|
|
|
+ if (ps[0] == "status") {
|
|
ZT_NodeStatus status;
|
|
ZT_NodeStatus status;
|
|
_node->status(&status);
|
|
_node->status(&status);
|
|
|
|
|
|
@@ -1497,7 +1466,7 @@ public:
|
|
if (bond) {
|
|
if (bond) {
|
|
scode = bond->abForciblyRotateLink() ? 200 : 400;
|
|
scode = bond->abForciblyRotateLink() ? 200 : 400;
|
|
} else {
|
|
} else {
|
|
- fprintf(stderr, "unable to find bond to peer %llx\n", (unsigned long long)id);
|
|
|
|
|
|
+ fprintf(stderr, "unable to find bond to peer %llx\n", id);
|
|
scode = 400;
|
|
scode = 400;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -1509,35 +1478,8 @@ public:
|
|
} else {
|
|
} else {
|
|
scode = 400; /* bond controller is not enabled */
|
|
scode = 400; /* bond controller is not enabled */
|
|
}
|
|
}
|
|
- } else if (ps[0] == "config") {
|
|
|
|
- // Right now we only support writing the things the UI supports changing.
|
|
|
|
- if (ps.size() == 2) {
|
|
|
|
- if (ps[1] == "settings") {
|
|
|
|
- try {
|
|
|
|
- json j(OSUtils::jsonParse(body));
|
|
|
|
- if (j.is_object()) {
|
|
|
|
- Mutex::Lock lcl(_localConfig_m);
|
|
|
|
- json lc(_localConfig);
|
|
|
|
- for(json::const_iterator s(j.begin());s!=j.end();++s) {
|
|
|
|
- lc["settings"][s.key()] = s.value();
|
|
|
|
- }
|
|
|
|
- std::string lcStr = OSUtils::jsonDump(lc, 4);
|
|
|
|
- if (OSUtils::writeFile((_homePath + ZT_PATH_SEPARATOR_S "local.conf").c_str(), lcStr)) {
|
|
|
|
- _localConfig = lc;
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- scode = 400;
|
|
|
|
- }
|
|
|
|
- } catch ( ... ) {
|
|
|
|
- scode = 400;
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- scode = 404;
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- scode = 404;
|
|
|
|
- }
|
|
|
|
- } else if (ps[0] == "moon") {
|
|
|
|
|
|
+ }
|
|
|
|
+ if (ps[0] == "moon") {
|
|
if (ps.size() == 2) {
|
|
if (ps.size() == 2) {
|
|
|
|
|
|
uint64_t seed = 0;
|
|
uint64_t seed = 0;
|
|
@@ -1769,11 +1711,11 @@ public:
|
|
if (basePolicyStr.empty()) {
|
|
if (basePolicyStr.empty()) {
|
|
fprintf(stderr, "error: no base policy was specified for custom policy (%s)\n", customPolicyStr.c_str());
|
|
fprintf(stderr, "error: no base policy was specified for custom policy (%s)\n", customPolicyStr.c_str());
|
|
}
|
|
}
|
|
- if (_node->bondController()->getPolicyCodeByStr(basePolicyStr) == ZT_BOND_POLICY_NONE) {
|
|
|
|
|
|
+ if (_node->bondController()->getPolicyCodeByStr(basePolicyStr) == ZT_BONDING_POLICY_NONE) {
|
|
fprintf(stderr, "error: custom policy (%s) is invalid, unknown base policy (%s).\n",
|
|
fprintf(stderr, "error: custom policy (%s) is invalid, unknown base policy (%s).\n",
|
|
customPolicyStr.c_str(), basePolicyStr.c_str());
|
|
customPolicyStr.c_str(), basePolicyStr.c_str());
|
|
continue;
|
|
continue;
|
|
- } if (_node->bondController()->getPolicyCodeByStr(customPolicyStr) != ZT_BOND_POLICY_NONE) {
|
|
|
|
|
|
+ } if (_node->bondController()->getPolicyCodeByStr(customPolicyStr) != ZT_BONDING_POLICY_NONE) {
|
|
fprintf(stderr, "error: custom policy (%s) will be ignored, cannot use standard policy names for custom policies.\n",
|
|
fprintf(stderr, "error: custom policy (%s) will be ignored, cannot use standard policy names for custom policies.\n",
|
|
customPolicyStr.c_str());
|
|
customPolicyStr.c_str());
|
|
continue;
|
|
continue;
|
|
@@ -1802,12 +1744,20 @@ public:
|
|
newTemplateBond->setUserQualityWeights(weights,ZT_QOS_WEIGHT_SIZE);
|
|
newTemplateBond->setUserQualityWeights(weights,ZT_QOS_WEIGHT_SIZE);
|
|
}
|
|
}
|
|
// Bond-specific properties
|
|
// Bond-specific properties
|
|
|
|
+ newTemplateBond->setOverflowMode(OSUtils::jsonInt(customPolicy["overflow"],false));
|
|
newTemplateBond->setUpDelay(OSUtils::jsonInt(customPolicy["upDelay"],-1));
|
|
newTemplateBond->setUpDelay(OSUtils::jsonInt(customPolicy["upDelay"],-1));
|
|
newTemplateBond->setDownDelay(OSUtils::jsonInt(customPolicy["downDelay"],-1));
|
|
newTemplateBond->setDownDelay(OSUtils::jsonInt(customPolicy["downDelay"],-1));
|
|
newTemplateBond->setFlowRebalanceStrategy(OSUtils::jsonInt(customPolicy["flowRebalanceStrategy"],(uint64_t)0));
|
|
newTemplateBond->setFlowRebalanceStrategy(OSUtils::jsonInt(customPolicy["flowRebalanceStrategy"],(uint64_t)0));
|
|
newTemplateBond->setFailoverInterval(OSUtils::jsonInt(customPolicy["failoverInterval"],(uint64_t)0));
|
|
newTemplateBond->setFailoverInterval(OSUtils::jsonInt(customPolicy["failoverInterval"],(uint64_t)0));
|
|
newTemplateBond->setPacketsPerLink(OSUtils::jsonInt(customPolicy["packetsPerLink"],-1));
|
|
newTemplateBond->setPacketsPerLink(OSUtils::jsonInt(customPolicy["packetsPerLink"],-1));
|
|
|
|
|
|
|
|
+ std::string linkMonitorStrategyStr(OSUtils::jsonString(customPolicy["linkMonitorStrategy"],""));
|
|
|
|
+ uint8_t linkMonitorStrategy = ZT_MULTIPATH_SLAVE_MONITOR_STRATEGY_DEFAULT;
|
|
|
|
+ if (linkMonitorStrategyStr == "passive") { linkMonitorStrategy = ZT_MULTIPATH_SLAVE_MONITOR_STRATEGY_PASSIVE; }
|
|
|
|
+ if (linkMonitorStrategyStr == "active") { linkMonitorStrategy = ZT_MULTIPATH_SLAVE_MONITOR_STRATEGY_ACTIVE; }
|
|
|
|
+ if (linkMonitorStrategyStr == "dynamic") { linkMonitorStrategy = ZT_MULTIPATH_SLAVE_MONITOR_STRATEGY_DYNAMIC; }
|
|
|
|
+ newTemplateBond->setLinkMonitorStrategy(linkMonitorStrategy);
|
|
|
|
+
|
|
// Policy-Specific link set
|
|
// Policy-Specific link set
|
|
json &links = customPolicy["links"];
|
|
json &links = customPolicy["links"];
|
|
for (json::iterator linkItr = links.begin(); linkItr != links.end();++linkItr) {
|
|
for (json::iterator linkItr = links.begin(); linkItr != links.end();++linkItr) {
|
|
@@ -1823,40 +1773,40 @@ public:
|
|
speed, alloc, linkNameStr.c_str());
|
|
speed, alloc, linkNameStr.c_str());
|
|
enabled = false;
|
|
enabled = false;
|
|
}
|
|
}
|
|
- //uint32_t upDelay = OSUtils::jsonInt(link["upDelay"],-1);
|
|
|
|
- //uint32_t downDelay = OSUtils::jsonInt(link["downDelay"],-1);
|
|
|
|
|
|
+ uint32_t upDelay = OSUtils::jsonInt(link["upDelay"],-1);
|
|
|
|
+ uint32_t downDelay = OSUtils::jsonInt(link["downDelay"],-1);
|
|
uint8_t ipvPref = OSUtils::jsonInt(link["ipvPref"],0);
|
|
uint8_t ipvPref = OSUtils::jsonInt(link["ipvPref"],0);
|
|
- //uint32_t linkMonitorInterval = OSUtils::jsonInt(link["monitorInterval"],(uint64_t)0);
|
|
|
|
|
|
+ uint32_t linkMonitorInterval = OSUtils::jsonInt(link["monitorInterval"],(uint64_t)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"));
|
|
- uint8_t linkMode = ZT_BOND_SLAVE_MODE_SPARE;
|
|
|
|
- if (linkModeStr == "primary") { linkMode = ZT_BOND_SLAVE_MODE_PRIMARY; }
|
|
|
|
- if (linkModeStr == "spare") { linkMode = ZT_BOND_SLAVE_MODE_SPARE; }
|
|
|
|
|
|
+ uint8_t linkMode = ZT_MULTIPATH_SLAVE_MODE_SPARE;
|
|
|
|
+ if (linkModeStr == "primary") { linkMode = ZT_MULTIPATH_SLAVE_MODE_PRIMARY; }
|
|
|
|
+ if (linkModeStr == "spare") { linkMode = ZT_MULTIPATH_SLAVE_MODE_SPARE; }
|
|
// ipvPref
|
|
// ipvPref
|
|
if ((ipvPref != 0) && (ipvPref != 4) && (ipvPref != 6) && (ipvPref != 46) && (ipvPref != 64)) {
|
|
if ((ipvPref != 0) && (ipvPref != 4) && (ipvPref != 6) && (ipvPref != 46) && (ipvPref != 64)) {
|
|
fprintf(stderr, "error: invalid ipvPref value (%d), link disabled.\n", ipvPref);
|
|
fprintf(stderr, "error: invalid ipvPref value (%d), link disabled.\n", ipvPref);
|
|
enabled = false;
|
|
enabled = false;
|
|
}
|
|
}
|
|
- if (linkMode == ZT_BOND_SLAVE_MODE_SPARE && failoverToStr.length()) {
|
|
|
|
|
|
+ if (linkMode == ZT_MULTIPATH_SLAVE_MODE_SPARE && failoverToStr.length()) {
|
|
fprintf(stderr, "error: cannot specify failover links for spares, link disabled.\n");
|
|
fprintf(stderr, "error: cannot specify failover links for spares, link disabled.\n");
|
|
failoverToStr = "";
|
|
failoverToStr = "";
|
|
enabled = false;
|
|
enabled = false;
|
|
}
|
|
}
|
|
- _node->bondController()->addCustomLink(customPolicyStr, new Link(linkNameStr,ipvPref,speed,enabled,linkMode,failoverToStr,alloc));
|
|
|
|
|
|
+ _node->bondController()->addCustomLink(customPolicyStr, new Link(linkNameStr,ipvPref,speed,linkMonitorInterval,upDelay,downDelay,enabled,linkMode,failoverToStr,alloc));
|
|
}
|
|
}
|
|
std::string linkSelectMethodStr(OSUtils::jsonString(customPolicy["activeReselect"],"optimize"));
|
|
std::string linkSelectMethodStr(OSUtils::jsonString(customPolicy["activeReselect"],"optimize"));
|
|
if (linkSelectMethodStr == "always") {
|
|
if (linkSelectMethodStr == "always") {
|
|
- newTemplateBond->setLinkSelectMethod(ZT_BOND_RESELECTION_POLICY_ALWAYS);
|
|
|
|
|
|
+ newTemplateBond->setLinkSelectMethod(ZT_MULTIPATH_RESELECTION_POLICY_ALWAYS);
|
|
}
|
|
}
|
|
if (linkSelectMethodStr == "better") {
|
|
if (linkSelectMethodStr == "better") {
|
|
- newTemplateBond->setLinkSelectMethod(ZT_BOND_RESELECTION_POLICY_BETTER);
|
|
|
|
|
|
+ newTemplateBond->setLinkSelectMethod(ZT_MULTIPATH_RESELECTION_POLICY_BETTER);
|
|
}
|
|
}
|
|
if (linkSelectMethodStr == "failure") {
|
|
if (linkSelectMethodStr == "failure") {
|
|
- newTemplateBond->setLinkSelectMethod(ZT_BOND_RESELECTION_POLICY_FAILURE);
|
|
|
|
|
|
+ newTemplateBond->setLinkSelectMethod(ZT_MULTIPATH_RESELECTION_POLICY_FAILURE);
|
|
}
|
|
}
|
|
if (linkSelectMethodStr == "optimize") {
|
|
if (linkSelectMethodStr == "optimize") {
|
|
- newTemplateBond->setLinkSelectMethod(ZT_BOND_RESELECTION_POLICY_OPTIMIZE);
|
|
|
|
|
|
+ newTemplateBond->setLinkSelectMethod(ZT_MULTIPATH_RESELECTION_POLICY_OPTIMIZE);
|
|
}
|
|
}
|
|
if (newTemplateBond->getLinkSelectMethod() < 0 || newTemplateBond->getLinkSelectMethod() > 3) {
|
|
if (newTemplateBond->getLinkSelectMethod() < 0 || newTemplateBond->getLinkSelectMethod() > 3) {
|
|
fprintf(stderr, "warning: invalid value (%s) for linkSelectMethod, assuming mode: always\n", linkSelectMethodStr.c_str());
|
|
fprintf(stderr, "warning: invalid value (%s) for linkSelectMethod, assuming mode: always\n", linkSelectMethodStr.c_str());
|
|
@@ -1889,7 +1839,7 @@ public:
|
|
_secondaryPort = (unsigned int)OSUtils::jsonInt(settings["secondaryPort"],0);
|
|
_secondaryPort = (unsigned int)OSUtils::jsonInt(settings["secondaryPort"],0);
|
|
_tertiaryPort = (unsigned int)OSUtils::jsonInt(settings["tertiaryPort"],0);
|
|
_tertiaryPort = (unsigned int)OSUtils::jsonInt(settings["tertiaryPort"],0);
|
|
if (_secondaryPort != 0 || _tertiaryPort != 0) {
|
|
if (_secondaryPort != 0 || _tertiaryPort != 0) {
|
|
- 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 ports. This can cause NAT issues." ZT_EOL_S);
|
|
}
|
|
}
|
|
_portMappingEnabled = OSUtils::jsonBool(settings["portMappingEnabled"],true);
|
|
_portMappingEnabled = OSUtils::jsonBool(settings["portMappingEnabled"],true);
|
|
|
|
|
|
@@ -2078,7 +2028,7 @@ public:
|
|
unsigned int mostMatchingPrefixBits = 0;
|
|
unsigned int mostMatchingPrefixBits = 0;
|
|
for(std::set<InetAddress>::const_iterator i(myIps.begin());i!=myIps.end();++i) {
|
|
for(std::set<InetAddress>::const_iterator i(myIps.begin());i!=myIps.end();++i) {
|
|
const unsigned int matchingPrefixBits = i->matchingPrefixBits(*target);
|
|
const unsigned int matchingPrefixBits = i->matchingPrefixBits(*target);
|
|
- if (matchingPrefixBits >= mostMatchingPrefixBits && ((target->isV4() && i->isV4()) || (target->isV6() && i->isV6()))) {
|
|
|
|
|
|
+ if (matchingPrefixBits >= mostMatchingPrefixBits) {
|
|
mostMatchingPrefixBits = matchingPrefixBits;
|
|
mostMatchingPrefixBits = matchingPrefixBits;
|
|
src = &(*i);
|
|
src = &(*i);
|
|
}
|
|
}
|
|
@@ -2441,7 +2391,7 @@ public:
|
|
Dictionary<4096> nc;
|
|
Dictionary<4096> nc;
|
|
nc.load(nlcbuf.c_str());
|
|
nc.load(nlcbuf.c_str());
|
|
Buffer<1024> allowManaged;
|
|
Buffer<1024> allowManaged;
|
|
- if (nc.get("allowManaged", allowManaged) && allowManaged.size() > 0) {
|
|
|
|
|
|
+ if (nc.get("allowManaged", allowManaged) && !allowManaged.size() == 0) {
|
|
std::string addresses (allowManaged.begin(), allowManaged.size());
|
|
std::string addresses (allowManaged.begin(), allowManaged.size());
|
|
if (allowManaged.size() <= 5) { // untidy parsing for backward compatibility
|
|
if (allowManaged.size() <= 5) { // untidy parsing for backward compatibility
|
|
if (allowManaged[0] == '1' || allowManaged[0] == 't' || allowManaged[0] == 'T') {
|
|
if (allowManaged[0] == '1' || allowManaged[0] == 't' || allowManaged[0] == 'T') {
|
|
@@ -2675,6 +2625,7 @@ public:
|
|
case ZT_STATE_OBJECT_NETWORK_CONFIG:
|
|
case ZT_STATE_OBJECT_NETWORK_CONFIG:
|
|
OSUtils::ztsnprintf(dirname,sizeof(dirname),"%s" ZT_PATH_SEPARATOR_S "networks.d",_homePath.c_str());
|
|
OSUtils::ztsnprintf(dirname,sizeof(dirname),"%s" ZT_PATH_SEPARATOR_S "networks.d",_homePath.c_str());
|
|
OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "%.16llx.conf",dirname,(unsigned long long)id[0]);
|
|
OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "%.16llx.conf",dirname,(unsigned long long)id[0]);
|
|
|
|
+ secure = true;
|
|
break;
|
|
break;
|
|
case ZT_STATE_OBJECT_PEER:
|
|
case ZT_STATE_OBJECT_PEER:
|
|
OSUtils::ztsnprintf(dirname,sizeof(dirname),"%s" ZT_PATH_SEPARATOR_S "peers.d",_homePath.c_str());
|
|
OSUtils::ztsnprintf(dirname,sizeof(dirname),"%s" ZT_PATH_SEPARATOR_S "peers.d",_homePath.c_str());
|
|
@@ -3093,6 +3044,9 @@ public:
|
|
if (!strncmp(p->c_str(),ifname,p->length()))
|
|
if (!strncmp(p->c_str(),ifname,p->length()))
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
+ if (!_node->bondController()->allowedToBind(std::string(ifname))) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
{
|
|
{
|
|
// Check global blacklists
|
|
// Check global blacklists
|
|
@@ -3130,23 +3084,6 @@ public:
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
- unsigned int _getRandomPort()
|
|
|
|
- {
|
|
|
|
- unsigned int randp = 0;
|
|
|
|
- Utils::getSecureRandom(&randp,sizeof(randp));
|
|
|
|
- randp = 20000 + (randp % 45500);
|
|
|
|
- for(int i=0;;++i) {
|
|
|
|
- if (i > 1000) {
|
|
|
|
- return 0;
|
|
|
|
- } else if (++randp >= 65536) {
|
|
|
|
- randp = 20000;
|
|
|
|
- }
|
|
|
|
- if (_trialBind(randp))
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- return randp;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
bool _trialBind(unsigned int port)
|
|
bool _trialBind(unsigned int port)
|
|
{
|
|
{
|
|
struct sockaddr_in in4;
|
|
struct sockaddr_in in4;
|