You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
703 lines
19 KiB
703 lines
19 KiB
/* |
|
* Copyright (c)2013-2021 ZeroTier, Inc. |
|
* |
|
* Use of this software is governed by the Business Source License included |
|
* in the LICENSE.TXT file in the project's root directory. |
|
* |
|
* Change Date: 2026-01-01 |
|
* |
|
* On the date above, in accordance with the Business Source License, use |
|
* of this software will be governed by version 2.0 of the Apache License. |
|
*/ |
|
/****/ |
|
|
|
/** |
|
* @file |
|
* |
|
* Node / Network control interface |
|
*/ |
|
|
|
#include "Events.hpp" |
|
#include "NodeService.hpp" |
|
#include "Signals.hpp" |
|
#include "VirtualTap.hpp" |
|
|
|
#include <string.h> |
|
|
|
using namespace ZeroTier; |
|
|
|
#ifdef __WINDOWS__ |
|
#include <Windows.h> |
|
WSADATA wsaData; |
|
#endif |
|
|
|
#ifdef ZTS_ENABLE_PYTHON |
|
#define ZTS_ENABLE_CUSTOM_SIGNAL_HANDLERS 1 |
|
#endif |
|
|
|
namespace ZeroTier { |
|
|
|
#ifdef ZTS_ENABLE_PYTHON |
|
#endif |
|
#ifdef ZTS_ENABLE_PINVOKE |
|
extern void (*_userEventCallback)(void*); |
|
#endif |
|
#ifdef ZTS_C_API_ONLY |
|
extern void (*_userEventCallback)(void*); |
|
#endif |
|
extern uint8_t allowNetworkCaching; |
|
extern uint8_t allowPeerCaching; |
|
|
|
NodeService* zts_service; |
|
Events* zts_events; |
|
|
|
extern Mutex events_m; |
|
Mutex service_m; |
|
|
|
int init_subsystems() |
|
{ |
|
/** Set up service and callback threads and tell them about one another. |
|
* A separate thread is used for callbacks so that if the user fails to |
|
* return control it won't affect the core service's operations. */ |
|
if (! zts_events) { |
|
zts_events = new Events(); |
|
} |
|
if (zts_events->getState(ZTS_STATE_FREE_CALLED)) { |
|
return ZTS_ERR_SERVICE; |
|
} |
|
#ifdef ZTS_ENABLE_CUSTOM_SIGNAL_HANDLERS |
|
zts_install_signal_handlers(); |
|
#endif // ZTS_ENABLE_CUSTOM_SIGNAL_HANDLERS |
|
if (! zts_service) { |
|
#if defined(__WINDOWS__) |
|
WSAStartup(MAKEWORD(2, 2), &wsaData); |
|
#endif |
|
zts_service = new NodeService(); |
|
zts_service->setUserEventSystem(zts_events); |
|
} |
|
return ZTS_ERR_OK; |
|
} |
|
|
|
#ifdef __cplusplus |
|
extern "C" { |
|
#endif |
|
|
|
int zts_init_from_storage(const char* path) |
|
{ |
|
ACQUIRE_SERVICE_OFFLINE(); |
|
zts_service->setHomePath(path); |
|
return ZTS_ERR_OK; |
|
} |
|
|
|
int zts_init_from_memory(const char* keypair, unsigned int len) |
|
{ |
|
ACQUIRE_SERVICE_OFFLINE(); |
|
return zts_service->setIdentity(keypair, len); |
|
} |
|
|
|
#ifdef ZTS_ENABLE_PYTHON |
|
int zts_init_set_event_handler(PythonDirectorCallbackClass* callback) |
|
#endif |
|
#ifdef ZTS_ENABLE_PINVOKE |
|
int zts_init_set_event_handler(CppCallback callback) |
|
#endif |
|
#ifdef ZTS_ENABLE_JAVA |
|
int zts_init_set_event_handler(jobject obj_ref, jmethodID id) |
|
#endif |
|
#ifdef ZTS_C_API_ONLY |
|
int zts_init_set_event_handler(void (*callback)(void*)) |
|
#endif |
|
{ |
|
ACQUIRE_SERVICE_OFFLINE(); |
|
#ifdef ZTS_ENABLE_JAVA |
|
zts_events->setJavaCallback(obj_ref, id); |
|
#else |
|
if (! callback) { |
|
return ZTS_ERR_ARG; |
|
} |
|
_userEventCallback = callback; |
|
#endif |
|
zts_service->enableEvents(); |
|
return ZTS_ERR_OK; |
|
} |
|
|
|
int zts_init_blacklist_if(const char* prefix, unsigned int len) |
|
{ |
|
ACQUIRE_SERVICE_OFFLINE(); |
|
return zts_service->addInterfacePrefixToBlacklist(prefix, len); |
|
} |
|
|
|
int zts_init_set_roots(const void* roots_data, unsigned int len) |
|
{ |
|
ACQUIRE_SERVICE_OFFLINE(); |
|
return zts_service->setWorld(roots_data, len); |
|
} |
|
|
|
int zts_init_set_port(unsigned short port) |
|
{ |
|
ACQUIRE_SERVICE_OFFLINE(); |
|
zts_service->setPrimaryPort(port); |
|
return ZTS_ERR_OK; |
|
} |
|
|
|
int zts_init_allow_peer_cache(unsigned int allowed) |
|
{ |
|
ACQUIRE_SERVICE_OFFLINE(); |
|
return zts_service->allowPeerCaching(allowed); |
|
} |
|
|
|
int zts_init_allow_net_cache(unsigned int allowed) |
|
{ |
|
ACQUIRE_SERVICE_OFFLINE(); |
|
return zts_service->allowNetworkCaching(allowed); |
|
} |
|
|
|
int zts_init_allow_roots_cache(unsigned int allowed) |
|
{ |
|
ACQUIRE_SERVICE_OFFLINE(); |
|
return zts_service->allowWorldCaching(allowed); |
|
} |
|
|
|
int zts_init_allow_id_cache(unsigned int allowed) |
|
{ |
|
ACQUIRE_SERVICE_OFFLINE(); |
|
return zts_service->allowIdentityCaching(allowed); |
|
} |
|
|
|
int zts_addr_compute_6plane(const uint64_t net_id, const uint64_t node_id, struct zts_sockaddr_storage* addr) |
|
{ |
|
if (! addr || ! net_id || ! node_id) { |
|
return ZTS_ERR_ARG; |
|
} |
|
InetAddress _6planeAddr = InetAddress::makeIpv66plane(net_id, node_id); |
|
struct sockaddr_in6* in6 = (struct sockaddr_in6*)addr; |
|
memcpy(in6->sin6_addr.s6_addr, _6planeAddr.rawIpData(), sizeof(struct in6_addr)); |
|
return ZTS_ERR_OK; |
|
} |
|
|
|
int zts_addr_compute_rfc4193(const uint64_t net_id, const uint64_t node_id, struct zts_sockaddr_storage* addr) |
|
{ |
|
if (! addr || ! net_id || ! node_id) { |
|
return ZTS_ERR_ARG; |
|
} |
|
InetAddress _rfc4193Addr = InetAddress::makeIpv6rfc4193(net_id, node_id); |
|
struct sockaddr_in6* in6 = (struct sockaddr_in6*)addr; |
|
memcpy(in6->sin6_addr.s6_addr, _rfc4193Addr.rawIpData(), sizeof(struct in6_addr)); |
|
return ZTS_ERR_OK; |
|
} |
|
|
|
int zts_addr_compute_rfc4193_str(uint64_t net_id, uint64_t node_id, char* dst, unsigned int len) |
|
{ |
|
if (! net_id || ! node_id || ! dst || len != ZTS_IP_MAX_STR_LEN) { |
|
return ZTS_ERR_ARG; |
|
} |
|
struct zts_sockaddr_storage ss; |
|
int err = ZTS_ERR_OK; |
|
if ((err = zts_addr_compute_rfc4193(net_id, node_id, &ss)) != ZTS_ERR_OK) { |
|
return err; |
|
} |
|
struct zts_sockaddr_in6* in6 = (struct zts_sockaddr_in6*)&ss; |
|
zts_inet_ntop(ZTS_AF_INET6, &(in6->sin6_addr), dst, ZTS_IP_MAX_STR_LEN); |
|
return ZTS_ERR_OK; |
|
} |
|
|
|
int zts_addr_compute_6plane_str(uint64_t net_id, uint64_t node_id, char* dst, unsigned int len) |
|
{ |
|
if (! net_id || ! node_id || ! dst || len != ZTS_IP_MAX_STR_LEN) { |
|
return ZTS_ERR_ARG; |
|
} |
|
struct zts_sockaddr_storage ss; |
|
int err = ZTS_ERR_OK; |
|
if ((err = zts_addr_compute_6plane(net_id, node_id, &ss)) != ZTS_ERR_OK) { |
|
return err; |
|
} |
|
struct zts_sockaddr_in6* in6 = (struct zts_sockaddr_in6*)&ss; |
|
zts_inet_ntop(ZTS_AF_INET6, &(in6->sin6_addr), dst, ZTS_IP_MAX_STR_LEN); |
|
return ZTS_ERR_OK; |
|
} |
|
|
|
uint64_t zts_net_compute_adhoc_id(unsigned short start_port, unsigned short end_port) |
|
{ |
|
char net_id_str[ZTS_INET6_ADDRSTRLEN] = { 0 }; |
|
OSUtils::ztsnprintf(net_id_str, ZTS_INET6_ADDRSTRLEN, "ff%04x%04x000000", start_port, end_port); |
|
return strtoull(net_id_str, NULL, 16); |
|
} |
|
|
|
int zts_id_new(char* key, unsigned int* dst_len) |
|
{ |
|
if (key == NULL || *dst_len != ZT_IDENTITY_STRING_BUFFER_LENGTH) { |
|
return ZTS_ERR_ARG; |
|
} |
|
Identity id; |
|
id.generate(); |
|
char idtmp[1024] = { 0 }; |
|
std::string idser = id.toString(true, idtmp); |
|
unsigned int key_pair_len = idser.length(); |
|
if (key_pair_len > *dst_len) { |
|
return ZTS_ERR_ARG; |
|
} |
|
memcpy(key, idser.c_str(), key_pair_len); |
|
*dst_len = key_pair_len; |
|
return ZTS_ERR_OK; |
|
} |
|
|
|
int zts_id_pair_is_valid(const char* key, unsigned int len) |
|
{ |
|
if (key == NULL || len != ZT_IDENTITY_STRING_BUFFER_LENGTH) { |
|
return false; |
|
} |
|
Identity id; |
|
if ((strnlen(key, len) > 32) && (key[10] == ':')) { |
|
if (id.fromString(key)) { |
|
return id.locallyValidate(); |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
int zts_node_get_id_pair(char* key, unsigned int* key_dst_len) |
|
{ |
|
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); |
|
int err = ZTS_ERR_OK; |
|
if ((err = zts_service->getIdentity(key, key_dst_len)) != ZTS_ERR_OK) { |
|
return err; |
|
} |
|
return *key_dst_len > 0 ? ZTS_ERR_OK : ZTS_ERR_GENERAL; |
|
} |
|
|
|
#if defined(__WINDOWS__) |
|
DWORD WINAPI cbRun(LPVOID arg) |
|
#else |
|
void* cbRun(void* arg) |
|
#endif |
|
{ |
|
ZTS_UNUSED_ARG(arg); |
|
#if defined(__APPLE__) |
|
// pthread_setname_np(ZTS_EVENT_CALLBACK_THREAD_NAME); |
|
#endif |
|
zts_events->run(); |
|
//#if ZTS_ENABLE_JAVA |
|
// _java_detach_from_thread(); |
|
// pthread_exit(0); |
|
//#endif |
|
return NULL; |
|
} |
|
|
|
int zts_addr_is_assigned(uint64_t net_id, unsigned int family) |
|
{ |
|
ACQUIRE_SERVICE(0); |
|
return zts_service->addrIsAssigned(net_id, family); |
|
} |
|
|
|
int zts_addr_get(uint64_t net_id, unsigned int family, struct zts_sockaddr_storage* addr) |
|
{ |
|
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); |
|
return zts_service->getFirstAssignedAddr(net_id, family, addr); |
|
} |
|
|
|
int zts_addr_get_str(uint64_t net_id, unsigned int family, char* dst, unsigned int len) |
|
{ |
|
// No service lock required since zts_addr_get will lock it |
|
if (net_id == 0) { |
|
return ZTS_ERR_ARG; |
|
} |
|
if (len < ZTS_INET6_ADDRSTRLEN) { |
|
return ZTS_ERR_ARG; |
|
} |
|
|
|
if (family == ZTS_AF_INET) { |
|
struct zts_sockaddr_storage ss; |
|
int err = ZTS_ERR_OK; |
|
if ((err = zts_addr_get(net_id, family, &ss)) != ZTS_ERR_OK) { |
|
return err; |
|
} |
|
struct zts_sockaddr_in* in4 = (struct zts_sockaddr_in*)&ss; |
|
zts_inet_ntop(family, &(in4->sin_addr), dst, ZTS_INET6_ADDRSTRLEN); |
|
} |
|
if (family == ZTS_AF_INET6) { |
|
struct zts_sockaddr_storage ss; |
|
int err = ZTS_ERR_OK; |
|
if ((err = zts_addr_get(net_id, family, &ss)) != ZTS_ERR_OK) { |
|
return err; |
|
} |
|
struct zts_sockaddr_in6* in6 = (struct zts_sockaddr_in6*)&ss; |
|
zts_inet_ntop(family, &(in6->sin6_addr), dst, ZTS_INET6_ADDRSTRLEN); |
|
} |
|
return ZTS_ERR_OK; |
|
} |
|
|
|
int zts_addr_get_all(uint64_t net_id, struct zts_sockaddr_storage* addr, unsigned int* count) |
|
{ |
|
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); |
|
return zts_service->getAllAssignedAddr(net_id, addr, count); |
|
} |
|
|
|
int zts_core_lock_obtain() |
|
{ |
|
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); |
|
zts_service->obtainLock(); |
|
return ZTS_ERR_OK; |
|
} |
|
|
|
int zts_core_lock_release() |
|
{ |
|
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); |
|
zts_service->releaseLock(); |
|
return ZTS_ERR_OK; |
|
} |
|
|
|
int zts_core_query_addr_count(uint64_t net_id) |
|
{ |
|
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); |
|
return zts_service->addressCount(net_id); |
|
} |
|
|
|
int zts_core_query_addr(uint64_t net_id, unsigned int idx, char* addr, unsigned int len) |
|
{ |
|
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); |
|
return zts_service->getAddrAtIdx(net_id, idx, addr, len); |
|
} |
|
|
|
int zts_core_query_route_count(uint64_t net_id) |
|
{ |
|
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); |
|
return zts_service->routeCount(net_id); |
|
} |
|
|
|
int zts_core_query_route( |
|
uint64_t net_id, |
|
unsigned int idx, |
|
char* target, |
|
char* via, |
|
unsigned int len, |
|
uint16_t* flags, |
|
uint16_t* metric) |
|
{ |
|
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); |
|
return zts_service->getRouteAtIdx(net_id, idx, target, via, len, flags, metric); |
|
} |
|
|
|
int zts_core_query_path_count(uint64_t peer_id) |
|
{ |
|
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); |
|
return zts_service->pathCount(peer_id); |
|
} |
|
int zts_core_query_path(uint64_t peer_id, unsigned int idx, char* path, unsigned int len) |
|
{ |
|
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); |
|
return zts_service->getPathAtIdx(peer_id, idx, path, len); |
|
} |
|
|
|
int zts_core_query_mc_count(uint64_t net_id) |
|
{ |
|
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); |
|
return zts_service->multicastSubCount(net_id); |
|
} |
|
int zts_core_query_mc(uint64_t net_id, unsigned int idx, uint64_t* mac, uint32_t* adi) |
|
{ |
|
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); |
|
return zts_service->getMulticastSubAtIdx(net_id, idx, mac, adi); |
|
} |
|
|
|
int zts_net_join(const uint64_t net_id) |
|
{ |
|
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); |
|
return zts_service->join(net_id); |
|
} |
|
|
|
int zts_net_leave(const uint64_t net_id) |
|
{ |
|
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); |
|
return zts_service->leave(net_id); |
|
} |
|
|
|
int zts_net_transport_is_ready(const uint64_t net_id) |
|
{ |
|
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); |
|
return zts_service->networkIsReady(net_id); |
|
} |
|
|
|
uint64_t zts_net_get_mac(uint64_t net_id) |
|
{ |
|
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); |
|
return zts_service->getMACAddress(net_id); |
|
} |
|
|
|
ZTS_API int ZTCALL zts_net_get_mac_str(uint64_t net_id, char* dst, unsigned int len) |
|
{ |
|
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); |
|
if (! dst || len < ZTS_MAC_ADDRSTRLEN) { |
|
return ZTS_ERR_ARG; |
|
} |
|
uint64_t mac = zts_service->getMACAddress(net_id); |
|
OSUtils::ztsnprintf( |
|
dst, |
|
ZTS_MAC_ADDRSTRLEN, |
|
"%x:%x:%x:%x:%x:%x", |
|
(mac >> 48) & 0xFF, |
|
(mac >> 32) & 0xFF, |
|
(mac >> 24) & 0xFF, |
|
(mac >> 16) & 0xFF, |
|
(mac >> 8) & 0xFF, |
|
(mac >> 0) & 0xFF); |
|
return ZTS_ERR_OK; |
|
} |
|
|
|
int zts_net_get_broadcast(uint64_t net_id) |
|
{ |
|
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); |
|
return zts_service->getNetworkBroadcast(net_id); |
|
} |
|
|
|
int zts_net_get_mtu(uint64_t net_id) |
|
{ |
|
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); |
|
return zts_service->getNetworkMTU(net_id); |
|
} |
|
|
|
int zts_net_get_name(uint64_t net_id, char* dst, unsigned int len) |
|
{ |
|
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); |
|
return zts_service->getNetworkName(net_id, dst, len); |
|
} |
|
|
|
int zts_net_get_status(uint64_t net_id) |
|
{ |
|
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); |
|
return zts_service->getNetworkStatus(net_id); |
|
} |
|
|
|
int zts_net_get_type(uint64_t net_id) |
|
{ |
|
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); |
|
return zts_service->getNetworkType(net_id); |
|
} |
|
|
|
int zts_route_is_assigned(uint64_t net_id, unsigned int family) |
|
{ |
|
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); |
|
return zts_service->networkHasRoute(net_id, family); |
|
} |
|
|
|
// Start a ZeroTier NodeService background thread |
|
#if defined(__WINDOWS__) |
|
DWORD WINAPI _runNodeService(LPVOID arg) |
|
#else |
|
void* _runNodeService(void* arg) |
|
#endif |
|
{ |
|
ZTS_UNUSED_ARG(arg); |
|
#if defined(__APPLE__) |
|
// pthread_setname_np(ZTS_SERVICE_THREAD_NAME); |
|
#endif |
|
try { |
|
zts_service->run(); |
|
// Begin shutdown |
|
service_m.lock(); |
|
zts_events->clrState(ZTS_STATE_NODE_RUNNING); |
|
delete zts_service; |
|
zts_service = (NodeService*)0; |
|
service_m.unlock(); |
|
events_m.lock(); |
|
zts_util_delay(ZTS_CALLBACK_PROCESSING_INTERVAL * 2); |
|
if (zts_events) { |
|
zts_events->disable(); |
|
} |
|
events_m.unlock(); |
|
} |
|
catch (...) { |
|
} |
|
#ifndef __WINDOWS__ |
|
pthread_exit(0); |
|
#endif |
|
return NULL; |
|
} |
|
|
|
int zts_node_start() |
|
{ |
|
ACQUIRE_SERVICE_OFFLINE(); |
|
// Start TCP/IP stack |
|
zts_lwip_driver_init(); |
|
// Start callback thread |
|
int res = ZTS_ERR_OK; |
|
if (zts_events->hasCallback()) { |
|
#if defined(__WINDOWS__) |
|
HANDLE callbackThread = CreateThread(NULL, 0, cbRun, NULL, 0, NULL); |
|
// TODO: Check success |
|
#else |
|
pthread_t cbThread; |
|
if ((res = pthread_create(&cbThread, NULL, cbRun, NULL)) != 0) {} |
|
#endif |
|
#if defined(__linux__) |
|
// pthread_setname_np(cbThread, ZTS_EVENT_CALLBACK_THREAD_NAME); |
|
#endif |
|
if (res != ZTS_ERR_OK) { |
|
zts_events->clrState(ZTS_STATE_CALLBACKS_RUNNING); |
|
zts_events->clrCallback(); |
|
} |
|
zts_events->setState(ZTS_STATE_CALLBACKS_RUNNING); |
|
} |
|
// Start ZeroTier service |
|
#if defined(__WINDOWS__) |
|
HANDLE serviceThread = CreateThread(NULL, 0, _runNodeService, (void*)NULL, 0, NULL); |
|
// TODO: Check success |
|
#else |
|
pthread_t service_thread; |
|
if ((res = pthread_create(&service_thread, NULL, _runNodeService, (void*)NULL)) != 0) {} |
|
#endif |
|
#if defined(__linux__) |
|
// pthread_setname_np(service_thread, ZTS_SERVICE_THREAD_NAME); |
|
#endif |
|
if (res != ZTS_ERR_OK) { |
|
zts_events->clrState(ZTS_STATE_NODE_RUNNING); |
|
} |
|
zts_events->setState(ZTS_STATE_NODE_RUNNING); |
|
return ZTS_ERR_OK; |
|
} |
|
|
|
int zts_node_is_online() |
|
{ |
|
ACQUIRE_SERVICE(0); |
|
return zts_service->nodeIsOnline(); |
|
} |
|
|
|
uint64_t zts_node_get_id() |
|
{ |
|
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); |
|
return zts_service->getNodeId(); |
|
} |
|
|
|
int zts_node_get_port() |
|
{ |
|
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); |
|
return zts_service->getPrimaryPort(); |
|
} |
|
|
|
int zts_node_stop() |
|
{ |
|
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); |
|
zts_events->clrState(ZTS_STATE_NODE_RUNNING); |
|
zts_service->terminate(); |
|
#if defined(__WINDOWS__) |
|
WSACleanup(); |
|
#endif |
|
return ZTS_ERR_OK; |
|
} |
|
|
|
int zts_node_free() |
|
{ |
|
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); |
|
zts_events->setState(ZTS_STATE_FREE_CALLED); |
|
zts_events->clrState(ZTS_STATE_NODE_RUNNING); |
|
zts_service->terminate(); |
|
#if defined(__WINDOWS__) |
|
WSACleanup(); |
|
#endif |
|
zts_lwip_driver_shutdown(); |
|
delete zts_events; |
|
zts_events = (Events*)0; |
|
return ZTS_ERR_OK; |
|
} |
|
|
|
int zts_moon_orbit(uint64_t moon_roots_id, uint64_t moon_seed) |
|
{ |
|
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); |
|
zts_service->orbit(moon_roots_id, moon_seed); |
|
return ZTS_ERR_OK; |
|
} |
|
|
|
int zts_moon_deorbit(uint64_t moon_roots_id) |
|
{ |
|
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); |
|
zts_service->deorbit(moon_roots_id); |
|
return ZTS_ERR_OK; |
|
} |
|
|
|
int zts_stats_get_all(zts_stats_counter_t* dst) |
|
{ |
|
if (! dst) { |
|
return ZTS_ERR_ARG; |
|
} |
|
if (! transport_ok()) { |
|
return ZTS_ERR_SERVICE; |
|
} |
|
#if LWIP_STATS |
|
|
|
extern struct stats_ lwip_stats; |
|
|
|
#define lws lwip_stats |
|
|
|
/* Summarize lwIP's statistics for simplicity at the expense of specificity */ |
|
|
|
// link |
|
dst->link_tx = lws.link.xmit; |
|
dst->link_rx = lws.link.recv; |
|
dst->link_drop = lws.link.drop; |
|
dst->link_err = lws.link.chkerr + lws.link.lenerr + lws.link.memerr + lws.link.rterr + lws.link.proterr |
|
+ lws.link.opterr + lws.link.err; |
|
// etharp |
|
dst->etharp_tx = lws.etharp.xmit; |
|
dst->etharp_rx = lws.etharp.recv; |
|
dst->etharp_drop = lws.etharp.drop; |
|
dst->etharp_err = lws.etharp.chkerr + lws.etharp.lenerr + lws.etharp.memerr + lws.etharp.rterr + lws.etharp.proterr |
|
+ lws.etharp.opterr + lws.etharp.err; |
|
// ip4 |
|
dst->ip4_tx = lws.ip.xmit; |
|
dst->ip4_rx = lws.ip.recv; |
|
dst->ip4_drop = lws.ip.drop; |
|
dst->ip4_err = lws.ip.chkerr + lws.ip.lenerr + lws.ip.memerr + lws.ip.rterr + lws.ip.proterr + lws.ip.opterr |
|
+ lws.ip.err + lws.ip_frag.chkerr + lws.ip_frag.lenerr + lws.ip_frag.memerr + lws.ip_frag.rterr |
|
+ lws.ip_frag.proterr + lws.ip_frag.opterr + lws.ip_frag.err; |
|
// ip6 |
|
dst->ip6_tx = lws.ip6.xmit; |
|
dst->ip6_rx = lws.ip6.recv; |
|
dst->ip6_drop = lws.ip6.drop; |
|
dst->ip6_err = lws.ip6.chkerr + lws.ip6.lenerr + lws.ip6.memerr + lws.ip6.rterr + lws.ip6.proterr + lws.ip6.opterr |
|
+ lws.ip6.err + lws.ip6_frag.chkerr + lws.ip6_frag.lenerr + lws.ip6_frag.memerr + lws.ip6_frag.rterr |
|
+ lws.ip6_frag.proterr + lws.ip6_frag.opterr + lws.ip6_frag.err; |
|
|
|
// icmp4 |
|
dst->icmp4_tx = lws.icmp.xmit; |
|
dst->icmp4_rx = lws.icmp.recv; |
|
dst->icmp4_drop = lws.icmp.drop; |
|
dst->icmp4_err = lws.icmp.chkerr + lws.icmp.lenerr + lws.icmp.memerr + lws.icmp.rterr + lws.icmp.proterr |
|
+ lws.icmp.opterr + lws.icmp.err; |
|
// icmp6 |
|
dst->icmp6_tx = lws.icmp6.xmit; |
|
dst->icmp6_rx = lws.icmp6.recv; |
|
dst->icmp6_drop = lws.icmp6.drop; |
|
dst->icmp6_err = lws.icmp6.chkerr + lws.icmp6.lenerr + lws.icmp6.memerr + lws.icmp6.rterr + lws.icmp6.proterr |
|
+ lws.icmp6.opterr + lws.icmp6.err; |
|
// udp |
|
dst->udp_tx = lws.udp.xmit; |
|
dst->udp_rx = lws.udp.recv; |
|
dst->udp_drop = lws.udp.drop; |
|
dst->udp_err = lws.udp.chkerr + lws.udp.lenerr + lws.udp.memerr + lws.udp.rterr + lws.udp.proterr + lws.udp.opterr |
|
+ lws.udp.err; |
|
// tcp |
|
dst->tcp_tx = lws.tcp.xmit; |
|
dst->tcp_rx = lws.tcp.recv; |
|
dst->tcp_drop = lws.tcp.drop; |
|
dst->tcp_err = lws.tcp.chkerr + lws.tcp.lenerr + lws.tcp.memerr + lws.tcp.rterr + lws.tcp.proterr + lws.tcp.opterr |
|
+ lws.tcp.err; |
|
// nd6 |
|
dst->nd6_tx = lws.nd6.xmit; |
|
dst->nd6_rx = lws.nd6.recv; |
|
dst->nd6_drop = lws.nd6.drop; |
|
dst->nd6_err = lws.nd6.chkerr + lws.nd6.lenerr + lws.nd6.memerr + lws.nd6.rterr + lws.nd6.proterr + lws.nd6.opterr |
|
+ lws.nd6.err; |
|
|
|
// TODO: Add mem and sys stats |
|
|
|
return ZTS_ERR_OK; |
|
#else |
|
return ZTS_ERR_NO_RESULT; |
|
#endif |
|
#undef lws |
|
} |
|
|
|
#ifdef __cplusplus |
|
} |
|
#endif |
|
|
|
} // namespace ZeroTier
|
|
|