From a4e021e04e27e591d4bf96121d09e45e6293e1b5 Mon Sep 17 00:00:00 2001 From: Aaron Johnson <4023+aaronjohnson@users.noreply.github.com> Date: Mon, 23 Jun 2025 12:46:44 -0700 Subject: [PATCH] Refactor dump logic into diagnostic/ with try/catch isolation, prepping for -j feature --- diagnostic/dump_interfaces.hpp | 3 + diagnostic/dump_interfaces_apple.cpp | 52 +++++ diagnostic/dump_interfaces_bsd.cpp | 53 +++++ diagnostic/dump_interfaces_linux.cpp | 69 ++++++ diagnostic/dump_interfaces_netbsd.cpp | 53 +++++ diagnostic/dump_interfaces_win32.cpp | 67 ++++++ diagnostic/dump_sections.cpp | 55 +++++ diagnostic/dump_sections.hpp | 10 + make-bsd.mk | 7 +- make-linux.mk | 6 +- make-mac.mk | 8 +- make-netbsd.mk | 7 +- one.cpp | 323 +++----------------------- 13 files changed, 414 insertions(+), 299 deletions(-) create mode 100644 diagnostic/dump_interfaces.hpp create mode 100644 diagnostic/dump_interfaces_apple.cpp create mode 100644 diagnostic/dump_interfaces_bsd.cpp create mode 100644 diagnostic/dump_interfaces_linux.cpp create mode 100644 diagnostic/dump_interfaces_netbsd.cpp create mode 100644 diagnostic/dump_interfaces_win32.cpp create mode 100644 diagnostic/dump_sections.cpp create mode 100644 diagnostic/dump_sections.hpp diff --git a/diagnostic/dump_interfaces.hpp b/diagnostic/dump_interfaces.hpp new file mode 100644 index 000000000..9dd2d22e4 --- /dev/null +++ b/diagnostic/dump_interfaces.hpp @@ -0,0 +1,3 @@ +#pragma once +#include +void dumpInterfaces(std::stringstream& dump); \ No newline at end of file diff --git a/diagnostic/dump_interfaces_apple.cpp b/diagnostic/dump_interfaces_apple.cpp new file mode 100644 index 000000000..664c82e21 --- /dev/null +++ b/diagnostic/dump_interfaces_apple.cpp @@ -0,0 +1,52 @@ +#include "diagnostic/dump_interfaces.hpp" +#include +#include +#include +#include +#include +#include +#include +#include + +void dumpInterfaces(std::stringstream& dump) { + CFArrayRef interfaces = SCNetworkInterfaceCopyAll(); + CFIndex size = CFArrayGetCount(interfaces); + for(CFIndex i = 0; i < size; ++i) { + SCNetworkInterfaceRef iface = (SCNetworkInterfaceRef)CFArrayGetValueAtIndex(interfaces, i); + dump << "Interface " << i << "\n-----------\n"; + CFStringRef tmp = SCNetworkInterfaceGetBSDName(iface); + char stringBuffer[512] = {}; + CFStringGetCString(tmp,stringBuffer, sizeof(stringBuffer), kCFStringEncodingUTF8); + dump << "Name: " << stringBuffer << "\n"; + std::string ifName(stringBuffer); + int mtuCur, mtuMin, mtuMax; + SCNetworkInterfaceCopyMTU(iface, &mtuCur, &mtuMin, &mtuMax); + dump << "MTU: " << mtuCur << "\n"; + tmp = SCNetworkInterfaceGetHardwareAddressString(iface); + CFStringGetCString(tmp, stringBuffer, sizeof(stringBuffer), kCFStringEncodingUTF8); + dump << "MAC: " << stringBuffer << "\n"; + tmp = SCNetworkInterfaceGetInterfaceType(iface); + CFStringGetCString(tmp, stringBuffer, sizeof(stringBuffer), kCFStringEncodingUTF8); + dump << "Type: " << stringBuffer << "\n"; + dump << "Addresses:" << "\n"; + 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 << "\n"; + } + } + dump << "\n"; + } +} \ No newline at end of file diff --git a/diagnostic/dump_interfaces_bsd.cpp b/diagnostic/dump_interfaces_bsd.cpp new file mode 100644 index 000000000..9b7611c47 --- /dev/null +++ b/diagnostic/dump_interfaces_bsd.cpp @@ -0,0 +1,53 @@ +#include "diagnostic/dump_interfaces.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void dumpInterfaces(std::stringstream& dump) { + struct ifaddrs *ifap, *ifa; + if (getifaddrs(&ifap) != 0) { + dump << "ERROR: getifaddrs failed\n"; + return; + } + for (ifa = ifap; ifa; ifa = ifa->ifa_next) { + if (!ifa->ifa_addr) continue; + dump << "Interface: " << ifa->ifa_name << "\n"; + int sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock >= 0) { + struct ifreq ifr; + strncpy(ifr.ifr_name, ifa->ifa_name, IFNAMSIZ); + if (ioctl(sock, SIOCGIFMTU, &ifr) == 0) { + dump << "MTU: " << ifr.ifr_mtu << "\n"; + } + if (ifa->ifa_addr->sa_family == AF_LINK) { + struct sockaddr_dl* sdl = (struct sockaddr_dl*)ifa->ifa_addr; + unsigned char* mac = (unsigned char*)LLADDR(sdl); + char macStr[32]; + snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + dump << "MAC: " << macStr << "\n"; + } + close(sock); + } + dump << "Addresses:\n"; + if (ifa->ifa_addr->sa_family == AF_INET) { + char addr[INET_ADDRSTRLEN]; + struct sockaddr_in* sa = (struct sockaddr_in*)ifa->ifa_addr; + inet_ntop(AF_INET, &(sa->sin_addr), addr, INET_ADDRSTRLEN); + dump << addr << "\n"; + } else if (ifa->ifa_addr->sa_family == AF_INET6) { + char addr[INET6_ADDRSTRLEN]; + struct sockaddr_in6* sa6 = (struct sockaddr_in6*)ifa->ifa_addr; + inet_ntop(AF_INET6, &(sa6->sin6_addr), addr, INET6_ADDRSTRLEN); + dump << addr << "\n"; + } + dump << "\n"; + } + freeifaddrs(ifap); +} \ No newline at end of file diff --git a/diagnostic/dump_interfaces_linux.cpp b/diagnostic/dump_interfaces_linux.cpp new file mode 100644 index 000000000..b3c242d55 --- /dev/null +++ b/diagnostic/dump_interfaces_linux.cpp @@ -0,0 +1,69 @@ +#include "diagnostic/dump_interfaces.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void dumpInterfaces(std::stringstream& dump) { + int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); + struct ifconf ifc; + char buf[1024]; + 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)); + for(; it != end; ++it) { + struct ifreq ifr; + strcpy(ifr.ifr_name, it->ifr_name); + if(ioctl(sock, SIOCGIFFLAGS, &ifr) == 0) { + if (!(ifr.ifr_flags & IFF_LOOPBACK)) { // skip loopback + dump << "Interface: " << ifr.ifr_name << "\n"; + if (ioctl(sock, SIOCGIFMTU, &ifr) == 0) { + dump << "MTU: " << ifr.ifr_mtu << "\n"; + } + 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 << "\n"; + } + dump << "Addresses:" << "\n"; + 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) { + char stringBuffer[128]; + 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 << "\n"; + } + } + dump << "\n"; + } + } + } + close(sock); +} \ No newline at end of file diff --git a/diagnostic/dump_interfaces_netbsd.cpp b/diagnostic/dump_interfaces_netbsd.cpp new file mode 100644 index 000000000..9b7611c47 --- /dev/null +++ b/diagnostic/dump_interfaces_netbsd.cpp @@ -0,0 +1,53 @@ +#include "diagnostic/dump_interfaces.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void dumpInterfaces(std::stringstream& dump) { + struct ifaddrs *ifap, *ifa; + if (getifaddrs(&ifap) != 0) { + dump << "ERROR: getifaddrs failed\n"; + return; + } + for (ifa = ifap; ifa; ifa = ifa->ifa_next) { + if (!ifa->ifa_addr) continue; + dump << "Interface: " << ifa->ifa_name << "\n"; + int sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock >= 0) { + struct ifreq ifr; + strncpy(ifr.ifr_name, ifa->ifa_name, IFNAMSIZ); + if (ioctl(sock, SIOCGIFMTU, &ifr) == 0) { + dump << "MTU: " << ifr.ifr_mtu << "\n"; + } + if (ifa->ifa_addr->sa_family == AF_LINK) { + struct sockaddr_dl* sdl = (struct sockaddr_dl*)ifa->ifa_addr; + unsigned char* mac = (unsigned char*)LLADDR(sdl); + char macStr[32]; + snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + dump << "MAC: " << macStr << "\n"; + } + close(sock); + } + dump << "Addresses:\n"; + if (ifa->ifa_addr->sa_family == AF_INET) { + char addr[INET_ADDRSTRLEN]; + struct sockaddr_in* sa = (struct sockaddr_in*)ifa->ifa_addr; + inet_ntop(AF_INET, &(sa->sin_addr), addr, INET_ADDRSTRLEN); + dump << addr << "\n"; + } else if (ifa->ifa_addr->sa_family == AF_INET6) { + char addr[INET6_ADDRSTRLEN]; + struct sockaddr_in6* sa6 = (struct sockaddr_in6*)ifa->ifa_addr; + inet_ntop(AF_INET6, &(sa6->sin6_addr), addr, INET6_ADDRSTRLEN); + dump << addr << "\n"; + } + dump << "\n"; + } + freeifaddrs(ifap); +} \ No newline at end of file diff --git a/diagnostic/dump_interfaces_win32.cpp b/diagnostic/dump_interfaces_win32.cpp new file mode 100644 index 000000000..845fdd195 --- /dev/null +++ b/diagnostic/dump_interfaces_win32.cpp @@ -0,0 +1,67 @@ +#include "diagnostic/dump_interfaces.hpp" +#include +#include +#include +#include +#include + +void dumpInterfaces(std::stringstream& dump) { + 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 << "\n-----------\n"; + dump << "Name: " << curAddr->AdapterName << "\n"; + dump << "MTU: " << curAddr->Mtu << "\n"; + 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 << "MAC: " << macBuffer << "\n"; + dump << "Type: " << curAddr->IfType << "\n"; + dump << "Addresses:" << "\n"; + 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 << "\n"; + pUnicast = pUnicast->Next; + } + } + dump << "\n"; + curAddr = curAddr->Next; + } + } + if (addresses) { + free(addresses); + addresses = NULL; + } +} \ No newline at end of file diff --git a/diagnostic/dump_sections.cpp b/diagnostic/dump_sections.cpp new file mode 100644 index 000000000..45e6c232f --- /dev/null +++ b/diagnostic/dump_sections.cpp @@ -0,0 +1,55 @@ +#include "diagnostic/dump_sections.hpp" +#include "node/InetAddress.hpp" +#include "osdep/OSUtils.hpp" +#include "osdep/Http.hpp" +#include +#include +#include + +void dumpStatus(std::stringstream& dump, const ZeroTier::InetAddress& addr, std::map& requestHeaders) { + dump << "status" << ZT_EOL_S << "------" << ZT_EOL_S; + std::map responseHeaders; + std::string responseBody; + unsigned int scode = ZeroTier::Http::GET(1024 * 1024 * 16,60000,(const struct sockaddr *)&addr,"/status",requestHeaders,responseHeaders,responseBody); + if (scode != 200) { + dump << responseBody << ZT_EOL_S; + return; + } + dump << responseBody << ZT_EOL_S; +} + +void dumpNetworks(std::stringstream& dump, const ZeroTier::InetAddress& addr, std::map& requestHeaders) { + dump << ZT_EOL_S << "networks" << ZT_EOL_S << "--------" << ZT_EOL_S; + std::map responseHeaders; + std::string responseBody; + unsigned int scode = ZeroTier::Http::GET(1024 * 1024 * 16,60000,(const struct sockaddr *)&addr,"/network",requestHeaders,responseHeaders,responseBody); + if (scode != 200) { + dump << responseBody << ZT_EOL_S; + return; + } + dump << responseBody << ZT_EOL_S; +} + +void dumpPeers(std::stringstream& dump, const ZeroTier::InetAddress& addr, std::map& requestHeaders) { + dump << ZT_EOL_S << "peers" << ZT_EOL_S << "-----" << ZT_EOL_S; + std::map responseHeaders; + std::string responseBody; + unsigned int scode = ZeroTier::Http::GET(1024 * 1024 * 16,60000,(const struct sockaddr *)&addr,"/peer",requestHeaders,responseHeaders,responseBody); + if (scode != 200) { + dump << responseBody << ZT_EOL_S; + return; + } + dump << responseBody << ZT_EOL_S; +} + +void dumpLocalConf(std::stringstream& dump, const std::string& homeDir) { + dump << ZT_EOL_S << "local.conf" << ZT_EOL_S << "----------" << ZT_EOL_S; + std::string localConf; + ZeroTier::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; + } +} \ No newline at end of file diff --git a/diagnostic/dump_sections.hpp b/diagnostic/dump_sections.hpp new file mode 100644 index 000000000..9b1a29b1c --- /dev/null +++ b/diagnostic/dump_sections.hpp @@ -0,0 +1,10 @@ +#pragma once +#include +#include +#include +#include "node/InetAddress.hpp" + +void dumpStatus(std::stringstream& dump, const ZeroTier::InetAddress& addr, std::map& requestHeaders); +void dumpNetworks(std::stringstream& dump, const ZeroTier::InetAddress& addr, std::map& requestHeaders); +void dumpPeers(std::stringstream& dump, const ZeroTier::InetAddress& addr, std::map& requestHeaders); +void dumpLocalConf(std::stringstream& dump, const std::string& homeDir); \ No newline at end of file diff --git a/make-bsd.mk b/make-bsd.mk index ce0b4dde1..767899c34 100644 --- a/make-bsd.mk +++ b/make-bsd.mk @@ -5,7 +5,7 @@ DEFS= LIBS= include objects.mk -ONE_OBJS+=osdep/BSDEthernetTap.o ext/http-parser/http_parser.o +ONE_OBJS+=osdep/BSDEthernetTap.o ext/http-parser/http_parser.o dump_interfaces_bsd.o ifeq ($(OSTYPE),FreeBSD) # Auto-detect miniupnpc and nat-pmp as well and use ports libs if present, @@ -153,11 +153,12 @@ endif override DEFS+=-DZT_BUILD_PLATFORM=$(ZT_BUILD_PLATFORM) -DZT_BUILD_ARCHITECTURE=$(ZT_ARCHITECTURE) -DZT_SOFTWARE_UPDATE_DEFAULT="\"disable\"" CXXFLAGS+=$(CFLAGS) -std=c++17 #-D_GLIBCXX_USE_C99 -D_GLIBCXX_USE_C99_MATH -D_GLIBCXX_USE_C99_MATH_TR1 +CPPFLAGS += -I. all: one -one: $(CORE_OBJS) $(ONE_OBJS) one.o - $(CXX) $(CXXFLAGS) $(LDFLAGS) -o zerotier-one $(CORE_OBJS) $(ONE_OBJS) one.o $(LIBS) +one: $(CORE_OBJS) $(ONE_OBJS) one.o diagnostic/dump_sections.o diagnostic/dump_interfaces_bsd.o + $(CXX) $(CXXFLAGS) $(LDFLAGS) -o zerotier-one $(CORE_OBJS) $(ONE_OBJS) one.o diagnostic/dump_sections.o diagnostic/dump_interfaces_bsd.o $(LIBS) $(STRIP) zerotier-one ln -sf zerotier-one zerotier-idtool ln -sf zerotier-one zerotier-cli diff --git a/make-linux.mk b/make-linux.mk index efc1badf6..67f7da483 100644 --- a/make-linux.mk +++ b/make-linux.mk @@ -376,8 +376,8 @@ from_builder: FORCE ln -sf zerotier-one zerotier-idtool ln -sf zerotier-one zerotier-cli -zerotier-one: $(CORE_OBJS) $(ONE_OBJS) one.o - $(CXX) $(CXXFLAGS) $(LDFLAGS) -o zerotier-one $(CORE_OBJS) $(ONE_OBJS) one.o $(LDLIBS) +zerotier-one: $(CORE_OBJS) $(ONE_OBJS) one.o diagnostic/dump_sections.o diagnostic/dump_interfaces_linux.o + $(CXX) $(CXXFLAGS) $(LDFLAGS) -o zerotier-one $(CORE_OBJS) $(ONE_OBJS) one.o diagnostic/dump_sections.o diagnostic/dump_interfaces_linux.o $(LDLIBS) zerotier-idtool: zerotier-one ln -sf zerotier-one zerotier-idtool @@ -566,3 +566,5 @@ munge_deb: ci/scripts/munge_debian_changelog.sh debian/changelog $(VERSION) "Adam Ierymenko " "see https://github.com/zerotier/ZeroTierOne for release notes" FORCE: + +CPPFLAGS += -I. diff --git a/make-mac.mk b/make-mac.mk index e10f96227..457a527cd 100644 --- a/make-mac.mk +++ b/make-mac.mk @@ -28,7 +28,7 @@ TIMESTAMP=$(shell date +"%Y%m%d%H%M") DEFS+=-DZT_BUILD_PLATFORM=$(ZT_BUILD_PLATFORM) -DZT_BUILD_ARCHITECTURE=$(ZT_BUILD_ARCHITECTURE) include objects.mk -ONE_OBJS+=osdep/MacEthernetTap.o osdep/MacKextEthernetTap.o osdep/MacDNSHelper.o ext/http-parser/http_parser.o +ONE_OBJS+=osdep/MacEthernetTap.o osdep/MacKextEthernetTap.o osdep/MacDNSHelper.o ext/http-parser/http_parser.o diagnostic/dump_interfaces_apple.o LIBS+=-framework CoreServices -framework SystemConfiguration -framework CoreFoundation -framework Security # Official releases are signed with our Apple cert and apply software updates by default @@ -103,6 +103,8 @@ ifeq ($(ZT_VAULT_SUPPORT),1) LIBS+=-lcurl endif +CPPFLAGS += -I. + all: one ext/x64-salsa2012-asm/salsa2012.o: @@ -115,8 +117,8 @@ mac-agent: FORCE osdep/MacDNSHelper.o: osdep/MacDNSHelper.mm $(CXX) $(CXXFLAGS) -c osdep/MacDNSHelper.mm -o osdep/MacDNSHelper.o -one: zeroidc $(CORE_OBJS) $(ONE_OBJS) one.o mac-agent - $(CXX) $(CXXFLAGS) -o zerotier-one $(CORE_OBJS) $(ONE_OBJS) one.o $(LIBS) rustybits/target/libzeroidc.a +one: zeroidc $(CORE_OBJS) $(ONE_OBJS) one.o diagnostic/dump_sections.o diagnostic/dump_interfaces_apple.o mac-agent + $(CXX) $(CXXFLAGS) -o zerotier-one $(CORE_OBJS) $(ONE_OBJS) one.o diagnostic/dump_sections.o diagnostic/dump_interfaces_apple.o $(LIBS) rustybits/target/libzeroidc.a # $(STRIP) zerotier-one ln -sf zerotier-one zerotier-idtool ln -sf zerotier-one zerotier-cli diff --git a/make-netbsd.mk b/make-netbsd.mk index f2490038b..bca12510c 100644 --- a/make-netbsd.mk +++ b/make-netbsd.mk @@ -6,7 +6,7 @@ DEFS= LIBS= include objects.mk -OBJS+=osdep/NetBSDEthernetTap.o ext/lz4/lz4.o ext/json-parser/json.o ext/http-parser/http_parser.o +OBJS+=osdep/NetBSDEthernetTap.o ext/lz4/lz4.o ext/json-parser/json.o ext/http-parser/http_parser.o diagnostic/dump_interfaces_netbsd.o # "make official" is a shortcut for this ifeq ($(ZT_OFFICIAL_RELEASE),1) @@ -35,11 +35,12 @@ else endif CXXFLAGS+=$(CFLAGS) -fno-rtti -fpermissive +CPPFLAGS += -I. all: one -one: $(OBJS) service/OneService.o one.o - $(CXX) $(CXXFLAGS) $(LDFLAGS) -o zerotier-one $(OBJS) service/OneService.o one.o $(LIBS) +one: $(OBJS) service/OneService.o one.o diagnostic/dump_sections.o diagnostic/dump_interfaces_netbsd.o + $(CXX) $(CXXFLAGS) $(LDFLAGS) -o zerotier-one $(OBJS) service/OneService.o one.o diagnostic/dump_sections.o diagnostic/dump_interfaces_netbsd.o $(LIBS) $(STRIP) zerotier-one ln -sf zerotier-one zerotier-idtool ln -sf zerotier-one zerotier-cli diff --git a/one.cpp b/one.cpp index 2e4e63847..dee039fb4 100644 --- a/one.cpp +++ b/one.cpp @@ -88,6 +88,9 @@ #include "service/OneService.hpp" +#include "diagnostic/dump_sections.hpp" +#include "diagnostic/dump_interfaces.hpp" + #include #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; + 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; } - 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; + 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; } - 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; + 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; } - 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; + 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; } - else { - dump << localConf << ZT_EOL_S; + 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; } - 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; - } - } - 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); - } - else { - fprintf(stdout, "%s", dump.str().c_str()); - } -#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; - } - } - } - } - } - 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; - } - 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;