mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-09-05 22:32:55 +02:00
Implements structured JSON diagnostic output for node state export with full schema documentation. This feature provides machine-readable diagnostics for automated analysis, monitoring, and AI/MCP integration. Key changes: - Add `zerotier-cli diagnostic` command for JSON node state export - Add `zerotier-cli dump -j` as alias for JSON output - Add `zerotier-cli diagnostic --schema` to print JSON schema - Implement platform-specific interface collection (Linux, BSD, macOS, Windows) - Create modular diagnostic/ directory with isolated try/catch error handling - Add comprehensive JSON schema (diagnostic_schema.json) for validation - Include build-time schema embedding for offline access - Add Python and Rust scripts for schema embedding during build - Update build systems to compile new diagnostic modules The diagnostic output includes: - Node configuration and identity - Network memberships and settings - Interface states and IP addresses - Peer connections and statistics - Moon orbits - Controller networks (if applicable) All diagnostic collection is wrapped in try/catch blocks to ensure partial failures don't prevent overall output generation. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
73 lines
No EOL
2.8 KiB
C++
73 lines
No EOL
2.8 KiB
C++
#include "diagnostic/node_state_interfaces_win32.hpp"
|
|
#include <windows.h>
|
|
#include <iphlpapi.h>
|
|
#include <ws2tcpip.h>
|
|
#include <vector>
|
|
|
|
void addNodeStateInterfacesJson(nlohmann::json& j) {
|
|
try {
|
|
std::vector<nlohmann::json> interfaces_json;
|
|
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);
|
|
if (ret == NO_ERROR) {
|
|
PIP_ADAPTER_ADDRESSES curAddr = addresses;
|
|
while (curAddr) {
|
|
nlohmann::json iface_json;
|
|
iface_json["name"] = curAddr->AdapterName;
|
|
iface_json["mtu"] = curAddr->Mtu;
|
|
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]);
|
|
iface_json["mac"] = macBuffer;
|
|
iface_json["type"] = curAddr->IfType;
|
|
std::vector<std::string> addresses;
|
|
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
|
|
);
|
|
addresses.push_back(buf);
|
|
pUnicast = pUnicast->Next;
|
|
}
|
|
}
|
|
iface_json["addresses"] = addresses;
|
|
interfaces_json.push_back(iface_json);
|
|
curAddr = curAddr->Next;
|
|
}
|
|
}
|
|
if (addresses) {
|
|
free(addresses);
|
|
addresses = NULL;
|
|
}
|
|
j["network_interfaces"] = interfaces_json;
|
|
} catch (const std::exception& e) {
|
|
j["network_interfaces"] = std::string("Exception: ") + e.what();
|
|
} catch (...) {
|
|
j["network_interfaces"] = "Unknown error retrieving interfaces";
|
|
}
|
|
}
|