Browse Source

Refactor dump logic into diagnostic/ with try/catch isolation, prepping for -j feature

Aaron Johnson 2 months ago
parent
commit
a4e021e04e

+ 3 - 0
diagnostic/dump_interfaces.hpp

@@ -0,0 +1,3 @@
+#pragma once
+#include <sstream>
+void dumpInterfaces(std::stringstream& dump); 

+ 52 - 0
diagnostic/dump_interfaces_apple.cpp

@@ -0,0 +1,52 @@
+#include "diagnostic/dump_interfaces.hpp"
+#include <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <ifaddrs.h>
+#include <net/if.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <string.h>
+
+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";
+    }
+} 

+ 53 - 0
diagnostic/dump_interfaces_bsd.cpp

@@ -0,0 +1,53 @@
+#include "diagnostic/dump_interfaces.hpp"
+#include <ifaddrs.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <net/if_dl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <cstring>
+#include <sstream>
+
+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);
+} 

+ 69 - 0
diagnostic/dump_interfaces_linux.cpp

@@ -0,0 +1,69 @@
+#include "diagnostic/dump_interfaces.hpp"
+#include <sys/types.h>
+#include <ifaddrs.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sstream>
+
+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);
+} 

+ 53 - 0
diagnostic/dump_interfaces_netbsd.cpp

@@ -0,0 +1,53 @@
+#include "diagnostic/dump_interfaces.hpp"
+#include <ifaddrs.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <net/if_dl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <cstring>
+#include <sstream>
+
+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);
+} 

+ 67 - 0
diagnostic/dump_interfaces_win32.cpp

@@ -0,0 +1,67 @@
+#include "diagnostic/dump_interfaces.hpp"
+#include <winsock2.h>
+#include <windows.h>
+#include <iphlpapi.h>
+#include <ws2tcpip.h>
+#include <string>
+
+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;
+    }
+} 

+ 55 - 0
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 <sstream>
+#include <string>
+#include <map>
+
+void dumpStatus(std::stringstream& dump, const ZeroTier::InetAddress& addr, std::map<std::string,std::string>& requestHeaders) {
+    dump << "status" << ZT_EOL_S << "------" << ZT_EOL_S;
+    std::map<std::string, std::string> 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<std::string,std::string>& requestHeaders) {
+    dump << ZT_EOL_S << "networks" << ZT_EOL_S << "--------" << ZT_EOL_S;
+    std::map<std::string, std::string> 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<std::string,std::string>& requestHeaders) {
+    dump << ZT_EOL_S << "peers" << ZT_EOL_S << "-----" << ZT_EOL_S;
+    std::map<std::string, std::string> 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;
+    }
+} 

+ 10 - 0
diagnostic/dump_sections.hpp

@@ -0,0 +1,10 @@
+#pragma once
+#include <sstream>
+#include <string>
+#include <map>
+#include "node/InetAddress.hpp"
+
+void dumpStatus(std::stringstream& dump, const ZeroTier::InetAddress& addr, std::map<std::string,std::string>& requestHeaders);
+void dumpNetworks(std::stringstream& dump, const ZeroTier::InetAddress& addr, std::map<std::string,std::string>& requestHeaders);
+void dumpPeers(std::stringstream& dump, const ZeroTier::InetAddress& addr, std::map<std::string,std::string>& requestHeaders);
+void dumpLocalConf(std::stringstream& dump, const std::string& homeDir); 

+ 4 - 3
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

+ 4 - 2
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 <[email protected]>" "see https://github.com/zerotier/ZeroTierOne for release notes"
 
 FORCE:
+
+CPPFLAGS += -I.

+ 5 - 3
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

+ 4 - 3
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

+ 35 - 288
one.cpp

@@ -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;