|
@@ -88,6 +88,9 @@
|
|
|
|
|
|
#include "service/OneService.hpp"
|
|
|
|
|
|
+#include "diagnostic/dump_sections.hpp"
|
|
|
+#include "diagnostic/dump_interfaces.hpp"
|
|
|
+
|
|
|
#include <nlohmann/json.hpp>
|
|
|
|
|
|
#ifdef __APPLE__
|
|
@@ -1110,300 +1113,44 @@ static int cli(int argc,char **argv)
|
|
|
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;
|
|
|
-
|
|
|
- // Bonds don't need to be queried separately since their data originates from "/peer" responses anyway
|
|
|
-
|
|
|
- responseHeaders.clear();
|
|
|
- responseBody = "";
|
|
|
-
|
|
|
- dump << ZT_EOL_S << "local.conf" << ZT_EOL_S << "----------" << 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__
|
|
|
- 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;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- FSRef fsref;
|
|
|
- UInt8 path[PATH_MAX];
|
|
|
- if (FSFindFolder(kUserDomain, kDesktopFolderType, kDontCreateFolder, &fsref) == noErr &&
|
|
|
- FSRefMakePath(&fsref, path, sizeof(path)) == noErr) {
|
|
|
-
|
|
|
- } else if (getenv("SUDO_USER")) {
|
|
|
- sprintf((char*)path, "/Users/%s/Desktop", getenv("SUDO_USER"));
|
|
|
- } else {
|
|
|
- fprintf(stdout, "%s", dump.str().c_str());
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
- sprintf((char*)path, "%s%szerotier_dump.txt", (char*)path, ZT_PATH_SEPARATOR_S);
|
|
|
-
|
|
|
- fprintf(stdout, "Writing dump to: %s\n", path);
|
|
|
- int fd = open((char*)path, O_CREAT|O_RDWR,0664);
|
|
|
- if (fd == -1) {
|
|
|
- fprintf(stderr, "Error creating file.\n");
|
|
|
- return 1;
|
|
|
- }
|
|
|
- write(fd, dump.str().c_str(), dump.str().size());
|
|
|
- close(fd);
|
|
|
-#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;
|
|
|
- }
|
|
|
+ try {
|
|
|
+ dumpStatus(dump, addr, requestHeaders);
|
|
|
+ } catch (const std::exception& e) {
|
|
|
+ dump << "[ERROR] status section failed: " << e.what() << ZT_EOL_S;
|
|
|
+ } catch (...) {
|
|
|
+ dump << "[ERROR] status section failed: unknown error" << ZT_EOL_S;
|
|
|
}
|
|
|
- if (addresses) {
|
|
|
- free(addresses);
|
|
|
- addresses = NULL;
|
|
|
- }
|
|
|
-
|
|
|
- char path[MAX_PATH + 1] = {};
|
|
|
- if (SHGetFolderPathA(NULL, CSIDL_DESKTOP, NULL, 0, path) == S_OK) {
|
|
|
- sprintf(path, "%s%szerotier_dump.txt", path, ZT_PATH_SEPARATOR_S);
|
|
|
- fprintf(stdout, "Writing dump to: %s\n", path);
|
|
|
- HANDLE file = CreateFileA(
|
|
|
- path,
|
|
|
- GENERIC_WRITE,
|
|
|
- 0,
|
|
|
- NULL,
|
|
|
- CREATE_ALWAYS,
|
|
|
- FILE_ATTRIBUTE_NORMAL,
|
|
|
- NULL
|
|
|
- );
|
|
|
- if (file == INVALID_HANDLE_VALUE) {
|
|
|
- fprintf(stdout, "%s", dump.str().c_str());
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
- BOOL err = WriteFile(
|
|
|
- file,
|
|
|
- dump.str().c_str(),
|
|
|
- dump.str().size(),
|
|
|
- NULL,
|
|
|
- NULL
|
|
|
- );
|
|
|
- if (err = FALSE) {
|
|
|
- fprintf(stderr, "Error writing file");
|
|
|
- return 1;
|
|
|
- }
|
|
|
- CloseHandle(file);
|
|
|
+ try {
|
|
|
+ dumpNetworks(dump, addr, requestHeaders);
|
|
|
+ } catch (const std::exception& e) {
|
|
|
+ dump << "[ERROR] networks section failed: " << e.what() << ZT_EOL_S;
|
|
|
+ } catch (...) {
|
|
|
+ dump << "[ERROR] networks section failed: unknown error" << ZT_EOL_S;
|
|
|
}
|
|
|
- else {
|
|
|
- fprintf(stdout, "%s", dump.str().c_str());
|
|
|
+ try {
|
|
|
+ dumpPeers(dump, addr, requestHeaders);
|
|
|
+ } catch (const std::exception& e) {
|
|
|
+ dump << "[ERROR] peers section failed: " << e.what() << ZT_EOL_S;
|
|
|
+ } catch (...) {
|
|
|
+ dump << "[ERROR] peers section failed: unknown error" << ZT_EOL_S;
|
|
|
}
|
|
|
-#elif defined(__LINUX__)
|
|
|
- struct ifreq ifr;
|
|
|
- struct ifconf ifc;
|
|
|
- char buf[1024];
|
|
|
- char stringBuffer[128];
|
|
|
-
|
|
|
- int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
|
|
|
-
|
|
|
- ifc.ifc_len = sizeof(buf);
|
|
|
- ifc.ifc_buf = buf;
|
|
|
- ioctl(sock, SIOCGIFCONF, &ifc);
|
|
|
-
|
|
|
- struct ifreq *it = ifc.ifc_req;
|
|
|
- const struct ifreq * const end = it + (ifc.ifc_len / sizeof(struct ifreq));
|
|
|
- int count = 0;
|
|
|
- for(; it != end; ++it) {
|
|
|
- strcpy(ifr.ifr_name, it->ifr_name);
|
|
|
- if(ioctl(sock, SIOCGIFFLAGS, &ifr) == 0) {
|
|
|
- if (!(ifr.ifr_flags & IFF_LOOPBACK)) { // skip loopback
|
|
|
- dump << "Interface " << count++ << ZT_EOL_S << "-----------" << ZT_EOL_S;
|
|
|
- dump << "Name: " << ifr.ifr_name << ZT_EOL_S;
|
|
|
- if (ioctl(sock, SIOCGIFMTU, &ifr) == 0) {
|
|
|
- dump << "MTU: " << ifr.ifr_mtu << ZT_EOL_S;
|
|
|
- }
|
|
|
- if (ioctl(sock, SIOCGIFHWADDR, &ifr) == 0) {
|
|
|
- unsigned char mac_addr[6];
|
|
|
- memcpy(mac_addr, ifr.ifr_hwaddr.sa_data, 6);
|
|
|
- char macStr[18];
|
|
|
- sprintf(macStr, "%02x:%02x:%02x:%02x:%02x:%02x",
|
|
|
- mac_addr[0],
|
|
|
- mac_addr[1],
|
|
|
- mac_addr[2],
|
|
|
- mac_addr[3],
|
|
|
- mac_addr[4],
|
|
|
- mac_addr[5]);
|
|
|
- dump << "MAC: " << macStr << 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(ifr.ifr_name, ifa->ifa_name) == 0 && ifa->ifa_addr != NULL) {
|
|
|
- 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;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
+ try {
|
|
|
+ dumpLocalConf(dump, homeDir);
|
|
|
+ } catch (const std::exception& e) {
|
|
|
+ dump << "[ERROR] local.conf section failed: " << e.what() << ZT_EOL_S;
|
|
|
+ } catch (...) {
|
|
|
+ dump << "[ERROR] local.conf section failed: unknown error" << ZT_EOL_S;
|
|
|
}
|
|
|
- close(sock);
|
|
|
- char cwd[16384];
|
|
|
- getcwd(cwd, sizeof(cwd));
|
|
|
- sprintf(cwd, "%s%szerotier_dump.txt", cwd, ZT_PATH_SEPARATOR_S);
|
|
|
- fprintf(stdout, "Writing dump to: %s\n", cwd);
|
|
|
- int fd = open(cwd, O_CREAT|O_RDWR,0664);
|
|
|
- if (fd == -1) {
|
|
|
- fprintf(stderr, "Error creating file.\n");
|
|
|
- return 1;
|
|
|
+ try {
|
|
|
+ dumpInterfaces(dump);
|
|
|
+ } catch (const std::exception& e) {
|
|
|
+ dump << "[ERROR] interfaces section failed: " << e.what() << ZT_EOL_S;
|
|
|
+ } catch (...) {
|
|
|
+ dump << "[ERROR] interfaces section failed: unknown error" << ZT_EOL_S;
|
|
|
}
|
|
|
- write(fd, dump.str().c_str(), dump.str().size());
|
|
|
- close(fd);
|
|
|
-#else
|
|
|
- fprintf(stderr, "%s", dump.str().c_str());
|
|
|
-#endif
|
|
|
-
|
|
|
- // fprintf(stderr, "%s\n", dump.str().c_str());
|
|
|
|
|
|
+ fprintf(stdout, "%s", dump.str().c_str());
|
|
|
+ return 0;
|
|
|
} else {
|
|
|
cliPrintHelp(argv[0],stderr);
|
|
|
return 0;
|