From a15883d49be1a4648b16cb3958dbba0cfc9027bd Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Tue, 15 Aug 2023 08:54:05 -0700 Subject: [PATCH 1/6] Catch all conditions in switch statement, remove trailing whitespaces --- service/OneService.cpp | 54 +++++++----------------------------------- 1 file changed, 8 insertions(+), 46 deletions(-) diff --git a/service/OneService.cpp b/service/OneService.cpp index 0a9842a7d..a96fbc030 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -277,7 +277,7 @@ std::string http_log(const httplib::Request &req, const httplib::Response &res) class NetworkState { public: - NetworkState() + NetworkState() : _webPort(9993) , _tap((EthernetTap *)0) #if ZT_SSO_ENABLED @@ -357,7 +357,7 @@ public: bool allowDNS() const { return _settings.allowDNS; } - + std::vector allowManagedWhitelist() const { return _settings.allowManagedWhitelist; } @@ -838,7 +838,7 @@ public: // Deadline for the next background task service function volatile int64_t _nextBackgroundTaskDeadline; - + std::map _nets; Mutex _nets_m; @@ -930,7 +930,7 @@ public: virtual ~OneServiceImpl() { -#ifdef __WINDOWS__ +#ifdef __WINDOWS__ WinFWHelper::removeICMPRules(); #endif _binder.closeAll(_phy); @@ -1047,10 +1047,10 @@ public: // 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 + // 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 + // in a node that appears to be in a coma. Secondary ports are now // randomized on startup. if (_allowSecondaryPort) { if (_secondaryPort) { @@ -2750,46 +2750,8 @@ public: TcpConnection *tc = reinterpret_cast(*uptr); tc->lastReceive = OSUtils::now(); switch(tc->type) { - - // TODO: Remove Me - // case TcpConnection::TCP_UNCATEGORIZED_INCOMING: - // switch(reinterpret_cast(data)[0]) { - // // HTTP: GET, PUT, POST, HEAD, DELETE - // case 'G': - // case 'P': - // case 'D': - // case 'H': { - // // This is only allowed from IPs permitted to access the management - // // backplane, which is just 127.0.0.1/::1 unless otherwise configured. - // bool allow; - // { - // Mutex::Lock _l(_localConfig_m); - // if (_allowManagementFrom.empty()) { - // allow = (tc->remoteAddr.ipScope() == InetAddress::IP_SCOPE_LOOPBACK); - // } else { - // allow = false; - // for(std::vector::const_iterator i(_allowManagementFrom.begin());i!=_allowManagementFrom.end();++i) { - // if (i->containsAddress(tc->remoteAddr)) { - // allow = true; - // break; - // } - // } - // } - // } - // if (allow) { - // tc->type = TcpConnection::TCP_HTTP_INCOMING; - // phyOnTcpData(sock,uptr,data,len); - // } else { - // _phy.close(sock); - // } - // } break; - - // // Drop unknown protocols - // default: - // _phy.close(sock); - // break; - // } - // return; + case TcpConnection::TCP_UNCATEGORIZED_INCOMING: + return; case TcpConnection::TCP_HTTP_INCOMING: case TcpConnection::TCP_HTTP_OUTGOING: From b8b5d0bff8b05d7b66439f25f1b4358f2a556f21 Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Tue, 15 Aug 2023 12:59:58 -0700 Subject: [PATCH 2/6] Add setmtu command, fix bond lifetime issue --- include/ZeroTierOne.h | 7 +++- node/Bond.cpp | 46 +++++++++++++++++++++-- node/Bond.hpp | 20 ++++++++++ node/IncomingPacket.cpp | 28 ++++---------- node/Node.cpp | 9 +++-- node/Path.hpp | 8 ++++ node/Peer.cpp | 23 ++++++++---- node/Peer.hpp | 81 ++++++++++++++++++++++++++++++++++++++++- one.cpp | 32 ++++++++++++++-- service/OneService.cpp | 17 +++++++-- 10 files changed, 228 insertions(+), 43 deletions(-) diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index a60116bd9..27b08ff5c 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -1194,7 +1194,7 @@ typedef struct uint64_t mac; /* MAC in lower 48 bits */ uint32_t adi; /* Additional distinguishing information, usually zero except for IPv4 ARP groups */ } multicastSubscriptions[ZT_MAX_MULTICAST_SUBSCRIPTIONS]; - + /** * Network specific DNS configuration */ @@ -1327,6 +1327,11 @@ typedef struct */ float packetErrorRatio; + /** + * Number of flows assigned to this path + */ + uint16_t assignedFlowCount; + /** * Address scope */ diff --git a/node/Bond.cpp b/node/Bond.cpp index 4c43ad505..9bd9ee41e 100644 --- a/node/Bond.cpp +++ b/node/Bond.cpp @@ -102,6 +102,43 @@ SharedPtr Bond::getBondByPeerId(int64_t identity) return _bonds.count(identity) ? _bonds[identity] : SharedPtr(); } +bool Bond::setAllMtuByTuple(uint16_t mtu, const std::string& ifStr, const std::string& ipStr) +{ + Mutex::Lock _l(_bonds_m); + std::map >::iterator bondItr = _bonds.begin(); + bool found = false; + while (bondItr != _bonds.end()) { + if (bondItr->second->setMtuByTuple(mtu,ifStr,ipStr)) { + found = true; + } + ++bondItr; + } + return found; +} + +bool Bond::setMtuByTuple(uint16_t mtu, const std::string& ifStr, const std::string& ipStr) +{ + Mutex::Lock _lp(_paths_m); + bool found = false; + for (int i = 0; i < ZT_MAX_PEER_NETWORK_PATHS; ++i) { + if (_paths[i].p) { + SharedPtr sl = getLink(_paths[i].p); + if (sl) { + if (sl->ifname() == ifStr) { + char ipBuf[64] = { 0 }; + _paths[i].p->address().toIpString(ipBuf); + std::string newString = std::string(ipBuf); + if (newString == ipStr) { + _paths[i].p->_mtu = mtu; + found = true; + } + } + } + } + } + return found; +} + SharedPtr Bond::createBond(const RuntimeEnvironment* renv, const SharedPtr& peer) { Mutex::Lock _l(_bonds_m); @@ -162,8 +199,8 @@ void Bond::destroyBond(uint64_t peerId) auto iter = _bonds.find(peerId); if (iter != _bonds.end()) { iter->second->stopBond(); + _bonds.erase(iter); } - _bonds.erase(peerId); } void Bond::stopBond() @@ -978,7 +1015,7 @@ void Bond::curateBond(int64_t now, bool rebuildBond) // Whether we've waited long enough since the link last came online bool satisfiedUpDelay = (now - _paths[i].lastAliveToggle) >= _upDelay; // How long since the last QoS was received (Must be less than ZT_PEER_PATH_EXPIRATION since the remote peer's _qosSendInterval isn't known) - bool acceptableQoSAge = _paths[i].lastQoSReceived == 0 || ((now - _paths[i].lastQoSReceived) < ZT_PEER_EXPIRED_PATH_TRIAL_PERIOD); + bool acceptableQoSAge = (_paths[i].lastQoSReceived == 0 && inTrial) || ((now - _paths[i].lastQoSReceived) < ZT_PEER_EXPIRED_PATH_TRIAL_PERIOD); currEligibility = _paths[i].allowed() && ((acceptableAge && satisfiedUpDelay && acceptableQoSAge) || inTrial); if (currEligibility) { @@ -1070,7 +1107,7 @@ void Bond::curateBond(int64_t now, bool rebuildBond) // Bond a spare link if required (no viable primary links left) if (! foundUsablePrimaryPath) { - debug("no usable primary links remain, will attempt to use spare if available"); + // debug("no usable primary links remain, will attempt to use spare if available"); for (int j = 0; j < it->second.size(); j++) { int idx = it->second.at(j); if (! _paths[idx].p || ! _paths[idx].eligible || ! _paths[idx].allowed() || ! _paths[idx].isSpare()) { @@ -1244,7 +1281,8 @@ void Bond::estimatePathQuality(int64_t now) if (link) { int linkSpeed = link->capacity(); _paths[i].p->_givenLinkSpeed = linkSpeed; - _paths[i].p->_mtu = link->mtu(); + _paths[i].p->_mtu = link->mtu() ? link->mtu() : _paths[i].p->_mtu; + _paths[i].p->_assignedFlowCount = _paths[i].assignedFlowCount; maxObservedLinkCap = linkSpeed > maxObservedLinkCap ? linkSpeed : maxObservedLinkCap; } } diff --git a/node/Bond.hpp b/node/Bond.hpp index 81b4691b5..c6347a8cb 100644 --- a/node/Bond.hpp +++ b/node/Bond.hpp @@ -456,6 +456,26 @@ class Bond { */ static SharedPtr getBondByPeerId(int64_t identity); + /** + * Set MTU for link by given interface name and IP address (across all bonds) + * + * @param mtu MTU to be used on this link + * @param ifStr interface name to match + * @param ipStr IP address to match + * @return Whether the MTU was set + */ + static bool setAllMtuByTuple(uint16_t mtu, const std::string& ifStr, const std::string& ipStr); + + /** + * Set MTU for link by given interface name and IP address + * + * @param mtu MTU to be used on this link + * @param ifStr interface name to match + * @param ipStr IP address to match + * @return Whether the MTU was set + */ + bool setMtuByTuple(uint16_t mtu, const std::string& ifStr, const std::string& ipStr); + /** * Add a new bond to the bond controller. * diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index f748bdb35..a5dd77017 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -317,8 +317,7 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,void *tPtr,const Shar bool IncomingPacket::_doACK(const RuntimeEnvironment* RR, void* tPtr, const SharedPtr& peer) { /* - SharedPtr bond = peer->bond(); - if (! bond || ! bond->rateGateACK(RR->node->now())) { + if (! peer->rateGateACK(RR->node->now())) { return true; } int32_t ackedBytes; @@ -326,9 +325,7 @@ bool IncomingPacket::_doACK(const RuntimeEnvironment* RR, void* tPtr, const Shar return true; // ignore } memcpy(&ackedBytes, payload(), sizeof(ackedBytes)); - if (bond) { - bond->receivedAck(_path, RR->node->now(), Utils::ntoh(ackedBytes)); - } + peer->receivedAck(_path, RR->node->now(), Utils::ntoh(ackedBytes)); */ Metrics::pkt_ack_in++; return true; @@ -338,7 +335,7 @@ bool IncomingPacket::_doQOS_MEASUREMENT(const RuntimeEnvironment* RR, void* tPtr { Metrics::pkt_qos_in++; SharedPtr bond = peer->bond(); - if (! bond || ! bond->rateGateQoS(RR->node->now(), _path)) { + if (! peer->rateGateQoS(RR->node->now(), _path)) { return true; } if (payloadLength() > ZT_QOS_MAX_PACKET_SIZE || payloadLength() < ZT_QOS_MIN_PACKET_SIZE) { @@ -359,9 +356,7 @@ bool IncomingPacket::_doQOS_MEASUREMENT(const RuntimeEnvironment* RR, void* tPtr ptr += sizeof(uint16_t); count++; } - if (bond) { - bond->receivedQoS(_path, now, count, rx_id, rx_ts); - } + peer->receivedQoS(_path, now, count, rx_id, rx_ts); return true; } @@ -626,10 +621,7 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,void *tPtr,const SharedP } if (!hops()) { - SharedPtr bond = peer->bond(); - if (!bond) { - _path->updateLatency((unsigned int)latency,RR->node->now()); - } + _path->updateLatency((unsigned int)latency,RR->node->now()); } peer->setRemoteVersion(vProto,vMajor,vMinor,vRevision); @@ -801,8 +793,7 @@ bool IncomingPacket::_doFRAME(const RuntimeEnvironment *RR,void *tPtr,const Shar { Metrics::pkt_frame_in++; int32_t _flowId = ZT_QOS_NO_FLOW; - SharedPtr bond = peer->bond(); - if (bond && bond->flowHashingSupported()) { + if (peer->flowHashingSupported()) { if (size() > ZT_PROTO_VERB_EXT_FRAME_IDX_PAYLOAD) { const unsigned int etherType = at(ZT_PROTO_VERB_FRAME_IDX_ETHERTYPE); const unsigned int frameLen = size() - ZT_PROTO_VERB_FRAME_IDX_PAYLOAD; @@ -1481,8 +1472,7 @@ bool IncomingPacket::_doPATH_NEGOTIATION_REQUEST(const RuntimeEnvironment *RR,vo { Metrics::pkt_path_negotiation_request_in++; uint64_t now = RR->node->now(); - SharedPtr bond = peer->bond(); - if (!bond || !bond->rateGatePathNegotiation(now, _path)) { + if (!peer->rateGatePathNegotiation(now, _path)) { return true; } if (payloadLength() != sizeof(int16_t)) { @@ -1490,9 +1480,7 @@ bool IncomingPacket::_doPATH_NEGOTIATION_REQUEST(const RuntimeEnvironment *RR,vo } int16_t remoteUtility = 0; memcpy(&remoteUtility, payload(), sizeof(int16_t)); - if (peer->bond()) { - peer->bond()->processIncomingPathNegotiationRequest(now, _path, Utils::ntoh(remoteUtility)); - } + peer->processIncomingPathNegotiationRequest(now, _path, Utils::ntoh(remoteUtility)); return true; } diff --git a/node/Node.cpp b/node/Node.cpp index 0657cbd0b..4913d1a4c 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -589,6 +589,7 @@ ZT_PeerList *Node::peers() const p->paths[p->pathCount].latencyVariance = (*path)->latencyVariance(); p->paths[p->pathCount].packetLossRatio = (*path)->packetLossRatio(); p->paths[p->pathCount].packetErrorRatio = (*path)->packetErrorRatio(); + p->paths[p->pathCount].assignedFlowCount = (*path)->assignedFlowCount(); p->paths[p->pathCount].relativeQuality = (*path)->relativeQuality(); p->paths[p->pathCount].linkSpeed = (*path)->givenLinkSpeed(); p->paths[p->pathCount].bonded = (*path)->bonded(); @@ -602,9 +603,9 @@ ZT_PeerList *Node::peers() const } if (pi->second->bond()) { p->isBonded = pi->second->bond(); - p->bondingPolicy = pi->second->bond()->policy(); - p->numAliveLinks = pi->second->bond()->getNumAliveLinks(); - p->numTotalLinks = pi->second->bond()->getNumTotalLinks(); + p->bondingPolicy = pi->second->bondingPolicy(); + p->numAliveLinks = pi->second->getNumAliveLinks(); + p->numTotalLinks = pi->second->getNumTotalLinks(); } } @@ -851,7 +852,7 @@ void Node::ncSendError(uint64_t nwid,uint64_t requestPacketId,const Address &des case NetworkController::NC_ERROR_AUTHENTICATION_REQUIRED: { //fprintf(stderr, "\n\nGot auth required\n\n"); break; - } + } default: break; diff --git a/node/Path.hpp b/node/Path.hpp index 31d8e60d1..b7694920e 100644 --- a/node/Path.hpp +++ b/node/Path.hpp @@ -89,6 +89,7 @@ public: _latencyVariance(0.0), _packetLossRatio(0.0), _packetErrorRatio(0.0), + _assignedFlowCount(0), _valid(true), _eligible(false), _bonded(false), @@ -110,6 +111,7 @@ public: _latencyVariance(0.0), _packetLossRatio(0.0), _packetErrorRatio(0.0), + _assignedFlowCount(0), _valid(true), _eligible(false), _bonded(false), @@ -320,6 +322,11 @@ public: */ inline float packetErrorRatio() const { return _packetErrorRatio; } + /** + * @return Number of flows assigned to this path + */ + inline unsigned int assignedFlowCount() const { return _assignedFlowCount; } + /** * @return Whether this path is valid as reported by the bonding layer. The bonding layer * actually checks with Phy to see if the interface is still up @@ -374,6 +381,7 @@ private: volatile float _latencyVariance; volatile float _packetLossRatio; volatile float _packetErrorRatio; + volatile uint16_t _assignedFlowCount; volatile bool _valid; volatile bool _eligible; volatile bool _bonded; diff --git a/node/Peer.cpp b/node/Peer.cpp index d7f543ead..2040a3b4d 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -28,7 +28,7 @@ namespace ZeroTier { static unsigned char s_freeRandomByteCounter = 0; -Peer::Peer(const RuntimeEnvironment *renv,const Identity &myIdentity,const Identity &peerIdentity) +Peer::Peer(const RuntimeEnvironment *renv,const Identity &myIdentity,const Identity &peerIdentity) : RR(renv) , _lastReceive(0) , _lastNontrivialReceive(0) @@ -487,20 +487,29 @@ void Peer::tryMemorizedPath(void *tPtr,int64_t now) void Peer::performMultipathStateCheck(void *tPtr, int64_t now) { Mutex::Lock _l(_bond_m); - if (_bond) { - // Once enabled the Bond object persists, no need to update state - return; - } /** * Check for conditions required for multipath bonding and create a bond * if allowed. */ int numAlivePaths = 0; + bool atLeastOneNonExpired = false; for(unsigned int i=0;ialive(now)) { - numAlivePaths++; + if (_paths[i].p) { + if(_paths[i].p->alive(now)) { + numAlivePaths++; + } + if ((now - _paths[i].lr) < ZT_PEER_PATH_EXPIRATION) { + atLeastOneNonExpired = true; + } } } + if (_bond) { + if (numAlivePaths == 0 && !atLeastOneNonExpired) { + _bond = SharedPtr(); + RR->bc->destroyBond(_id.address().toInt()); + } + return; + } _localMultipathSupported = ((numAlivePaths >= 1) && (RR->bc->inUse()) && (ZT_PROTO_VERSION > 9)); if (_localMultipathSupported && !_bond) { if (RR->bc) { diff --git a/node/Peer.hpp b/node/Peer.hpp index d03e8f884..e29975b19 100644 --- a/node/Peer.hpp +++ b/node/Peer.hpp @@ -56,7 +56,6 @@ private: public: ~Peer() { Utils::burn(_key,sizeof(_key)); - RR->bc->destroyBond(_id.address().toInt()); } /** @@ -434,6 +433,64 @@ public: return false; } + /** + * See definition in Bond + */ + inline bool rateGateQoS(int64_t now, SharedPtr& path) + { + Mutex::Lock _l(_bond_m); + if(_bond) { + return _bond->rateGateQoS(now, path); + } + return false; // Default behavior. If there is no bond, we drop these + } + + /** + * See definition in Bond + */ + void receivedQoS(const SharedPtr& path, int64_t now, int count, uint64_t* rx_id, uint16_t* rx_ts) + { + Mutex::Lock _l(_bond_m); + if(_bond) { + _bond->receivedQoS(path, now, count, rx_id, rx_ts); + } + } + + /** + * See definition in Bond + */ + void processIncomingPathNegotiationRequest(uint64_t now, SharedPtr& path, int16_t remoteUtility) + { + Mutex::Lock _l(_bond_m); + if(_bond) { + _bond->processIncomingPathNegotiationRequest(now, path, remoteUtility); + } + } + + /** + * See definition in Bond + */ + inline bool rateGatePathNegotiation(int64_t now, SharedPtr& path) + { + Mutex::Lock _l(_bond_m); + if(_bond) { + return _bond->rateGatePathNegotiation(now, path); + } + return false; // Default behavior. If there is no bond, we drop these + } + + /** + * See definition in Bond + */ + bool flowHashingSupported() + { + Mutex::Lock _l(_bond_m); + if(_bond) { + return _bond->flowHashingSupported(); + } + return false; + } + /** * Serialize a peer for storage in local cache * @@ -533,6 +590,28 @@ public: return ZT_BOND_POLICY_NONE; } + /** + * @return the number of links in this bond which are considered alive + */ + inline uint8_t getNumAliveLinks() { + Mutex::Lock _l(_paths_m); + if (_bond) { + return _bond->getNumAliveLinks(); + } + return 0; + } + + /** + * @return the number of links in this bond + */ + inline uint8_t getNumTotalLinks() { + Mutex::Lock _l(_paths_m); + if (_bond) { + return _bond->getNumTotalLinks(); + } + return 0; + } + //inline const AES *aesKeysIfSupported() const //{ return (const AES *)0; } diff --git a/one.cpp b/one.cpp index ba5be9b18..4c7dd9cc1 100644 --- a/one.cpp +++ b/one.cpp @@ -171,7 +171,7 @@ static int cli(int argc,char **argv) #endif { unsigned int port = 0; - std::string homeDir,command,arg1,arg2,authToken; + std::string homeDir,command,arg1,arg2,arg3,arg4,authToken; std::string ip("127.0.0.1"); bool json = false; for(int i=1;i */ + requestHeaders["Content-Type"] = "application/json"; + requestHeaders["Content-Length"] = "2"; + if (argc == 8) { + arg2 = argv[5]; + arg3 = argv[6]; + arg4 = argv[7]; + } + unsigned int scode = Http::POST( + 1024 * 1024 * 16, + 60000, + (const struct sockaddr *)&addr, + (std::string("/bond/") + arg1 + "/" + arg2 + "/" + arg3 + "/" + arg4).c_str(), + requestHeaders, + "{}", + 2, + responseHeaders, + responseBody); + if (scode == 200) { + printf("200 setmtu OK" ZT_EOL_S); + return 0; + } else { + printf("no link match found, new MTU was not applied" ZT_EOL_S); + return 1; + } + return 0; + } else if (arg1.length() == 10) { if (arg2 == "rotate") { /* zerotier-cli bond rotate */ - fprintf(stderr, "zerotier-cli bond rotate\n"); requestHeaders["Content-Type"] = "application/json"; requestHeaders["Content-Length"] = "2"; unsigned int scode = Http::POST( @@ -588,7 +614,7 @@ static int cli(int argc,char **argv) if (json) { printf("%s",cliFixJsonCRs(responseBody).c_str()); } else { - printf("200 bond OK" ZT_EOL_S); + printf("200 rotate OK" ZT_EOL_S); } return 0; } else { diff --git a/service/OneService.cpp b/service/OneService.cpp index a96fbc030..b5e5c1924 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -644,6 +644,7 @@ static void _peerToJson(nlohmann::json &pj,const ZT_Peer *peer, SharedPtr j["latencyVariance"] = peer->paths[i].latencyVariance; j["packetLossRatio"] = peer->paths[i].packetLossRatio; j["packetErrorRatio"] = peer->paths[i].packetErrorRatio; + j["assignedFlowCount"] = peer->paths[i].assignedFlowCount; j["lastInAge"] = (now - lastReceive); j["lastOutAge"] = (now - lastSend); j["bonded"] = peer->paths[i].bonded; @@ -1659,11 +1660,8 @@ public: res.status = 400; return; } - auto bondID = req.matches[1]; uint64_t id = Utils::hexStrToU64(bondID.str().c_str()); - - exit(0); SharedPtr bond = _node->bondController()->getBondByPeerId(id); if (bond) { if (bond->abForciblyRotateLink()) { @@ -1680,6 +1678,19 @@ public: _controlPlane.Post("/bond/rotate/([0-9a-fA-F]{10})", bondRotate); _controlPlane.Put("/bond/rotate/([0-9a-fA-F]{10})", bondRotate); + auto setMtu = [&, setContent](const httplib::Request &req, httplib::Response &res) { + if (!_node->bondController()->inUse()) { + setContent(req, res, ""); + res.status = 400; + return; + } + uint16_t mtu = atoi(req.matches[1].str().c_str()); + res.status = _node->bondController()->setAllMtuByTuple(mtu, req.matches[2].str().c_str(), req.matches[3].str().c_str()) ? 200 : 400; + setContent(req, res, "{}"); + }; + _controlPlane.Post("/bond/setmtu/([0-9]{3,5})/([a-zA-Z0-9_]{1,16})/([0-9a-fA-F\\.\\:]{1,39})", setMtu); + _controlPlane.Put("/bond/setmtu/([0-9]{3,5})/([a-zA-Z0-9_]{1,16})/([0-9a-fA-F\\.\\:]{1,39})", setMtu); + _controlPlane.Get("/config", [&, setContent](const httplib::Request &req, httplib::Response &res) { std::string config; { From 0806b881eab9425275275f60b14ba2f23ec04c85 Mon Sep 17 00:00:00 2001 From: Brenton Bostick Date: Tue, 14 Mar 2023 14:52:59 -0400 Subject: [PATCH 3/6] Basic cleanups --- java/src/com/zerotier/sdk/Event.java | 10 +++++----- java/src/com/zerotier/sdk/Node.java | 2 +- java/src/com/zerotier/sdk/NodeStatus.java | 2 +- java/src/com/zerotier/sdk/PathChecker.java | 8 ++++---- java/src/com/zerotier/sdk/Peer.java | 2 +- java/src/com/zerotier/sdk/PeerPhysicalPath.java | 2 +- java/src/com/zerotier/sdk/PeerRole.java | 2 +- java/src/com/zerotier/sdk/VirtualNetworkConfig.java | 6 +++--- .../com/zerotier/sdk/VirtualNetworkConfigListener.java | 4 ++-- .../zerotier/sdk/VirtualNetworkConfigOperation.java | 2 +- java/src/com/zerotier/sdk/VirtualNetworkDNS.java | 3 ++- java/src/com/zerotier/sdk/VirtualNetworkRoute.java | 3 ++- java/src/com/zerotier/sdk/VirtualNetworkStatus.java | 2 +- java/src/com/zerotier/sdk/VirtualNetworkType.java | 2 +- 14 files changed, 26 insertions(+), 24 deletions(-) diff --git a/java/src/com/zerotier/sdk/Event.java b/java/src/com/zerotier/sdk/Event.java index fbc016c66..c55da2cc0 100644 --- a/java/src/com/zerotier/sdk/Event.java +++ b/java/src/com/zerotier/sdk/Event.java @@ -29,14 +29,14 @@ package com.zerotier.sdk; /** * Status codes sent to status update callback when things happen - * + *

* Defined in ZeroTierOne.h as ZT_Event */ public enum Event { /** * Node has been initialized - * + *

* This is the first event generated, and is always sent. It may occur * before Node's constructor returns. */ @@ -49,7 +49,7 @@ public enum Event { /** * Node is online -- at least one upstream node appears reachable - * + *

* Meta-data: none */ EVENT_ONLINE(2), @@ -104,7 +104,7 @@ public enum Event { /** * VERB_USER_MESSAGE received - * + *

* These are generated when a VERB_USER_MESSAGE packet is received via * ZeroTier VL1. */ @@ -112,7 +112,7 @@ public enum Event { /** * Remote trace received - * + *

* These are generated when a VERB_REMOTE_TRACE is received. Note * that any node can fling one of these at us. It is your responsibility * to filter and determine if it's worth paying attention to. If it's diff --git a/java/src/com/zerotier/sdk/Node.java b/java/src/com/zerotier/sdk/Node.java index a3f3ab470..7ba269e60 100644 --- a/java/src/com/zerotier/sdk/Node.java +++ b/java/src/com/zerotier/sdk/Node.java @@ -299,7 +299,7 @@ public class Node { /** * Add or update a moon - * + *

* Moons are persisted in the data store in moons.d/, so this can persist * across invocations if the contents of moon.d are scanned and orbit is * called for each on startup. diff --git a/java/src/com/zerotier/sdk/NodeStatus.java b/java/src/com/zerotier/sdk/NodeStatus.java index 1172650b1..04c3ee60c 100644 --- a/java/src/com/zerotier/sdk/NodeStatus.java +++ b/java/src/com/zerotier/sdk/NodeStatus.java @@ -31,7 +31,7 @@ import com.zerotier.sdk.util.StringUtils; /** * Current node status - * + *

* Defined in ZeroTierOne.h as ZT_NodeStatus */ public class NodeStatus { diff --git a/java/src/com/zerotier/sdk/PathChecker.java b/java/src/com/zerotier/sdk/PathChecker.java index cfc97d60e..66a297dc4 100644 --- a/java/src/com/zerotier/sdk/PathChecker.java +++ b/java/src/com/zerotier/sdk/PathChecker.java @@ -11,9 +11,9 @@ public interface PathChecker { /** * Callback to check whether a path should be used for ZeroTier traffic - * + *

* This function must return true if the path should be used. - * + *

* If no path check function is specified, ZeroTier will still exclude paths * that overlap with ZeroTier-assigned and managed IP address blocks. But the * use of a path check function is recommended to ensure that recursion does @@ -22,7 +22,7 @@ public interface PathChecker { * all configured ZeroTier interfaces and check to ensure that the supplied * addresses will not result in ZeroTier traffic being sent over a ZeroTier * interface (recursion). - * + *

* Obviously this is not required in configurations where this can't happen, * such as network containers or embedded. * @@ -35,7 +35,7 @@ public interface PathChecker { /** * Function to get physical addresses for ZeroTier peers - * + *

* If provided this function will be occasionally called to get physical * addresses that might be tried to reach a ZeroTier address. * diff --git a/java/src/com/zerotier/sdk/Peer.java b/java/src/com/zerotier/sdk/Peer.java index e3d544381..de7d64e56 100644 --- a/java/src/com/zerotier/sdk/Peer.java +++ b/java/src/com/zerotier/sdk/Peer.java @@ -33,7 +33,7 @@ import java.util.Arrays; /** * Peer status result buffer - * + *

* Defined in ZeroTierOne.h as ZT_Peer */ public class Peer { diff --git a/java/src/com/zerotier/sdk/PeerPhysicalPath.java b/java/src/com/zerotier/sdk/PeerPhysicalPath.java index f6d326425..849725b50 100644 --- a/java/src/com/zerotier/sdk/PeerPhysicalPath.java +++ b/java/src/com/zerotier/sdk/PeerPhysicalPath.java @@ -31,7 +31,7 @@ import java.net.InetSocketAddress; /** * Physical network path to a peer - * + *

* Defined in ZeroTierOne.h as ZT_PeerPhysicalPath */ public class PeerPhysicalPath { diff --git a/java/src/com/zerotier/sdk/PeerRole.java b/java/src/com/zerotier/sdk/PeerRole.java index d69a1f1bb..e05ba4a3b 100644 --- a/java/src/com/zerotier/sdk/PeerRole.java +++ b/java/src/com/zerotier/sdk/PeerRole.java @@ -29,7 +29,7 @@ package com.zerotier.sdk; /** * What trust hierarchy role does this peer have? - * + *

* Defined in ZeroTierOne.h as ZT_PeerRole */ public enum PeerRole { diff --git a/java/src/com/zerotier/sdk/VirtualNetworkConfig.java b/java/src/com/zerotier/sdk/VirtualNetworkConfig.java index bcf64854a..6245436a7 100644 --- a/java/src/com/zerotier/sdk/VirtualNetworkConfig.java +++ b/java/src/com/zerotier/sdk/VirtualNetworkConfig.java @@ -38,7 +38,7 @@ import java.util.Collections; /** * Virtual network configuration - * + *

* Defined in ZeroTierOne.h as ZT_VirtualNetworkConfig */ public class VirtualNetworkConfig implements Comparable { @@ -374,11 +374,11 @@ public class VirtualNetworkConfig implements Comparable { /** * ZeroTier-assigned addresses (in {@link InetSocketAddress} objects) - * + *

* For IP, the port number of the sockaddr_XX structure contains the number * of bits in the address netmask. Only the IP address and port are used. * Other fields like interface number can be ignored. - * + *

* This is only used for ZeroTier-managed address assignments sent by the * virtual network's configuration master. */ diff --git a/java/src/com/zerotier/sdk/VirtualNetworkConfigListener.java b/java/src/com/zerotier/sdk/VirtualNetworkConfigListener.java index ce91e79d9..7c140bd77 100644 --- a/java/src/com/zerotier/sdk/VirtualNetworkConfigListener.java +++ b/java/src/com/zerotier/sdk/VirtualNetworkConfigListener.java @@ -36,14 +36,14 @@ public interface VirtualNetworkConfigListener { *

This can be called at any time to update the configuration of a virtual * network port. The parameter after the network ID specifies whether this * port is being brought up, updated, brought down, or permanently deleted. - * + *

* This in turn should be used by the underlying implementation to create * and configure tap devices at the OS (or virtual network stack) layer.

* * This should not call {@link Node#multicastSubscribe(long, long)} or other network-modifying * methods, as this could cause a deadlock in multithreaded or interrupt * driven environments. - * + *

* This must return 0 on success. It can return any OS-dependent error code * on failure, and this results in the network being placed into the * PORT_ERROR state. diff --git a/java/src/com/zerotier/sdk/VirtualNetworkConfigOperation.java b/java/src/com/zerotier/sdk/VirtualNetworkConfigOperation.java index a1981bd15..59837a6be 100644 --- a/java/src/com/zerotier/sdk/VirtualNetworkConfigOperation.java +++ b/java/src/com/zerotier/sdk/VirtualNetworkConfigOperation.java @@ -29,7 +29,7 @@ package com.zerotier.sdk; /** * Virtual network configuration update type - * + *

* Defined in ZeroTierOne.h as ZT_VirtualNetworkConfigOperation */ public enum VirtualNetworkConfigOperation { diff --git a/java/src/com/zerotier/sdk/VirtualNetworkDNS.java b/java/src/com/zerotier/sdk/VirtualNetworkDNS.java index 6e4bb3d22..48d24046d 100644 --- a/java/src/com/zerotier/sdk/VirtualNetworkDNS.java +++ b/java/src/com/zerotier/sdk/VirtualNetworkDNS.java @@ -10,7 +10,7 @@ import java.util.ArrayList; /** * DNS configuration to be pushed on a virtual network - * + *

* Defined in ZeroTierOne.h as ZT_VirtualNetworkDNS */ public class VirtualNetworkDNS implements Comparable { @@ -45,6 +45,7 @@ public class VirtualNetworkDNS implements Comparable { return false; } + //noinspection RedundantIfStatement if (!servers.equals(d.servers)) { return false; } diff --git a/java/src/com/zerotier/sdk/VirtualNetworkRoute.java b/java/src/com/zerotier/sdk/VirtualNetworkRoute.java index afd9ee45a..ec569813b 100644 --- a/java/src/com/zerotier/sdk/VirtualNetworkRoute.java +++ b/java/src/com/zerotier/sdk/VirtualNetworkRoute.java @@ -31,7 +31,7 @@ import java.net.InetSocketAddress; /** * A route to be pushed on a virtual network - * + *

* Defined in ZeroTierOne.h as ZT_VirtualNetworkRoute */ public class VirtualNetworkRoute implements Comparable @@ -126,6 +126,7 @@ public class VirtualNetworkRoute implements Comparable return false; } + //noinspection RedundantIfStatement if (metric != other.metric) { return false; } diff --git a/java/src/com/zerotier/sdk/VirtualNetworkStatus.java b/java/src/com/zerotier/sdk/VirtualNetworkStatus.java index 8a32ba6ad..9539bdcc6 100644 --- a/java/src/com/zerotier/sdk/VirtualNetworkStatus.java +++ b/java/src/com/zerotier/sdk/VirtualNetworkStatus.java @@ -29,7 +29,7 @@ package com.zerotier.sdk; /** * Virtual network status codes - * + *

* Defined in ZeroTierOne.h as ZT_VirtualNetworkStatus */ public enum VirtualNetworkStatus { diff --git a/java/src/com/zerotier/sdk/VirtualNetworkType.java b/java/src/com/zerotier/sdk/VirtualNetworkType.java index 44be8864b..5c1239c02 100644 --- a/java/src/com/zerotier/sdk/VirtualNetworkType.java +++ b/java/src/com/zerotier/sdk/VirtualNetworkType.java @@ -29,7 +29,7 @@ package com.zerotier.sdk; /** * Virtual network type codes - * + *

* Defined in ZeroTierOne.h as ZT_VirtualNetworkType */ public enum VirtualNetworkType { From d4e63fcdfeedc39c6a9cb6063889184f81b30953 Mon Sep 17 00:00:00 2001 From: Brenton Bostick Date: Tue, 15 Aug 2023 10:44:08 -0400 Subject: [PATCH 4/6] Check if null is passed to VirtualNetworkConfig.equals and name fixes --- .../zerotier/sdk/VirtualNetworkConfig.java | 112 ++++++++++-------- 1 file changed, 61 insertions(+), 51 deletions(-) diff --git a/java/src/com/zerotier/sdk/VirtualNetworkConfig.java b/java/src/com/zerotier/sdk/VirtualNetworkConfig.java index 6245436a7..275266823 100644 --- a/java/src/com/zerotier/sdk/VirtualNetworkConfig.java +++ b/java/src/com/zerotier/sdk/VirtualNetworkConfig.java @@ -107,100 +107,108 @@ public class VirtualNetworkConfig implements Comparable { @Override public boolean equals(Object o) { + if (o == null) { + Log.i(TAG, "Old is null"); + + return false; + } + if (!(o instanceof VirtualNetworkConfig)) { - return false; - } - - VirtualNetworkConfig cfg = (VirtualNetworkConfig) o; - - if (this.nwid != cfg.nwid) { - Log.i(TAG, "NetworkID Changed. Old: " + StringUtils.networkIdToString(this.nwid) + " (" + this.nwid + "), " + - "New: " + StringUtils.networkIdToString(cfg.nwid) + " (" + cfg.nwid + ")"); + Log.i(TAG, "Old is not an instance of VirtualNetworkConfig: " + o); return false; } - if (this.mac != cfg.mac) { - Log.i(TAG, "MAC Changed. Old: " + StringUtils.macAddressToString(this.mac) + ", New: " + StringUtils.macAddressToString(cfg.mac)); + VirtualNetworkConfig old = (VirtualNetworkConfig) o; + + if (this.nwid != old.nwid) { + Log.i(TAG, "NetworkID Changed. New: " + StringUtils.networkIdToString(this.nwid) + " (" + this.nwid + "), " + + "Old: " + StringUtils.networkIdToString(old.nwid) + " (" + old.nwid + ")"); return false; } - if (!this.name.equals(cfg.name)) { - Log.i(TAG, "Name Changed. Old: " + this.name + ", New: " + cfg.name); + if (this.mac != old.mac) { + Log.i(TAG, "MAC Changed. New: " + StringUtils.macAddressToString(this.mac) + ", Old: " + StringUtils.macAddressToString(old.mac)); return false; } - if (this.status != cfg.status) { - Log.i(TAG, "Status Changed. Old: " + this.status + ", New: " + cfg.status); + if (!this.name.equals(old.name)) { + Log.i(TAG, "Name Changed. New: " + this.name + ", Old: " + old.name); return false; } - if (this.type != cfg.type) { - Log.i(TAG, "Type changed. Old " + this.type + ", New: " + cfg.type); + if (this.status != old.status) { + Log.i(TAG, "Status Changed. New: " + this.status + ", Old: " + old.status); return false; } - if (this.mtu != cfg.mtu) { - Log.i(TAG, "MTU Changed. Old: " + this.mtu + ", New: " + cfg.mtu); + if (this.type != old.type) { + Log.i(TAG, "Type changed. New: " + this.type + ", Old: " + old.type); return false; } - if (this.dhcp != cfg.dhcp) { - Log.i(TAG, "DHCP Flag Changed. Old: " + this.dhcp + ", New: " + cfg.dhcp); + if (this.mtu != old.mtu) { + Log.i(TAG, "MTU Changed. New: " + this.mtu + ", Old: " + old.mtu); return false; } - if (this.bridge != cfg.bridge) { - Log.i(TAG, "Bridge Flag Changed. Old: " + this.bridge + ", New: " + cfg.bridge); + if (this.dhcp != old.dhcp) { + Log.i(TAG, "DHCP Flag Changed. New: " + this.dhcp + ", Old: " + old.dhcp); return false; } - if (this.broadcastEnabled != cfg.broadcastEnabled) { - Log.i(TAG, "Broadcast Flag Changed. Old: "+ this.broadcastEnabled + ", New: " + cfg.broadcastEnabled); + if (this.bridge != old.bridge) { + Log.i(TAG, "Bridge Flag Changed. New: " + this.bridge + ", Old: " + old.bridge); return false; } - if (this.portError != cfg.portError) { - Log.i(TAG, "Port Error Changed. Old: " + this.portError + ", New: " + cfg.portError); + if (this.broadcastEnabled != old.broadcastEnabled) { + Log.i(TAG, "Broadcast Flag Changed. New: "+ this.broadcastEnabled + ", Old: " + old.broadcastEnabled); return false; } - if (this.netconfRevision != cfg.netconfRevision) { - Log.i(TAG, "NetConfRevision Changed. Old: " + this.netconfRevision + ", New: " + cfg.netconfRevision); + if (this.portError != old.portError) { + Log.i(TAG, "Port Error Changed. New: " + this.portError + ", Old: " + old.portError); return false; } - if (!Arrays.equals(assignedAddresses, cfg.assignedAddresses)) { + if (this.netconfRevision != old.netconfRevision) { + Log.i(TAG, "NetConfRevision Changed. New: " + this.netconfRevision + ", Old: " + old.netconfRevision); + + return false; + } + + if (!Arrays.equals(assignedAddresses, old.assignedAddresses)) { - ArrayList aaCurrent = new ArrayList<>(); ArrayList aaNew = new ArrayList<>(); + ArrayList aaOld = new ArrayList<>(); for (InetSocketAddress s : assignedAddresses) { - aaCurrent.add(s.toString()); - } - for (InetSocketAddress s : cfg.assignedAddresses) { aaNew.add(s.toString()); } - Collections.sort(aaCurrent); + for (InetSocketAddress s : old.assignedAddresses) { + aaOld.add(s.toString()); + } Collections.sort(aaNew); + Collections.sort(aaOld); Log.i(TAG, "Assigned Addresses Changed"); - Log.i(TAG, "Old:"); - for (String s : aaCurrent) { + Log.i(TAG, "New:"); + for (String s : aaNew) { Log.i(TAG, " " + s); } Log.i(TAG, ""); - Log.i(TAG, "New:"); - for (String s : aaNew) { + Log.i(TAG, "Old:"); + for (String s : aaOld) { Log.i(TAG, " " +s); } Log.i(TAG, ""); @@ -208,27 +216,27 @@ public class VirtualNetworkConfig implements Comparable { return false; } - if (!Arrays.equals(routes, cfg.routes)) { + if (!Arrays.equals(routes, old.routes)) { - ArrayList rCurrent = new ArrayList<>(); ArrayList rNew = new ArrayList<>(); + ArrayList rOld = new ArrayList<>(); for (VirtualNetworkRoute r : routes) { - rCurrent.add(r.toString()); - } - for (VirtualNetworkRoute r : cfg.routes) { rNew.add(r.toString()); } - Collections.sort(rCurrent); + for (VirtualNetworkRoute r : old.routes) { + rOld.add(r.toString()); + } Collections.sort(rNew); + Collections.sort(rOld); Log.i(TAG, "Managed Routes Changed"); - Log.i(TAG, "Old:"); - for (String s : rCurrent) { + Log.i(TAG, "New:"); + for (String s : rNew) { Log.i(TAG, " " + s); } Log.i(TAG, ""); - Log.i(TAG, "New:"); - for (String s : rNew) { + Log.i(TAG, "Old:"); + for (String s : rOld) { Log.i(TAG, " " + s); } Log.i(TAG, ""); @@ -239,20 +247,22 @@ public class VirtualNetworkConfig implements Comparable { boolean dnsEquals; if (this.dns == null) { //noinspection RedundantIfStatement - if (cfg.dns == null) { + if (old.dns == null) { dnsEquals = true; } else { dnsEquals = false; } } else { - if (cfg.dns == null) { + if (old.dns == null) { dnsEquals = false; } else { - dnsEquals = this.dns.equals(cfg.dns); + dnsEquals = this.dns.equals(old.dns); } } if (!dnsEquals) { + Log.i(TAG, "DNS Changed. New: " + this.dns + ", Old: " + old.dns); + return false; } From 826a1ee346975f8c3844b7864ee10842027560f5 Mon Sep 17 00:00:00 2001 From: Brenton Bostick Date: Tue, 15 Aug 2023 10:42:05 -0400 Subject: [PATCH 5/6] ANDROID-96: Simplify and use return code from node_init directly --- java/src/com/zerotier/sdk/Node.java | 8 ++--- java/src/com/zerotier/sdk/NodeException.java | 37 -------------------- 2 files changed, 2 insertions(+), 43 deletions(-) delete mode 100644 java/src/com/zerotier/sdk/NodeException.java diff --git a/java/src/com/zerotier/sdk/Node.java b/java/src/com/zerotier/sdk/Node.java index 7ba269e60..280b5cd50 100644 --- a/java/src/com/zerotier/sdk/Node.java +++ b/java/src/com/zerotier/sdk/Node.java @@ -75,8 +75,8 @@ public class Node { EventListener eventListener, VirtualNetworkFrameListener frameListener, VirtualNetworkConfigListener configListener, - PathChecker pathChecker) throws NodeException { - ResultCode rc = node_init( + PathChecker pathChecker) { + return node_init( nodeId, getListener, putListener, @@ -85,10 +85,6 @@ public class Node { frameListener, configListener, pathChecker); - if(rc != ResultCode.RESULT_OK) { - throw new NodeException(rc.toString()); - } - return rc; } public boolean isInited() { diff --git a/java/src/com/zerotier/sdk/NodeException.java b/java/src/com/zerotier/sdk/NodeException.java deleted file mode 100644 index beeb06063..000000000 --- a/java/src/com/zerotier/sdk/NodeException.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2015 ZeroTier, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * ZeroTier may be used and distributed under the terms of the GPLv3, which - * are available at: http://www.gnu.org/licenses/gpl-3.0.html - * - * If you would like to embed ZeroTier into a commercial application or - * redistribute it in a modified binary form, please contact ZeroTier Networks - * LLC. Start here: http://www.zerotier.com/ - */ - -package com.zerotier.sdk; - -public class NodeException extends Exception { - - private static final long serialVersionUID = 6268040509883125819L; - - public NodeException(String message) { - super(message); - } -} From 1817c98b5ce1ee90a437a14f24ea1fa6386f8d0e Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 16 Aug 2023 13:13:31 -0400 Subject: [PATCH 6/6] Mac version bump. --- ext/installfiles/mac/ZeroTier One.pkgproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/installfiles/mac/ZeroTier One.pkgproj b/ext/installfiles/mac/ZeroTier One.pkgproj index bbdb3d0b3..efae3e02b 100755 --- a/ext/installfiles/mac/ZeroTier One.pkgproj +++ b/ext/installfiles/mac/ZeroTier One.pkgproj @@ -701,7 +701,7 @@ USE_HFS+_COMPRESSION VERSION - 1.10.6 + 1.12.0 TYPE 0