From c456a87f97a35a8444229370b0d8e6696bb544d3 Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Mon, 26 Apr 2021 21:55:01 -0700 Subject: [PATCH] Add zts_core_query_ and world sub-APIs. Adjust event subsystem --- CMakeLists.txt | 13 +- examples/c/adhoc.c | 7 +- examples/c/callbackapi.c | 13 +- examples/c/client.c | 6 +- examples/c/customroots.c | 119 +++++++ examples/c/nonblockingclient.c | 6 +- examples/c/nonblockingserver.c | 4 +- examples/c/pingable-node.c | 8 +- examples/c/server.c | 7 +- examples/c/statistics.c | 4 +- include/ZeroTierSockets.h | 408 +++++++++++++++--------- src/Central.cpp | 14 +- src/Controls.cpp | 237 ++++++++------ src/Debug.hpp | 41 +-- src/Events.cpp | 28 +- src/Events.hpp | 42 +-- src/NodeService.cpp | 554 +++++++++++++++++---------------- src/NodeService.hpp | 194 +++++++----- src/Sockets.cpp | 52 +--- src/Utilities.cpp | 96 +++++- src/VirtualTap.cpp | 40 +-- src/VirtualTap.hpp | 14 +- 22 files changed, 1117 insertions(+), 790 deletions(-) create mode 100644 examples/c/customroots.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 92f9d108..eef216d4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 3.0) project(zt) find_package(Threads) +set (CMAKE_BUILD_PARALLEL_LEVEL 8) + # ------------------------------------------------------------------------------ # | PLATFORM DETECTION | # ------------------------------------------------------------------------------ @@ -101,7 +103,7 @@ if (ZTS_ENABLE_PINVOKE) set(ALLOW_INSTALL_TARGET FALSE) set(BUILD_HOST_SELFTEST FALSE) # Sources and libraries - set(LANG_WRAPPER_FILE ${LIBZT_SRC_DIR}/bindings/csharp/*.cpp) + set(LANG_WRAPPER_FILE ${LIBZT_SRC_DIR}/bindings/csharp/*.cxx) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DZTS_ENABLE_PINVOKE=1") endif() @@ -119,7 +121,7 @@ if (ZTS_ENABLE_PYTHON) # Sources and libraries find_package(PythonLibs REQUIRED) include_directories(${PYTHON_INCLUDE_DIRS}) - set(LANG_WRAPPER_FILE ${LIBZT_SRC_DIR}/bindings/python/*.cpp) + set(LANG_WRAPPER_FILE ${LIBZT_SRC_DIR}/bindings/python/*.cxx) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DZTS_ENABLE_PYTHON=1") endif() @@ -131,7 +133,7 @@ if (ZTS_ENABLE_JAVA) set(ALLOW_INSTALL_TARGET FALSE) set(BUILD_HOST_SELFTEST FALSE) set(ZTS_ENABLE_STATS FALSE) - set(LANG_WRAPPER_FILE ${LIBZT_SRC_DIR}/bindings/java/*.cpp) + set(LANG_WRAPPER_FILE ${LIBZT_SRC_DIR}/bindings/java/*.cxx) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DZTS_ENABLE_JAVA=1") endif() @@ -286,6 +288,10 @@ if(BUILD_HOST_EXAMPLES) ${PROJ_DIR}/examples/c/nostorage.c) target_link_libraries(nostorage ${STATIC_LIB_NAME}) + add_executable(customroots + ${PROJ_DIR}/examples/c/customroots.c) + target_link_libraries(customroots ${STATIC_LIB_NAME}) + add_executable(client ${PROJ_DIR}/examples/c/client.c) target_link_libraries(client ${STATIC_LIB_NAME}) @@ -316,6 +322,7 @@ set(SILENCE "-Wno-missing-field-initializers \ -Wno-tautological-constant-out-of-range-compare \ -Wno-parentheses-equality") +#set(ZT_FLAGS "${ZT_FLAGS} -DNO_GETADDRINFO=1") set(ZT_FLAGS "${ZT_FLAGS} -DZT_USE_MINIUPNPC=1") set(ZT_FLAGS "${ZT_FLAGS} -D_USING_LWIP_DEFINITIONS_=0") diff --git a/examples/c/adhoc.c b/examples/c/adhoc.c index 6ce0a7ea..b36177a7 100644 --- a/examples/c/adhoc.c +++ b/examples/c/adhoc.c @@ -44,7 +44,7 @@ int main(int argc, char** argv) uint16_t adhocStartPort = atoi(argv[1]); // Start of port range your application will use uint16_t adhocEndPort = atoi(argv[2]); // End of port range your application will use - uint64_t net_id = zts_net_compute_adhoc_id(adhocStartPort, adhocEndPort); + long long int net_id = zts_net_compute_adhoc_id(adhocStartPort, adhocEndPort); // At least 64 bits // Start node and get identity @@ -71,15 +71,14 @@ int main(int argc, char** argv) exit(1); } printf("Waiting for join to complete\n"); - while (zts_net_count() < 1) { + while (! zts_net_transport_is_ready(net_id)) { zts_util_delay(50); } // Get address char ipstr[ZTS_IP_MAX_STR_LEN] = { 0 }; - if ((err = zts_addr_compute_rfc4193_str(net_id, node_id, ipstr, ZTS_IP_MAX_STR_LEN)) - != ZTS_ERR_OK) { + if ((err = zts_addr_compute_rfc4193_str(net_id, node_id, ipstr, ZTS_IP_MAX_STR_LEN)) != ZTS_ERR_OK) { printf("Unable to compute address (error = %d). Exiting.\n", err); exit(1); } diff --git a/examples/c/callbackapi.c b/examples/c/callbackapi.c index 794112cd..5c1441b7 100644 --- a/examples/c/callbackapi.c +++ b/examples/c/callbackapi.c @@ -23,9 +23,7 @@ void on_zts_event(void* msgPtr) } // Virtual network events if (msg->event_code == ZTS_EVENT_NETWORK_NOT_FOUND) { - printf( - "ZTS_EVENT_NETWORK_NOT_FOUND --- Are you sure %llx is a valid network?\n", - msg->network->net_id); + printf("ZTS_EVENT_NETWORK_NOT_FOUND --- Are you sure %llx is a valid network?\n", msg->network->net_id); } if (msg->event_code == ZTS_EVENT_NETWORK_ACCESS_DENIED) { printf( @@ -44,10 +42,7 @@ void on_zts_event(void* msgPtr) char ipstr[ZTS_INET6_ADDRSTRLEN] = { 0 }; struct zts_sockaddr_in6* in6 = (struct zts_sockaddr_in6*)&(msg->addr->addr); zts_inet_ntop(ZTS_AF_INET6, &(in6->sin6_addr), ipstr, ZTS_INET6_ADDRSTRLEN); - printf( - "ZTS_EVENT_ADDR_NEW_IP6 --- Join %llx and ping me at %s\n", - msg->addr->net_id, - ipstr); + printf("ZTS_EVENT_ADDR_NEW_IP6 --- Join %llx and ping me at %s\n", msg->addr->net_id, ipstr); } // To see more exhaustive examples look at test/selftest.c @@ -60,7 +55,7 @@ int main(int argc, char** argv) printf("pingable-node \n"); exit(0); } - uint64_t net_id = strtoull(argv[1], NULL, 16); + long long int net_id = strtoull(argv[1], NULL, 16); // At least 64 bits zts_init_set_event_handler(&on_zts_event); @@ -87,7 +82,7 @@ int main(int argc, char** argv) } printf("Waiting for join to complete\n"); - while (zts_net_count() < 1) { + while (! zts_net_transport_is_ready(net_id)) { zts_util_delay(50); } diff --git a/examples/c/client.c b/examples/c/client.c index e64bbecd..3b63381c 100644 --- a/examples/c/client.c +++ b/examples/c/client.c @@ -18,7 +18,7 @@ int main(int argc, char** argv) exit(0); } char* storage_path = argv[1]; - uint64_t net_id = strtoull(argv[2], NULL, 16); + long long int net_id = strtoull(argv[2], NULL, 16); // At least 64 bits char* remote_addr = argv[3]; int remote_port = atoi(argv[4]); int err = ZTS_ERR_OK; @@ -40,7 +40,7 @@ int main(int argc, char** argv) while (! zts_node_is_online()) { zts_util_delay(50); } - printf("Public identity (node ID) is %llx\n", zts_node_get_id()); + printf("Public identity (node ID) is %llx\n", (long long int)zts_node_get_id()); // Join network @@ -51,7 +51,7 @@ int main(int argc, char** argv) } printf("Don't forget to authorize this device in my.zerotier.com or the web API!\n"); printf("Waiting for join to complete\n"); - while (zts_net_count() < 1) { + while (! zts_net_transport_is_ready(net_id)) { zts_util_delay(50); } diff --git a/examples/c/customroots.c b/examples/c/customroots.c new file mode 100644 index 00000000..8f05e7ae --- /dev/null +++ b/examples/c/customroots.c @@ -0,0 +1,119 @@ +/** + * libzt C API example + * + * An example demonstrating how to define your own planet. In this example + * we limit the roots to US-only. + */ + +#include "ZeroTierSockets.h" + +#include +#include + +void print_peer_details(const char* msg, zts_peer_info_t* d) +{ + printf(" %s\n", msg); + printf("\t- peer : %llx\n", d->address); + printf("\t- role : %d\n", d->role); + printf("\t- latency : %d\n", d->latency); + printf("\t- version : %d.%d.%d\n", d->ver_major, d->ver_minor, d->ver_rev); + printf("\t- path_count : %d\n", d->path_count); + printf("\t- paths:\n"); + + // Print all known paths for each peer + for (unsigned int j = 0; j < d->path_count; j++) { + char ipstr[ZTS_INET6_ADDRSTRLEN] = { 0 }; + int port = 0; + struct zts_sockaddr* sa = (struct zts_sockaddr*)&(d->paths[j].address); + if (sa->sa_family == ZTS_AF_INET) { + struct zts_sockaddr_in* in4 = (struct zts_sockaddr_in*)sa; + zts_inet_ntop(ZTS_AF_INET, &(in4->sin_addr), ipstr, ZTS_INET_ADDRSTRLEN); + port = ntohs(in4->sin_port); + } + if (sa->sa_family == ZTS_AF_INET6) { + struct zts_sockaddr_in6* in6 = (struct zts_sockaddr_in6*)sa; + zts_inet_ntop(ZTS_AF_INET6, &(in6->sin6_addr), ipstr, ZTS_INET6_ADDRSTRLEN); + } + printf("\t - %15s : %6d\n", ipstr, port); + } + printf("\n\n"); +} + +void on_zts_event(void* msgPtr) +{ + zts_event_msg_t* msg = (zts_event_msg_t*)msgPtr; + printf("event_code = %d\n", msg->event_code); + + if (msg->peer) { + if (msg->peer->role != ZTS_PEER_ROLE_PLANET) { + return; // Don't print controllers and ordinary nodes. + } + } + if (msg->event_code == ZTS_EVENT_PEER_DIRECT) { + print_peer_details("ZTS_EVENT_PEER_DIRECT", msg->peer); + } + if (msg->event_code == ZTS_EVENT_PEER_RELAY) { + print_peer_details("ZTS_EVENT_PEER_RELAY", msg->peer); + } +} + +int main() +{ + // World generation + + // Buffers that will be filled after generating the world + char world_data_out[4096] = { 0 }; // (binary) Your new world definition + unsigned int world_len = 0; + unsigned int prev_key_len = 0; + unsigned int curr_key_len = 0; + char prev_key[4096] = { 0 }; // (binary) (optional) For updating a world + char curr_key[4096] = { 0 }; // (binary) You should save this + + // Arbitrary World ID + uint64_t id = 149604618; + + // Timestamp indicating when this world was generated + uint64_t ts = 1567191349589ULL; + + // struct containing public keys and stable IP endpoints for roots + zts_world_t world = { 0 }; + + world.public_id_str[0] = + "992fcf1db7:0:" + "206ed59350b31916f749a1f85dffb3a8787dcbf83b8c6e9448d4e3ea0e3369301be716c3609344a9d1533850fb4460c5" + "0af43322bcfc8e13d3301a1f1003ceb6"; + world.endpoint_ip_str[0][0] = "195.181.173.159/9993"; + world.endpoint_ip_str[0][1] = "2a02:6ea0:c024::/9993"; + + // Generate world + + zts_util_world_new(&world_data_out, &world_len, &prev_key, &prev_key_len, &curr_key, &curr_key_len, id, ts, &world); + + printf("world_data_out= "); + for (int i = 0; i < world_len; i++) { + if (i > 0) { + printf(","); + } + printf("0x%.2x", (unsigned char)world_data_out[i]); + } + printf("\n"); + printf("world_len = %d\n", world_len); + printf("prev_key_len = %d\n", prev_key_len); + printf("curr_key_len = %d\n", curr_key_len); + + // Now, initialize node and use newly-generated world definition + + zts_init_set_world(&world_data_out, world_len); + zts_init_set_event_handler(&on_zts_event); + zts_init_from_storage("."); + + // Start node + + zts_node_start(); + + while (1) { + zts_util_delay(500); + } + + return zts_node_stop(); +} diff --git a/examples/c/nonblockingclient.c b/examples/c/nonblockingclient.c index b0943d75..7fdaed2f 100644 --- a/examples/c/nonblockingclient.c +++ b/examples/c/nonblockingclient.c @@ -18,7 +18,7 @@ int main(int argc, char** argv) exit(0); } char* storage_path = argv[1]; - uint64_t net_id = strtoull(argv[2], NULL, 16); + long long int net_id = strtoull(argv[2], NULL, 16); // At least 64 bits char* remote_addr = argv[3]; int remote_port = atoi(argv[4]); int err = ZTS_ERR_OK; @@ -42,7 +42,7 @@ int main(int argc, char** argv) zts_util_delay(50); } - printf("Public identity (node ID) is %llx\n", zts_node_get_id()); + printf("Public identity (node ID) is %llx\n", (long long int)zts_node_get_id()); printf("Joining network %llx\n", net_id); if (zts_net_join(net_id) != ZTS_ERR_OK) { @@ -52,7 +52,7 @@ int main(int argc, char** argv) printf("Don't forget to authorize this device in my.zerotier.com or the web API!\n"); printf("Waiting for join to complete\n"); - while (zts_net_count() < 1) { + while (! zts_net_transport_is_ready(net_id)) { zts_util_delay(50); } diff --git a/examples/c/nonblockingserver.c b/examples/c/nonblockingserver.c index 2bdfeef7..cf2d6b48 100644 --- a/examples/c/nonblockingserver.c +++ b/examples/c/nonblockingserver.c @@ -18,7 +18,7 @@ int main(int argc, char** argv) exit(0); } char* storage_path = argv[1]; - uint64_t net_id = strtoull(argv[2], NULL, 16); + long long int net_id = strtoull(argv[2], NULL, 16); // At least 64 bits char* local_addr = argv[3]; int local_port = atoi(argv[4]); int fd, accfd; @@ -53,7 +53,7 @@ int main(int argc, char** argv) printf("Don't forget to authorize this device in my.zerotier.com or the web API!\n"); printf("Waiting for join to complete\n"); - while (zts_net_count() < 1) { + while (! zts_net_transport_is_ready(net_id)) { zts_util_delay(50); } diff --git a/examples/c/pingable-node.c b/examples/c/pingable-node.c index 3c098d34..0767de86 100644 --- a/examples/c/pingable-node.c +++ b/examples/c/pingable-node.c @@ -16,7 +16,7 @@ int main(int argc, char** argv) printf("pingable-node \n"); exit(0); } - uint64_t net_id = strtoull(argv[1], NULL, 16); + long long int net_id = strtoull(argv[1], NULL, 16); // At least 64 bits printf("Starting node...\n"); zts_node_start(); @@ -26,9 +26,9 @@ int main(int argc, char** argv) zts_util_delay(50); } - printf("My public identity (node ID) is %llx\n", zts_node_get_id()); + printf("My public identity (node ID) is %llx\n", (long long int)zts_node_get_id()); char keypair[ZTS_ID_STR_BUF_LEN] = { 0 }; - uint16_t len = ZTS_ID_STR_BUF_LEN; + unsigned int len = ZTS_ID_STR_BUF_LEN; if (zts_node_get_id_pair(keypair, &len) != ZTS_ERR_OK) { printf("Error getting identity keypair. Exiting.\n"); } @@ -41,7 +41,7 @@ int main(int argc, char** argv) } printf("Waiting for join to complete\n"); - while (zts_net_count() < 1) { + while (! zts_net_transport_is_ready(net_id)) { zts_util_delay(50); } diff --git a/examples/c/server.c b/examples/c/server.c index 206ddad4..0d23b6ff 100644 --- a/examples/c/server.c +++ b/examples/c/server.c @@ -18,7 +18,7 @@ int main(int argc, char** argv) exit(0); } char* storage_path = argv[1]; - uint64_t net_id = strtoull(argv[2], NULL, 16); + long long int net_id = strtoull(argv[2], NULL, 16); // At least 64 bits char* local_addr = argv[3]; int local_port = atoi(argv[4]); int fd, accfd; @@ -52,7 +52,7 @@ int main(int argc, char** argv) } printf("Don't forget to authorize this device in my.zerotier.com or the web API!\n"); printf("Waiting for join to complete\n"); - while (zts_net_count() < 1) { + while (! zts_net_transport_is_ready(net_id)) { zts_util_delay(50); } @@ -77,8 +77,7 @@ int main(int argc, char** argv) char remote_addr[ZTS_INET6_ADDRSTRLEN] = { 0 }; int remote_port = 0; int len = ZTS_INET6_ADDRSTRLEN; - if ((accfd = zts_simple_tcp_server(local_addr, local_port, remote_addr, len, &remote_port)) - < 0) { + if ((accfd = zts_simple_tcp_server(local_addr, local_port, remote_addr, len, &remote_port)) < 0) { printf("Error (fd=%d, zts_errno=%d). Exiting.\n", accfd, zts_errno); exit(1); } diff --git a/examples/c/statistics.c b/examples/c/statistics.c index 05e45e4e..87e2740b 100644 --- a/examples/c/statistics.c +++ b/examples/c/statistics.c @@ -17,7 +17,7 @@ int main(int argc, char** argv) printf("pingable-node \n"); exit(0); } - uint64_t net_id = strtoull(argv[1], NULL, 16); + long long int net_id = strtoull(argv[1], NULL, 16); // At least 64 bits printf("Starting node...\n"); zts_node_start(); @@ -42,7 +42,7 @@ int main(int argc, char** argv) } printf("Waiting for join to complete\n"); - while (zts_net_count() < 1) { + while (! zts_net_transport_is_ready(net_id)) { zts_util_delay(50); } diff --git a/include/ZeroTierSockets.h b/include/ZeroTierSockets.h index 685d6d73..bbae5d58 100644 --- a/include/ZeroTierSockets.h +++ b/include/ZeroTierSockets.h @@ -467,10 +467,8 @@ typedef void (*CppCallback)(void* msg); #define ZTS_IOC_IN 0x80000000UL #define ZTS_IOC_INOUT (ZTS_IOC_IN | ZTS_IOC_OUT) #define ZTS_IO(x, y) (ZTS_IOC_VOID | ((x) << 8) | (y)) -#define ZTS_IOR(x, y, t) \ - (ZTS_IOC_OUT | (((long)sizeof(t) & ZTS_IOCPARM_MASK) << 16) | ((x) << 8) | (y)) -#define ZTS_IOW(x, y, t) \ - (ZTS_IOC_IN | (((long)sizeof(t) & ZTS_IOCPARM_MASK) << 16) | ((x) << 8) | (y)) +#define ZTS_IOR(x, y, t) (ZTS_IOC_OUT | (((long)sizeof(t) & ZTS_IOCPARM_MASK) << 16) | ((x) << 8) | (y)) +#define ZTS_IOW(x, y, t) (ZTS_IOC_IN | (((long)sizeof(t) & ZTS_IOCPARM_MASK) << 16) | ((x) << 8) | (y)) // ioctl() commands #define ZTS_FIONREAD ZTS_IOR('f', 127, unsigned long) #define ZTS_FIONBIO ZTS_IOW('f', 126, unsigned long) @@ -922,8 +920,19 @@ typedef struct { zts_path_t paths[ZTS_MAX_PEER_NETWORK_PATHS]; } zts_peer_info_t; +#define ZTS_MAX_NUM_ROOTS 16 +#define ZTS_MAX_ENDPOINTS_PER_ROOT 32 + +/** + * Structure used to specify a root topology (aka a world) + */ +typedef struct { + char* public_id_str[ZTS_MAX_NUM_ROOTS]; + char* endpoint_ip_str[ZTS_MAX_NUM_ROOTS][ZTS_MAX_ENDPOINTS_PER_ROOT]; +} zts_world_t; + /** - * A structure used to convey information about a virtual network + * Structure used to convey information about a virtual network * interface (netif) to a user application. */ typedef struct { @@ -1096,8 +1105,7 @@ ZTS_API void ZTCALL zts_central_clear_resp_buf(); * size) * @return `ZTS_ERR_OK` if successful, `ZTS_ERR_ARG` if invalid argument. */ -ZTS_API int ZTCALL -zts_central_init(const char* url_str, const char* token_str, char* resp_buf, uint32_t buf_len); +ZTS_API int ZTCALL zts_central_init(const char* url_str, const char* token_str, char* resp_buf, uint32_t buf_len); ZTS_API void ZTCALL zts_central_cleanup(); @@ -1177,8 +1185,7 @@ ZTS_API int ZTCALL zts_central_member_get(int* http_resp_code, uint64_t net_id, * * @return Standard HTTP response codes. */ -ZTS_API int ZTCALL -zts_central_member_update(int* http_resp_code, uint64_t net_id, uint64_t node_id, char* post_data); +ZTS_API int ZTCALL zts_central_member_update(int* http_resp_code, uint64_t net_id, uint64_t node_id, char* post_data); /** * @brief Authorize or (De)authorize a node on a network. This operation @@ -1189,8 +1196,7 @@ zts_central_member_update(int* http_resp_code, uint64_t net_id, uint64_t node_id * @param is_authed Boolean value for whether this node should be authorized * @return `ZTS_ERR_OK` if successful, `ZTS_ERR_ARG` if invalid argument. */ -ZTS_API int ZTCALL -zts_central_node_auth(int* http_resp_code, uint64_t net_id, uint64_t node_id, uint8_t is_authed); +ZTS_API int ZTCALL zts_central_node_auth(int* http_resp_code, uint64_t net_id, uint64_t node_id, uint8_t is_authed); /** * @brief Get All Members of a Network. @@ -1221,7 +1227,7 @@ ZTS_API int ZTCALL zts_central_net_get_members(int* http_resp_code, uint64_t net * to the number of bytes copied. * @return `ZTS_ERR_OK` if successful, `ZTS_ERR_ARG` if invalid argument. */ -ZTS_API int ZTCALL zts_id_new(char* key, uint16_t* key_buf_len); +ZTS_API int ZTCALL zts_id_new(char* key, unsigned int* key_buf_len); /** * @brief Verifies that a key-pair is valid. Checks formatting and pairing of @@ -1231,7 +1237,7 @@ ZTS_API int ZTCALL zts_id_new(char* key, uint16_t* key_buf_len); * @param len Length of key-pair buffer * @return `1` if true, `0` if false. */ -ZTS_API int ZTCALL zts_id_pair_is_valid(const char* key, int len); +ZTS_API int ZTCALL zts_id_pair_is_valid(const char* key, unsigned int len); /** * @brief Instruct ZeroTier to look for node identity files at the given location. This is an @@ -1262,7 +1268,7 @@ ZTS_API int ZTCALL zts_init_from_storage(const char* path); * @return `ZTS_ERR_OK` if successful, `ZTS_ERR_SERVICE` if the node * experiences a problem, `ZTS_ERR_ARG` if invalid argument. */ -ZTS_API int ZTCALL zts_init_from_memory(const char* key, uint16_t len); +ZTS_API int ZTCALL zts_init_from_memory(const char* key, unsigned int len); /** * @brief Set the event handler function. This is an initialization function that can only be called @@ -1293,18 +1299,18 @@ ZTS_API int ZTCALL zts_init_set_event_handler(void (*callback)(void*)); * @return `ZTS_ERR_OK` if successful, `ZTS_ERR_SERVICE` if the node * experiences a problem, `ZTS_ERR_ARG` if invalid argument. */ -ZTS_API int ZTCALL zts_init_blacklist_if(const char* prefix, int len); +ZTS_API int ZTCALL zts_init_blacklist_if(const char* prefix, unsigned int len); /** - * @brief Present a planet definition for ZeroTier to use instead of the default. + * @brief Present a world definition for ZeroTier to use instead of the default. * This is an initialization function that can only be called before `zts_node_start()`. * - * @param planet_data Array of planet definition data (binary) + * @param world_data Array of world definition data (binary) * @param len Length of binary data * @return `ZTS_ERR_OK` if successful, `ZTS_ERR_SERVICE` if the node * experiences a problem, `ZTS_ERR_ARG` if invalid argument. */ -ZTS_API int ZTCALL zts_init_set_planet(const char* planet_data, int len); +ZTS_API int ZTCALL zts_init_set_world(const void* world_data, unsigned int len); /** * @brief Set the port to which the node should bind. This is an initialization function that can @@ -1334,7 +1340,7 @@ ZTS_API int ZTCALL zts_init_set_port(unsigned short port); * @return `ZTS_ERR_OK` if successful, `ZTS_ERR_SERVICE` if the node * experiences a problem, `ZTS_ERR_ARG` if invalid argument. */ -ZTS_API int ZTCALL zts_init_allow_net_cache(int allowed); +ZTS_API int ZTCALL zts_init_allow_net_cache(unsigned int allowed); /** * @brief Enable or disable whether the node will cache peer details (enabled @@ -1353,16 +1359,27 @@ ZTS_API int ZTCALL zts_init_allow_net_cache(int allowed); * @return `ZTS_ERR_OK` if successful, `ZTS_ERR_SERVICE` if the node * experiences a problem, `ZTS_ERR_ARG` if invalid argument. */ -ZTS_API int ZTCALL zts_init_allow_peer_cache(int allowed); +ZTS_API int ZTCALL zts_init_allow_peer_cache(unsigned int allowed); /** - * @brief Clear all initialization settings. This is an initialization function that can - * only be called before `zts_node_start()` or after `zts_node_stop()`. + * @brief Enable or disable whether the node will cache world definitions (enabled + * by default when `zts_init_from_storage()` is used.) Must be called before `zts_node_start()`. * + * @param enabled Whether or not this feature is enabled * @return `ZTS_ERR_OK` if successful, `ZTS_ERR_SERVICE` if the node - * experiences a problem. + * experiences a problem, `ZTS_ERR_ARG` if invalid argument. */ -ZTS_API int ZTCALL zts_init_clear(); +ZTS_API int ZTCALL zts_init_allow_world_cache(unsigned int allowed); + +/** + * @brief Enable or disable whether the node will cache identities (enabled + * by default when `zts_init_from_storage()` is used.) Must be called before `zts_node_start()`. + * + * @param enabled Whether or not this feature is enabled + * @return `ZTS_ERR_OK` if successful, `ZTS_ERR_SERVICE` if the node + * experiences a problem, `ZTS_ERR_ARG` if invalid argument. + */ +ZTS_API int ZTCALL zts_init_allow_id_cache(unsigned int allowed); /** * @brief Return whether an address of the given family has been assigned by the network @@ -1371,7 +1388,7 @@ ZTS_API int ZTCALL zts_init_clear(); * @param family `ZTS_AF_INET`, or `ZTS_AF_INET6` * @return `1` if true, `0` if false. */ -ZTS_API int ZTCALL zts_addr_is_assigned(uint64_t net_id, int family); +ZTS_API int ZTCALL zts_addr_is_assigned(uint64_t net_id, unsigned int family); /** * @brief Get the first-assigned IP on the given network. @@ -1384,7 +1401,7 @@ ZTS_API int ZTCALL zts_addr_is_assigned(uint64_t net_id, int family); * @return `ZTS_ERR_OK` if successful, `ZTS_ERR_SERVICE` if the node * experiences a problem, `ZTS_ERR_ARG` if invalid argument. */ -ZTS_API int ZTCALL zts_addr_get(uint64_t net_id, int family, struct zts_sockaddr_storage* addr); +ZTS_API int ZTCALL zts_addr_get(uint64_t net_id, unsigned int family, struct zts_sockaddr_storage* addr); /** * @brief Get the first-assigned IP on the given network as a null-terminated human-readable string @@ -1398,7 +1415,7 @@ ZTS_API int ZTCALL zts_addr_get(uint64_t net_id, int family, struct zts_sockaddr * @return `ZTS_ERR_OK` if successful, `ZTS_ERR_SERVICE` if the node * experiences a problem, `ZTS_ERR_ARG` if invalid argument. */ -ZTS_API int ZTCALL zts_addr_get_str(uint64_t net_id, int family, char* dst, int len); +ZTS_API int ZTCALL zts_addr_get_str(uint64_t net_id, unsigned int family, char* dst, unsigned int len); /** * @brief Get all IP addresses assigned to this node by the given network @@ -1409,7 +1426,7 @@ ZTS_API int ZTCALL zts_addr_get_str(uint64_t net_id, int family, char* dst, int * @return `ZTS_ERR_OK` if successful, `ZTS_ERR_SERVICE` if the node * experiences a problem, `ZTS_ERR_ARG` if invalid argument. */ -ZTS_API int ZTCALL zts_addr_get_all(uint64_t net_id, struct zts_sockaddr_storage* addr, int* count); +ZTS_API int ZTCALL zts_addr_get_all(uint64_t net_id, struct zts_sockaddr_storage* addr, unsigned int* count); /** * @brief Compute a `6PLANE` IPv6 address for the given Network ID and Node ID @@ -1419,10 +1436,8 @@ ZTS_API int ZTCALL zts_addr_get_all(uint64_t net_id, struct zts_sockaddr_storage * @param addr Destination structure for address * @return `ZTS_ERR_OK` if successful, `ZTS_ERR_ARG` if invalid argument. */ -ZTS_API int ZTCALL zts_addr_compute_6plane( - const uint64_t net_id, - const uint64_t node_id, - struct zts_sockaddr_storage* addr); +ZTS_API int ZTCALL +zts_addr_compute_6plane(const uint64_t net_id, const uint64_t node_id, struct zts_sockaddr_storage* addr); /** * @brief Compute `RFC4193` IPv6 address for the given Network ID and Node ID @@ -1432,10 +1447,8 @@ ZTS_API int ZTCALL zts_addr_compute_6plane( * @param addr Destination structure for address * @return `ZTS_ERR_OK` if successful, `ZTS_ERR_ARG` if invalid argument. */ -ZTS_API int ZTCALL zts_addr_compute_rfc4193( - const uint64_t net_id, - const uint64_t node_id, - struct zts_sockaddr_storage* addr); +ZTS_API int ZTCALL +zts_addr_compute_rfc4193(const uint64_t net_id, const uint64_t node_id, struct zts_sockaddr_storage* addr); /** * @brief Compute `RFC4193` IPv6 address for the given Network ID and Node ID and copy its @@ -1447,8 +1460,7 @@ ZTS_API int ZTCALL zts_addr_compute_rfc4193( * @param len Length of destination string buffer (must be exactly `ZTS_IP_MAX_STR_LEN`) * @return `ZTS_ERR_OK` if successful, `ZTS_ERR_ARG` if invalid argument. */ -ZTS_API int ZTCALL -zts_addr_compute_rfc4193_str(uint64_t net_id, uint64_t node_id, char* dst, int len); +ZTS_API int ZTCALL zts_addr_compute_rfc4193_str(uint64_t net_id, uint64_t node_id, char* dst, unsigned int len); /** * @brief Compute `6PLANE` IPv6 address for the given Network ID and Node ID and copy its @@ -1460,8 +1472,7 @@ zts_addr_compute_rfc4193_str(uint64_t net_id, uint64_t node_id, char* dst, int l * @param len Length of destination string buffer (must be exactly `ZTS_IP_MAX_STR_LEN`) * @return `ZTS_ERR_OK` if successful, `ZTS_ERR_ARG` if invalid argument. */ -ZTS_API int ZTCALL -zts_addr_compute_6plane_str(uint64_t net_id, uint64_t node_id, char* dst, int len); +ZTS_API int ZTCALL zts_addr_compute_6plane_str(uint64_t net_id, uint64_t node_id, char* dst, unsigned int len); /** * @brief Compute `RFC4193` IPv6 address for the given Network ID and Node ID @@ -1516,11 +1527,11 @@ ZTS_API int ZTCALL zts_net_join(uint64_t net_id); ZTS_API int ZTCALL zts_net_leave(uint64_t net_id); /** - * @brief Return number of joined networks + * @brief Return whether this network is ready to send and receive traffic. * - * @return Number of joined networks + * @return `1` if true, `0` if false. */ -ZTS_API int ZTCALL zts_net_count(); +ZTS_API int ZTCALL zts_net_transport_is_ready(const uint64_t net_id); /** * @brief Get the MAC Address for this node on the given network @@ -1540,7 +1551,7 @@ ZTS_API uint64_t ZTCALL zts_net_get_mac(uint64_t net_id); * * @return MAC address in string format */ -ZTS_API int ZTCALL zts_net_get_mac_str(uint64_t net_id, char* dst, int len); +ZTS_API int ZTCALL zts_net_get_mac_str(uint64_t net_id, char* dst, unsigned int len); /** * @brief Return whether broadcast is enabled on this network @@ -1570,7 +1581,7 @@ ZTS_API int ZTCALL zts_net_get_mtu(uint64_t net_id); * @return `ZTS_ERR_OK` if successful, `ZTS_ERR_SERVICE` if the node * experiences a problem, `ZTS_ERR_ARG` if invalid argument. */ -ZTS_API int ZTCALL zts_net_get_name(uint64_t net_id, char* dst, int len); +ZTS_API int ZTCALL zts_net_get_name(uint64_t net_id, char* dst, unsigned int len); /** * @brief Get the status of the network @@ -1598,7 +1609,7 @@ ZTS_API int ZTCALL zts_net_get_type(uint64_t net_id); * @param family `ZTS_AF_INET`, or `ZTS_AF_INET6` * @return `1` if true, `0` if false. */ -ZTS_API int ZTCALL zts_route_is_assigned(uint64_t net_id, int family); +ZTS_API int ZTCALL zts_route_is_assigned(uint64_t net_id, unsigned int family); /** * @brief Start the ZeroTier node. Should be called after calling the relevant @@ -1641,7 +1652,7 @@ ZTS_API uint64_t ZTCALL zts_node_get_id(); * @return `ZTS_ERR_OK` if successful, `ZTS_ERR_SERVICE` if the node * experiences a problem, `ZTS_ERR_ARG` if invalid argument. */ -ZTS_API int ZTCALL zts_node_get_id_pair(char* key, uint16_t* key_buf_len); +ZTS_API int ZTCALL zts_node_get_id_pair(char* key, unsigned int* key_buf_len); /** * @brief Get the primary port to which the node is bound. Callable only after the node has been @@ -1664,17 +1675,6 @@ ZTS_API int ZTCALL zts_node_get_port(); */ ZTS_API int ZTCALL zts_node_stop(); -/** - * @brief Restart the ZeroTier node. Callable only after the node has been started. - * - * This call will block until the node has been brought offline. Then - * it will return and the user application can then watch for the appropriate - * startup callback events. - * @return `ZTS_ERR_OK` if successful, `ZTS_ERR_SERVICE` if the node - * experiences a problem. - */ -ZTS_API int ZTCALL zts_node_restart(); - /** * @brief Stop all background threads, bring down all transport services, free all * resources. After calling this function an application restart will be @@ -1943,12 +1943,8 @@ ZTS_API int ZTCALL zts_simple_tcp_client(const char* remote_ipstr, int remote_po * @return New file descriptor if successful, `ZTS_ERR_SERVICE` if the node * experiences a problem, `ZTS_ERR_ARG` if invalid argument. Sets `zts_errno` */ -ZTS_API int ZTCALL zts_simple_tcp_server( - const char* local_ipstr, - int local_port, - char* remote_ipstr, - int len, - int* remote_port); +ZTS_API int ZTCALL +zts_simple_tcp_server(const char* local_ipstr, int local_port, char* remote_ipstr, int len, int* remote_port); /** * @brief A convenience function that takes a remote address IP string and creates @@ -2019,11 +2015,11 @@ struct zts_linger { #define ZTS_TCP_KEEPINTVL 0x0004 #define ZTS_TCP_KEEPCNT 0x0005 // IPPROTO_IPV6 options -#define ZTS_IPV6_CHECKSUM \ - 0x0007 /* RFC3542: calculate and insert the ICMPv6 checksum for raw \ +#define ZTS_IPV6_CHECKSUM \ + 0x0007 /* RFC3542: calculate and insert the ICMPv6 checksum for raw \ sockets. */ -#define ZTS_IPV6_V6ONLY \ - 0x001b /* RFC3493: boolean control to restrict ZTS_AF_INET6 sockets to \ +#define ZTS_IPV6_V6ONLY \ + 0x001b /* RFC3493: boolean control to restrict ZTS_AF_INET6 sockets to \ IPv6 communications only. */ // UDPLITE options #define ZTS_UDPLITE_SEND_CSCOV 0x01 /* sender checksum coverage */ @@ -2112,8 +2108,7 @@ typedef struct zts_ipv6_mreq { * @return `ZTS_ERR_OK` if successful, `ZTS_ERR_SERVICE` if the node * experiences a problem, `ZTS_ERR_ARG` if invalid argument. Sets `zts_errno` */ -ZTS_API int ZTCALL -zts_setsockopt(int fd, int level, int optname, const void* optval, zts_socklen_t optlen); +ZTS_API int ZTCALL zts_setsockopt(int fd, int level, int optname, const void* optval, zts_socklen_t optlen); /** * @brief Get socket options. @@ -2126,8 +2121,7 @@ zts_setsockopt(int fd, int level, int optname, const void* optval, zts_socklen_t * @return `ZTS_ERR_OK` if successful, `ZTS_ERR_SERVICE` if the node * experiences a problem, `ZTS_ERR_ARG` if invalid argument. Sets `zts_errno` */ -ZTS_API int ZTCALL -zts_getsockopt(int fd, int level, int optname, void* optval, zts_socklen_t* optlen); +ZTS_API int ZTCALL zts_getsockopt(int fd, int level, int optname, void* optval, zts_socklen_t* optlen); /** * @brief Get socket name. @@ -2169,27 +2163,20 @@ ZTS_API int ZTCALL zts_close(int fd); #undef ZTS_FD_SETSIZE // Make FD_SETSIZE match NUM_SOCKETS in socket.c #define ZTS_FD_SETSIZE MEMP_NUM_NETCONN -#define ZTS_FDSETSAFESET(n, code) \ - do { \ - if (((n)-LWIP_SOCKET_OFFSET < MEMP_NUM_NETCONN) && (((int)(n)-LWIP_SOCKET_OFFSET) >= 0)) { \ - code; \ - } \ +#define ZTS_FDSETSAFESET(n, code) \ + do { \ + if (((n)-LWIP_SOCKET_OFFSET < MEMP_NUM_NETCONN) && (((int)(n)-LWIP_SOCKET_OFFSET) >= 0)) { \ + code; \ + } \ } while (0) -#define ZTS_FDSETSAFEGET(n, code) \ - (((n)-LWIP_SOCKET_OFFSET < MEMP_NUM_NETCONN) && (((int)(n)-LWIP_SOCKET_OFFSET) >= 0) ? (code) \ - : 0) -#define ZTS_FD_SET(n, p) \ - ZTS_FDSETSAFESET( \ - n, \ - (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET) / 8] |= (1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) -#define ZTS_FD_CLR(n, p) \ - ZTS_FDSETSAFESET( \ - n, \ - (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET) / 8] &= ~(1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) -#define ZTS_FD_ISSET(n, p) \ - ZTS_FDSETSAFEGET( \ - n, \ - (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET) / 8] & (1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) +#define ZTS_FDSETSAFEGET(n, code) \ + (((n)-LWIP_SOCKET_OFFSET < MEMP_NUM_NETCONN) && (((int)(n)-LWIP_SOCKET_OFFSET) >= 0) ? (code) : 0) +#define ZTS_FD_SET(n, p) \ + ZTS_FDSETSAFESET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET) / 8] |= (1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) +#define ZTS_FD_CLR(n, p) \ + ZTS_FDSETSAFESET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET) / 8] &= ~(1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) +#define ZTS_FD_ISSET(n, p) \ + ZTS_FDSETSAFEGET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET) / 8] & (1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) #define ZTS_FD_ZERO(p) memset((void*)(p), 0, sizeof(*(p))) #elif LWIP_SOCKET_OFFSET @@ -2220,12 +2207,8 @@ typedef struct zts_timeval { * @return Number of ready file descriptors on success. `ZTS_ERR_SOCKET`, * `ZTS_ERR_SERVICE` on failure. Sets `zts_errno` */ -ZTS_API int ZTCALL zts_select( - int nfds, - zts_fd_set* readfds, - zts_fd_set* writefds, - zts_fd_set* exceptfds, - struct zts_timeval* timeout); +ZTS_API int ZTCALL +zts_select(int nfds, zts_fd_set* readfds, zts_fd_set* writefds, zts_fd_set* exceptfds, struct zts_timeval* timeout); // fnctl() commands #define ZTS_F_GETFL 0x0003 @@ -2315,13 +2298,8 @@ ZTS_API ssize_t ZTCALL zts_send(int fd, const void* buf, size_t len, int flags); * @return Number of bytes sent if successful, `ZTS_ERR_SERVICE` if the node * experiences a problem, `ZTS_ERR_ARG` if invalid argument. Sets `zts_errno` */ -ZTS_API ssize_t ZTCALL zts_sendto( - int fd, - const void* buf, - size_t len, - int flags, - const struct zts_sockaddr* addr, - zts_socklen_t addrlen); +ZTS_API ssize_t ZTCALL +zts_sendto(int fd, const void* buf, size_t len, int flags, const struct zts_sockaddr* addr, zts_socklen_t addrlen); struct zts_iovec { void* iov_base; @@ -2378,13 +2356,8 @@ ZTS_API ssize_t ZTCALL zts_recv(int fd, void* buf, size_t len, int flags); * @return Number of bytes received if successful, `ZTS_ERR_SERVICE` if the node * experiences a problem, `ZTS_ERR_ARG` if invalid argument. Sets `zts_errno` */ -ZTS_API ssize_t ZTCALL zts_recvfrom( - int fd, - void* buf, - size_t len, - int flags, - struct zts_sockaddr* addr, - zts_socklen_t* addrlen); +ZTS_API ssize_t ZTCALL +zts_recvfrom(int fd, void* buf, size_t len, int flags, struct zts_sockaddr* addr, zts_socklen_t* addrlen); /** * @brief Receive a message from remote host @@ -2731,63 +2704,161 @@ ZTS_API int ZTCALL zts_dns_set_server(uint8_t index, const zts_ip_addr* addr); ZTS_API const zts_ip_addr* ZTCALL zts_dns_get_server(uint8_t index); //----------------------------------------------------------------------------// -// Convenience functions pulled from lwIP // +// Core query sub-API (Used for simplifying high-level language wrappers) // //----------------------------------------------------------------------------// /** - * Convert numeric IP address (both versions) into `ASCII` representation. - * returns ptr to static buffer. Not reentrant. + * @brief Lock the core service so that queries about addresses, routes, paths, etc. can be + * performed. * - * @param addr IP address in network order to convert - * @return Pointer to a global static (!) buffer that holds the `ASCII` - * representation of addr + * `Notice`: `zts_core_` functions are intended to be used by high-level language wrappers. + * Only lock the core if you know *exactly* what you are doing. + * + * @return `ZTS_ERR_OK` if successful. `ZTS_ERR_SERVICE` if the core service is unavailable. */ -char* zts_ipaddr_ntoa(const zts_ip_addr* addr); +ZTS_API int ZTCALL zts_core_lock_obtain(); /** - * Convert IP address string (both versions) to numeric. - * The version is auto-detected from the string. + * @brief Lock the core service so that queries about addresses, routes, paths, etc. can be + * performed. * - * @param cp IP address string to convert - * @param addr conversion result is stored here - * @return `1` on success, `0` on error + * `Notice`: `zts_core_` functions are intended to be used by high-level language wrappers. + * Only lock the core if you know *exactly* what you are doing. + * + * @return `ZTS_ERR_OK` if successful. `ZTS_ERR_SERVICE` if the core service is unavailable. */ -int zts_ipaddr_aton(const char* cp, zts_ip_addr* addr); +ZTS_API int ZTCALL zts_core_lock_release(); /** - * Convert IPv4 and IPv6 address structures to human-readable text form. + * @brief Lock the core service so that queries about addresses, routes, paths, etc. can be + * performed. * - * @param family Address family: `ZTS_AF_INET` or `ZTS_AF_INET6` - * @param src Pointer to source address structure - * @param dst Pointer to destination character array - * @param size Size of the destination buffer - * @return On success, returns a non-null pointer to the destination character - * array + * `Notice`: `zts_core_` functions are intended to be used by high-level language wrappers. + * Only lock the core if you know *exactly* what you are doing. `zts_core_lock_obtain()` and + * `zts_core_lock_release()` must be called before and after this function. + * + * @return `ZTS_ERR_OK` if successful. `ZTS_ERR_SERVICE` if the core service is unavailable. */ -ZTS_API const char* ZTCALL -zts_inet_ntop(int family, const void* src, char* dst, zts_socklen_t size); +ZTS_API int ZTCALL zts_core_query_addr_count(uint64_t net_id); /** - * Convert C-string IPv4 and IPv6 addresses to binary form. + * @brief Lock the core service so that queries about addresses, routes, paths, etc. can be + * performed. * - * @param family Address family: `ZTS_AF_INET` or `ZTS_AF_INET6` - * @param src Pointer to source character array - * @param dst Pointer to destination address structure - * @return return `1` on success. `0` or `-1` on failure. (Does not follow regular - * `zts_*` conventions) + * `Notice`: `zts_core_` functions are intended to be used by high-level language wrappers. + * Only lock the core if you know *exactly* what you are doing. `zts_core_lock_obtain()` and + * `zts_core_lock_release()` must be called before and after this function. + * + * @return `ZTS_ERR_OK` if successful. `ZTS_ERR_SERVICE` if the core service is unavailable. */ -ZTS_API int ZTCALL zts_inet_pton(int family, const char* src, void* dst); +ZTS_API int ZTCALL zts_core_query_addr(uint64_t net_id, unsigned int idx, char* addr, unsigned int len); + +/** + * @brief Lock the core service so that queries about addresses, routes, paths, etc. can be + * performed. + * + * `Notice`: `zts_core_` functions are intended to be used by high-level language wrappers. + * Only lock the core if you know *exactly* what you are doing. `zts_core_lock_obtain()` and + * `zts_core_lock_release()` must be called before and after this function. + * + * @return `ZTS_ERR_OK` if successful. `ZTS_ERR_SERVICE` if the core service is unavailable. + */ +ZTS_API int ZTCALL zts_core_query_route_count(uint64_t net_id); + +/** + * @brief Lock the core service so that queries about addresses, routes, paths, etc. can be + * performed. + * + * `Notice`: `zts_core_` functions are intended to be used by high-level language wrappers. + * Only lock the core if you know *exactly* what you are doing. `zts_core_lock_obtain()` and + * `zts_core_lock_release()` must be called before and after this function. + * + * @return `ZTS_ERR_OK` if successful. `ZTS_ERR_SERVICE` if the core service is unavailable. + */ +ZTS_API int ZTCALL zts_core_query_route( + uint64_t net_id, + unsigned int idx, + char* target, + char* via, + unsigned int len, + uint16_t* flags, + uint16_t* metric); + +/** + * @brief Lock the core service so that queries about addresses, routes, paths, etc. can be + * performed. + * + * `Notice`: `zts_core_` functions are intended to be used by high-level language wrappers. + * Only lock the core if you know *exactly* what you are doing. `zts_core_lock_obtain()` and + * `zts_core_lock_release()` must be called before and after this function. + * + * @return `ZTS_ERR_OK` if successful. `ZTS_ERR_SERVICE` if the core service is unavailable. + */ +ZTS_API int ZTCALL zts_core_query_path_count(uint64_t peer_id); + +/** + * @brief Lock the core service so that queries about addresses, routes, paths, etc. can be + * performed. + * + * `Notice`: `zts_core_` functions are intended to be used by high-level language wrappers. + * Only lock the core if you know *exactly* what you are doing. `zts_core_lock_obtain()` and + * `zts_core_lock_release()` must be called before and after this function. + * + * @return `ZTS_ERR_OK` if successful. `ZTS_ERR_SERVICE` if the core service is unavailable. + */ +ZTS_API int ZTCALL zts_core_query_path(uint64_t peer_id, unsigned int idx, char* dst, unsigned int len); + +/** + * @brief Lock the core service so that queries about addresses, routes, paths, etc. can be + * performed. + * + * `Notice`: `zts_core_` functions are intended to be used by high-level language wrappers. + * Only lock the core if you know *exactly* what you are doing. `zts_core_lock_obtain()` and + * `zts_core_lock_release()` must be called before and after this function. + * + * @return `ZTS_ERR_OK` if successful. `ZTS_ERR_SERVICE` if the core service is unavailable. + */ +ZTS_API int ZTCALL zts_core_query_mc_count(uint64_t net_id); + +/** + * @brief Lock the core service so that queries about addresses, routes, paths, etc. can be + * performed. + * + * `Notice`: `zts_core_` functions are intended to be used by high-level language wrappers. + * Only lock the core if you know *exactly* what you are doing. `zts_core_lock_obtain()` and + * `zts_core_lock_release()` must be called before and after this function. + * + * @return `ZTS_ERR_OK` if successful. `ZTS_ERR_SERVICE` if the core service is unavailable. + */ +ZTS_API int ZTCALL zts_core_query_mc(uint64_t net_id, unsigned int idx, uint64_t* mac, uint32_t* adi); //----------------------------------------------------------------------------// // Utilities // //----------------------------------------------------------------------------// /** - * @brief Platform-agnostic delay (provided for convenience) + * @brief Generates a new world definition * - * @param interval_ms Number of milliseconds to delay + * @param world_id The desired World ID (arbitrary) + * @param ts Timestamp indicating when this generation took place */ -ZTS_API void ZTCALL zts_util_delay(long interval_ms); +ZTS_API int ZTCALL zts_util_world_new( + char* world_out, + unsigned int* world_len, + char* prev_key, + unsigned int* prev_key_len, + char* curr_key, + unsigned int* curr_key_len, + uint64_t id, + uint64_t ts, + zts_world_t* world_spec); + +/** + * @brief Platform-agnostic delay + * + * @param milliseconds How long to delay + */ +ZTS_API void ZTCALL zts_util_delay(unsigned long milliseconds); /** * @brief Return the family type of the IP string @@ -2810,10 +2881,57 @@ ZTS_API int ZTCALL zts_util_get_ip_family(const char* ipstr); */ int zts_util_ipstr_to_saddr( const char* src_ipstr, - int port, + unsigned int port, struct zts_sockaddr* dstaddr, zts_socklen_t* addrlen); +//----------------------------------------------------------------------------// +// Convenience functions pulled from lwIP // +//----------------------------------------------------------------------------// + +/** + * Convert numeric IP address (both versions) into `ASCII` representation. + * returns ptr to static buffer. Not reentrant. + * + * @param addr IP address in network order to convert + * @return Pointer to a global static (!) buffer that holds the `ASCII` + * representation of addr + */ +char* zts_ipaddr_ntoa(const zts_ip_addr* addr); + +/** + * Convert IP address string (both versions) to numeric. + * The version is auto-detected from the string. + * + * @param cp IP address string to convert + * @param addr conversion result is stored here + * @return `1` on success, `0` on error + */ +int zts_ipaddr_aton(const char* cp, zts_ip_addr* addr); + +/** + * Convert IPv4 and IPv6 address structures to human-readable text form. + * + * @param family Address family: `ZTS_AF_INET` or `ZTS_AF_INET6` + * @param src Pointer to source address structure + * @param dst Pointer to destination character array + * @param size Size of the destination buffer + * @return On success, returns a non-null pointer to the destination character + * array + */ +ZTS_API const char* ZTCALL zts_inet_ntop(int family, const void* src, char* dst, zts_socklen_t size); + +/** + * Convert C-string IPv4 and IPv6 addresses to binary form. + * + * @param family Address family: `ZTS_AF_INET` or `ZTS_AF_INET6` + * @param src Pointer to source character array + * @param dst Pointer to destination address structure + * @return return `1` on success. `0` or `-1` on failure. (Does not follow regular + * `zts_*` conventions) + */ +ZTS_API int ZTCALL zts_inet_pton(int family, const char* src, void* dst); + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/Central.cpp b/src/Central.cpp index b6e29b81..c0f17e65 100644 --- a/src/Central.cpp +++ b/src/Central.cpp @@ -84,11 +84,7 @@ void zts_central_clear_resp_buf() _resp_buf_offset = 0; } -int zts_central_init( - const char* url_str, - const char* token_str, - char* resp_buf, - uint32_t resp_buf_len) +int zts_central_init(const char* url_str, const char* token_str, char* resp_buf, uint32_t resp_buf_len) { _access_modes = ZTS_CENTRAL_READ; // Default read-only _bIsVerbose = 0; // Default disable libcurl verbose output @@ -175,11 +171,7 @@ int central_req( struct curl_slist* hs = NULL; char auth_str[ZTS_CENTRAL_TOKEN_LEN + 32] = { 0 }; // + Authorization: Bearer if (token_strlen == ZTS_CENTRAL_TOKEN_LEN) { - OSUtils::ztsnprintf( - auth_str, - ZTS_CENTRAL_TOKEN_LEN + 32, - "Authorization: Bearer %s", - token_str); + OSUtils::ztsnprintf(auth_str, ZTS_CENTRAL_TOKEN_LEN + 32, "Authorization: Bearer %s", token_str); } hs = curl_slist_append(hs, auth_str); @@ -230,7 +222,7 @@ int central_req( return err; } -int zts_get_last_resp_buf(char* dest_buffer, int dest_buf_len) +int zts_central_get_last_resp_buf(char* dest_buffer, int dest_buf_len) { if (dest_buf_len <= _resp_buf_offset) { return ZTS_ERR_ARG; diff --git a/src/Controls.cpp b/src/Controls.cpp index acfece16..f43f7a1c 100644 --- a/src/Controls.cpp +++ b/src/Controls.cpp @@ -69,15 +69,15 @@ Mutex service_m; */ int init_subsystems() { + 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 _install_signal_handlers(); #endif // ZTS_ENABLE_CUSTOM_SIGNAL_HANDLERS - if (! zts_events) { - zts_events = new Events(); - } if (! zts_service) { zts_service = new NodeService(); zts_service->setUserEventSystem(zts_events); @@ -96,20 +96,20 @@ int zts_init_from_storage(const char* path) return ZTS_ERR_OK; } -int zts_init_from_memory(const char* keypair, uint16_t len) +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); +int zts_init_set_event_handler(PythonDirectorCallbackClass* callback) #endif #ifdef ZTS_ENABLE_PINVOKE -int zts_init_set_event_handler(CppCallback callback); + int zts_init_set_event_handler(CppCallback callback) #endif #ifdef ZTS_C_API_ONLY -int zts_init_set_event_handler(void (*callback)(void*)) + int zts_init_set_event_handler(void (*callback)(void*)) #endif { ACQUIRE_SERVICE_OFFLINE(); @@ -117,19 +117,20 @@ int zts_init_set_event_handler(void (*callback)(void*)) return ZTS_ERR_ARG; } _userEventCallback = callback; + zts_service->enableEvents(); return ZTS_ERR_OK; } -int zts_init_blacklist_if(const char* prefix, int len) +int zts_init_blacklist_if(const char* prefix, unsigned int len) { ACQUIRE_SERVICE_OFFLINE(); return zts_service->addInterfacePrefixToBlacklist(prefix, len); } -int zts_init_set_planet(const char* planet_data, int len) +int zts_init_set_world(const void* world_data, unsigned int len) { ACQUIRE_SERVICE_OFFLINE(); - return zts_service->setPlanet(planet_data, len); + return zts_service->setWorld(world_data, len); } int zts_init_set_port(unsigned short port) @@ -139,31 +140,31 @@ int zts_init_set_port(unsigned short port) return ZTS_ERR_OK; } -int zts_init_allow_peer_cache(int allowed) +int zts_init_allow_peer_cache(unsigned int allowed) { ACQUIRE_SERVICE_OFFLINE(); return zts_service->allowPeerCaching(allowed); } -int zts_init_allow_net_cache(int allowed) +int zts_init_allow_net_cache(unsigned int allowed) { ACQUIRE_SERVICE_OFFLINE(); return zts_service->allowNetworkCaching(allowed); } -int zts_init_clear() +int zts_init_allow_world_cache(unsigned int allowed) { ACQUIRE_SERVICE_OFFLINE(); - ACQUIRE_EVENTS(); - _userEventCallback = NULL; - zts_service->uninitialize(); - return ZTS_ERR_OK; + 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) +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; @@ -174,10 +175,7 @@ int zts_addr_compute_6plane( return ZTS_ERR_OK; } -int zts_addr_compute_rfc4193( - const uint64_t net_id, - const uint64_t node_id, - struct zts_sockaddr_storage* addr) +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; @@ -188,7 +186,7 @@ int zts_addr_compute_rfc4193( return ZTS_ERR_OK; } -int zts_addr_compute_rfc4193_str(uint64_t net_id, uint64_t node_id, char* dst, int len) +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; @@ -203,7 +201,7 @@ int zts_addr_compute_rfc4193_str(uint64_t net_id, uint64_t node_id, char* dst, i return ZTS_ERR_OK; } -int zts_addr_compute_6plane_str(uint64_t net_id, uint64_t node_id, char* dst, int len) +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; @@ -225,7 +223,7 @@ uint64_t zts_net_compute_adhoc_id(uint16_t start_port, uint16_t end_port) return strtoull(net_id_str, NULL, 16); } -int zts_id_new(char* key, uint16_t* dst_len) +int zts_id_new(char* key, unsigned int* dst_len) { if (key == NULL || *dst_len != ZT_IDENTITY_STRING_BUFFER_LENGTH) { return ZTS_ERR_ARG; @@ -234,7 +232,7 @@ int zts_id_new(char* key, uint16_t* dst_len) id.generate(); char idtmp[1024] = { 0 }; std::string idser = id.toString(true, idtmp); - uint16_t key_pair_len = idser.length(); + unsigned int key_pair_len = idser.length(); if (key_pair_len > *dst_len) { return ZTS_ERR_ARG; } @@ -243,7 +241,7 @@ int zts_id_new(char* key, uint16_t* dst_len) return ZTS_ERR_OK; } -int zts_id_pair_is_valid(const char* key, int len) +int zts_id_pair_is_valid(const char* key, unsigned int len) { if (key == NULL || len != ZT_IDENTITY_STRING_BUFFER_LENGTH) { return false; @@ -257,7 +255,7 @@ int zts_id_pair_is_valid(const char* key, int len) return false; } -int zts_node_get_id_pair(char* key, uint16_t* dst_len) +int zts_node_get_id_pair(char* key, unsigned int* dst_len) { ACQUIRE_SERVICE(ZTS_ERR_SERVICE); zts_service->getIdentity(key, dst_len); @@ -281,19 +279,19 @@ void* cbRun(void* arg) return NULL; } -int zts_addr_is_assigned(uint64_t net_id, int family) +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, int family, struct zts_sockaddr_storage* addr) +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, int family, char* dst, int len) +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) { @@ -324,12 +322,79 @@ int zts_addr_get_str(uint64_t net_id, int family, char* dst, int len) return ZTS_ERR_OK; } -int zts_addr_get_all(uint64_t net_id, struct zts_sockaddr_storage* addr, int* count) +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); @@ -342,10 +407,10 @@ int zts_net_leave(const uint64_t net_id) return zts_service->leave(net_id); } -int zts_net_count() +int zts_net_transport_is_ready(const uint64_t net_id) { ACQUIRE_SERVICE(ZTS_ERR_SERVICE); - return zts_service->networkCount(); + return zts_service->networkIsReady(net_id); } uint64_t zts_net_get_mac(uint64_t net_id) @@ -354,7 +419,7 @@ uint64_t zts_net_get_mac(uint64_t net_id) return zts_service->getMACAddress(net_id); } -ZTS_API int ZTCALL zts_net_get_mac_str(uint64_t net_id, char* dst, int len) +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) { @@ -386,7 +451,7 @@ int zts_net_get_mtu(uint64_t net_id) return zts_service->getNetworkMTU(net_id); } -int zts_net_get_name(uint64_t net_id, char* dst, int len) +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); @@ -404,7 +469,7 @@ int zts_net_get_type(uint64_t net_id) return zts_service->getNetworkType(net_id); } -int zts_route_is_assigned(uint64_t net_id, int family) +int zts_route_is_assigned(uint64_t net_id, unsigned int family) { ACQUIRE_SERVICE(ZTS_ERR_SERVICE); return zts_service->networkHasRoute(net_id, family); @@ -421,41 +486,24 @@ void* _runNodeService(void* arg) pthread_setname_np(ZTS_SERVICE_THREAD_NAME); #endif try { - for (;;) { - switch (zts_service->run()) { - case NodeService::ONE_STILL_RUNNING: - case NodeService::ONE_NORMAL_TERMINATION: - // zts_events->enqueue(ZTS_EVENT_NODE_NORMAL_TERMINATION, NULL); - break; - case NodeService::ONE_UNRECOVERABLE_ERROR: - // DEBUG_ERROR("fatal error: %s", - // zts_service->fatalErrorMessage().c_str()); - // zts_events->enqueue(ZTS_EVENT_NODE_UNRECOVERABLE_ERROR, NULL); - break; - case NodeService::ONE_IDENTITY_COLLISION: { - delete zts_service; - zts_service = (NodeService*)0; - // zts_events->enqueue(ZTS_EVENT_NODE_IDENTITY_COLLISION, NULL); - } - continue; // restart! - } - break; // terminate loop -- normally we don't keep restarting - } + 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(); - // zts_events->enqueue(ZTS_EVENT_NODE_DOWN, NULL); events_m.lock(); - delete zts_events; - zts_events = NULL; + zts_util_delay(ZTS_CALLBACK_PROCESSING_INTERVAL * 2); + if (zts_events) { + zts_events->disable(); + delete zts_events; + zts_events = (Events*)0; + } events_m.unlock(); } catch (...) { - // DEBUG_ERROR("unexpected exception starting ZeroTier"); } - zts_util_delay(ZTS_CALLBACK_PROCESSING_INTERVAL * 2); #ifndef __WINDOWS__ pthread_exit(0); #endif @@ -472,6 +520,7 @@ int zts_node_start() 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) {} @@ -489,6 +538,7 @@ int zts_node_start() #if defined(__WINDOWS__) WSAStartup(MAKEWORD(2, 2), &wsaData); 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) {} @@ -532,23 +582,6 @@ int zts_node_stop() return ZTS_ERR_OK; } -int zts_node_restart() -{ - ACQUIRE_SERVICE(ZTS_ERR_SERVICE); - // Stop - zts_events->clrState(ZTS_STATE_NODE_RUNNING); - zts_service->terminate(); -#if defined(__WINDOWS__) - WSACleanup(); -#endif - RELEASE_SERVICE(); - // Start - while (zts_service) { - zts_util_delay(ZTS_CALLBACK_PROCESSING_INTERVAL); - } - return zts_node_start(); -} - int zts_node_free() { ACQUIRE_SERVICE(ZTS_ERR_SERVICE); @@ -596,61 +629,59 @@ int zts_stats_get_all(zts_stats_counter_t* dst) 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; + 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; + 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; + 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 + 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; + 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; + 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; + 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; + 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; + 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 diff --git a/src/Debug.hpp b/src/Debug.hpp index 45b90cb1..be38235b 100644 --- a/src/Debug.hpp +++ b/src/Debug.hpp @@ -31,9 +31,8 @@ #if defined(__APPLE__) #include "TargetConditionals.h" #endif -#if defined(ZT_COLOR) && ! defined(_WIN32) && ! defined(__ANDROID__) \ - && ! defined(TARGET_OS_IPHONE) && ! defined(TARGET_IPHONE_SIMULATOR) \ - && ! defined(__APP_FRAMEWORK__) +#if defined(ZT_COLOR) && ! defined(_WIN32) && ! defined(__ANDROID__) && ! defined(TARGET_OS_IPHONE) \ + && ! defined(TARGET_IPHONE_SIMULATOR) && ! defined(__APP_FRAMEWORK__) #define ZT_RED "\x1B[31m" #define ZT_GRN "\x1B[32m" #define ZT_YEL "\x1B[33m" @@ -62,33 +61,21 @@ #if defined(LIBZT_DEBUG) #if defined(__ANDROID__) -#define DEBUG_INFO(fmt, args...) \ - ((void)__android_log_print( \ - ANDROID_LOG_VERBOSE, \ - ZT_LOG_TAG, \ - "%17s:%5d:%20s: " fmt "\n", \ - ZT_FILENAME, \ - __LINE__, \ - __FUNCTION__, \ +#define DEBUG_INFO(fmt, args...) \ + ((void)__android_log_print( \ + ANDROID_LOG_VERBOSE, \ + ZT_LOG_TAG, \ + "%17s:%5d:%20s: " fmt "\n", \ + ZT_FILENAME, \ + __LINE__, \ + __FUNCTION__, \ ##args)) #elif defined(_WIN32) -#define DEBUG_INFO(fmt, ...) \ - fprintf( \ - stderr, \ - ZT_WHT "%17s:%5d:%25s: " fmt "\n" ZT_RESET, \ - ZT_FILENAME, \ - __LINE__, \ - __FUNCTION__, \ - __VA_ARGS__) +#define DEBUG_INFO(fmt, ...) \ + fprintf(stderr, ZT_WHT "%17s:%5d:%25s: " fmt "\n" ZT_RESET, ZT_FILENAME, __LINE__, __FUNCTION__, __VA_ARGS__) #else -#define DEBUG_INFO(fmt, args...) \ - fprintf( \ - stderr, \ - ZT_WHT "%17s:%5d:%25s: " fmt "\n" ZT_RESET, \ - ZT_FILENAME, \ - __LINE__, \ - __FUNCTION__, \ - ##args) +#define DEBUG_INFO(fmt, args...) \ + fprintf(stderr, ZT_WHT "%17s:%5d:%25s: " fmt "\n" ZT_RESET, ZT_FILENAME, __LINE__, __FUNCTION__, ##args) #endif #else // !LIBZT_DEBUG #if defined(_WIN32) diff --git a/src/Events.cpp b/src/Events.cpp index e41503b6..53ced3a5 100644 --- a/src/Events.cpp +++ b/src/Events.cpp @@ -38,16 +38,14 @@ void PythonDirectorCallbackClass::on_zerotier_event(zts_event_msg_t* msg) } #endif -#define ZTS_NODE_EVENT(code) code >= ZTS_EVENT_NODE_UP&& code <= ZTS_EVENT_NODE_FATAL_ERROR -#define ZTS_NETWORK_EVENT(code) \ - code >= ZTS_EVENT_NETWORK_NOT_FOUND&& code <= ZTS_EVENT_NETWORK_UPDATE -#define ZTS_STACK_EVENT(code) code >= ZTS_EVENT_STACK_UP&& code <= ZTS_EVENT_STACK_DOWN -#define ZTS_NETIF_EVENT(code) code >= ZTS_EVENT_NETIF_UP&& code <= ZTS_EVENT_NETIF_LINK_DOWN -#define ZTS_PEER_EVENT(code) code >= ZTS_EVENT_PEER_DIRECT&& code <= ZTS_EVENT_PEER_PATH_DEAD -#define ZTS_ROUTE_EVENT(code) code >= ZTS_EVENT_ROUTE_ADDED&& code <= ZTS_EVENT_ROUTE_REMOVED -#define ZTS_ADDR_EVENT(code) code >= ZTS_EVENT_ADDR_ADDED_IP4&& code <= ZTS_EVENT_ADDR_REMOVED_IP6 -#define ZTS_STORE_EVENT(code) \ - code >= ZTS_EVENT_STORE_IDENTITY_SECRET&& code <= ZTS_EVENT_STORE_NETWORK +#define ZTS_NODE_EVENT(code) code >= ZTS_EVENT_NODE_UP&& code <= ZTS_EVENT_NODE_FATAL_ERROR +#define ZTS_NETWORK_EVENT(code) code >= ZTS_EVENT_NETWORK_NOT_FOUND&& code <= ZTS_EVENT_NETWORK_UPDATE +#define ZTS_STACK_EVENT(code) code >= ZTS_EVENT_STACK_UP&& code <= ZTS_EVENT_STACK_DOWN +#define ZTS_NETIF_EVENT(code) code >= ZTS_EVENT_NETIF_UP&& code <= ZTS_EVENT_NETIF_LINK_DOWN +#define ZTS_PEER_EVENT(code) code >= ZTS_EVENT_PEER_DIRECT&& code <= ZTS_EVENT_PEER_PATH_DEAD +#define ZTS_ROUTE_EVENT(code) code >= ZTS_EVENT_ROUTE_ADDED&& code <= ZTS_EVENT_ROUTE_REMOVED +#define ZTS_ADDR_EVENT(code) code >= ZTS_EVENT_ADDR_ADDED_IP4&& code <= ZTS_EVENT_ADDR_REMOVED_IP6 +#define ZTS_STORE_EVENT(code) code >= ZTS_EVENT_STORE_IDENTITY_SECRET&& code <= ZTS_EVENT_STORE_NETWORK namespace ZeroTier { @@ -85,14 +83,13 @@ void Events::run() events_m.lock(); sendToUser(msg); events_m.unlock(); - delete msg; } } zts_util_delay(ZTS_CALLBACK_PROCESSING_INTERVAL); } } -void Events::enqueue(int16_t event_code, const void* arg, int len) +void Events::enqueue(unsigned int event_code, const void* arg, int len) { if (! _enabled) { return; @@ -132,7 +129,9 @@ void Events::enqueue(int16_t event_code, const void* arg, int len) msg->len = len; } if (msg && _callbackMsgQueue.size_approx() > 1024) { - // Rate-limit number of events + /* Rate-limit number of events. This value should only grow if the + user application isn't returning from the event handler in a timely manner. + For most applications it should hover around 1 to 2 */ destroy(msg); } else { @@ -163,6 +162,8 @@ void Events::destroy(zts_event_msg_t* msg) if (msg->addr) { delete msg->addr; } + delete msg; + msg = NULL; } void Events::sendToUser(zts_event_msg_t* msg) @@ -181,7 +182,6 @@ void Events::sendToUser(zts_event_msg_t* msg) #else jint rs = jvm->AttachCurrentThread((void**)&env, NULL); #endif - assert(rs == JNI_OK); uint64_t arg = 0; uint64_t id = 0; if (ZTS_NODE_EVENT(msg->event_code)) { diff --git a/src/Events.hpp b/src/Events.hpp index 6c272dcc..0ed21f90 100644 --- a/src/Events.hpp +++ b/src/Events.hpp @@ -33,33 +33,33 @@ * frequency socket calls use a unguarded state flags */ // Lock service and check that it is running -#define ACQUIRE_SERVICE(x) \ - Mutex::Lock _ls(service_m); \ - if (! zts_service || ! zts_service->isRunning()) { \ - return x; \ +#define ACQUIRE_SERVICE(x) \ + Mutex::Lock _ls(service_m); \ + if (! zts_service || ! zts_service->isRunning()) { \ + return x; \ } // Lock service and check that it is not currently running -#define ACQUIRE_SERVICE_OFFLINE() \ - Mutex::Lock _ls(service_m); \ - if (zts_service && zts_service->isRunning()) { \ - return ZTS_ERR_SERVICE; \ - } \ - if (! zts_service) { \ - init_subsystems(); \ +#define ACQUIRE_SERVICE_OFFLINE() \ + Mutex::Lock _ls(service_m); \ + if (zts_service && zts_service->isRunning()) { \ + return ZTS_ERR_SERVICE; \ + } \ + if (! zts_service) { \ + init_subsystems(); \ } // Unlock service #define RELEASE_SERVICE() service_m.unlock(); // Lock service, ensure node is online -#define ACQUIRE_ONLINE_NODE() \ - ACQUIRE_SERVICE() if (! zts_service->nodeIsOnline()) \ - { \ - return ZTS_ERR_SERVICE; \ +#define ACQUIRE_ONLINE_NODE() \ + ACQUIRE_SERVICE() if (! zts_service->nodeIsOnline()) \ + { \ + return ZTS_ERR_SERVICE; \ } // Lock event callback -#define ACQUIRE_EVENTS() \ - Mutex::Lock _lc(events_m); \ - if (! zts_events) { \ - return ZTS_ERR_SERVICE; \ +#define ACQUIRE_EVENTS() \ + Mutex::Lock _lc(events_m); \ + if (! zts_events) { \ + return ZTS_ERR_SERVICE; \ } namespace ZeroTier { @@ -96,7 +96,7 @@ class Events { bool _enabled; public: - Events() : _enabled(true) + Events() : _enabled(false) { } @@ -118,7 +118,7 @@ class Events { /** * Enqueue an event to be sent to the user application */ - void enqueue(int16_t event_code, const void* arg, int len = 0); + void enqueue(unsigned int event_code, const void* arg, int len = 0); /** * Send callback message to user application diff --git a/src/NodeService.cpp b/src/NodeService.cpp index 700d4282..6f2cac7b 100644 --- a/src/NodeService.cpp +++ b/src/NodeService.cpp @@ -31,6 +31,7 @@ #include "Utils.hpp" #include "ZeroTierSockets.h" +#include #include #if defined(__WINDOWS__) @@ -60,6 +61,12 @@ NodeService::NodeService() #endif , _allowNetworkCaching(true) , _allowPeerCaching(true) + , _allowIdentityCaching(true) + , _allowWorldCaching(true) + , _userDefinedWorld(false) + , _nodeIsOnline(false) + , _eventsEnabled(false) + , _events(NULL) , _homePath("") { } @@ -79,8 +86,7 @@ NodeService::ReasonForTermination NodeService::run() // Create home path (if necessary) // By default, _homePath is empty and nothing is written to storage if (_homePath.length() > 0) { - std::vector hpsp( - OSUtils::split(_homePath.c_str(), ZT_PATH_SEPARATOR_S, "", "")); + std::vector hpsp(OSUtils::split(_homePath.c_str(), ZT_PATH_SEPARATOR_S, "", "")); std::string ptmp; if (_homePath[0] == ZT_PATH_SEPARATOR) { ptmp.push_back(ZT_PATH_SEPARATOR); @@ -144,8 +150,7 @@ NodeService::ReasonForTermination NodeService::run() // fail if more than one device behind the same NAT tries to use the // same internal private address port number. Buggy NATs are a // running theme. - _ports[1] = (_secondaryPort == 0) ? 20000 + ((unsigned int)_node->address() % 45500) - : _secondaryPort; + _ports[1] = (_secondaryPort == 0) ? 20000 + ((unsigned int)_node->address() % 45500) : _secondaryPort; for (int i = 0;; ++i) { if (i > 1000) { _ports[1] = 0; @@ -195,9 +200,7 @@ NodeService::ReasonForTermination NodeService::run() if (_allowNetworkCaching) { std::vector networksDotD( OSUtils::listDirectory((_homePath + ZT_PATH_SEPARATOR_S "networks.d").c_str())); - for (std::vector::iterator f(networksDotD.begin()); - f != networksDotD.end(); - ++f) { + for (std::vector::iterator f(networksDotD.begin()); f != networksDotD.end(); ++f) { std::size_t dot = f->find_last_of('.'); if ((dot == 16) && (f->substr(16) == ".conf")) { _node->join(Utils::hexStrToU64(f->substr(0, dot).c_str()), (void*)0, (void*)0); @@ -212,9 +215,8 @@ NodeService::ReasonForTermination NodeService::run() int64_t lastBindRefresh = 0; int64_t lastCleanedPeersDb = 0; int64_t lastLocalInterfaceAddressCheck = - (clockShouldBe - ZT_LOCAL_INTERFACE_CHECK_INTERVAL) - + 15000; // do this in 15s to give portmapper time to - // configure and other things time to settle + (clockShouldBe - ZT_LOCAL_INTERFACE_CHECK_INTERVAL) + 15000; // do this in 15s to give portmapper time to + // configure and other things time to settle for (;;) { _run_m.lock(); if (! _run) { @@ -266,46 +268,33 @@ NodeService::ReasonForTermination NodeService::run() // Sync multicast group memberships if ((now - lastTapMulticastGroupCheck) >= ZT_TAP_CHECK_MULTICAST_INTERVAL) { lastTapMulticastGroupCheck = now; - std::vector, std::vector > > > + std::vector, std::vector > > > mgChanges; { Mutex::Lock _l(_nets_m); mgChanges.reserve(_nets.size() + 1); - for (std::map::const_iterator n(_nets.begin()); - n != _nets.end(); - ++n) { + for (std::map::const_iterator n(_nets.begin()); n != _nets.end(); ++n) { if (n->second.tap) { mgChanges.push_back(std::pair< uint64_t, - std::pair< - std::vector, - std::vector > >( + std::pair, std::vector > >( n->first, - std::pair< - std::vector, - std::vector >())); + std::pair, std::vector >())); n->second.tap->scanMulticastGroups( mgChanges.back().second.first, mgChanges.back().second.second); } } } - for (std::vector, std::vector > > >:: + for (std::vector< + std::pair, std::vector > > >:: iterator c(mgChanges.begin()); c != mgChanges.end(); ++c) { auto mgpair = c->second; - for (std::vector::iterator m(mgpair.first.begin()); - m != mgpair.first.end(); - ++m) + for (std::vector::iterator m(mgpair.first.begin()); m != mgpair.first.end(); ++m) _node->multicastSubscribe((void*)0, c->first, m->mac().toInt(), m->adi()); - for (std::vector::iterator m(mgpair.second.begin()); - m != mgpair.second.end(); - ++m) + for (std::vector::iterator m(mgpair.second.begin()); m != mgpair.second.end(); ++m) _node->multicastUnsubscribe(c->first, m->mac().toInt(), m->adi()); } } @@ -322,17 +311,13 @@ NodeService::ReasonForTermination NodeService::run() for (std::vector::const_iterator ext(mappedAddresses.begin()); ext != mappedAddresses.end(); ++ext) - _node->addLocalInterfaceAddress( - reinterpret_cast(&(*ext))); + _node->addLocalInterfaceAddress(reinterpret_cast(&(*ext))); } #endif std::vector boundAddrs(_binder.allBoundLocalInterfaceAddresses()); - for (std::vector::const_iterator i(boundAddrs.begin()); - i != boundAddrs.end(); - ++i) - _node->addLocalInterfaceAddress( - reinterpret_cast(&(*i))); + for (std::vector::const_iterator i(boundAddrs.begin()); i != boundAddrs.end(); ++i) + _node->addLocalInterfaceAddress(reinterpret_cast(&(*i))); } // Clean peers.d periodically @@ -393,86 +378,24 @@ std::string NodeService::fatalErrorMessage() const return _fatalErrorMessage; } -void NodeService::getRoutes(uint64_t net_id, void* routeArray, unsigned int* numRoutes) -{ - Mutex::Lock _l(_nets_m); - NetworkState& n = _nets[net_id]; - *numRoutes = *numRoutes < n.config.routeCount ? *numRoutes : n.config.routeCount; - for (unsigned int i = 0; i < *numRoutes; i++) { - ZT_VirtualNetworkRoute* vnr = (ZT_VirtualNetworkRoute*)routeArray; - memcpy(&vnr[i], &(n.config.routes[i]), sizeof(ZT_VirtualNetworkRoute)); - } -} - void NodeService::terminate() { _run_m.lock(); _run = false; _run_m.unlock(); - _phy.whack(); -} - -void NodeService::uninitialize() -{ - // Reset port _primaryPort = 0; - // Reset storage location _homePath.clear(); - // Reset cache settings _allowNetworkCaching = true; _allowPeerCaching = true; - // Reset identities + _allowIdentityCaching = true; + _allowWorldCaching = true; memset(_publicIdStr, 0, ZT_IDENTITY_STRING_BUFFER_LENGTH); memset(_secretIdStr, 0, ZT_IDENTITY_STRING_BUFFER_LENGTH); - // Reset blacklist _interfacePrefixBlacklist.clear(); + _events->disable(); + _phy.whack(); } -int NodeService::getNetworkSettings(const uint64_t net_id, NetworkSettings& settings) const -{ - Mutex::Lock _l(_nets_m); - std::map::const_iterator n(_nets.find(net_id)); - if (n == _nets.end()) { - return false; - } - settings = n->second.settings; - return true; -} - -// Checks if a managed IP or route target is allowed -int NodeService::checkIfManagedIsAllowed(const NetworkState& n, const InetAddress& target) -{ - if (! n.settings.allowManaged) { - return false; - } - if (n.settings.allowManagedWhitelist.size() > 0) { - bool allowed = false; - for (InetAddress addr : n.settings.allowManagedWhitelist) { - if (addr.containsAddress(target) && addr.netmaskBits() <= target.netmaskBits()) { - allowed = true; - break; - } - } - if (! allowed) - return false; - } - if (target.isDefaultRoute()) - return n.settings.allowDefault; - switch (target.ipScope()) { - case InetAddress::IP_SCOPE_NONE: - case InetAddress::IP_SCOPE_MULTICAST: - case InetAddress::IP_SCOPE_LOOPBACK: - case InetAddress::IP_SCOPE_LINK_LOCAL: - return false; - case InetAddress::IP_SCOPE_GLOBAL: - return n.settings.allowGlobal; - default: - return true; - } -} - -// Apply or update managed IPs for a configured network (be sure n.tap -// exists) void NodeService::syncManagedStuff(NetworkState& n) { char ipbuf[64] = { 0 }; @@ -480,24 +403,15 @@ void NodeService::syncManagedStuff(NetworkState& n) std::vector newManagedIps; newManagedIps.reserve(n.config.assignedAddressCount); for (unsigned int i = 0; i < n.config.assignedAddressCount; ++i) { - const InetAddress* ii = - reinterpret_cast(&(n.config.assignedAddresses[i])); - if (checkIfManagedIsAllowed(n, *ii)) { - newManagedIps.push_back(*ii); - } + const InetAddress* ii = reinterpret_cast(&(n.config.assignedAddresses[i])); + newManagedIps.push_back(*ii); } std::sort(newManagedIps.begin(), newManagedIps.end()); - newManagedIps.erase( - std::unique(newManagedIps.begin(), newManagedIps.end()), - newManagedIps.end()); - for (std::vector::iterator ip(n.managedIps.begin()); ip != n.managedIps.end(); - ++ip) { + newManagedIps.erase(std::unique(newManagedIps.begin(), newManagedIps.end()), newManagedIps.end()); + for (std::vector::iterator ip(n.managedIps.begin()); ip != n.managedIps.end(); ++ip) { if (std::find(newManagedIps.begin(), newManagedIps.end(), *ip) == newManagedIps.end()) { if (! n.tap->removeIp(*ip)) { - fprintf( - stderr, - "ERROR: unable to remove ip address %s" ZT_EOL_S, - ip->toString(ipbuf)); + fprintf(stderr, "ERROR: unable to remove ip address %s" ZT_EOL_S, ip->toString(ipbuf)); } else { zts_addr_info_t* ad = new zts_addr_info_t(); @@ -506,19 +420,18 @@ void NodeService::syncManagedStuff(NetworkState& n) struct sockaddr_in* in4 = (struct sockaddr_in*)&(ad->addr); memcpy(&(in4->sin_addr.s_addr), (*ip).rawIpData(), 4); in4->sin_family = ZTS_AF_INET; - _events->enqueue(ZTS_EVENT_ADDR_REMOVED_IP4, (void*)ad); + sendEventToUser(ZTS_EVENT_ADDR_REMOVED_IP4, (void*)ad); } if ((*ip).isV6()) { struct sockaddr_in6* in6 = (struct sockaddr_in6*)&(ad->addr); memcpy(&(in6->sin6_addr.s6_addr), (*ip).rawIpData(), 16); in6->sin6_family = ZTS_AF_INET6; - _events->enqueue(ZTS_EVENT_ADDR_REMOVED_IP6, (void*)ad); + sendEventToUser(ZTS_EVENT_ADDR_REMOVED_IP6, (void*)ad); } } } } - for (std::vector::iterator ip(newManagedIps.begin()); ip != newManagedIps.end(); - ++ip) { + for (std::vector::iterator ip(newManagedIps.begin()); ip != newManagedIps.end(); ++ip) { if (std::find(n.managedIps.begin(), n.managedIps.end(), *ip) == n.managedIps.end()) { if (! n.tap->addIp(*ip)) { fprintf(stderr, "ERROR: unable to add ip address %s" ZT_EOL_S, ip->toString(ipbuf)); @@ -530,13 +443,13 @@ void NodeService::syncManagedStuff(NetworkState& n) struct sockaddr_in* in4 = (struct sockaddr_in*)&(ad->addr); memcpy(&(in4->sin_addr.s_addr), (*ip).rawIpData(), 4); in4->sin_family = ZTS_AF_INET; - _events->enqueue(ZTS_EVENT_ADDR_ADDED_IP4, (void*)ad); + sendEventToUser(ZTS_EVENT_ADDR_ADDED_IP4, (void*)ad); } if ((*ip).isV6()) { struct sockaddr_in6* in6 = (struct sockaddr_in6*)&(ad->addr); memcpy(&(in6->sin6_addr.s6_addr), (*ip).rawIpData(), 16); in6->sin6_family = ZTS_AF_INET6; - _events->enqueue(ZTS_EVENT_ADDR_ADDED_IP6, (void*)ad); + sendEventToUser(ZTS_EVENT_ADDR_ADDED_IP6, (void*)ad); } } } @@ -552,8 +465,7 @@ void NodeService::phyOnDatagram( void* data, unsigned long len) { - if ((len >= 16) - && (reinterpret_cast(from)->ipScope() == InetAddress::IP_SCOPE_GLOBAL)) + if ((len >= 16) && (reinterpret_cast(from)->ipScope() == InetAddress::IP_SCOPE_GLOBAL)) _lastDirectReceiveFromGlobal = OSUtils::now(); const ZT_ResultCode rc = _node->processWirePacket( (void*)0, @@ -566,11 +478,7 @@ void NodeService::phyOnDatagram( &_nextBackgroundTaskDeadline); if (ZT_ResultCode_isFatal(rc)) { char tmp[256] = { 0 }; - OSUtils::ztsnprintf( - tmp, - sizeof(tmp), - "fatal error code from processWirePacket: %d", - (int)rc); + OSUtils::ztsnprintf(tmp, sizeof(tmp), "fatal error code from processWirePacket: %d", (int)rc); Mutex::Lock _l(_termReason_m); _termReason = ONE_UNRECOVERABLE_ERROR; _fatalErrorMessage = tmp; @@ -590,20 +498,12 @@ int NodeService::nodeVirtualNetworkConfigFunction( switch (op) { case ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP: if (! n.tap) { - char friendlyName[128] = { 0 }; - OSUtils::ztsnprintf( - friendlyName, - sizeof(friendlyName), - "ZeroTier One [%.16llx]", - net_id); - n.tap = new VirtualTap( _homePath.c_str(), MAC(nwc->mac), nwc->mtu, (unsigned int)ZT_IF_METRIC, net_id, - friendlyName, StapFrameHandler, (void*)this); *nuptr = (void*)&n; @@ -611,7 +511,6 @@ int NodeService::nodeVirtualNetworkConfigFunction( } // After setting up tap, fall through to CONFIG_UPDATE since we // also want to do this... - case ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE: memcpy(&(n.config), nwc, sizeof(ZT_VirtualNetworkConfig)); if (n.tap) { // sanity check @@ -623,12 +522,12 @@ int NodeService::nodeVirtualNetworkConfigFunction( return -999; // tap init failed } if (op == ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE) { - _events->enqueue(ZTS_EVENT_NETWORK_UPDATE, (void*)prepare_network_details_msg(n)); + sendEventToUser(ZTS_EVENT_NETWORK_UPDATE, (void*)prepare_network_details_msg(n)); } break; - case ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DOWN: case ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY: + sendEventToUser(ZTS_EVENT_NETWORK_DOWN, (void*)prepare_network_details_msg(n)); if (n.tap) { // sanity check *nuptr = (void*)0; delete n.tap; @@ -639,8 +538,7 @@ int NodeService::nodeVirtualNetworkConfigFunction( OSUtils::ztsnprintf( nlcpath, sizeof(nlcpath), - "%s" ZT_PATH_SEPARATOR_S "networks.d" ZT_PATH_SEPARATOR_S - "%.16llx.local.conf", + "%s" ZT_PATH_SEPARATOR_S "networks.d" ZT_PATH_SEPARATOR_S "%.16llx.local.conf", _homePath.c_str(), net_id); OSUtils::rm(nlcpath); @@ -692,17 +590,16 @@ void NodeService::nodeEventCallback(enum ZT_Event event, const void* metaData) break; } if (event_code) { - _events->enqueue(event_code, (void*)nd); + sendEventToUser(event_code, (void*)nd); } } zts_net_info_t* NodeService::prepare_network_details_msg(const NetworkState& n) { zts_net_info_t* nd = new zts_net_info_t(); - nd->net_id = n.config.nwid; nd->mac = n.config.mac; - memcpy(nd->name, n.config.name, sizeof(n.config.name)); + strncpy(nd->name, n.config.name, sizeof(n.config.name)); nd->status = (zts_network_status_t)n.config.status; nd->type = (zts_net_info_type_t)n.config.type; nd->mtu = n.config.mtu; @@ -711,13 +608,11 @@ zts_net_info_t* NodeService::prepare_network_details_msg(const NetworkState& n) nd->broadcast_enabled = n.config.broadcastEnabled; nd->port_error = n.config.portError; nd->netconf_rev = n.config.netconfRevision; - // Copy and convert address structures nd->assigned_addr_count = n.config.assignedAddressCount; for (unsigned int i = 0; i < n.config.assignedAddressCount; i++) { native_ss_to_zts_ss(&(nd->assigned_addrs[i]), &(n.config.assignedAddresses[i])); } - nd->route_count = n.config.routeCount; for (unsigned int i = 0; i < n.config.routeCount; i++) { native_ss_to_zts_ss(&(nd->routes[i].target), &(n.config.routes[i].target)); @@ -725,13 +620,8 @@ zts_net_info_t* NodeService::prepare_network_details_msg(const NetworkState& n) nd->routes[i].flags = n.config.routes[i].flags; nd->routes[i].metric = n.config.routes[i].metric; } - nd->multicast_sub_count = n.config.multicastSubscriptionCount; - memcpy( - nd->multicast_subs, - &(n.config.multicastSubscriptions), - sizeof(n.config.multicastSubscriptions)); - + memcpy(nd->multicast_subs, &(n.config.multicastSubscriptions), sizeof(n.config.multicastSubscriptions)); return nd; } @@ -754,40 +644,26 @@ void NodeService::generateEventMsgs() } switch (mostRecentStatus) { case ZT_NETWORK_STATUS_NOT_FOUND: - _events->enqueue( - ZTS_EVENT_NETWORK_NOT_FOUND, - (void*)prepare_network_details_msg(netState)); + sendEventToUser(ZTS_EVENT_NETWORK_NOT_FOUND, (void*)prepare_network_details_msg(netState)); break; case ZT_NETWORK_STATUS_CLIENT_TOO_OLD: - _events->enqueue( - ZTS_EVENT_NETWORK_CLIENT_TOO_OLD, - (void*)prepare_network_details_msg(netState)); + sendEventToUser(ZTS_EVENT_NETWORK_CLIENT_TOO_OLD, (void*)prepare_network_details_msg(netState)); break; case ZT_NETWORK_STATUS_REQUESTING_CONFIGURATION: - _events->enqueue( - ZTS_EVENT_NETWORK_REQ_CONFIG, - (void*)prepare_network_details_msg(netState)); + sendEventToUser(ZTS_EVENT_NETWORK_REQ_CONFIG, (void*)prepare_network_details_msg(netState)); break; case ZT_NETWORK_STATUS_OK: if (tap->hasIpv4Addr() && _lwip_is_netif_up(tap->netif4)) { - _events->enqueue( - ZTS_EVENT_NETWORK_READY_IP4, - (void*)prepare_network_details_msg(netState)); + sendEventToUser(ZTS_EVENT_NETWORK_READY_IP4, (void*)prepare_network_details_msg(netState)); } if (tap->hasIpv6Addr() && _lwip_is_netif_up(tap->netif6)) { - _events->enqueue( - ZTS_EVENT_NETWORK_READY_IP6, - (void*)prepare_network_details_msg(netState)); + sendEventToUser(ZTS_EVENT_NETWORK_READY_IP6, (void*)prepare_network_details_msg(netState)); } // In addition to the READY messages, send one OK message - _events->enqueue( - ZTS_EVENT_NETWORK_OK, - (void*)prepare_network_details_msg(netState)); + sendEventToUser(ZTS_EVENT_NETWORK_OK, (void*)prepare_network_details_msg(netState)); break; case ZT_NETWORK_STATUS_ACCESS_DENIED: - _events->enqueue( - ZTS_EVENT_NETWORK_ACCESS_DENIED, - (void*)prepare_network_details_msg(netState)); + sendEventToUser(ZTS_EVENT_NETWORK_ACCESS_DENIED, (void*)prepare_network_details_msg(netState)); break; default: break; @@ -836,7 +712,7 @@ void NodeService::generateEventMsgs() for (unsigned int j = 0; j < pl->peers[i].pathCount; j++) { native_ss_to_zts_ss(&(pd->paths[j].address), &(pl->peers[i].paths[j].address)); } - _events->enqueue(event_code, (void*)pd); + sendEventToUser(event_code, (void*)pd); bShouldCopyPeerInfo = false; } // Update our cache with most recently observed path count @@ -864,18 +740,160 @@ int NodeService::leave(uint64_t net_id) return ZTS_ERR_OK; } -int NodeService::networkCount() +void NodeService::obtainLock() const +{ + _nets_m.lock(); +} + +void NodeService::releaseLock() const +{ + _nets_m.unlock(); +} + +bool NodeService::networkIsReady(uint64_t net_id) const { + if (! net_id) { + return ZTS_ERR_ARG; + } Mutex::Lock _l(_nets_m); - return _nets.size(); + std::map::const_iterator n(_nets.find(net_id)); + if (n == _nets.end()) { + return false; + } + auto netState = n->second; + if (netState.config.assignedAddressCount == 0) { + return ZTS_ERR_NO_RESULT; + } } -int NodeService::getFirstAssignedAddr( +int NodeService::addressCount(uint64_t net_id) const +{ + std::map::const_iterator n(_nets.find(net_id)); + if (n == _nets.end()) { + return ZTS_ERR_NO_RESULT; + } + return n->second.config.assignedAddressCount; +} + +int NodeService::routeCount(uint64_t net_id) const +{ + std::map::const_iterator n(_nets.find(net_id)); + if (n == _nets.end()) { + return ZTS_ERR_NO_RESULT; + } + return n->second.config.routeCount; +} + +int NodeService::multicastSubCount(uint64_t net_id) const +{ + std::map::const_iterator n(_nets.find(net_id)); + if (n == _nets.end()) { + return ZTS_ERR_NO_RESULT; + } + return n->second.config.multicastSubscriptionCount; +} + +int NodeService::pathCount(uint64_t peer_id) const +{ + return ZTS_ERR_NO_RESULT; // TODO +} + +int NodeService::getAddrAtIdx(uint64_t net_id, unsigned int idx, char* dst, unsigned int len) +{ + std::map::const_iterator n(_nets.find(net_id)); + if (n == _nets.end()) { + return 0; + } + auto netState = n->second; + if (idx >= netState.config.assignedAddressCount) { + return ZTS_ERR_ARG; + } + struct sockaddr* sa = (struct sockaddr*)&(netState.config.assignedAddresses[idx]); + + if (sa->sa_family == AF_INET) { + struct sockaddr_in* in4 = (struct sockaddr_in*)sa; + inet_ntop(AF_INET, &(in4->sin_addr), dst, ZTS_INET6_ADDRSTRLEN); + } + if (sa->sa_family == AF_INET6) { + struct sockaddr_in6* in6 = (struct sockaddr_in6*)sa; + inet_ntop(AF_INET6, &(in6->sin6_addr), dst, ZTS_INET6_ADDRSTRLEN); + } + return ZTS_ERR_OK; +} + +int NodeService::getRouteAtIdx( uint64_t net_id, - int family, - struct zts_sockaddr_storage* addr) + unsigned int idx, + char* target, + char* via, + unsigned int len, + uint16_t* flags, + uint16_t* metric) { - if (net_id == 0 || family < 0 || ! addr) { + // We want to use strlen later so let's ensure there's no junk first. + memset(target, 0, len); + memset(via, 0, len); + std::map::const_iterator n(_nets.find(net_id)); + if (n == _nets.end()) { + return 0; + } + auto netState = n->second; + if (idx >= netState.config.routeCount) { + return ZTS_ERR_ARG; + } + // target + const char* err = NULL; + struct sockaddr* sa = (struct sockaddr*)&(netState.config.routes[idx].target); + if (sa->sa_family == AF_INET) { + struct sockaddr_in* in4 = (struct sockaddr_in*)sa; + err = inet_ntop(AF_INET, &(in4->sin_addr), target, ZTS_INET6_ADDRSTRLEN); + } + if (sa->sa_family == AF_INET6) { + struct sockaddr_in6* in6 = (struct sockaddr_in6*)sa; + err = inet_ntop(AF_INET6, &(in6->sin6_addr), target, ZTS_INET6_ADDRSTRLEN); + } + // via + struct sockaddr* sa_via = (struct sockaddr*)&(netState.config.routes[idx].via); + if (sa_via->sa_family == AF_INET) { + struct sockaddr_in* in4 = (struct sockaddr_in*)sa_via; + err = inet_ntop(AF_INET, &(in4->sin_addr), via, ZTS_INET6_ADDRSTRLEN); + } + if (sa_via->sa_family == AF_INET6) { + struct sockaddr_in6* in6 = (struct sockaddr_in6*)sa_via; + err = inet_ntop(AF_INET6, &(in6->sin6_addr), via, ZTS_INET6_ADDRSTRLEN); + } + if (strlen(via) == 0) { + strncpy(via, "0.0.0.0", 7); + // TODO: Double check + } + *flags = netState.config.routes[idx].flags; + *metric = netState.config.routes[idx].metric; + return ZTS_ERR_OK; +} + +int NodeService::getMulticastSubAtIdx(uint64_t net_id, unsigned int idx, uint64_t* mac, uint32_t* adi) +{ + std::map::const_iterator n(_nets.find(net_id)); + if (n == _nets.end()) { + return 0; + } + auto netState = n->second; + if (idx >= netState.config.multicastSubscriptionCount) { + return ZTS_ERR_ARG; + } + *mac = netState.config.multicastSubscriptions[idx].mac; + *adi = netState.config.multicastSubscriptions[idx].adi; + return ZTS_ERR_OK; +} + +int NodeService::getPathAtIdx(uint64_t peer_id, unsigned int idx, char* path, unsigned int len) +{ + return ZTS_ERR_NO_RESULT; // TODO +} + +int NodeService::getFirstAssignedAddr(uint64_t net_id, unsigned int family, struct zts_sockaddr_storage* addr) +{ + if (net_id == 0 || ((family != ZTS_AF_INET) && (family != ZTS_AF_INET6)) || ! addr) { return ZTS_ERR_ARG; } Mutex::Lock _l(_nets_m); @@ -902,7 +920,7 @@ int NodeService::getFirstAssignedAddr( return ZTS_ERR_NO_RESULT; } -int NodeService::getAllAssignedAddr(uint64_t net_id, struct zts_sockaddr_storage* addr, int* count) +int NodeService::getAllAssignedAddr(uint64_t net_id, struct zts_sockaddr_storage* addr, unsigned int* count) { if (net_id == 0 || ! addr || ! count || *count != ZTS_MAX_ASSIGNED_ADDRESSES) { return ZTS_ERR_ARG; @@ -924,7 +942,7 @@ int NodeService::getAllAssignedAddr(uint64_t net_id, struct zts_sockaddr_storage return ZTS_ERR_OK; } -int NodeService::addrIsAssigned(uint64_t net_id, int family) +int NodeService::addrIsAssigned(uint64_t net_id, unsigned int family) { if (net_id == 0) { return ZTS_ERR_ARG; @@ -933,7 +951,7 @@ int NodeService::addrIsAssigned(uint64_t net_id, int family) return getFirstAssignedAddr(net_id, family, &addr) != ZTS_ERR_NO_RESULT; } -int NodeService::networkHasRoute(uint64_t net_id, int family) +int NodeService::networkHasRoute(uint64_t net_id, unsigned int family) { Mutex::Lock _l(_nets_m); std::map::const_iterator n(_nets.find(net_id)); @@ -986,7 +1004,7 @@ uint64_t NodeService::getNodeId() return _node ? _node->address() : 0x0; } -int NodeService::setIdentity(const char* keypair, uint16_t len) +int NodeService::setIdentity(const char* keypair, unsigned int len) { if (keypair == NULL || len < ZT_IDENTITY_STRING_BUFFER_LENGTH) { return ZTS_ERR_ARG; @@ -1007,7 +1025,7 @@ int NodeService::setIdentity(const char* keypair, uint16_t len) return ZTS_ERR_OK; } -int NodeService::getIdentity(char* keypair, uint16_t* len) +int NodeService::getIdentity(char* keypair, unsigned int* len) { if (keypair == NULL || *len < ZT_IDENTITY_STRING_BUFFER_LENGTH) { return ZTS_ERR_ARG; @@ -1018,11 +1036,19 @@ int NodeService::getIdentity(char* keypair, uint16_t* len) return ZTS_ERR_OK; } +void NodeService::sendEventToUser(unsigned int event_code, const void* arg, unsigned int len) +{ + if (! _events) { + return; + } + _events->enqueue(event_code, arg, len); +} + void NodeService::nodeStatePutFunction( enum ZT_StateObjectType type, const uint64_t id[2], const void* data, - int len) + unsigned int len) { char p[1024] = { 0 }; FILE* f; @@ -1034,28 +1060,20 @@ void NodeService::nodeStatePutFunction( switch (type) { case ZT_STATE_OBJECT_IDENTITY_PUBLIC: - _events->enqueue(ZTS_EVENT_STORE_IDENTITY_PUBLIC, data, len); + sendEventToUser(ZTS_EVENT_STORE_IDENTITY_PUBLIC, data, len); memcpy(_publicIdStr, data, len); - if (_homePath.length() > 0) { - OSUtils::ztsnprintf( - p, - sizeof(p), - "%s" ZT_PATH_SEPARATOR_S "identity.public", - _homePath.c_str()); + if (_homePath.length() > 0 && _allowIdentityCaching) { + OSUtils::ztsnprintf(p, sizeof(p), "%s" ZT_PATH_SEPARATOR_S "identity.public", _homePath.c_str()); } else { return; } break; case ZT_STATE_OBJECT_IDENTITY_SECRET: - _events->enqueue(ZTS_EVENT_STORE_IDENTITY_SECRET, data, len); + sendEventToUser(ZTS_EVENT_STORE_IDENTITY_SECRET, data, len); memcpy(_secretIdStr, data, len); - if (_homePath.length() > 0) { - OSUtils::ztsnprintf( - p, - sizeof(p), - "%s" ZT_PATH_SEPARATOR_S "identity.secret", - _homePath.c_str()); + if (_homePath.length() > 0 && _allowIdentityCaching) { + OSUtils::ztsnprintf(p, sizeof(p), "%s" ZT_PATH_SEPARATOR_S "identity.secret", _homePath.c_str()); secure = true; } else { @@ -1063,14 +1081,10 @@ void NodeService::nodeStatePutFunction( } break; case ZT_STATE_OBJECT_PLANET: - _events->enqueue(ZTS_EVENT_STORE_PLANET, data, len); - memcpy(_planetData, data, len); - if (_homePath.length() > 0) { - OSUtils::ztsnprintf( - p, - sizeof(p), - "%s" ZT_PATH_SEPARATOR_S "planet", - _homePath.c_str()); + sendEventToUser(ZTS_EVENT_STORE_PLANET, data, len); + memcpy(_worldData, data, len); + if (_homePath.length() > 0 && _allowWorldCaching) { + OSUtils::ztsnprintf(p, sizeof(p), "%s" ZT_PATH_SEPARATOR_S "world", _homePath.c_str()); } else { return; @@ -1078,11 +1092,7 @@ void NodeService::nodeStatePutFunction( break; case ZT_STATE_OBJECT_NETWORK_CONFIG: if (_homePath.length() > 0 && _allowNetworkCaching) { - OSUtils::ztsnprintf( - dirname, - sizeof(dirname), - "%s" ZT_PATH_SEPARATOR_S "networks.d", - _homePath.c_str()); + OSUtils::ztsnprintf(dirname, sizeof(dirname), "%s" ZT_PATH_SEPARATOR_S "networks.d", _homePath.c_str()); OSUtils::ztsnprintf( p, sizeof(p), @@ -1097,11 +1107,7 @@ void NodeService::nodeStatePutFunction( break; case ZT_STATE_OBJECT_PEER: if (_homePath.length() > 0 && _allowPeerCaching) { - OSUtils::ztsnprintf( - dirname, - sizeof(dirname), - "%s" ZT_PATH_SEPARATOR_S "peers.d", - _homePath.c_str()); + OSUtils::ztsnprintf(dirname, sizeof(dirname), "%s" ZT_PATH_SEPARATOR_S "peers.d", _homePath.c_str()); OSUtils::ztsnprintf( p, sizeof(p), @@ -1177,17 +1183,8 @@ int NodeService::nodeStateGetFunction( return keylen; } if (_homePath.length() > 0) { - OSUtils::ztsnprintf( - p, - sizeof(p), - "%s" ZT_PATH_SEPARATOR_S "identity.public", - _homePath.c_str()); + OSUtils::ztsnprintf(p, sizeof(p), "%s" ZT_PATH_SEPARATOR_S "identity.public", _homePath.c_str()); } - /* - if (_shouldGenerateNewId) { - - } - */ break; case ZT_STATE_OBJECT_IDENTITY_SECRET: keylen = strlen(_secretIdStr); @@ -1196,15 +1193,15 @@ int NodeService::nodeStateGetFunction( return keylen; } if (_homePath.length() > 0) { - OSUtils::ztsnprintf( - p, - sizeof(p), - "%s" ZT_PATH_SEPARATOR_S "identity.secret", - _homePath.c_str()); + OSUtils::ztsnprintf(p, sizeof(p), "%s" ZT_PATH_SEPARATOR_S "identity.secret", _homePath.c_str()); } break; case ZT_STATE_OBJECT_PLANET: - OSUtils::ztsnprintf(p, sizeof(p), "%s" ZT_PATH_SEPARATOR_S "planet", _homePath.c_str()); + if (_userDefinedWorld) { + memcpy(data, _worldData, _worldDataLen); + return _worldDataLen; + } + OSUtils::ztsnprintf(p, sizeof(p), "%s" ZT_PATH_SEPARATOR_S "world", _homePath.c_str()); break; case ZT_STATE_OBJECT_NETWORK_CONFIG: OSUtils::ztsnprintf( @@ -1247,15 +1244,10 @@ int NodeService::nodeWirePacketSendFunction( // working we can instantly "fail forward" to it and stop using TCP // proxy fallback, which is slow. - if ((localSocket != -1) && (localSocket != 0) - && (_binder.isUdpSocketValid((PhySocket*)((uintptr_t)localSocket)))) { + if ((localSocket != -1) && (localSocket != 0) && (_binder.isUdpSocketValid((PhySocket*)((uintptr_t)localSocket)))) { if ((ttl) && (addr->ss_family == AF_INET)) _phy.setIp4UdpTtl((PhySocket*)((uintptr_t)localSocket), ttl); - const bool r = _phy.udpSend( - (PhySocket*)((uintptr_t)localSocket), - (const struct sockaddr*)addr, - data, - len); + const bool r = _phy.udpSend((PhySocket*)((uintptr_t)localSocket), (const struct sockaddr*)addr, data, len); if ((ttl) && (addr->ss_family == AF_INET)) _phy.setIp4UdpTtl((PhySocket*)((uintptr_t)localSocket), 255); return ((r) ? 0 : -1); @@ -1290,8 +1282,7 @@ int NodeService::nodePathCheckFunction( // Make sure we're not trying to do ZeroTier-over-ZeroTier { Mutex::Lock _l(_nets_m); - for (std::map::const_iterator n(_nets.begin()); n != _nets.end(); - ++n) { + for (std::map::const_iterator n(_nets.begin()); n != _nets.end(); ++n) { if (n->second.tap) { std::vector ips(n->second.tap->ips()); for (std::vector::const_iterator i(ips.begin()); i != ips.end(); ++i) { @@ -1334,20 +1325,17 @@ int NodeService::nodePathCheckFunction( } if (gbl) { for (std::vector::const_iterator a(gbl->begin()); a != gbl->end(); ++a) { - if (a->containsAddress(*reinterpret_cast(remoteAddr))) + if (a->containsAddress(*reinterpret_cast(remoteAddr))) { return 0; + } } } return 1; } -int NodeService::nodePathLookupFunction( - uint64_t ztaddr, - int family, - struct sockaddr_storage* result) +int NodeService::nodePathLookupFunction(uint64_t ztaddr, unsigned int family, struct sockaddr_storage* result) { - const Hashtable >* lh = - (const Hashtable >*)0; + const Hashtable >* lh = (const Hashtable >*)0; if (family < 0) { lh = (_node->prng() & 1) ? &_v4Hints : &_v6Hints; } @@ -1362,10 +1350,7 @@ int NodeService::nodePathLookupFunction( } const std::vector* l = lh->get(ztaddr); if ((l) && (l->size() > 0)) { - memcpy( - result, - &((*l)[(unsigned long)_node->prng() % l->size()]), - sizeof(struct sockaddr_storage)); + memcpy(result, &((*l)[(unsigned long)_node->prng() % l->size()]), sizeof(struct sockaddr_storage)); return 1; } else { @@ -1463,8 +1448,7 @@ int NodeService::shouldBindInterface(const char* ifname, const InetAddress& ifad } { Mutex::Lock _l(_nets_m); - for (std::map::const_iterator n(_nets.begin()); n != _nets.end(); - ++n) { + for (std::map::const_iterator n(_nets.begin()); n != _nets.end(); ++n) { if (n->second.tap) { std::vector ips(n->second.tap->ips()); for (std::vector::const_iterator i(ips.begin()); i != ips.end(); ++i) { @@ -1504,12 +1488,12 @@ int NodeService::_trialBind(unsigned int port) return false; } -int NodeService::isRunning() +int NodeService::isRunning() const { return _run; } -int NodeService::nodeIsOnline() +int NodeService::nodeIsOnline() const { return _nodeIsOnline; } @@ -1537,7 +1521,7 @@ int NodeService::setPrimaryPort(unsigned short primaryPort) return ZTS_ERR_OK; } -unsigned short NodeService::getPrimaryPort() +unsigned short NodeService::getPrimaryPort() const { return _primaryPort; } @@ -1552,9 +1536,18 @@ int NodeService::setUserEventSystem(Events* events) return ZTS_ERR_OK; } -int NodeService::setPlanet(const char* planetData, int len) +void NodeService::enableEvents() { - if (! planetData || len <= 0 || len > ZTS_STORE_DATA_LEN) { + Mutex::Lock _lr(_run_m); + if (! _events) { + return; + } + _events->enable(); +} + +int NodeService::setWorld(const void* worldData, unsigned int len) +{ + if (! worldData || len <= 0 || len > ZTS_STORE_DATA_LEN) { return ZTS_ERR_ARG; } Mutex::Lock _lr(_run_m); @@ -1562,11 +1555,13 @@ int NodeService::setPlanet(const char* planetData, int len) return ZTS_ERR_SERVICE; } Mutex::Lock _ls(_store_m); - memcpy(_planetData, planetData, len); + memcpy(_worldData, worldData, len); + _worldDataLen = len; + _userDefinedWorld = true; return ZTS_ERR_OK; } -int NodeService::addInterfacePrefixToBlacklist(const char* prefix, int len) +int NodeService::addInterfacePrefixToBlacklist(const char* prefix, unsigned int len) { if (! prefix || len == 0 || len > 15) { return ZTS_ERR_ARG; @@ -1580,7 +1575,7 @@ int NodeService::addInterfacePrefixToBlacklist(const char* prefix, int len) return ZTS_ERR_OK; } -uint64_t NodeService::getMACAddress(uint64_t net_id) +uint64_t NodeService::getMACAddress(uint64_t net_id) const { if (net_id == 0) { return ZTS_ERR_ARG; @@ -1597,7 +1592,7 @@ uint64_t NodeService::getMACAddress(uint64_t net_id) return n->second.config.mac; } -int NodeService::getNetworkName(uint64_t net_id, char* dst, int len) +int NodeService::getNetworkName(uint64_t net_id, char* dst, unsigned int len) const { if (net_id == 0 || ! dst || len != ZTS_MAX_NETWORK_SHORT_NAME_LENGTH) { return ZTS_ERR_ARG; @@ -1619,7 +1614,7 @@ int NodeService::getNetworkName(uint64_t net_id, char* dst, int len) return ZTS_ERR_OK; } -int NodeService::allowPeerCaching(int allowed) +int NodeService::allowPeerCaching(unsigned int allowed) { Mutex::Lock _lr(_run_m); if (_run) { @@ -1629,7 +1624,7 @@ int NodeService::allowPeerCaching(int allowed) return ZTS_ERR_OK; } -int NodeService::allowNetworkCaching(int allowed) +int NodeService::allowNetworkCaching(unsigned int allowed) { Mutex::Lock _lr(_run_m); if (_run) { @@ -1639,6 +1634,25 @@ int NodeService::allowNetworkCaching(int allowed) return ZTS_ERR_OK; } +int NodeService::allowIdentityCaching(unsigned int allowed) +{ + Mutex::Lock _lr(_run_m); + if (_run) { + return ZTS_ERR_SERVICE; + } + _allowIdentityCaching = allowed; + return ZTS_ERR_OK; +} + +int NodeService::allowWorldCaching(unsigned int allowed) +{ + Mutex::Lock _lr(_run_m); + if (_run) { + return ZTS_ERR_SERVICE; + } + _allowWorldCaching = allowed; + return ZTS_ERR_OK; +} int NodeService::getNetworkBroadcast(uint64_t net_id) { if (net_id == 0) { diff --git a/src/NodeService.hpp b/src/NodeService.hpp index 57714ebe..1cea16f5 100644 --- a/src/NodeService.hpp +++ b/src/NodeService.hpp @@ -196,15 +196,17 @@ class NodeService { PortMapper* _portMapper; #endif - /** Whether we allow caching network configs to storage */ uint8_t _allowNetworkCaching; - - /** Whether we allow caching peer hints to storage */ uint8_t _allowPeerCaching; + uint8_t _allowIdentityCaching; + uint8_t _allowWorldCaching; char _publicIdStr[ZT_IDENTITY_STRING_BUFFER_LENGTH] = { 0 }; char _secretIdStr[ZT_IDENTITY_STRING_BUFFER_LENGTH] = { 0 }; - char _planetData[ZTS_STORE_DATA_LEN] = { 0 }; + + bool _userDefinedWorld; + char _worldData[ZTS_STORE_DATA_LEN] = { 0 }; + int _worldDataLen = 0; /** Whether the node has successfully come online */ bool _nodeIsOnline; @@ -212,41 +214,26 @@ class NodeService { /** Whether we allow the NodeService to generate events for the user */ bool _eventsEnabled; - /** Primary port defined by the user */ - uint16_t _userProvidedPort; - /** Storage path defined by the user */ std::string _homePath; /** System to ingest events from this class and emit them to the user */ Events* _events; - /** - * Constructor - */ NodeService(); - - /** - * Destructor - */ ~NodeService(); + /** Main service loop */ ReasonForTermination run(); ReasonForTermination reasonForTermination() const; std::string fatalErrorMessage() const; - void getRoutes(uint64_t net_id, void* routeArray, unsigned int* numRoutes); - + /** Stop the node and service */ void terminate(); - void uninitialize(); - - int getNetworkSettings(const uint64_t net_id, NetworkSettings& settings) const; - - int checkIfManagedIsAllowed(const NetworkState& n, const InetAddress& target); - + /** Apply or update managed IPs for a configured network */ void syncManagedStuff(NetworkState& n); void phyOnDatagram( @@ -264,18 +251,54 @@ class NodeService { const ZT_VirtualNetworkConfig* nwc); void nodeEventCallback(enum ZT_Event event, const void* metaData); + zts_net_info_t* prepare_network_details_msg(const NetworkState& n); void generateEventMsgs(); + void sendEventToUser(unsigned int event_code, const void* arg, unsigned int len = 0); + /** Join a network */ int join(uint64_t net_id); /** Leave a network */ int leave(uint64_t net_id); - /** Return number of networks joined */ - int networkCount(); + /** Return whether the network is ready for transport services */ + bool networkIsReady(uint64_t net_id) const; + + /** Lock the service so we can perform queries */ + void obtainLock() const; + + /** Unlock the service */ + void releaseLock() const; + + /** Return number of assigned addresses on the network. Service must be locked. */ + int addressCount(uint64_t net_id) const; + + /** Return number of managed routes on the network. Service must be locked. */ + int routeCount(uint64_t net_id) const; + + /** Return number of multicast subscriptions on the network. Service must be locked. */ + int multicastSubCount(uint64_t net_id) const; + + /** Return number of known physical paths to the peer. Service must be locked. */ + int pathCount(uint64_t peer_id) const; + + int getAddrAtIdx(uint64_t net_id, unsigned int idx, char* dst, unsigned int len); + + int getRouteAtIdx( + uint64_t net_id, + unsigned int idx, + char* target, + char* via, + unsigned int len, + uint16_t* flags, + uint16_t* metric); + + int getMulticastSubAtIdx(uint64_t net_id, unsigned int idx, uint64_t* mac, uint32_t* adi); + + int getPathAtIdx(uint64_t peer_id, unsigned int idx, char* path, unsigned int len); /** Orbit a moon */ int orbit(void* tptr, uint64_t moonWorldId, uint64_t moonSeed); @@ -283,23 +306,18 @@ class NodeService { /** De-orbit a moon */ int deorbit(void* tptr, uint64_t moonWorldId); + /** Return the integer-form of the node's identity */ uint64_t getNodeId(); - int getIdentity(char* keypair, uint16_t* len); + /** Gets the node's identity */ + int getIdentity(char* keypair, unsigned int* len); - int setIdentity(const char* keypair, uint16_t len); + /** Set the node's identity */ + int setIdentity(const char* keypair, unsigned int len); - void nodeStatePutFunction( - enum ZT_StateObjectType type, - const uint64_t id[2], - const void* data, - int len); + void nodeStatePutFunction(enum ZT_StateObjectType type, const uint64_t id[2], const void* data, unsigned int len); - int nodeStateGetFunction( - enum ZT_StateObjectType type, - const uint64_t id[2], - void* data, - unsigned int maxlen); + int nodeStateGetFunction(enum ZT_StateObjectType type, const uint64_t id[2], void* data, unsigned int maxlen); int nodeWirePacketSendFunction( const int64_t localSocket, @@ -318,12 +336,9 @@ class NodeService { const void* data, unsigned int len); - int nodePathCheckFunction( - uint64_t ztaddr, - const int64_t localSocket, - const struct sockaddr_storage* remoteAddr); + int nodePathCheckFunction(uint64_t ztaddr, const int64_t localSocket, const struct sockaddr_storage* remoteAddr); - int nodePathLookupFunction(uint64_t ztaddr, int family, struct sockaddr_storage* result); + int nodePathLookupFunction(uint64_t ztaddr, unsigned int family, struct sockaddr_storage* result); void tapFrameHandler( uint64_t net_id, @@ -339,10 +354,10 @@ class NodeService { int _trialBind(unsigned int port); /** Return whether the NodeService is running */ - int isRunning(); + int isRunning() const; /** Return whether the node is online */ - int nodeIsOnline(); + int nodeIsOnline() const; /** Instruct the NodeService on where to look for identity files and caches */ int setHomePath(const char* homePath); @@ -351,71 +366,100 @@ class NodeService { int setPrimaryPort(unsigned short primaryPort); /** Get the NodeService's primary port */ - unsigned short getPrimaryPort(); + unsigned short getPrimaryPort() const; /** Set the event system instance used to convey messages to the user */ int setUserEventSystem(Events* events); - /** Set the planet definition */ - int setPlanet(const char* data, int len); + void enableEvents(); + + /** Set the world definition */ + int setWorld(const void* data, unsigned int len); /** Add Interface prefix to blacklist (prevents ZeroTier from using that interface) */ - int addInterfacePrefixToBlacklist(const char* prefix, int len); + int addInterfacePrefixToBlacklist(const char* prefix, unsigned int len); /** Return the MAC Address of the node in the given network */ - uint64_t getMACAddress(uint64_t net_id); + uint64_t getMACAddress(uint64_t net_id) const; - int getNetworkName(uint64_t net_id, char* dst, int len); + /** Get the string format name of a network */ + int getNetworkName(uint64_t net_id, char* dst, unsigned int len) const; - int allowPeerCaching(int allowed); - int allowNetworkCaching(int allowed); + /** Allow ZeroTier to cache peer hints to storage */ + int allowPeerCaching(unsigned int allowed); + + /** Allow ZeroTier to cache network info to storage */ + int allowNetworkCaching(unsigned int allowed); + + /** Allow ZeroTier to write identities to storage */ + int allowIdentityCaching(unsigned int allowed); + + /** Allow ZeroTier to cache world definitions to storage */ + int allowWorldCaching(unsigned int allowed); + + /** Return whether broadcast is enabled on the given network */ int getNetworkBroadcast(uint64_t net_id); + + /** Return the MTU of the given network */ int getNetworkMTU(uint64_t net_id); + + /** Return whether the network is public or private */ int getNetworkType(uint64_t net_id); + + /** Return the status of the network join */ int getNetworkStatus(uint64_t net_id); - int getFirstAssignedAddr(uint64_t net_id, int family, struct zts_sockaddr_storage* addr); + /** Get the first address assigned by the network */ + int getFirstAssignedAddr(uint64_t net_id, unsigned int family, struct zts_sockaddr_storage* addr); - int getAllAssignedAddr(uint64_t net_id, struct zts_sockaddr_storage* addr, int* count); + /** Get an array of assigned addresses for the given network */ + int getAllAssignedAddr(uint64_t net_id, struct zts_sockaddr_storage* addr, unsigned int* count); - int networkHasRoute(uint64_t net_id, int family); + /** Return whether a managed route of the given family has been assigned by the network */ + int networkHasRoute(uint64_t net_id, unsigned int family); - int addrIsAssigned(uint64_t net_id, int family); + /** Return whether an address of the given family has been assigned by the network */ + int addrIsAssigned(uint64_t net_id, unsigned int family); void phyOnTcpConnect(PhySocket* sock, void** uptr, bool success) { + // Intentionally left empty } - void phyOnTcpAccept( - PhySocket* sockL, - PhySocket* sockN, - void** uptrL, - void** uptrN, - const struct sockaddr* from) + void phyOnTcpAccept(PhySocket* sockL, PhySocket* sockN, void** uptrL, void** uptrN, const struct sockaddr* from) { + // Intentionally left empty } void phyOnTcpClose(PhySocket* sock, void** uptr) { + // Intentionally left empty } void phyOnTcpData(PhySocket* sock, void** uptr, void* data, unsigned long len) { + // Intentionally left empty } void phyOnTcpWritable(PhySocket* sock, void** uptr) { + // Intentionally left empty } void phyOnFileDescriptorActivity(PhySocket* sock, void** uptr, bool readable, bool writable) { + // Intentionally left empty } void phyOnUnixAccept(PhySocket* sockL, PhySocket* sockN, void** uptrL, void** uptrN) { + // Intentionally left empty } void phyOnUnixClose(PhySocket* sock, void** uptr) { + // Intentionally left empty } void phyOnUnixData(PhySocket* sock, void** uptr, void* data, unsigned long len) { + // Intentionally left empty } void phyOnUnixWritable(PhySocket* sock, void** uptr) { + // Intentionally left empty } }; @@ -428,12 +472,10 @@ static int SnodeVirtualNetworkConfigFunction( enum ZT_VirtualNetworkConfigOperation op, const ZT_VirtualNetworkConfig* nwconf) { - return reinterpret_cast(uptr) - ->nodeVirtualNetworkConfigFunction(net_id, nuptr, op, nwconf); + return reinterpret_cast(uptr)->nodeVirtualNetworkConfigFunction(net_id, nuptr, op, nwconf); } -static void -SnodeEventCallback(ZT_Node* node, void* uptr, void* tptr, enum ZT_Event event, const void* metaData) +static void SnodeEventCallback(ZT_Node* node, void* uptr, void* tptr, enum ZT_Event event, const void* metaData) { reinterpret_cast(uptr)->nodeEventCallback(event, metaData); } @@ -472,8 +514,7 @@ static int SnodeWirePacketSendFunction( unsigned int len, unsigned int ttl) { - return reinterpret_cast(uptr) - ->nodeWirePacketSendFunction(localSocket, addr, data, len, ttl); + return reinterpret_cast(uptr)->nodeWirePacketSendFunction(localSocket, addr, data, len, ttl); } static void SnodeVirtualNetworkFrameFunction( @@ -489,15 +530,8 @@ static void SnodeVirtualNetworkFrameFunction( const void* data, unsigned int len) { - reinterpret_cast(uptr)->nodeVirtualNetworkFrameFunction( - net_id, - nuptr, - sourceMac, - destMac, - etherType, - vlanId, - data, - len); + reinterpret_cast(uptr) + ->nodeVirtualNetworkFrameFunction(net_id, nuptr, sourceMac, destMac, etherType, vlanId, data, len); } static int SnodePathCheckFunction( @@ -508,10 +542,7 @@ static int SnodePathCheckFunction( int64_t localSocket, const struct sockaddr_storage* remoteAddr) { - return reinterpret_cast(uptr)->nodePathCheckFunction( - ztaddr, - localSocket, - remoteAddr); + return reinterpret_cast(uptr)->nodePathCheckFunction(ztaddr, localSocket, remoteAddr); } static int SnodePathLookupFunction( @@ -536,8 +567,7 @@ static void StapFrameHandler( const void* data, unsigned int len) { - reinterpret_cast(uptr) - ->tapFrameHandler(net_id, from, to, etherType, vlanId, data, len); + reinterpret_cast(uptr)->tapFrameHandler(net_id, from, to, etherType, vlanId, data, len); } } // namespace ZeroTier diff --git a/src/Sockets.cpp b/src/Sockets.cpp index 963e60cc..0864bc10 100644 --- a/src/Sockets.cpp +++ b/src/Sockets.cpp @@ -108,8 +108,7 @@ int zts_bind(int fd, const struct zts_sockaddr* addr, zts_socklen_t addrlen) if (! addr) { return ZTS_ERR_ARG; } - if (addrlen > (int)sizeof(struct zts_sockaddr_storage) - || addrlen < (int)sizeof(struct zts_sockaddr_in)) { + if (addrlen > (int)sizeof(struct zts_sockaddr_storage) || addrlen < (int)sizeof(struct zts_sockaddr_in)) { return ZTS_ERR_ARG; } return lwip_bind(fd, (sockaddr*)addr, addrlen); @@ -188,12 +187,7 @@ int zts_simple_tcp_client(const char* remote_ipstr, int remote_port) return fd; } -int zts_simple_tcp_server( - const char* local_ipstr, - int local_port, - char* remote_ipstr, - int len, - int* remote_port) +int zts_simple_tcp_server(const char* local_ipstr, int local_port, char* remote_ipstr, int len, int* remote_port) { int listen_fd, family = zts_util_get_ip_family(local_ipstr); if ((listen_fd = zts_socket(family, ZTS_SOCK_STREAM, 0)) < 0) { @@ -260,8 +254,7 @@ int zts_getsockname(int fd, struct zts_sockaddr* addr, zts_socklen_t* addrlen) if (! addr) { return ZTS_ERR_ARG; } - if (*addrlen > (int)sizeof(struct zts_sockaddr_storage) - || *addrlen < (int)sizeof(struct zts_sockaddr_in)) { + if (*addrlen > (int)sizeof(struct zts_sockaddr_storage) || *addrlen < (int)sizeof(struct zts_sockaddr_in)) { return ZTS_ERR_ARG; } return lwip_getsockname(fd, (sockaddr*)addr, (socklen_t*)addrlen); @@ -275,8 +268,7 @@ int zts_getpeername(int fd, struct zts_sockaddr* addr, zts_socklen_t* addrlen) if (! addr) { return ZTS_ERR_ARG; } - if (*addrlen > (int)sizeof(struct zts_sockaddr_storage) - || *addrlen < (int)sizeof(struct zts_sockaddr_in)) { + if (*addrlen > (int)sizeof(struct zts_sockaddr_storage) || *addrlen < (int)sizeof(struct zts_sockaddr_in)) { return ZTS_ERR_ARG; } return lwip_getpeername(fd, (sockaddr*)addr, (socklen_t*)addrlen); @@ -290,22 +282,12 @@ int zts_close(int fd) return lwip_close(fd); } -int zts_select( - int nfds, - zts_fd_set* readfds, - zts_fd_set* writefds, - zts_fd_set* exceptfds, - struct zts_timeval* timeout) +int zts_select(int nfds, zts_fd_set* readfds, zts_fd_set* writefds, zts_fd_set* exceptfds, struct zts_timeval* timeout) { if (! transport_ok()) { return ZTS_ERR_SERVICE; } - return lwip_select( - nfds, - (fd_set*)readfds, - (fd_set*)writefds, - (fd_set*)exceptfds, - (timeval*)timeout); + return lwip_select(nfds, (fd_set*)readfds, (fd_set*)writefds, (fd_set*)exceptfds, (timeval*)timeout); } int zts_fcntl(int fd, int cmd, int flags) @@ -346,13 +328,8 @@ ssize_t zts_send(int fd, const void* buf, size_t len, int flags) return lwip_send(fd, buf, len, flags); } -ssize_t zts_sendto( - int fd, - const void* buf, - size_t len, - int flags, - const struct zts_sockaddr* addr, - zts_socklen_t addrlen) +ssize_t +zts_sendto(int fd, const void* buf, size_t len, int flags, const struct zts_sockaddr* addr, zts_socklen_t addrlen) { if (! transport_ok()) { return ZTS_ERR_SERVICE; @@ -360,8 +337,7 @@ ssize_t zts_sendto( if (! addr || ! buf) { return ZTS_ERR_ARG; } - if (addrlen > (int)sizeof(struct zts_sockaddr_storage) - || addrlen < (int)sizeof(struct zts_sockaddr_in)) { + if (addrlen > (int)sizeof(struct zts_sockaddr_storage) || addrlen < (int)sizeof(struct zts_sockaddr_in)) { return ZTS_ERR_ARG; } return lwip_sendto(fd, buf, len, flags, (sockaddr*)addr, addrlen); @@ -386,13 +362,7 @@ ssize_t zts_recv(int fd, void* buf, size_t len, int flags) return lwip_recv(fd, buf, len, flags); } -ssize_t zts_recvfrom( - int fd, - void* buf, - size_t len, - int flags, - struct zts_sockaddr* addr, - zts_socklen_t* addrlen) +ssize_t zts_recvfrom(int fd, void* buf, size_t len, int flags, struct zts_sockaddr* addr, zts_socklen_t* addrlen) { if (! transport_ok()) { return ZTS_ERR_SERVICE; @@ -519,7 +489,7 @@ int zts_inet_pton(int family, const char* src, void* dst) int zts_util_ipstr_to_saddr( const char* src_ipstr, - int port, + unsigned int port, struct zts_sockaddr* dest_addr, zts_socklen_t* addrlen) { diff --git a/src/Utilities.cpp b/src/Utilities.cpp index 5b34a513..32ca4eb0 100644 --- a/src/Utilities.cpp +++ b/src/Utilities.cpp @@ -15,8 +15,20 @@ #include "ZeroTierSockets.h" +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include +#include #ifdef __WINDOWS__ #include @@ -26,6 +38,8 @@ #include // for usleep #endif +namespace ZeroTier { + #ifdef __cplusplus extern "C" { #endif @@ -47,7 +61,7 @@ int zts_util_get_ip_family(const char* ipstr) return family; } -void zts_util_delay(long milliseconds) +void zts_util_delay(unsigned long milliseconds) { #ifdef __WINDOWS__ Sleep(milliseconds); @@ -61,6 +75,84 @@ void zts_util_delay(long milliseconds) #endif } +int zts_util_world_new( + char* world_out, + unsigned int* world_len, + char* prev_key, + unsigned int* prev_key_len, + char* curr_key, + unsigned int* curr_key_len, + uint64_t id, + uint64_t ts, + zts_world_t* world_spec) +{ + if (! world_spec || ! prev_key || ! curr_key || ! prev_key_len || ! curr_key_len) { + return ZTS_ERR_ARG; + } + // Generate signing keys + std::string previous, current; + if ((! OSUtils::readFile("previous.c25519", previous)) || (! OSUtils::readFile("current.c25519", current))) { + C25519::Pair np(C25519::generate()); + previous = std::string(); + previous.append((const char*)np.pub.data, ZT_C25519_PUBLIC_KEY_LEN); + previous.append((const char*)np.priv.data, ZT_C25519_PRIVATE_KEY_LEN); + current = previous; + } + if ((previous.length() != (ZT_C25519_PUBLIC_KEY_LEN + ZT_C25519_PRIVATE_KEY_LEN)) + || (current.length() != (ZT_C25519_PUBLIC_KEY_LEN + ZT_C25519_PRIVATE_KEY_LEN))) { + // Previous.c25519 or current.c25519 empty or invalid + return ZTS_ERR_ARG; + } + C25519::Pair previousKP; + memcpy(previousKP.pub.data, previous.data(), ZT_C25519_PUBLIC_KEY_LEN); + memcpy(previousKP.priv.data, previous.data() + ZT_C25519_PUBLIC_KEY_LEN, ZT_C25519_PRIVATE_KEY_LEN); + C25519::Pair currentKP; + memcpy(currentKP.pub.data, current.data(), ZT_C25519_PUBLIC_KEY_LEN); + memcpy(currentKP.priv.data, current.data() + ZT_C25519_PUBLIC_KEY_LEN, ZT_C25519_PRIVATE_KEY_LEN); + + // Set up world definition + std::vector roots; + for (int i = 0; i < ZTS_MAX_NUM_ROOTS; i++) { + if (! world_spec->public_id_str[i]) { + break; + } + if (strlen(world_spec->public_id_str[i])) { + // printf("id = %s\n", world_spec->public_id_str[i]); + roots.push_back(World::Root()); + roots.back().identity = Identity(world_spec->public_id_str[i]); + for (int j = 0; j < ZTS_MAX_ENDPOINTS_PER_ROOT; j++) { + if (! world_spec->endpoint_ip_str[i][j]) { + break; + } + if (strlen(world_spec->endpoint_ip_str[i][j])) { + roots.back().stableEndpoints.push_back(InetAddress(world_spec->endpoint_ip_str[i][j])); + // printf(" ep = %s\n", world_spec->endpoint_ip_str[i][j]); + } + } + } + } + + // Generate + World nw = World::make(World::TYPE_PLANET, id, ts, currentKP.pub, roots, previousKP); + // Test + Buffer outtmp; + nw.serialize(outtmp, false); + World testw; + testw.deserialize(outtmp, 0); + if (testw != nw) { + // Serialization test failed + return ZTS_ERR_GENERAL; + } + // Write output + memcpy(world_out, (char*)outtmp.data(), outtmp.size()); + *world_len = outtmp.size(); + memcpy(prev_key, previous.data(), previous.length()); + *prev_key_len = ZT_C25519_PRIVATE_KEY_LEN + ZT_C25519_PUBLIC_KEY_LEN; + memcpy(curr_key, current.data(), current.length()); + *curr_key_len = ZT_C25519_PRIVATE_KEY_LEN + ZT_C25519_PUBLIC_KEY_LEN; + return ZTS_ERR_OK; +} + void native_ss_to_zts_ss(struct zts_sockaddr_storage* ss_out, const struct sockaddr_storage* ss_in) { if (ss_in->ss_family == AF_INET) { @@ -90,3 +182,5 @@ void native_ss_to_zts_ss(struct zts_sockaddr_storage* ss_out, const struct socka #ifdef __cplusplus } #endif + +} // namespace ZeroTier diff --git a/src/VirtualTap.cpp b/src/VirtualTap.cpp index 8d1d45d4..b5d3dc1c 100644 --- a/src/VirtualTap.cpp +++ b/src/VirtualTap.cpp @@ -61,7 +61,6 @@ VirtualTap::VirtualTap( unsigned int mtu, unsigned int metric, uint64_t net_id, - const char* friendlyName, void (*handler)( void*, void*, @@ -95,8 +94,6 @@ VirtualTap::VirtualTap( VirtualTap::~VirtualTap() { - zts_net_info_t* nd = new zts_net_info_t; - nd->net_id = _net_id; _run = false; #ifndef __WINDOWS__ ::write(_shutdownSignalPipe[1], "\0", 1); @@ -106,7 +103,6 @@ VirtualTap::~VirtualTap() netif4 = NULL; _lwip_remove_netif(netif6); netif6 = NULL; - _events->enqueue(ZTS_EVENT_NETWORK_DOWN, (void*)nd); Thread::join(_thread); #ifndef __WINDOWS__ ::close(_shutdownSignalPipe[0]); @@ -209,21 +205,14 @@ std::vector VirtualTap::ips() const return _ips; } -void VirtualTap::put( - const MAC& from, - const MAC& to, - unsigned int etherType, - const void* data, - unsigned int len) +void VirtualTap::put(const MAC& from, const MAC& to, unsigned int etherType, const void* data, unsigned int len) { if (len && _enabled) { _lwip_eth_rx(this, from, to, etherType, data, len); } } -void VirtualTap::scanMulticastGroups( - std::vector& added, - std::vector& removed) +void VirtualTap::scanMulticastGroups(std::vector& added, std::vector& removed) { std::vector newGroups; Mutex::Lock _l(_multicastGroups_m); @@ -238,9 +227,7 @@ void VirtualTap::scanMulticastGroups( if (! std::binary_search(_multicastGroups.begin(), _multicastGroups.end(), *m)) added.push_back(*m); } - for (std::vector::iterator m(_multicastGroups.begin()); - m != _multicastGroups.end(); - ++m) { + for (std::vector::iterator m(_multicastGroups.begin()); m != _multicastGroups.end(); ++m) { if (! std::binary_search(newGroups.begin(), newGroups.end(), *m)) removed.push_back(*m); } @@ -389,12 +376,7 @@ void _lwip_driver_init() #if defined(__WINDOWS__) sys_init(); // Required for win32 init of critical sections #endif - sys_thread_new( - ZTS_LWIP_THREAD_NAME, - _main_lwip_driver_loop, - NULL, - DEFAULT_THREAD_STACKSIZE, - DEFAULT_THREAD_PRIO); + sys_thread_new(ZTS_LWIP_THREAD_NAME, _main_lwip_driver_loop, NULL, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO); } void _lwip_driver_shutdown() @@ -510,8 +492,7 @@ void _lwip_eth_rx( if (Utils::ntoh(ethhdr.type) == 0x800 || Utils::ntoh(ethhdr.type) == 0x806) { if (tap->netif4) { - if ((err = ((struct netif*)tap->netif4)->input(p, (struct netif*)tap->netif4)) - != ERR_OK) { + if ((err = ((struct netif*)tap->netif4)->input(p, (struct netif*)tap->netif4)) != ERR_OK) { // DEBUG_ERROR("packet input error (%d)", err); pbuf_free(p); } @@ -519,8 +500,7 @@ void _lwip_eth_rx( } if (Utils::ntoh(ethhdr.type) == 0x86DD) { if (tap->netif6) { - if ((err = ((struct netif*)tap->netif6)->input(p, (struct netif*)tap->netif6)) - != ERR_OK) { + if ((err = ((struct netif*)tap->netif6)->input(p, (struct netif*)tap->netif6)) != ERR_OK) { // DEBUG_ERROR("packet input error (%d)", err); pbuf_free(p); } @@ -552,8 +532,8 @@ static err_t _netif_init4(struct netif* n) n->linkoutput = _lwip_eth_tx; n->output = etharp_output; n->mtu = std::min(LWIP_MTU, (int)tap->_mtu); - n->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP - | NETIF_FLAG_MLD6 | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP; + n->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP | NETIF_FLAG_MLD6 + | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP; n->hwaddr_len = sizeof(n->hwaddr); tap->_mac.copyTo(n->hwaddr, n->hwaddr_len); return ERR_OK; @@ -574,8 +554,8 @@ static err_t _netif_init6(struct netif* n) n->linkoutput = _lwip_eth_tx; n->output_ip6 = ethip6_output; n->mtu = std::min(LWIP_MTU, (int)tap->_mtu); - n->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP - | NETIF_FLAG_MLD6 | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP; + n->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP | NETIF_FLAG_MLD6 + | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP; return ERR_OK; } diff --git a/src/VirtualTap.hpp b/src/VirtualTap.hpp index b2409164..757f4571 100644 --- a/src/VirtualTap.hpp +++ b/src/VirtualTap.hpp @@ -51,7 +51,6 @@ class VirtualTap { unsigned int mtu, unsigned int metric, uint64_t net_id, - const char* friendlyName, void (*handler)( void*, void*, @@ -108,14 +107,12 @@ class VirtualTap { /** * Presents data to the user-space stack */ - void - put(const MAC& from, const MAC& to, unsigned int etherType, const void* data, unsigned int len); + void put(const MAC& from, const MAC& to, unsigned int etherType, const void* data, unsigned int len); /** * Scan multicast groups */ - void - scanMulticastGroups(std::vector& added, std::vector& removed); + void scanMulticastGroups(std::vector& added, std::vector& removed); /** * Set MTU @@ -187,12 +184,7 @@ class VirtualTap { void* data, unsigned long len); void phyOnTcpConnect(PhySocket* sock, void** uptr, bool success); - void phyOnTcpAccept( - PhySocket* sockL, - PhySocket* sockN, - void** uptrL, - void** uptrN, - const struct sockaddr* from); + void phyOnTcpAccept(PhySocket* sockL, PhySocket* sockN, void** uptrL, void** uptrN, const struct sockaddr* from); void phyOnTcpClose(PhySocket* sock, void** uptr); void phyOnTcpData(PhySocket* sock, void** uptr, void* data, unsigned long len); void phyOnTcpWritable(PhySocket* sock, void** uptr);