From 62f23e0cfd5b97dbaeccdd892a1babed7d7942c4 Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Fri, 11 Sep 2020 15:31:56 -0700 Subject: [PATCH 1/6] step 1 of `zerotier-cli dump` dump status, networks, peers, bonds & version --- one.cpp | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/one.cpp b/one.cpp index 91d3e471a..4b05ef58d 100644 --- a/one.cpp +++ b/one.cpp @@ -858,6 +858,58 @@ static int cli(int argc,char **argv) printf("%u %s %s" ZT_EOL_S,scode,command.c_str(),responseBody.c_str()); return 1; } + } else if (command == "dump") { + std::stringstream dump; + + dump << "zerotier version: " << ZEROTIER_ONE_VERSION_MAJOR << "." + << ZEROTIER_ONE_VERSION_MINOR << "." << ZEROTIER_ONE_VERSION_REVISION << ZT_EOL_S << ZT_EOL_S; + + // grab status + dump << "status" << ZT_EOL_S << "------" << ZT_EOL_S; + unsigned int scode = Http::GET(1024 * 1024 * 16,60000,(const struct sockaddr *)&addr,"/status",requestHeaders,responseHeaders,responseBody); + if (scode != 200) { + printf("Error connecting to the ZeroTier service: %s\n\nPlease check that the service is running and that TCP port 9993 can be contacted via 127.0.0.1." ZT_EOL_S, responseBody.c_str()); + return 1; + } + dump << responseBody << ZT_EOL_S; + + responseHeaders.clear(); + responseBody = ""; + + // grab network list + dump << ZT_EOL_S << "networks" << ZT_EOL_S << "--------" << ZT_EOL_S; + scode = Http::GET(1024 * 1024 * 16,60000,(const struct sockaddr *)&addr,"/network",requestHeaders,responseHeaders,responseBody); + if (scode != 200) { + printf("Error connecting to the ZeroTier service: %s\n\nPlease check that the service is running and that TCP port 9993 can be contacted via 127.0.0.1." ZT_EOL_S, responseBody.c_str()); + return 1; + } + dump << responseBody << ZT_EOL_S; + + responseHeaders.clear(); + responseBody = ""; + + // list peers + dump << ZT_EOL_S << "peers" << ZT_EOL_S << "-----" << ZT_EOL_S; + scode = Http::GET(1024 * 1024 * 16,60000,(const struct sockaddr *)&addr,"/peer",requestHeaders,responseHeaders,responseBody); + if (scode != 200) { + printf("Error connecting to the ZeroTier service: %s\n\nPlease check that the service is running and that TCP port 9993 can be contacted via 127.0.0.1." ZT_EOL_S, responseBody.c_str()); + return 1; + } + dump << responseBody << ZT_EOL_S; + + // get bonds + dump << ZT_EOL_S << "bonds" << ZT_EOL_S << "-----" << ZT_EOL_S; + scode = Http::GET(1024 * 1024 * 16,60000,(const struct sockaddr *)&addr,"/bonds",requestHeaders,responseHeaders,responseBody); + if (scode != 200) { + printf("Error connecting to the ZeroTier service: %s\n\nPlease check that the service is running and that TCP port 9993 can be contacted via 127.0.0.1." ZT_EOL_S, responseBody.c_str()); + return 1; + } + dump << responseBody << ZT_EOL_S; + + responseHeaders.clear(); + responseBody = ""; + + fprintf(stderr, "%s", dump.str().c_str()); } else { cliPrintHelp(argv[0],stderr); return 0; From 36d867c3faf6604b027a9c35e69c2352c81beb0c Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Fri, 11 Sep 2020 16:43:30 -0700 Subject: [PATCH 2/6] more config dump for macOS --- one.cpp | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 69 insertions(+), 3 deletions(-) diff --git a/one.cpp b/one.cpp index 4b05ef58d..6ce37f9a1 100644 --- a/one.cpp +++ b/one.cpp @@ -78,6 +78,13 @@ #include "ext/json/json.hpp" +#ifdef __APPLE__ +#include +#include +#include +#include +#endif + #define ZT_PID_PATH "zerotier-one.pid" using namespace ZeroTier; @@ -860,10 +867,17 @@ static int cli(int argc,char **argv) } } else if (command == "dump") { std::stringstream dump; - + dump << "platform: "; +#ifdef __APPLE__ + dump << "macOS" << ZT_EOL_S; +#elif defined(_WIN32) + dump << "Windows" << ZT_EOL_S; +#else + dump << "other unix based OS" << ZT_EOL_S; +#endif dump << "zerotier version: " << ZEROTIER_ONE_VERSION_MAJOR << "." << ZEROTIER_ONE_VERSION_MINOR << "." << ZEROTIER_ONE_VERSION_REVISION << ZT_EOL_S << ZT_EOL_S; - + // grab status dump << "status" << ZT_EOL_S << "------" << ZT_EOL_S; unsigned int scode = Http::GET(1024 * 1024 * 16,60000,(const struct sockaddr *)&addr,"/status",requestHeaders,responseHeaders,responseBody); @@ -909,7 +923,59 @@ static int cli(int argc,char **argv) responseHeaders.clear(); responseBody = ""; - fprintf(stderr, "%s", dump.str().c_str()); + dump << ZT_EOL_S << "local.conf" << ZT_EOL_S << "----------" << ZT_EOL_S; + // TODO: Dump local.conf + dump << "TODO" << ZT_EOL_S; + + dump << ZT_EOL_S << "Network Interfaces" << ZT_EOL_S << "------------------" << ZT_EOL_S << ZT_EOL_S; +#ifdef __APPLE__ + CFArrayRef interfaces = SCNetworkInterfaceCopyAll(); + CFIndex size = CFArrayGetCount(interfaces); + for(CFIndex i = 0; i < size; ++i) { + SCNetworkInterfaceRef iface = (SCNetworkInterfaceRef)CFArrayGetValueAtIndex(interfaces, i); + + dump << "Interface " << i << ZT_EOL_S << "-----------" << ZT_EOL_S; + CFStringRef tmp = SCNetworkInterfaceGetBSDName(iface); + char stringBuffer[512] = {}; + CFStringGetCString(tmp,stringBuffer, sizeof(stringBuffer), kCFStringEncodingUTF8); + dump << "Name: " << stringBuffer << ZT_EOL_S; + std::string ifName(stringBuffer); + int mtuCur, mtuMin, mtuMax; + SCNetworkInterfaceCopyMTU(iface, &mtuCur, &mtuMin, &mtuMax); + dump << "MTU: " << mtuCur << ZT_EOL_S; + tmp = SCNetworkInterfaceGetHardwareAddressString(iface); + CFStringGetCString(tmp, stringBuffer, sizeof(stringBuffer), kCFStringEncodingUTF8); + dump << "MAC: " << stringBuffer << ZT_EOL_S; + tmp = SCNetworkInterfaceGetInterfaceType(iface); + CFStringGetCString(tmp, stringBuffer, sizeof(stringBuffer), kCFStringEncodingUTF8); + dump << "Type: " << stringBuffer << ZT_EOL_S; + dump << "Addresses:" << ZT_EOL_S; + + struct ifaddrs *ifap, *ifa; + void *addr; + getifaddrs(&ifap); + for (ifa = ifap; ifa; ifa = ifa->ifa_next) { + if (strcmp(ifName.c_str(), ifa->ifa_name) == 0) { + if (ifa->ifa_addr->sa_family == AF_INET) { + struct sockaddr_in *ipv4 = (struct sockaddr_in*)ifa->ifa_addr; + addr = &ipv4->sin_addr; + } else if (ifa->ifa_addr->sa_family == AF_INET6) { + struct sockaddr_in6 *ipv6 = (struct sockaddr_in6*)ifa->ifa_addr; + addr = &ipv6->sin6_addr; + } else { + continue; + } + inet_ntop(ifa->ifa_addr->sa_family, addr, stringBuffer, sizeof(stringBuffer)); + dump << stringBuffer << ZT_EOL_S; + } + } + + dump << ZT_EOL_S; + } +#endif + + fprintf(stderr, "%s", dump.str().c_str()); + } else { cliPrintHelp(argv[0],stderr); return 0; From 059dfee0c325c375d5748618d8e2bc5ad6b0ce8a Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Mon, 14 Sep 2020 12:42:39 -0700 Subject: [PATCH 3/6] fix windows compilation --- node/Utils.cpp | 1 + windows/ZeroTierOne/ZeroTierOne.vcxproj | 1 + windows/ZeroTierOne/ZeroTierOne.vcxproj.filters | 3 +++ 3 files changed, 5 insertions(+) diff --git a/node/Utils.cpp b/node/Utils.cpp index 7e3617c95..87a37b004 100644 --- a/node/Utils.cpp +++ b/node/Utils.cpp @@ -32,6 +32,7 @@ #ifdef __WINDOWS__ #include +#include #endif #include "Utils.hpp" diff --git a/windows/ZeroTierOne/ZeroTierOne.vcxproj b/windows/ZeroTierOne/ZeroTierOne.vcxproj index 69036aa0a..75dcad6ce 100644 --- a/windows/ZeroTierOne/ZeroTierOne.vcxproj +++ b/windows/ZeroTierOne/ZeroTierOne.vcxproj @@ -50,6 +50,7 @@ + diff --git a/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters b/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters index 6abe49c0d..f474c19b5 100644 --- a/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters +++ b/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters @@ -282,6 +282,9 @@ Source Files\osdep + + Source Files\node + From ace03d7c7bfeb5b00ef10ec5fdfc16f9bf3f04b6 Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Mon, 14 Sep 2020 15:17:59 -0700 Subject: [PATCH 4/6] zerotier-cli dump for Windows --- one.cpp | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 75 insertions(+), 3 deletions(-) diff --git a/one.cpp b/one.cpp index 6ce37f9a1..f582f94f9 100644 --- a/one.cpp +++ b/one.cpp @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include "osdep/WindowsEthernetTap.hpp" #include "windows/ZeroTierOne/ServiceInstaller.h" #include "windows/ZeroTierOne/ServiceBase.h" @@ -924,8 +926,14 @@ static int cli(int argc,char **argv) responseBody = ""; dump << ZT_EOL_S << "local.conf" << ZT_EOL_S << "----------" << ZT_EOL_S; - // TODO: Dump local.conf - dump << "TODO" << ZT_EOL_S; + std::string localConf; + OSUtils::readFile((homeDir + ZT_PATH_SEPARATOR_S + "local.conf").c_str(), localConf); + if (localConf.empty()) { + dump << "None Present" << ZT_EOL_S; + } + else { + dump << localConf << ZT_EOL_S; + } dump << ZT_EOL_S << "Network Interfaces" << ZT_EOL_S << "------------------" << ZT_EOL_S << ZT_EOL_S; #ifdef __APPLE__ @@ -972,9 +980,73 @@ static int cli(int argc,char **argv) dump << ZT_EOL_S; } +#elif defined(_WIN32) + ULONG buffLen = 16384; + PIP_ADAPTER_ADDRESSES addresses; + + ULONG ret = 0; + do { + addresses = (PIP_ADAPTER_ADDRESSES)malloc(buffLen); + + ret = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, addresses, &buffLen); + if (ret == ERROR_BUFFER_OVERFLOW) { + free(addresses); + addresses = NULL; + } + else { + break; + } + } while (ret == ERROR_BUFFER_OVERFLOW); + + int i = 0; + if (ret == NO_ERROR) { + PIP_ADAPTER_ADDRESSES curAddr = addresses; + while (curAddr) { + dump << "Interface " << i << ZT_EOL_S << "-----------" << ZT_EOL_S; + dump << "Name: " << curAddr->AdapterName << ZT_EOL_S; + dump << "MTU: " << curAddr->Mtu << ZT_EOL_S; + dump << "MAC: "; + char macBuffer[64] = {}; + sprintf(macBuffer, "%02x:%02x:%02x:%02x:%02x:%02x", + curAddr->PhysicalAddress[0], + curAddr->PhysicalAddress[1], + curAddr->PhysicalAddress[2], + curAddr->PhysicalAddress[3], + curAddr->PhysicalAddress[4], + curAddr->PhysicalAddress[5]); + dump << macBuffer << ZT_EOL_S; + dump << "Type: " << curAddr->IfType << ZT_EOL_S; + dump << "Addresses:" << ZT_EOL_S; + PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL; + pUnicast = curAddr->FirstUnicastAddress; + if (pUnicast) { + for (int j = 0; pUnicast != NULL; ++j) { + char buf[128] = {}; + DWORD bufLen = 128; + LPSOCKADDR a = pUnicast->Address.lpSockaddr; + WSAAddressToStringA( + pUnicast->Address.lpSockaddr, + pUnicast->Address.iSockaddrLength, + NULL, + buf, + &bufLen + ); + dump << buf << ZT_EOL_S; + pUnicast = pUnicast->Next; + } + } + + curAddr = curAddr->Next; + ++i; + } + } + if (addresses) { + free(addresses); + addresses = NULL; + } #endif - fprintf(stderr, "%s", dump.str().c_str()); + fprintf(stderr, "%s\n", dump.str().c_str()); } else { cliPrintHelp(argv[0],stderr); From f3c9ab8a7e907fa8d824bd65d24661782cca458d Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Fri, 11 Sep 2020 14:47:18 -0700 Subject: [PATCH 5/6] Add minor trace output formatting changes. Change ZT_MULTIPATH_BOND_STATUS_INTERVAL from 30000 to 60000 --- node/Bond.cpp | 11 ++++++----- node/Constants.hpp | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/node/Bond.cpp b/node/Bond.cpp index 3f65c0fe4..aa8a5a426 100644 --- a/node/Bond.cpp +++ b/node/Bond.cpp @@ -362,7 +362,8 @@ bool Bond::assignFlowToBondedPath(SharedPtr &flow, int64_t now) if (_bondingPolicy == ZT_BONDING_POLICY_BALANCE_XOR) { idx = abs((int)(flow->id() % (_numBondedPaths))); SharedPtr link = RR->bc->getLinkBySocket(_policyAlias, _paths[_bondedIdx[idx]]->localSocket()); - sprintf(traceMsg, "%s (balance-xor) Assigned outgoing flow %x to peer %llx to link %s/%s, %lu active flow(s)\n", + _paths[_bondedIdx[idx]]->address().toString(curPathStr); + sprintf(traceMsg, "%s (balance-xor) Assigned outgoing flow %x to peer %llx to link %s/%s, %lu active flow(s)", OSUtils::humanReadableTimestamp().c_str(), flow->id(), _peer->_id.address().toInt(), link->ifname().c_str(), curPathStr, _flows.size()); RR->t->bondStateMessage(NULL, traceMsg); flow->assignPath(_paths[_bondedIdx[idx]],now); @@ -417,7 +418,7 @@ bool Bond::assignFlowToBondedPath(SharedPtr &flow, int64_t now) } flow->assignedPath()->address().toString(curPathStr); SharedPtr link = RR->bc->getLinkBySocket(_policyAlias, flow->assignedPath()->localSocket()); - sprintf(traceMsg, "%s (bond) Assigned outgoing flow %x to peer %llx to link %s/%s, %lu active flow(s)\n", + sprintf(traceMsg, "%s (bond) Assigned outgoing flow %x to peer %llx to link %s/%s, %lu active flow(s)", OSUtils::humanReadableTimestamp().c_str(), flow->id(), _peer->_id.address().toInt(), link->ifname().c_str(), curPathStr, _flows.size()); RR->t->bondStateMessage(NULL, traceMsg); return true; @@ -452,7 +453,7 @@ SharedPtr Bond::createFlow(const SharedPtr &path, int32_t flowId, un path->address().toString(curPathStr); path->_assignedFlowCount++; SharedPtr link = RR->bc->getLinkBySocket(_policyAlias, flow->assignedPath()->localSocket()); - sprintf(traceMsg, "%s (bond) Assigned incoming flow %x from peer %llx to link %s/%s, %lu active flow(s)\n", + sprintf(traceMsg, "%s (bond) Assigned incoming flow %x from peer %llx to link %s/%s, %lu active flow(s)", OSUtils::humanReadableTimestamp().c_str(), flow->id(), _peer->_id.address().toInt(), link->ifname().c_str(), curPathStr, _flows.size()); RR->t->bondStateMessage(NULL, traceMsg); } @@ -475,7 +476,7 @@ void Bond::forgetFlowsWhenNecessary(uint64_t age, bool oldest, int64_t now) if (age) { // Remove by specific age while (it != _flows.end()) { if (it->second->age(now) > age) { - sprintf(traceMsg, "%s (bond) Forgetting flow %x between this node and peer %llx, %lu active flow(s)\n", + sprintf(traceMsg, "%s (bond) Forgetting flow %x between this node and peer %llx, %lu active flow(s)", OSUtils::humanReadableTimestamp().c_str(), it->first, _peer->_id.address().toInt(), (_flows.size()-1)); RR->t->bondStateMessage(NULL, traceMsg); it->second->assignedPath()->_assignedFlowCount--; @@ -495,7 +496,7 @@ void Bond::forgetFlowsWhenNecessary(uint64_t age, bool oldest, int64_t now) ++it; } if (oldestFlow != _flows.end()) { - sprintf(traceMsg, "%s (bond) Forgetting oldest flow %x (of age %llu) between this node and peer %llx, %lu active flow(s)\n", + sprintf(traceMsg, "%s (bond) Forgetting oldest flow %x (of age %llu) between this node and peer %llx, %lu active flow(s)", OSUtils::humanReadableTimestamp().c_str(), oldestFlow->first, oldestFlow->second->age(now), _peer->_id.address().toInt(), (_flows.size()-1)); RR->t->bondStateMessage(NULL, traceMsg); oldestFlow->second->assignedPath()->_assignedFlowCount--; diff --git a/node/Constants.hpp b/node/Constants.hpp index 5d6e735c4..d8c0a0d5f 100644 --- a/node/Constants.hpp +++ b/node/Constants.hpp @@ -396,7 +396,7 @@ /** * How often we emit a one-liner bond summary for each peer */ -#define ZT_MULTIPATH_BOND_STATUS_INTERVAL 30000 +#define ZT_MULTIPATH_BOND_STATUS_INTERVAL 60000 /** * How long before we consider a path to be dead in the general sense. This is From fa86b8bae0e37a39f094629fd30ff3c2b8270883 Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Fri, 11 Sep 2020 16:09:46 -0700 Subject: [PATCH 6/6] Change ZT_MULTIPATH_FLOW_EXPIRATION_INTERVAL from 30 seconds to 5 minutes --- node/Constants.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node/Constants.hpp b/node/Constants.hpp index d8c0a0d5f..562ae7be4 100644 --- a/node/Constants.hpp +++ b/node/Constants.hpp @@ -414,7 +414,7 @@ * How long before we consider a flow to be dead and remove it from the * policy's list. */ -#define ZT_MULTIPATH_FLOW_EXPIRATION_INTERVAL 30000 +#define ZT_MULTIPATH_FLOW_EXPIRATION_INTERVAL (60000 * 5) /** * How often a flow's statistical counters are reset