Adjust nomenclature. Add more C API extension functions

This commit is contained in:
Joseph Henry
2021-04-29 14:03:15 -07:00
parent 9ed0ee68ab
commit 016b0ffc0e
17 changed files with 492 additions and 445 deletions

View File

@@ -100,6 +100,7 @@ int main(int argc, char** argv)
// Close // Close
printf("Closing sockets\n");
zts_close(fd); zts_close(fd);
return zts_node_stop(); return zts_node_stop();
} }

View File

@@ -13,7 +13,7 @@
void print_peer_details(const char* msg, zts_peer_info_t* d) void print_peer_details(const char* msg, zts_peer_info_t* d)
{ {
printf(" %s\n", msg); printf(" %s\n", msg);
printf("\t- peer : %llx\n", d->address); printf("\t- peer : %llx\n", d->peer_id);
printf("\t- role : %d\n", d->role); printf("\t- role : %d\n", d->role);
printf("\t- latency : %d\n", d->latency); 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- version : %d.%d.%d\n", d->ver_major, d->ver_minor, d->ver_rev);
@@ -61,49 +61,58 @@ int main()
{ {
// World generation // World generation
// Buffers that will be filled after generating the world // Buffers that will be filled after generating the roots
char world_data_out[4096] = { 0 }; // (binary) Your new world definition char roots_data_out[4096] = { 0 }; // (binary) Your new custom roots definition
unsigned int world_len = 0; unsigned int roots_len = 0;
unsigned int prev_key_len = 0; unsigned int prev_key_len = 0;
unsigned int curr_key_len = 0; unsigned int curr_key_len = 0;
char prev_key[4096] = { 0 }; // (binary) (optional) For updating a world char prev_key[4096] = { 0 }; // (binary) (optional) For updating roots
char curr_key[4096] = { 0 }; // (binary) You should save this char curr_key[4096] = { 0 }; // (binary) You should save this
// Arbitrary World ID // Arbitrary World ID
uint64_t id = 149604618; uint64_t id = 149604618;
// Timestamp indicating when this world was generated // Timestamp indicating when this signed root blob was generated
uint64_t ts = 1567191349589ULL; uint64_t ts = 1567191349589ULL;
// struct containing public keys and stable IP endpoints for roots // struct containing public keys and stable IP endpoints for roots
zts_world_t world = { 0 }; zts_root_set_t roots = { 0 };
world.public_id_str[0] = roots.public_id_str[0] =
"992fcf1db7:0:" "992fcf1db7:0:"
"206ed59350b31916f749a1f85dffb3a8787dcbf83b8c6e9448d4e3ea0e3369301be716c3609344a9d1533850fb4460c5" "206ed59350b31916f749a1f85dffb3a8787dcbf83b8c6e9448d4e3ea0e3369301be716c3609344a9d1533850fb4460c5"
"0af43322bcfc8e13d3301a1f1003ceb6"; "0af43322bcfc8e13d3301a1f1003ceb6";
world.endpoint_ip_str[0][0] = "195.181.173.159/9993"; roots.endpoint_ip_str[0][0] = "195.181.173.159/9993";
world.endpoint_ip_str[0][1] = "2a02:6ea0:c024::/9993"; roots.endpoint_ip_str[0][1] = "2a02:6ea0:c024::/9993";
// Generate world // Generate roots
zts_util_world_new(&world_data_out, &world_len, &prev_key, &prev_key_len, &curr_key, &curr_key_len, id, ts, &world); zts_util_sign_root_set(
&roots_data_out,
&roots_len,
&prev_key,
&prev_key_len,
&curr_key,
&curr_key_len,
id,
ts,
&roots);
printf("world_data_out= "); printf("roots_data_out= ");
for (int i = 0; i < world_len; i++) { for (int i = 0; i < roots_len; i++) {
if (i > 0) { if (i > 0) {
printf(","); printf(",");
} }
printf("0x%.2x", (unsigned char)world_data_out[i]); printf("0x%.2x", (unsigned char)roots_data_out[i]);
} }
printf("\n"); printf("\n");
printf("world_len = %d\n", world_len); printf("roots_len = %d\n", roots_len);
printf("prev_key_len = %d\n", prev_key_len); printf("prev_key_len = %d\n", prev_key_len);
printf("curr_key_len = %d\n", curr_key_len); printf("curr_key_len = %d\n", curr_key_len);
// Now, initialize node and use newly-generated world definition // Now, initialize node and use newly-generated roots definition
zts_init_set_world(&world_data_out, world_len); zts_init_set_roots(&roots_data_out, roots_len);
zts_init_set_event_handler(&on_zts_event); zts_init_set_event_handler(&on_zts_event);
zts_init_from_storage("."); zts_init_from_storage(".");

View File

@@ -103,7 +103,7 @@ int main(int argc, char** argv)
// Close // Close
printf("Closing connection socket\n"); printf("Closing sockets\n");
err = zts_close(accfd); err = zts_close(accfd);
err = zts_close(fd); err = zts_close(fd);
return zts_node_stop(); return zts_node_stop();

View File

@@ -344,11 +344,13 @@ typedef enum {
*/ */
#define ZTS_MAX_MULTICAST_SUBSCRIPTIONS 1024 #define ZTS_MAX_MULTICAST_SUBSCRIPTIONS 1024
#define ZTS_MAX_ENDPOINT_STR_LEN ZTS_INET6_ADDRSTRLEN + 6
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
// Misc // // Misc //
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
#if ! defined(ZTS_ENABLE_PYTHON) && ! defined(ZTS_ENABLE_PINVOKE) #if ! defined(ZTS_ENABLE_PYTHON) && ! defined(ZTS_ENABLE_PINVOKE) && ! defined(ZTS_ENABLE_JAVA)
#define ZTS_C_API_ONLY 1 #define ZTS_C_API_ONLY 1
#endif #endif
@@ -877,7 +879,7 @@ typedef struct {
/** /**
* ZeroTier address (40 bits) * ZeroTier address (40 bits)
*/ */
uint64_t address; uint64_t peer_id;
/** /**
* Remote major version or -1 if not known * Remote major version or -1 if not known
@@ -929,7 +931,7 @@ typedef struct {
typedef struct { typedef struct {
char* public_id_str[ZTS_MAX_NUM_ROOTS]; char* public_id_str[ZTS_MAX_NUM_ROOTS];
char* endpoint_ip_str[ZTS_MAX_NUM_ROOTS][ZTS_MAX_ENDPOINTS_PER_ROOT]; char* endpoint_ip_str[ZTS_MAX_NUM_ROOTS][ZTS_MAX_ENDPOINTS_PER_ROOT];
} zts_world_t; } zts_root_set_t;
/** /**
* Structure used to convey information about a virtual network * Structure used to convey information about a virtual network
@@ -1285,6 +1287,10 @@ ZTS_API int ZTCALL zts_init_set_event_handler(PythonDirectorCallbackClass* callb
#ifdef ZTS_ENABLE_PINVOKE #ifdef ZTS_ENABLE_PINVOKE
ZTS_API int ZTCALL zts_init_set_event_handler(CppCallback callback); ZTS_API int ZTCALL zts_init_set_event_handler(CppCallback callback);
#endif #endif
#ifdef ZTS_ENABLE_JAVA
#include <jni.h>
int zts_init_set_event_handler(jobject obj_ref, jmethodID id);
#endif
#ifdef ZTS_C_API_ONLY #ifdef ZTS_C_API_ONLY
ZTS_API int ZTCALL zts_init_set_event_handler(void (*callback)(void*)); ZTS_API int ZTCALL zts_init_set_event_handler(void (*callback)(void*));
#endif #endif
@@ -1302,15 +1308,15 @@ ZTS_API int ZTCALL zts_init_set_event_handler(void (*callback)(void*));
ZTS_API int ZTCALL zts_init_blacklist_if(const char* prefix, unsigned int len); ZTS_API int ZTCALL zts_init_blacklist_if(const char* prefix, unsigned int len);
/** /**
* @brief Present a world definition for ZeroTier to use instead of the default. * @brief Present a root set definition for ZeroTier to use instead of the default.
* This is an initialization function that can only be called before `zts_node_start()`. * This is an initialization function that can only be called before `zts_node_start()`.
* *
* @param world_data Array of world definition data (binary) * @param roots_data Array of roots definition data (binary)
* @param len Length of binary data * @param len Length of binary data
* @return `ZTS_ERR_OK` if successful, `ZTS_ERR_SERVICE` if the node * @return `ZTS_ERR_OK` if successful, `ZTS_ERR_SERVICE` if the node
* experiences a problem, `ZTS_ERR_ARG` if invalid argument. * experiences a problem, `ZTS_ERR_ARG` if invalid argument.
*/ */
ZTS_API int ZTCALL zts_init_set_world(const void* world_data, unsigned int len); ZTS_API int ZTCALL zts_init_set_roots(const void* roots_data, unsigned int len);
/** /**
* @brief Set the port to which the node should bind. This is an initialization function that can * @brief Set the port to which the node should bind. This is an initialization function that can
@@ -1362,14 +1368,14 @@ ZTS_API int ZTCALL zts_init_allow_net_cache(unsigned int allowed);
ZTS_API int ZTCALL zts_init_allow_peer_cache(unsigned int allowed); ZTS_API int ZTCALL zts_init_allow_peer_cache(unsigned int allowed);
/** /**
* @brief Enable or disable whether the node will cache world definitions (enabled * @brief Enable or disable whether the node will cache root definitions (enabled
* by default when `zts_init_from_storage()` is used.) Must be called before `zts_node_start()`. * 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 * @param enabled Whether or not this feature is enabled
* @return `ZTS_ERR_OK` if successful, `ZTS_ERR_SERVICE` if the node * @return `ZTS_ERR_OK` if successful, `ZTS_ERR_SERVICE` if the node
* experiences a problem, `ZTS_ERR_ARG` if invalid argument. * experiences a problem, `ZTS_ERR_ARG` if invalid argument.
*/ */
ZTS_API int ZTCALL zts_init_allow_world_cache(unsigned int allowed); ZTS_API int ZTCALL zts_init_allow_roots_cache(unsigned int allowed);
/** /**
* @brief Enable or disable whether the node will cache identities (enabled * @brief Enable or disable whether the node will cache identities (enabled
@@ -1647,12 +1653,12 @@ ZTS_API uint64_t ZTCALL zts_node_get_id();
* `WARNING`: This function exports your secret key and should be used carefully. * `WARNING`: This function exports your secret key and should be used carefully.
* *
* @param key User-provided destination buffer * @param key User-provided destination buffer
* @param key_buf_len Length of user-provided destination buffer. Will be set to * @param key_dst_len Length of user-provided destination buffer. Will be set to
* number of bytes copied. * number of bytes copied.
* @return `ZTS_ERR_OK` if successful, `ZTS_ERR_SERVICE` if the node * @return `ZTS_ERR_OK` if successful, `ZTS_ERR_SERVICE` if the node
* experiences a problem, `ZTS_ERR_ARG` if invalid argument. * experiences a problem, `ZTS_ERR_ARG` if invalid argument.
*/ */
ZTS_API int ZTCALL zts_node_get_id_pair(char* key, unsigned int* key_buf_len); ZTS_API int ZTCALL zts_node_get_id_pair(char* key, unsigned int* key_dst_len);
/** /**
* @brief Get the primary port to which the node is bound. Callable only after the node has been * @brief Get the primary port to which the node is bound. Callable only after the node has been
@@ -1692,21 +1698,21 @@ ZTS_API int ZTCALL zts_node_free();
/** /**
* @brief Orbit a given moon (user-defined root server) * @brief Orbit a given moon (user-defined root server)
* *
* @param moon_world_id World ID * @param moon_roots_id World ID
* @param moon_seed Seed ID * @param moon_seed Seed ID
* @return `ZTS_ERR_OK` if successful, `ZTS_ERR_SERVICE` if the node * @return `ZTS_ERR_OK` if successful, `ZTS_ERR_SERVICE` if the node
* experiences a problem, `ZTS_ERR_ARG` if invalid argument. * experiences a problem, `ZTS_ERR_ARG` if invalid argument.
*/ */
ZTS_API int ZTCALL zts_moon_orbit(uint64_t moon_world_id, uint64_t moon_seed); ZTS_API int ZTCALL zts_moon_orbit(uint64_t moon_roots_id, uint64_t moon_seed);
/** /**
* @brief De-orbit a given moon (user-defined root server) * @brief De-orbit a given moon (user-defined root server)
* *
* @param moon_world_id World ID * @param moon_roots_id World ID
* @return `ZTS_ERR_OK` if successful, `ZTS_ERR_SERVICE` if the node * @return `ZTS_ERR_OK` if successful, `ZTS_ERR_SERVICE` if the node
* experiences a problem, `ZTS_ERR_ARG` if invalid argument. * experiences a problem, `ZTS_ERR_ARG` if invalid argument.
*/ */
ZTS_API int ZTCALL zts_moon_deorbit(uint64_t moon_world_id); ZTS_API int ZTCALL zts_moon_deorbit(uint64_t moon_roots_id);
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
// Statistics // // Statistics //
@@ -1837,31 +1843,6 @@ ZTS_API int ZTCALL zts_socket(int family, int type, int protocol);
*/ */
ZTS_API int ZTCALL zts_connect(int fd, const struct zts_sockaddr* addr, zts_socklen_t addrlen); ZTS_API int ZTCALL zts_connect(int fd, const struct zts_sockaddr* addr, zts_socklen_t addrlen);
/**
* @brief Connect a socket to a remote host
*
* This convenience function exists because ZeroTier uses transport-triggered
* links. This means that links between peers do not exist until peers try to
* talk to each other. This can be a problem during connection procedures since
* some of the initial packets are lost. To alleviate the need to try
* `zts_connect` many times, this function will keep re-trying for you, even if
* no known routes exist. However, if the socket is set to `non-blocking` mode
* it will behave identically to `zts_connect` and return immediately upon
* failure.
*
* @param fd Socket file descriptor
* @param ipstr Human-readable IP string
* @param port Port
* @param timeout_ms (Approximate) amount of time in milliseconds before
* connection attempt is aborted. Will block for `30 seconds` if timeout is
* set to `0`.
*
* @return `ZTS_ERR_OK` if successful, `ZTS_ERR_SOCKET` if the function times
* out with no connection made, `ZTS_ERR_SERVICE` if the node experiences a
* problem, `ZTS_ERR_ARG` if invalid argument. Sets `zts_errno`
*/
ZTS_API int ZTCALL zts_simple_connect(int fd, const char* ipstr, int port, int timeout_ms);
/** /**
* @brief Bind a socket to a local address * @brief Bind a socket to a local address
* *
@@ -1873,17 +1854,6 @@ ZTS_API int ZTCALL zts_simple_connect(int fd, const char* ipstr, int port, int t
*/ */
ZTS_API int ZTCALL zts_bind(int fd, const struct zts_sockaddr* addr, zts_socklen_t addrlen); ZTS_API int ZTCALL zts_bind(int fd, const struct zts_sockaddr* addr, zts_socklen_t addrlen);
/**
* @brief Bind a socket to a local address
*
* @param fd Socket file descriptor
* @param ipstr Human-readable IP string
* @param port Port
* @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_simple_bind(int fd, const char* ipstr, int port);
/** /**
* @brief Listen for incoming connections on socket * @brief Listen for incoming connections on socket
* *
@@ -1905,71 +1875,6 @@ ZTS_API int ZTCALL zts_listen(int fd, int backlog);
*/ */
ZTS_API int ZTCALL zts_accept(int fd, struct zts_sockaddr* addr, zts_socklen_t* addrlen); ZTS_API int ZTCALL zts_accept(int fd, struct zts_sockaddr* addr, zts_socklen_t* addrlen);
/**
* @brief Accept an incoming connection
*
* @param fd Socket file descriptor
* @param remote_addr Buffer that will receive remote host IP string
* @param len Size of buffer that will receive remote host IP string
* (must be exactly `ZTS_IP_MAX_STR_LEN`)
* @param port Port number of the newly connected remote host (value-result)
* @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_accept(int fd, char* remote_addr, int len, int* port);
/**
* @brief A convenience function that takes a remote address IP string and creates
* the appropriate type of socket, and uses it to connect to a remote host.
*
* @param remote_ipstr Remote address string. IPv4 or IPv6
* @param remote_port Port to
*
* @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_client(const char* remote_ipstr, int remote_port);
/**
* @brief A convenience function that takes a remote address IP string and creates
* the appropriate type of socket, binds, listens, and then accepts on it.
*
* @param local_ipstr Local address to bind
* @param local_port Local port to bind
* @param remote_ipstr String-format IP address of newly connected remote host
* @param len Length of `remote_ipstr`
* @param remote_port Port of remote host
*
* @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);
/**
* @brief A convenience function that takes a remote address IP string and creates
* the appropriate type of socket, and binds to it.
*
* @param local_ipstr Local address to bind
* @param local_port Local port to bind
*
* @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_udp_server(const char* local_ipstr, int local_port);
/**
* @brief This function doesn't really do anything other than be a namespace
* counterpart to `zts_simple_udp_server`. All this function does is create a
* `ZTS_SOCK_DGRAM` socket and return its file descriptor.
*
* @param remote_ipstr Remote address string. IPv4 or IPv6
*
* @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_udp_client(const char* remote_ipstr);
// Socket level option number // Socket level option number
#define ZTS_SOL_SOCKET 0x0fff #define ZTS_SOL_SOCKET 0x0fff
// Socket options // Socket options
@@ -2124,7 +2029,7 @@ ZTS_API int ZTCALL zts_setsockopt(int fd, int level, int optname, const void* op
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. * @brief Get the name (address) of the local end of the socket
* *
* @param fd Socket file descriptor * @param fd Socket file descriptor
* @param addr Name associated with this socket * @param addr Name associated with this socket
@@ -2135,7 +2040,7 @@ ZTS_API int ZTCALL zts_getsockopt(int fd, int level, int optname, void* optval,
ZTS_API int ZTCALL zts_getsockname(int fd, struct zts_sockaddr* addr, zts_socklen_t* addrlen); ZTS_API int ZTCALL zts_getsockname(int fd, struct zts_sockaddr* addr, zts_socklen_t* addrlen);
/** /**
* @brief Get the peer name for the remote end of a connected socket. * @brief Get the name (address) of the remote end of the socket
* *
* @param fd Socket file descriptor * @param fd Socket file descriptor
* @param addr Name associated with remote end of this socket * @param addr Name associated with remote end of this socket
@@ -2433,6 +2338,141 @@ ZTS_API int ZTCALL zts_shutdown(int fd, int how);
// Convenience functions // // Convenience functions //
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
/**
* Helper functions that simplify API wrapper generation and usage in other
* non-C-like languages. Use simple integer types instead of bit flags,
* limit the number of operations each function performs, prevent the user
* from needing to manipulate the contents of structures in a non-native
* language.
*/
/**
* @brief Connect a socket to a remote host
*
* This convenience function exists because ZeroTier uses transport-triggered
* links. This means that links between peers do not exist until peers try to
* talk to each other. This can be a problem during connection procedures since
* some of the initial packets are lost. To alleviate the need to try
* `zts_connect` many times, this function will keep re-trying for you, even if
* no known routes exist. However, if the socket is set to `non-blocking` mode
* it will behave identically to `zts_connect` and return immediately upon
* failure.
*
* @param fd Socket file descriptor
* @param ipstr Human-readable IP string
* @param port Port
* @param timeout_ms (Approximate) amount of time in milliseconds before
* connection attempt is aborted. Will block for `30 seconds` if timeout is
* set to `0`.
*
* @return `ZTS_ERR_OK` if successful, `ZTS_ERR_SOCKET` if the function times
* out with no connection made, `ZTS_ERR_SERVICE` if the node experiences a
* problem, `ZTS_ERR_ARG` if invalid argument. Sets `zts_errno`
*/
ZTS_API int ZTCALL zts_simple_connect(int fd, const char* ipstr, unsigned short port, int timeout_ms);
/**
* @brief Bind a socket to a local address
*
* @param fd Socket file descriptor
* @param ipstr Human-readable IP string
* @param port Port
* @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_simple_bind(int fd, const char* ipstr, unsigned short port);
/**
* @brief Accept an incoming connection
*
* @param fd Socket file descriptor
* @param remote_addr Buffer that will receive remote host IP string
* @param len Size of buffer that will receive remote host IP string
* (must be exactly `ZTS_IP_MAX_STR_LEN`)
* @param port Port number of the newly connected remote host (value-result)
* @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_accept(int fd, char* remote_addr, int len, unsigned short* port);
/**
* @brief Get the name (address) of the remote end of the socket
*
* @param fd Socket file descriptor
* @param remote_addr_str Destination buffer to contain name (address) of the remote end of the socket
* @param len Length of destination buffer
* @param port Value-result parameter that will contain resultant port number
* @return `ZTS_ERR_OK` if successful, `ZTS_ERR_ARG` if invalid argument. Sets `zts_errno`
*/
ZTS_API int ZTCALL zts_simple_getpeername(int fd, char* remote_addr_str, int len, unsigned short* port);
/**
* @brief Get the name (address) of the local end of the socket
*
* @param fd Socket file descriptor
* @param local_addr_str Destination buffer to contain name (address) of the local end of the socket
* @param len Length of destination buffer
* @param port Value-result parameter that will contain resultant port number
* @return `ZTS_ERR_OK` if successful, `ZTS_ERR_ARG` if invalid argument. Sets `zts_errno`
*/
ZTS_API int ZTCALL zts_simple_getsockname(int fd, char* local_addr_str, int len, unsigned short* port);
/**
* @brief A convenience function that takes a remote address IP string and creates
* the appropriate type of socket, and uses it to connect to a remote host.
*
* @param remote_ipstr Remote address string. IPv4 or IPv6
* @param remote_port Port to
*
* @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_client(const char* remote_ipstr, unsigned short remote_port);
/**
* @brief A convenience function that takes a remote address IP string and creates
* the appropriate type of socket, binds, listens, and then accepts on it.
*
* @param local_ipstr Local address to bind
* @param local_port Local port to bind
* @param remote_ipstr String-format IP address of newly connected remote host
* @param len Length of `remote_ipstr`
* @param remote_port Port of remote host
*
* @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,
unsigned short local_port,
char* remote_ipstr,
int len,
unsigned short* remote_port);
/**
* @brief A convenience function that takes a remote address IP string and creates
* the appropriate type of socket, and binds to it.
*
* @param local_ipstr Local address to bind
* @param local_port Local port to bind
*
* @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_udp_server(const char* local_ipstr, unsigned short local_port);
/**
* @brief This function doesn't really do anything other than be a namespace
* counterpart to `zts_simple_udp_server`. All this function does is create a
* `ZTS_SOCK_DGRAM` socket and return its file descriptor.
*
* @param remote_ipstr Remote address string. IPv4 or IPv6
*
* @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_udp_client(const char* remote_ipstr);
/** /**
* @brief Enable or disable `TCP_NODELAY`. Enabling this is equivalent to * @brief Enable or disable `TCP_NODELAY`. Enabling this is equivalent to
* turning off Nagle's algorithm * turning off Nagle's algorithm
@@ -2482,6 +2522,15 @@ ZTS_API int ZTCALL zts_simple_get_linger_enabled(int fd);
*/ */
ZTS_API int ZTCALL zts_simple_get_linger_value(int fd); ZTS_API int ZTCALL zts_simple_get_linger_value(int fd);
/**
* @brief Return the number of bytes available to read from the network buffer
*
* @param fd Socket file descriptor
* @return Number of bytes to read 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_get_pending_data_size(int fd);
/** /**
* @brief Enable or disable `SO_REUSEADDR` * @brief Enable or disable `SO_REUSEADDR`
* *
@@ -2837,21 +2886,21 @@ ZTS_API int ZTCALL zts_core_query_mc(uint64_t net_id, unsigned int idx, uint64_t
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
/** /**
* @brief Generates a new world definition * @brief Generates a new root set definition
* *
* @param world_id The desired World ID (arbitrary) * @param roots_id The desired World ID (arbitrary)
* @param ts Timestamp indicating when this generation took place * @param ts Timestamp indicating when this generation took place
*/ */
ZTS_API int ZTCALL zts_util_world_new( ZTS_API int ZTCALL zts_util_sign_root_set(
char* world_out, char* roots_out,
unsigned int* world_len, unsigned int* roots_len,
char* prev_key, char* prev_key,
unsigned int* prev_key_len, unsigned int* prev_key_len,
char* curr_key, char* curr_key,
unsigned int* curr_key_len, unsigned int* curr_key_len,
uint64_t id, uint64_t id,
uint64_t ts, uint64_t ts,
zts_world_t* world_spec); zts_root_set_t* roots_spec);
/** /**
* @brief Platform-agnostic delay * @brief Platform-agnostic delay
@@ -2881,10 +2930,25 @@ ZTS_API int ZTCALL zts_util_get_ip_family(const char* ipstr);
*/ */
int zts_util_ipstr_to_saddr( int zts_util_ipstr_to_saddr(
const char* src_ipstr, const char* src_ipstr,
unsigned int port, unsigned short port,
struct zts_sockaddr* dstaddr, struct zts_sockaddr* dstaddr,
zts_socklen_t* addrlen); zts_socklen_t* addrlen);
/**
* @brief Similar to `inet_ntop` but determines family automatically and returns
* port as a value result parameter.
*
* @param addr Pointer to address structure
* @param addrlen Length of address structure
* @param dst_str Destination buffer
* @param len Length of destination buffer
* @param port Value-result parameter that will contain resultant port number
*
* @return return `ZTS_ERR_OK` on success, `ZTS_ERR_ARG` if invalid argument
*/
ZTS_API int ZTCALL
zts_util_ntop(struct zts_sockaddr* addr, zts_socklen_t addrlen, char* dst_str, int len, unsigned short* port);
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
// Convenience functions pulled from lwIP // // Convenience functions pulled from lwIP //
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//

View File

@@ -18,11 +18,9 @@
#include "OSUtils.hpp" #include "OSUtils.hpp"
#include "ZeroTierSockets.h" #include "ZeroTierSockets.h"
#include <cstdint>
#include <cstring>
#include <curl/curl.h> #include <curl/curl.h>
#include <iomanip>
#include <iostream>
#include <stdio.h>
#include <string.h>
#define REQ_LEN 64 #define REQ_LEN 64
@@ -98,7 +96,7 @@ int zts_central_init(const char* url_str, const char* token_str, char* resp_buf,
// Initialize all curl internal submodules // Initialize all curl internal submodules
curl_global_init(CURL_GLOBAL_ALL); curl_global_init(CURL_GLOBAL_ALL);
int url_len = strlen(url_str); int url_len = strnlen(url_str, ZTS_CENRTAL_MAX_URL_LEN);
if (url_len < 3 || url_len > ZTS_CENRTAL_MAX_URL_LEN) { if (url_len < 3 || url_len > ZTS_CENRTAL_MAX_URL_LEN) {
return ZTS_ERR_ARG; return ZTS_ERR_ARG;
} }
@@ -106,7 +104,7 @@ int zts_central_init(const char* url_str, const char* token_str, char* resp_buf,
memset(api_url, 0, ZTS_CENRTAL_MAX_URL_LEN); memset(api_url, 0, ZTS_CENRTAL_MAX_URL_LEN);
strncpy(api_url, url_str, url_len); strncpy(api_url, url_str, url_len);
} }
int token_len = strlen(token_str); int token_len = strnlen(token_str, ZTS_CENTRAL_TOKEN_LEN);
if (token_len != ZTS_CENTRAL_TOKEN_LEN) { if (token_len != ZTS_CENTRAL_TOKEN_LEN) {
return ZTS_ERR_ARG; return ZTS_ERR_ARG;
} }
@@ -147,9 +145,9 @@ int central_req(
return ZTS_ERR_SERVICE; return ZTS_ERR_SERVICE;
} }
zts_central_clear_resp_buf(); zts_central_clear_resp_buf();
int central_strlen = strlen(central_str); int central_strlen = strnlen(central_str, ZTS_CENRTAL_MAX_URL_LEN);
int api_route_strlen = strlen(api_route_str); int api_route_strlen = strnlen(api_route_str, ZTS_CENRTAL_MAX_URL_LEN);
int token_strlen = strlen(token_str); int token_strlen = strnlen(token_str, ZTS_CENTRAL_TOKEN_LEN);
int url_len = central_strlen + api_route_strlen; int url_len = central_strlen + api_route_strlen;
if (token_strlen > ZTS_CENTRAL_TOKEN_LEN) { if (token_strlen > ZTS_CENTRAL_TOKEN_LEN) {
return ZTS_ERR_ARG; return ZTS_ERR_ARG;

View File

@@ -17,21 +17,11 @@
* Node / Network control interface * Node / Network control interface
*/ */
#include "Constants.hpp"
#include "Events.hpp" #include "Events.hpp"
#include "Mutex.hpp"
#include "Node.hpp"
#include "NodeService.hpp" #include "NodeService.hpp"
#include "OSUtils.hpp"
#include "Signals.hpp"
#include "Thread.hpp"
#include "VirtualTap.hpp" #include "VirtualTap.hpp"
#include "ZeroTierSockets.h"
#include "lwip/stats.h"
#include <inttypes.h> #include <string.h>
#include <sys/types.h>
#include <thread>
using namespace ZeroTier; using namespace ZeroTier;
@@ -63,12 +53,11 @@ Events* zts_events;
extern Mutex events_m; extern Mutex events_m;
Mutex service_m; Mutex service_m;
/** Set up service and callback threads and tell them about one another.
* A separate thread is used for callbacks so that if the user fails to return
* control it won't affect the core service's operations.
*/
int init_subsystems() int init_subsystems()
{ {
/** Set up service and callback threads and tell them about one another.
* A separate thread is used for callbacks so that if the user fails to
* return control it won't affect the core service's operations. */
if (! zts_events) { if (! zts_events) {
zts_events = new Events(); zts_events = new Events();
} }
@@ -108,15 +97,22 @@ int zts_init_set_event_handler(PythonDirectorCallbackClass* callback)
#ifdef ZTS_ENABLE_PINVOKE #ifdef ZTS_ENABLE_PINVOKE
int zts_init_set_event_handler(CppCallback callback) int zts_init_set_event_handler(CppCallback callback)
#endif #endif
#ifdef ZTS_ENABLE_JAVA
int zts_init_set_event_handler(jobject obj_ref, jmethodID id)
#endif
#ifdef ZTS_C_API_ONLY #ifdef ZTS_C_API_ONLY
int zts_init_set_event_handler(void (*callback)(void*)) int zts_init_set_event_handler(void (*callback)(void*))
#endif #endif
{ {
ACQUIRE_SERVICE_OFFLINE(); ACQUIRE_SERVICE_OFFLINE();
#ifdef ZTS_ENABLE_JAVA
zts_events->setJavaCallback(obj_ref, id);
#else
if (! callback) { if (! callback) {
return ZTS_ERR_ARG; return ZTS_ERR_ARG;
} }
_userEventCallback = callback; _userEventCallback = callback;
#endif
zts_service->enableEvents(); zts_service->enableEvents();
return ZTS_ERR_OK; return ZTS_ERR_OK;
} }
@@ -127,10 +123,10 @@ int zts_init_blacklist_if(const char* prefix, unsigned int len)
return zts_service->addInterfacePrefixToBlacklist(prefix, len); return zts_service->addInterfacePrefixToBlacklist(prefix, len);
} }
int zts_init_set_world(const void* world_data, unsigned int len) int zts_init_set_roots(const void* roots_data, unsigned int len)
{ {
ACQUIRE_SERVICE_OFFLINE(); ACQUIRE_SERVICE_OFFLINE();
return zts_service->setWorld(world_data, len); return zts_service->setWorld(roots_data, len);
} }
int zts_init_set_port(unsigned short port) int zts_init_set_port(unsigned short port)
@@ -152,7 +148,7 @@ int zts_init_allow_net_cache(unsigned int allowed)
return zts_service->allowNetworkCaching(allowed); return zts_service->allowNetworkCaching(allowed);
} }
int zts_init_allow_world_cache(unsigned int allowed) int zts_init_allow_roots_cache(unsigned int allowed)
{ {
ACQUIRE_SERVICE_OFFLINE(); ACQUIRE_SERVICE_OFFLINE();
return zts_service->allowWorldCaching(allowed); return zts_service->allowWorldCaching(allowed);
@@ -216,7 +212,7 @@ int zts_addr_compute_6plane_str(uint64_t net_id, uint64_t node_id, char* dst, un
return ZTS_ERR_OK; return ZTS_ERR_OK;
} }
uint64_t zts_net_compute_adhoc_id(uint16_t start_port, uint16_t end_port) uint64_t zts_net_compute_adhoc_id(unsigned short start_port, unsigned short end_port)
{ {
char net_id_str[ZTS_INET6_ADDRSTRLEN] = { 0 }; char net_id_str[ZTS_INET6_ADDRSTRLEN] = { 0 };
OSUtils::ztsnprintf(net_id_str, ZTS_INET6_ADDRSTRLEN, "ff%04x%04x000000", start_port, end_port); OSUtils::ztsnprintf(net_id_str, ZTS_INET6_ADDRSTRLEN, "ff%04x%04x000000", start_port, end_port);
@@ -247,7 +243,7 @@ int zts_id_pair_is_valid(const char* key, unsigned int len)
return false; return false;
} }
Identity id; Identity id;
if ((strlen(key) > 32) && (key[10] == ':')) { if ((strnlen(key, len) > 32) && (key[10] == ':')) {
if (id.fromString(key)) { if (id.fromString(key)) {
return id.locallyValidate(); return id.locallyValidate();
} }
@@ -255,11 +251,14 @@ int zts_id_pair_is_valid(const char* key, unsigned int len)
return false; return false;
} }
int zts_node_get_id_pair(char* key, unsigned int* dst_len) int zts_node_get_id_pair(char* key, unsigned int* key_dst_len)
{ {
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); ACQUIRE_SERVICE(ZTS_ERR_SERVICE);
zts_service->getIdentity(key, dst_len); int err = ZTS_ERR_OK;
return *dst_len > 0 ? ZTS_ERR_OK : ZTS_ERR_GENERAL; if ((err = zts_service->getIdentity(key, key_dst_len)) != ZTS_ERR_OK) {
return err;
}
return *key_dst_len > 0 ? ZTS_ERR_OK : ZTS_ERR_GENERAL;
} }
#if defined(__WINDOWS__) #if defined(__WINDOWS__)
@@ -272,10 +271,10 @@ void* cbRun(void* arg)
pthread_setname_np(ZTS_EVENT_CALLBACK_THREAD_NAME); pthread_setname_np(ZTS_EVENT_CALLBACK_THREAD_NAME);
#endif #endif
zts_events->run(); zts_events->run();
#if ZTS_ENABLE_JAVA //#if ZTS_ENABLE_JAVA
_java_detach_from_thread(); // _java_detach_from_thread();
// pthread_exit(0); // pthread_exit(0);
#endif //#endif
return NULL; return NULL;
} }
@@ -497,8 +496,6 @@ void* _runNodeService(void* arg)
zts_util_delay(ZTS_CALLBACK_PROCESSING_INTERVAL * 2); zts_util_delay(ZTS_CALLBACK_PROCESSING_INTERVAL * 2);
if (zts_events) { if (zts_events) {
zts_events->disable(); zts_events->disable();
delete zts_events;
zts_events = (Events*)0;
} }
events_m.unlock(); events_m.unlock();
} }
@@ -514,7 +511,7 @@ int zts_node_start()
{ {
ACQUIRE_SERVICE_OFFLINE(); ACQUIRE_SERVICE_OFFLINE();
// Start TCP/IP stack // Start TCP/IP stack
_lwip_driver_init(); zts_lwip_driver_init();
// Start callback thread // Start callback thread
int res = ZTS_ERR_OK; int res = ZTS_ERR_OK;
if (zts_events->hasCallback()) { if (zts_events->hasCallback()) {
@@ -591,21 +588,23 @@ int zts_node_free()
#if defined(__WINDOWS__) #if defined(__WINDOWS__)
WSACleanup(); WSACleanup();
#endif #endif
_lwip_driver_shutdown(); zts_lwip_driver_shutdown();
delete zts_events;
zts_events = (Events*)0;
return ZTS_ERR_OK; return ZTS_ERR_OK;
} }
int zts_moon_orbit(uint64_t moon_world_id, uint64_t moon_seed) int zts_moon_orbit(uint64_t moon_roots_id, uint64_t moon_seed)
{ {
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); ACQUIRE_SERVICE(ZTS_ERR_SERVICE);
zts_service->orbit(NULL, moon_world_id, moon_seed); zts_service->orbit(NULL, moon_roots_id, moon_seed);
return ZTS_ERR_OK; return ZTS_ERR_OK;
} }
int zts_moon_deorbit(uint64_t moon_world_id) int zts_moon_deorbit(uint64_t moon_roots_id)
{ {
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); ACQUIRE_SERVICE(ZTS_ERR_SERVICE);
zts_service->deorbit(NULL, moon_world_id); zts_service->deorbit(NULL, moon_roots_id);
return ZTS_ERR_OK; return ZTS_ERR_OK;
} }
@@ -623,7 +622,7 @@ int zts_stats_get_all(zts_stats_counter_t* dst)
#define lws lwip_stats #define lws lwip_stats
/* Here we summarize lwIP's statistics for simplicity at the expense of specificity */ /* Summarize lwIP's statistics for simplicity at the expense of specificity */
// link // link
dst->link_tx = lws.link.xmit; dst->link_tx = lws.link.xmit;

View File

@@ -20,9 +20,6 @@
#ifndef ZTS_DEBUG_HPP #ifndef ZTS_DEBUG_HPP
#define ZTS_DEBUG_HPP #define ZTS_DEBUG_HPP
#if defined(__linux__) || defined(__APPLE__)
#include <unistd.h>
#endif
#include <string.h> #include <string.h>
#define ZT_COLOR true #define ZT_COLOR true

View File

@@ -19,11 +19,8 @@
#include "Events.hpp" #include "Events.hpp"
#include "Constants.hpp" #include "Mutex.hpp"
#include "Node.hpp"
#include "NodeService.hpp" #include "NodeService.hpp"
#include "OSUtils.hpp"
#include "ZeroTierSockets.h"
#include "concurrentqueue.h" #include "concurrentqueue.h"
#ifdef ZTS_ENABLE_JAVA #ifdef ZTS_ENABLE_JAVA
@@ -49,6 +46,13 @@ void PythonDirectorCallbackClass::on_zerotier_event(zts_event_msg_t* msg)
namespace ZeroTier { namespace ZeroTier {
#ifdef ZTS_ENABLE_JAVA
// References to JNI objects and VM kept for future callbacks
JavaVM* jvm;
jobject javaCbObjRef = NULL;
jmethodID javaCbMethodId = NULL;
#endif
extern NodeService* zts_service; extern NodeService* zts_service;
// Global state variable shared between Socket, Control, Event and // Global state variable shared between Socket, Control, Event and
@@ -175,7 +179,7 @@ void Events::sendToUser(zts_event_msg_t* msg)
PyGILState_Release(state); PyGILState_Release(state);
#endif #endif
#ifdef ZTS_ENABLE_JAVA #ifdef ZTS_ENABLE_JAVA
if (_userCallbackMethodRef) { if (javaCbMethodId) {
JNIEnv* env; JNIEnv* env;
#if defined(__ANDROID__) #if defined(__ANDROID__)
jint rs = jvm->AttachCurrentThread(&env, NULL); jint rs = jvm->AttachCurrentThread(&env, NULL);
@@ -185,15 +189,15 @@ void Events::sendToUser(zts_event_msg_t* msg)
uint64_t arg = 0; uint64_t arg = 0;
uint64_t id = 0; uint64_t id = 0;
if (ZTS_NODE_EVENT(msg->event_code)) { if (ZTS_NODE_EVENT(msg->event_code)) {
id = msg->node ? msg->node->address : 0; id = msg->node ? msg->node->node_id : 0;
} }
if (ZTS_NETWORK_EVENT(msg->event_code)) { if (ZTS_NETWORK_EVENT(msg->event_code)) {
id = msg->network ? msg->network->nwid : 0; id = msg->network ? msg->network->net_id : 0;
} }
if (ZTS_PEER_EVENT(msg->event_code)) { if (ZTS_PEER_EVENT(msg->event_code)) {
id = msg->peer ? msg->peer->address : 0; id = msg->peer ? msg->peer->peer_id : 0;
} }
env->CallVoidMethod(objRef, _userCallbackMethodRef, id, msg->event_code); env->CallVoidMethod(javaCbObjRef, javaCbMethodId, id, msg->event_code);
} }
#endif // ZTS_ENABLE_JAVA #endif // ZTS_ENABLE_JAVA
#ifdef ZTS_ENABLE_PINVOKE #ifdef ZTS_ENABLE_PINVOKE
@@ -214,12 +218,19 @@ void Events::sendToUser(zts_event_msg_t* msg)
} }
} }
#ifdef ZTS_ENABLE_JAVA
void Events::setJavaCallback(jobject objRef, jmethodID methodId)
{
javaCbObjRef = objRef;
javaCbMethodId = methodId;
}
#endif
bool Events::hasCallback() bool Events::hasCallback()
{ {
events_m.lock(); events_m.lock();
bool retval = false; bool retval = false;
#ifdef ZTS_ENABLE_JAVA #ifdef ZTS_ENABLE_JAVA
retval = (jvm && objRef && _userCallbackMethodRef); retval = (jvm && javaCbObjRef && javaCbMethodId);
#else #else
retval = _userEventCallback; retval = _userEventCallback;
#endif #endif
@@ -231,8 +242,8 @@ void Events::clrCallback()
{ {
events_m.lock(); events_m.lock();
#ifdef ZTS_ENABLE_JAVA #ifdef ZTS_ENABLE_JAVA
objRef = NULL; javaCbObjRef = NULL;
_userCallbackMethodRef = NULL; javaCbMethodId = NULL;
#else #else
_userEventCallback = NULL; _userEventCallback = NULL;
#endif #endif

View File

@@ -22,8 +22,6 @@
#include "ZeroTierSockets.h" #include "ZeroTierSockets.h"
#include <string>
#ifdef __WINDOWS__ #ifdef __WINDOWS__
#include <BaseTsd.h> #include <BaseTsd.h>
#endif #endif
@@ -130,6 +128,10 @@ class Events {
*/ */
void destroy(zts_event_msg_t* msg); void destroy(zts_event_msg_t* msg);
#ifdef ZTS_ENABLE_JAVA
void setJavaCallback(jobject objRef, jmethodID methodId);
#endif
/** /**
* Return whether a callback method has been set * Return whether a callback method has been set
*/ */

View File

@@ -20,19 +20,12 @@
#include "NodeService.hpp" #include "NodeService.hpp"
#include "../version.h" #include "../version.h"
#include "BlockingQueue.hpp" #include "Events.hpp"
#include "Constants.hpp"
#include "InetAddress.hpp" #include "InetAddress.hpp"
#include "MAC.hpp" #include "Mutex.hpp"
#include "Node.hpp" #include "Node.hpp"
#include "OSUtils.hpp"
#include "Phy.hpp"
#include "Utilities.hpp" #include "Utilities.hpp"
#include "Utils.hpp" #include "VirtualTap.hpp"
#include "ZeroTierSockets.h"
#include <arpa/inet.h>
#include <iostream>
#if defined(__WINDOWS__) #if defined(__WINDOWS__)
#include <ShlObj.h> #include <ShlObj.h>
@@ -629,7 +622,7 @@ void NodeService::generateEventMsgs()
{ {
// Force the ordering of callback messages, these messages are // Force the ordering of callback messages, these messages are
// only useful if the node and stack are both up and running // only useful if the node and stack are both up and running
if (! _node->online() || ! _lwip_is_up()) { if (! _node->online() || ! zts_lwip_is_up()) {
return; return;
} }
// Generate messages to be dequeued by the callback message thread // Generate messages to be dequeued by the callback message thread
@@ -653,10 +646,10 @@ void NodeService::generateEventMsgs()
sendEventToUser(ZTS_EVENT_NETWORK_REQ_CONFIG, (void*)prepare_network_details_msg(netState)); sendEventToUser(ZTS_EVENT_NETWORK_REQ_CONFIG, (void*)prepare_network_details_msg(netState));
break; break;
case ZT_NETWORK_STATUS_OK: case ZT_NETWORK_STATUS_OK:
if (tap->hasIpv4Addr() && _lwip_is_netif_up(tap->netif4)) { if (tap->hasIpv4Addr() && zts_lwip_is_netif_up(tap->netif4)) {
sendEventToUser(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)) { if (tap->hasIpv6Addr() && zts_lwip_is_netif_up(tap->netif6)) {
sendEventToUser(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 // In addition to the READY messages, send one OK message
@@ -971,28 +964,28 @@ int NodeService::networkHasRoute(uint64_t net_id, unsigned int family)
return false; return false;
} }
int NodeService::orbit(void* tptr, uint64_t moon_world_id, uint64_t moon_seed) int NodeService::orbit(void* tptr, uint64_t moon_roots_id, uint64_t moon_seed)
{ {
if (! moon_world_id || ! moon_seed) { if (! moon_roots_id || ! moon_seed) {
return ZTS_ERR_ARG; return ZTS_ERR_ARG;
} }
Mutex::Lock _lr(_run_m); Mutex::Lock _lr(_run_m);
if (! _run) { if (! _run) {
return ZTS_ERR_SERVICE; return ZTS_ERR_SERVICE;
} }
return _node->orbit(NULL, moon_world_id, moon_seed); return _node->orbit(NULL, moon_roots_id, moon_seed);
} }
int NodeService::deorbit(void* tptr, uint64_t moon_world_id) int NodeService::deorbit(void* tptr, uint64_t moon_roots_id)
{ {
if (! moon_world_id) { if (! moon_roots_id) {
return ZTS_ERR_ARG; return ZTS_ERR_ARG;
} }
Mutex::Lock _lr(_run_m); Mutex::Lock _lr(_run_m);
if (! _run) { if (! _run) {
return ZTS_ERR_SERVICE; return ZTS_ERR_SERVICE;
} }
return _node->deorbit(NULL, moon_world_id); return _node->deorbit(NULL, moon_roots_id);
} }
uint64_t NodeService::getNodeId() uint64_t NodeService::getNodeId()
@@ -1033,6 +1026,10 @@ int NodeService::getIdentity(char* keypair, unsigned int* len)
if (_node) { if (_node) {
_node->identity().toString(true, keypair); _node->identity().toString(true, keypair);
} }
else {
return ZTS_ERR_GENERAL;
}
*len = strnlen(keypair, ZT_IDENTITY_STRING_BUFFER_LENGTH);
return ZTS_ERR_OK; return ZTS_ERR_OK;
} }
@@ -1082,9 +1079,9 @@ void NodeService::nodeStatePutFunction(
break; break;
case ZT_STATE_OBJECT_PLANET: case ZT_STATE_OBJECT_PLANET:
sendEventToUser(ZTS_EVENT_STORE_PLANET, data, len); sendEventToUser(ZTS_EVENT_STORE_PLANET, data, len);
memcpy(_worldData, data, len); memcpy(_rootsData, data, len);
if (_homePath.length() > 0 && _allowWorldCaching) { if (_homePath.length() > 0 && _allowWorldCaching) {
OSUtils::ztsnprintf(p, sizeof(p), "%s" ZT_PATH_SEPARATOR_S "world", _homePath.c_str()); OSUtils::ztsnprintf(p, sizeof(p), "%s" ZT_PATH_SEPARATOR_S "roots", _homePath.c_str());
} }
else { else {
return; return;
@@ -1198,10 +1195,10 @@ int NodeService::nodeStateGetFunction(
break; break;
case ZT_STATE_OBJECT_PLANET: case ZT_STATE_OBJECT_PLANET:
if (_userDefinedWorld) { if (_userDefinedWorld) {
memcpy(data, _worldData, _worldDataLen); memcpy(data, _rootsData, _rootsDataLen);
return _worldDataLen; return _rootsDataLen;
} }
OSUtils::ztsnprintf(p, sizeof(p), "%s" ZT_PATH_SEPARATOR_S "world", _homePath.c_str()); OSUtils::ztsnprintf(p, sizeof(p), "%s" ZT_PATH_SEPARATOR_S "roots", _homePath.c_str());
break; break;
case ZT_STATE_OBJECT_NETWORK_CONFIG: case ZT_STATE_OBJECT_NETWORK_CONFIG:
OSUtils::ztsnprintf( OSUtils::ztsnprintf(
@@ -1545,9 +1542,9 @@ void NodeService::enableEvents()
_events->enable(); _events->enable();
} }
int NodeService::setWorld(const void* worldData, unsigned int len) int NodeService::setWorld(const void* rootsData, unsigned int len)
{ {
if (! worldData || len <= 0 || len > ZTS_STORE_DATA_LEN) { if (! rootsData || len <= 0 || len > ZTS_STORE_DATA_LEN) {
return ZTS_ERR_ARG; return ZTS_ERR_ARG;
} }
Mutex::Lock _lr(_run_m); Mutex::Lock _lr(_run_m);
@@ -1555,8 +1552,8 @@ int NodeService::setWorld(const void* worldData, unsigned int len)
return ZTS_ERR_SERVICE; return ZTS_ERR_SERVICE;
} }
Mutex::Lock _ls(_store_m); Mutex::Lock _ls(_store_m);
memcpy(_worldData, worldData, len); memcpy(_rootsData, rootsData, len);
_worldDataLen = len; _rootsDataLen = len;
_userDefinedWorld = true; _userDefinedWorld = true;
return ZTS_ERR_OK; return ZTS_ERR_OK;
} }
@@ -1610,7 +1607,7 @@ int NodeService::getNetworkName(uint64_t net_id, char* dst, unsigned int len) co
return ZTS_ERR_NO_RESULT; return ZTS_ERR_NO_RESULT;
} }
auto netState = n->second; auto netState = n->second;
memcpy(dst, netState.config.name, sizeof(netState.config.name)); strncpy(dst, netState.config.name, ZTS_MAX_NETWORK_SHORT_NAME_LENGTH);
return ZTS_ERR_OK; return ZTS_ERR_OK;
} }

View File

@@ -21,13 +21,10 @@
#define ZTS_NODE_SERVICE_HPP #define ZTS_NODE_SERVICE_HPP
#include "Binder.hpp" #include "Binder.hpp"
#include "Constants.hpp"
#include "Events.hpp"
#include "InetAddress.hpp"
#include "Mutex.hpp" #include "Mutex.hpp"
#include "Node.hpp" #include "Node.hpp"
#include "Phy.hpp"
#include "PortMapper.hpp" #include "PortMapper.hpp"
#include "VirtualTap.hpp"
#include "ZeroTierSockets.h" #include "ZeroTierSockets.h"
#include <string> #include <string>
@@ -50,6 +47,11 @@
namespace ZeroTier { namespace ZeroTier {
class InetAddress;
class VirtualTap;
class MAC;
class Events;
/** /**
* ZeroTier node service * ZeroTier node service
*/ */
@@ -205,8 +207,8 @@ class NodeService {
char _secretIdStr[ZT_IDENTITY_STRING_BUFFER_LENGTH] = { 0 }; char _secretIdStr[ZT_IDENTITY_STRING_BUFFER_LENGTH] = { 0 };
bool _userDefinedWorld; bool _userDefinedWorld;
char _worldData[ZTS_STORE_DATA_LEN] = { 0 }; char _rootsData[ZTS_STORE_DATA_LEN] = { 0 };
int _worldDataLen = 0; int _rootsDataLen = 0;
/** Whether the node has successfully come online */ /** Whether the node has successfully come online */
bool _nodeIsOnline; bool _nodeIsOnline;
@@ -373,7 +375,7 @@ class NodeService {
void enableEvents(); void enableEvents();
/** Set the world definition */ /** Set the roots definition */
int setWorld(const void* data, unsigned int len); int setWorld(const void* data, unsigned int len);
/** Add Interface prefix to blacklist (prevents ZeroTier from using that interface) */ /** Add Interface prefix to blacklist (prevents ZeroTier from using that interface) */
@@ -394,7 +396,7 @@ class NodeService {
/** Allow ZeroTier to write identities to storage */ /** Allow ZeroTier to write identities to storage */
int allowIdentityCaching(unsigned int allowed); int allowIdentityCaching(unsigned int allowed);
/** Allow ZeroTier to cache world definitions to storage */ /** Allow ZeroTier to cache root definitions to storage */
int allowWorldCaching(unsigned int allowed); int allowWorldCaching(unsigned int allowed);
/** Return whether broadcast is enabled on the given network */ /** Return whether broadcast is enabled on the given network */

View File

@@ -26,14 +26,8 @@
#ifdef ZTS_ENABLE_CUSTOM_SIGNAL_HANDLERS #ifdef ZTS_ENABLE_CUSTOM_SIGNAL_HANDLERS
/**
*
*/
void _signal_handler(int signal); void _signal_handler(int signal);
/**
*
*/
void _install_signal_handlers(); void _install_signal_handlers();
#endif // ZTS_ENABLE_CUSTOM_SIGNAL_HANDLERS #endif // ZTS_ENABLE_CUSTOM_SIGNAL_HANDLERS

View File

@@ -20,17 +20,11 @@
#include "lwip/sockets.h" #include "lwip/sockets.h"
#include "Events.hpp" #include "Events.hpp"
#include "Utilities.hpp"
#include "ZeroTierSockets.h" #include "ZeroTierSockets.h"
#include "lwip/def.h"
#include "lwip/dns.h" #include "lwip/dns.h"
#include "lwip/inet.h"
#include "lwip/ip_addr.h"
#include "lwip/netdb.h" #include "lwip/netdb.h"
// errno-like reporting variable
int zts_errno; int zts_errno;
extern int last_state_check;
namespace ZeroTier { namespace ZeroTier {
@@ -61,7 +55,7 @@ int zts_connect(int fd, const struct zts_sockaddr* addr, zts_socklen_t addrlen)
return lwip_connect(fd, (sockaddr*)addr, addrlen); return lwip_connect(fd, (sockaddr*)addr, addrlen);
} }
int zts_simple_connect(int fd, const char* ipstr, int port, int timeout_ms) int zts_simple_connect(int fd, const char* ipstr, unsigned short port, int timeout_ms)
{ {
if (! transport_ok()) { if (! transport_ok()) {
return ZTS_ERR_SERVICE; return ZTS_ERR_SERVICE;
@@ -114,20 +108,22 @@ int zts_bind(int fd, const struct zts_sockaddr* addr, zts_socklen_t addrlen)
return lwip_bind(fd, (sockaddr*)addr, addrlen); return lwip_bind(fd, (sockaddr*)addr, addrlen);
} }
int zts_simple_bind(int fd, const char* ipstr, int port) int zts_simple_bind(int fd, const char* ipstr, unsigned short port)
{ {
if (! transport_ok()) { if (! transport_ok()) {
return ZTS_ERR_SERVICE; return ZTS_ERR_SERVICE;
} }
zts_socklen_t addrlen = 0; zts_socklen_t addrlen = 0;
struct zts_sockaddr_storage ss; struct zts_sockaddr_storage ss;
struct zts_sockaddr* sa = NULL; struct zts_sockaddr* sa = NULL;
addrlen = sizeof(ss); addrlen = sizeof(ss);
zts_util_ipstr_to_saddr(ipstr, port, (struct zts_sockaddr*)&ss, &addrlen); int err = ZTS_ERR_OK;
if ((err = zts_util_ipstr_to_saddr(ipstr, port, (struct zts_sockaddr*)&ss, &addrlen)) != ZTS_ERR_OK) {
printf("ERRRRRRR=%d\n", err);
return err;
}
sa = (struct zts_sockaddr*)&ss; sa = (struct zts_sockaddr*)&ss;
return zts_bind(fd, sa, addrlen); return zts_bind(fd, sa, addrlen);
} }
@@ -147,7 +143,7 @@ int zts_accept(int fd, struct zts_sockaddr* addr, zts_socklen_t* addrlen)
return lwip_accept(fd, (sockaddr*)addr, (socklen_t*)addrlen); return lwip_accept(fd, (sockaddr*)addr, (socklen_t*)addrlen);
} }
int zts_simple_accept(int fd, char* remote_addr, int len, int* port) int zts_simple_accept(int fd, char* remote_addr, int len, unsigned short* port)
{ {
if (! transport_ok()) { if (! transport_ok()) {
return ZTS_ERR_SERVICE; return ZTS_ERR_SERVICE;
@@ -159,21 +155,50 @@ int zts_simple_accept(int fd, char* remote_addr, int len, int* port)
zts_socklen_t addrlen = sizeof(ss); zts_socklen_t addrlen = sizeof(ss);
int acc_fd = zts_accept(fd, (zts_sockaddr*)&ss, (zts_socklen_t*)&addrlen); int acc_fd = zts_accept(fd, (zts_sockaddr*)&ss, (zts_socklen_t*)&addrlen);
struct zts_sockaddr* sa = (struct zts_sockaddr*)&ss; int err = ZTS_ERR_OK;
if (sa->sa_family == ZTS_AF_INET) { if ((err = zts_util_ntop((struct zts_sockaddr*)&ss, addrlen, remote_addr, len, port)) < ZTS_ERR_OK) {
struct zts_sockaddr_in* in4 = (struct zts_sockaddr_in*)sa; return err;
zts_inet_ntop(ZTS_AF_INET, &(in4->sin_addr), remote_addr, 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), remote_addr, ZTS_INET6_ADDRSTRLEN);
*port = ntohs(in6->sin6_port);
} }
return acc_fd; return acc_fd;
} }
int zts_simple_tcp_client(const char* remote_ipstr, int remote_port) int zts_simple_getpeername(int fd, char* remote_addr_str, int len, unsigned short* port)
{
if (! transport_ok()) {
return ZTS_ERR_SERVICE;
}
if (len != ZTS_INET6_ADDRSTRLEN) {
return ZTS_ERR_ARG;
}
struct zts_sockaddr_storage ss;
struct zts_sockaddr* sa = (struct zts_sockaddr*)&ss;
int err = ZTS_ERR_OK;
zts_socklen_t addrlen = sizeof(ss);
if ((err = zts_getpeername(fd, sa, &addrlen)) < 0) {
return err;
}
return zts_util_ntop(sa, addrlen, remote_addr_str, len, port);
}
int zts_simple_getsockname(int fd, char* local_addr_str, int len, unsigned short* port)
{
if (! transport_ok()) {
return ZTS_ERR_SERVICE;
}
if (len != ZTS_INET6_ADDRSTRLEN) {
return ZTS_ERR_ARG;
}
struct zts_sockaddr_storage ss;
struct zts_sockaddr* sa = (struct zts_sockaddr*)&ss;
int err = ZTS_ERR_OK;
zts_socklen_t addrlen = sizeof(ss);
if ((err = zts_getsockname(fd, sa, &addrlen)) < 0) {
return err;
}
return zts_util_ntop(sa, addrlen, local_addr_str, len, port);
}
int zts_simple_tcp_client(const char* remote_ipstr, unsigned short remote_port)
{ {
int fd, family = zts_util_get_ip_family(remote_ipstr); int fd, family = zts_util_get_ip_family(remote_ipstr);
if ((fd = zts_socket(family, ZTS_SOCK_STREAM, 0)) < 0) { if ((fd = zts_socket(family, ZTS_SOCK_STREAM, 0)) < 0) {
@@ -187,7 +212,12 @@ int zts_simple_tcp_client(const char* remote_ipstr, int remote_port)
return fd; 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,
unsigned short local_port,
char* remote_ipstr,
int len,
unsigned short* remote_port)
{ {
int listen_fd, family = zts_util_get_ip_family(local_ipstr); int listen_fd, family = zts_util_get_ip_family(local_ipstr);
if ((listen_fd = zts_socket(family, ZTS_SOCK_STREAM, 0)) < 0) { if ((listen_fd = zts_socket(family, ZTS_SOCK_STREAM, 0)) < 0) {
@@ -208,7 +238,7 @@ int zts_simple_tcp_server(const char* local_ipstr, int local_port, char* remote_
return acc_fd; return acc_fd;
} }
int zts_simple_udp_server(const char* local_ipstr, int local_port) int zts_simple_udp_server(const char* local_ipstr, unsigned short local_port)
{ {
int fd, family = zts_util_get_ip_family(local_ipstr); int fd, family = zts_util_get_ip_family(local_ipstr);
if ((fd = zts_socket(family, ZTS_SOCK_DGRAM, 0)) < 0) { if ((fd = zts_socket(family, ZTS_SOCK_DGRAM, 0)) < 0) {
@@ -489,7 +519,7 @@ int zts_inet_pton(int family, const char* src, void* dst)
int zts_util_ipstr_to_saddr( int zts_util_ipstr_to_saddr(
const char* src_ipstr, const char* src_ipstr,
unsigned int port, unsigned short port,
struct zts_sockaddr* dest_addr, struct zts_sockaddr* dest_addr,
zts_socklen_t* addrlen) zts_socklen_t* addrlen)
{ {
@@ -524,18 +554,6 @@ int zts_util_ipstr_to_saddr(
return ZTS_ERR_ARG; return ZTS_ERR_ARG;
} }
//----------------------------------------------------------------------------//
// Convenience functions //
//----------------------------------------------------------------------------//
/**
* Helper functions that simplify API wrapper generation and usage in other
* non-C-like languages. Use simple integer types instead of bit flags,
* limit the number of operations each function performs, prevent the user
* from needing to manipulate the content of structures in a non-native
* language.
*/
int zts_simple_set_no_delay(int fd, int enabled) int zts_simple_set_no_delay(int fd, int enabled)
{ {
if (! transport_ok()) { if (! transport_ok()) {
@@ -605,6 +623,19 @@ int zts_simple_get_linger_value(int fd)
return linger.l_linger; return linger.l_linger;
} }
int zts_simple_get_pending_data_size(int fd)
{
if (! transport_ok()) {
return ZTS_ERR_SERVICE;
}
int bytes_available = 0;
int err = ZTS_ERR_OK;
if ((err = zts_ioctl(fd, ZTS_FIONREAD, &bytes_available)) < 0) {
return err;
}
return bytes_available;
}
int zts_simple_set_reuse_addr(int fd, int enabled) int zts_simple_set_reuse_addr(int fd, int enabled)
{ {
if (! transport_ok()) { if (! transport_ok()) {
@@ -812,6 +843,27 @@ int zts_simple_get_keepalive(int fd)
return optval != 0; return optval != 0;
} }
int zts_util_ntop(struct zts_sockaddr* addr, zts_socklen_t addrlen, char* dst_str, int len, unsigned short* port)
{
if (! addr || addrlen < sizeof(struct zts_sockaddr_in) || addrlen > sizeof(struct zts_sockaddr_storage) || ! dst_str
|| len != ZTS_INET6_ADDRSTRLEN) {
return ZTS_ERR_ARG;
}
if (addr->sa_family == ZTS_AF_INET) {
struct zts_sockaddr_in* in4 = (struct zts_sockaddr_in*)addr;
zts_inet_ntop(ZTS_AF_INET, &(in4->sin_addr), dst_str, len);
*port = ntohs(in4->sin_port);
return ZTS_ERR_OK;
}
if (addr->sa_family == ZTS_AF_INET6) {
struct zts_sockaddr_in6* in6 = (struct zts_sockaddr_in6*)addr;
zts_inet_ntop(ZTS_AF_INET6, &(in6->sin6_addr), dst_str, len);
*port = ntohs(in6->sin6_port);
return ZTS_ERR_OK;
}
return ZTS_ERR_ARG;
}
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -15,20 +15,9 @@
#include "ZeroTierSockets.h" #include "ZeroTierSockets.h"
#include <algorithm>
#include <netinet/in.h>
#include <node/C25519.hpp> #include <node/C25519.hpp>
#include <node/Constants.hpp>
#include <node/Identity.hpp>
#include <node/InetAddress.hpp>
#include <node/World.hpp> #include <node/World.hpp>
#include <osdep/OSUtils.hpp> #include <osdep/OSUtils.hpp>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <vector>
#ifdef __WINDOWS__ #ifdef __WINDOWS__
#include <windows.h> #include <windows.h>
@@ -75,18 +64,18 @@ void zts_util_delay(unsigned long milliseconds)
#endif #endif
} }
int zts_util_world_new( int zts_util_sign_root_set(
char* world_out, char* roots_out,
unsigned int* world_len, unsigned int* roots_len,
char* prev_key, char* prev_key,
unsigned int* prev_key_len, unsigned int* prev_key_len,
char* curr_key, char* curr_key,
unsigned int* curr_key_len, unsigned int* curr_key_len,
uint64_t id, uint64_t id,
uint64_t ts, uint64_t ts,
zts_world_t* world_spec) zts_root_set_t* roots_spec)
{ {
if (! world_spec || ! prev_key || ! curr_key || ! prev_key_len || ! curr_key_len) { if (! roots_spec || ! prev_key || ! curr_key || ! prev_key_len || ! curr_key_len) {
return ZTS_ERR_ARG; return ZTS_ERR_ARG;
} }
// Generate signing keys // Generate signing keys
@@ -110,23 +99,23 @@ int zts_util_world_new(
memcpy(currentKP.pub.data, current.data(), ZT_C25519_PUBLIC_KEY_LEN); 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); memcpy(currentKP.priv.data, current.data() + ZT_C25519_PUBLIC_KEY_LEN, ZT_C25519_PRIVATE_KEY_LEN);
// Set up world definition // Set up roots definition
std::vector<World::Root> roots; std::vector<World::Root> roots;
for (int i = 0; i < ZTS_MAX_NUM_ROOTS; i++) { for (int i = 0; i < ZTS_MAX_NUM_ROOTS; i++) {
if (! world_spec->public_id_str[i]) { if (! roots_spec->public_id_str[i]) {
break; break;
} }
if (strlen(world_spec->public_id_str[i])) { if (strnlen(roots_spec->public_id_str[i], ZT_IDENTITY_STRING_BUFFER_LENGTH)) {
// printf("id = %s\n", world_spec->public_id_str[i]); // printf("id = %s\n", roots_spec->public_id_str[i]);
roots.push_back(World::Root()); roots.push_back(World::Root());
roots.back().identity = Identity(world_spec->public_id_str[i]); roots.back().identity = Identity(roots_spec->public_id_str[i]);
for (int j = 0; j < ZTS_MAX_ENDPOINTS_PER_ROOT; j++) { for (int j = 0; j < ZTS_MAX_ENDPOINTS_PER_ROOT; j++) {
if (! world_spec->endpoint_ip_str[i][j]) { if (! roots_spec->endpoint_ip_str[i][j]) {
break; break;
} }
if (strlen(world_spec->endpoint_ip_str[i][j])) { if (strnlen(roots_spec->endpoint_ip_str[i][j], ZTS_MAX_ENDPOINT_STR_LEN)) {
roots.back().stableEndpoints.push_back(InetAddress(world_spec->endpoint_ip_str[i][j])); roots.back().stableEndpoints.push_back(InetAddress(roots_spec->endpoint_ip_str[i][j]));
// printf(" ep = %s\n", world_spec->endpoint_ip_str[i][j]); // printf(" ep = %s\n", roots_spec->endpoint_ip_str[i][j]);
} }
} }
} }
@@ -144,8 +133,8 @@ int zts_util_world_new(
return ZTS_ERR_GENERAL; return ZTS_ERR_GENERAL;
} }
// Write output // Write output
memcpy(world_out, (char*)outtmp.data(), outtmp.size()); memcpy(roots_out, (char*)outtmp.data(), outtmp.size());
*world_len = outtmp.size(); *roots_len = outtmp.size();
memcpy(prev_key, previous.data(), previous.length()); memcpy(prev_key, previous.data(), previous.length());
*prev_key_len = ZT_C25519_PRIVATE_KEY_LEN + ZT_C25519_PUBLIC_KEY_LEN; *prev_key_len = ZT_C25519_PRIVATE_KEY_LEN + ZT_C25519_PUBLIC_KEY_LEN;
memcpy(curr_key, current.data(), current.length()); memcpy(curr_key, current.data(), current.length());

View File

@@ -14,7 +14,7 @@
#ifndef ZTS_UTILITIES_HPP #ifndef ZTS_UTILITIES_HPP
#define ZTS_UTILITIES_HPP #define ZTS_UTILITIES_HPP
#include "ZeroTierSockets.h" struct zts_sockaddr_storage;
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

View File

@@ -17,7 +17,6 @@
* Virtual Ethernet tap device and combined network stack driver * Virtual Ethernet tap device and combined network stack driver
*/ */
#include "Constants.hpp"
#include "InetAddress.hpp" #include "InetAddress.hpp"
#include "MAC.hpp" #include "MAC.hpp"
#include "MulticastGroup.hpp" #include "MulticastGroup.hpp"
@@ -36,7 +35,6 @@
#include "Events.hpp" #include "Events.hpp"
#include "VirtualTap.hpp" #include "VirtualTap.hpp"
#include "ZeroTierSockets.h"
#if defined(__WINDOWS__) #if defined(__WINDOWS__)
#include "Synchapi.h" #include "Synchapi.h"
@@ -45,7 +43,7 @@
#endif #endif
#define ZTS_TAP_THREAD_POLLING_INTERVAL 50 #define ZTS_TAP_THREAD_POLLING_INTERVAL 50
#define LWIP_DRIVER_LOOP_INTERVAL 250 #define LWIP_DRIVER_LOOP_INTERVAL 100
namespace ZeroTier { namespace ZeroTier {
@@ -81,7 +79,6 @@ VirtualTap::VirtualTap(
, _mac(mac) , _mac(mac)
, _mtu(mtu) , _mtu(mtu)
, _net_id(net_id) , _net_id(net_id)
, _unixListenSocket((PhySocket*)0)
, _phy(this, false, true) , _phy(this, false, true)
{ {
OSUtils::ztsnprintf(vtap_full_name, VTAP_NAME_LEN, "libzt-vtap-%llx", _net_id); OSUtils::ztsnprintf(vtap_full_name, VTAP_NAME_LEN, "libzt-vtap-%llx", _net_id);
@@ -99,9 +96,9 @@ VirtualTap::~VirtualTap()
::write(_shutdownSignalPipe[1], "\0", 1); ::write(_shutdownSignalPipe[1], "\0", 1);
#endif #endif
_phy.whack(); _phy.whack();
_lwip_remove_netif(netif4); zts_lwip_remove_netif(netif4);
netif4 = NULL; netif4 = NULL;
_lwip_remove_netif(netif6); zts_lwip_remove_netif(netif6);
netif6 = NULL; netif6 = NULL;
Thread::join(_thread); Thread::join(_thread);
#ifndef __WINDOWS__ #ifndef __WINDOWS__
@@ -181,7 +178,7 @@ bool VirtualTap::addIp(const InetAddress& ip)
return false; return false;
} }
if (std::find(_ips.begin(), _ips.end(), ip) == _ips.end()) { if (std::find(_ips.begin(), _ips.end(), ip) == _ips.end()) {
_lwip_init_interface((void*)this, ip); zts_lwip_init_interface((void*)this, ip);
_ips.push_back(ip); _ips.push_back(ip);
std::sort(_ips.begin(), _ips.end()); std::sort(_ips.begin(), _ips.end());
} }
@@ -193,7 +190,7 @@ bool VirtualTap::removeIp(const InetAddress& ip)
Mutex::Lock _l(_ips_m); Mutex::Lock _l(_ips_m);
if (std::find(_ips.begin(), _ips.end(), ip) != _ips.end()) { if (std::find(_ips.begin(), _ips.end(), ip) != _ips.end()) {
std::vector<InetAddress>::iterator i(std::find(_ips.begin(), _ips.end(), ip)); std::vector<InetAddress>::iterator i(std::find(_ips.begin(), _ips.end(), ip));
_lwip_remove_address_from_netif((void*)this, ip); zts_lwip_remove_address_from_netif((void*)this, ip);
_ips.erase(i); _ips.erase(i);
} }
return true; return true;
@@ -208,7 +205,7 @@ std::vector<InetAddress> VirtualTap::ips() const
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) { if (len && _enabled) {
_lwip_eth_rx(this, from, to, etherType, data, len); zts_lwip_eth_rx(this, from, to, etherType, data, len);
} }
} }
@@ -271,46 +268,6 @@ void VirtualTap::threadMain() throw()
} }
} }
void VirtualTap::phyOnDatagram(
PhySocket* sock,
void** uptr,
const struct sockaddr* local_address,
const struct sockaddr* from,
void* data,
unsigned long len)
{
// Intentionally empty
}
void VirtualTap::phyOnTcpConnect(PhySocket* sock, void** uptr, bool success)
{
}
void VirtualTap::phyOnTcpAccept(
PhySocket* sockL,
PhySocket* sockN,
void** uptrL,
void** uptrN,
const struct sockaddr* from)
{
}
void VirtualTap::phyOnTcpClose(PhySocket* sock, void** uptr)
{
}
void VirtualTap::phyOnTcpData(PhySocket* sock, void** uptr, void* data, unsigned long len)
{
}
void VirtualTap::phyOnTcpWritable(PhySocket* sock, void** uptr)
{
}
void VirtualTap::phyOnUnixClose(PhySocket* sock, void** uptr)
{
}
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
// Netif driver code for lwIP network stack // // Netif driver code for lwIP network stack //
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
@@ -322,20 +279,20 @@ bool _has_started = false;
int netifCount = 0; int netifCount = 0;
// Lock to guard access to network stack state changes // Lock to guard access to network stack state changes
Mutex stackLock; Mutex lwip_state_m;
// Callback for when the TCPIP thread has been successfully started // Callback for when the TCPIP thread has been successfully started
static void _tcpip_init_done(void* arg) static void zts_tcpip_init_done(void* arg)
{ {
sys_sem_t* sem; sys_sem_t* sem;
sem = (sys_sem_t*)arg; sem = (sys_sem_t*)arg;
zts_events->setState(ZTS_STATE_STACK_RUNNING); zts_events->setState(ZTS_STATE_STACK_RUNNING);
_has_started = true; _has_started = true;
zts_events->enqueue(ZTS_EVENT_STACK_UP, NULL); // zts_events->enqueue(ZTS_EVENT_STACK_UP, NULL);
sys_sem_signal(sem); sys_sem_signal(sem);
} }
static void _main_lwip_driver_loop(void* arg) static void zts_main_lwip_driver_loop(void* arg)
{ {
#if defined(__linux__) #if defined(__linux__)
pthread_setname_np(pthread_self(), ZTS_LWIP_THREAD_NAME); pthread_setname_np(pthread_self(), ZTS_LWIP_THREAD_NAME);
@@ -348,7 +305,7 @@ static void _main_lwip_driver_loop(void* arg)
if (sys_sem_new(&sem, 0) != ERR_OK) { if (sys_sem_new(&sem, 0) != ERR_OK) {
// DEBUG_ERROR("failed to create semaphore"); // DEBUG_ERROR("failed to create semaphore");
} }
tcpip_init(_tcpip_init_done, &sem); tcpip_init(zts_tcpip_init_done, &sem);
sys_sem_wait(&sem); sys_sem_wait(&sem);
// Main loop // Main loop
while (zts_events->getState(ZTS_STATE_STACK_RUNNING)) { while (zts_events->getState(ZTS_STATE_STACK_RUNNING)) {
@@ -358,33 +315,38 @@ static void _main_lwip_driver_loop(void* arg)
zts_events->enqueue(ZTS_EVENT_STACK_DOWN, NULL); zts_events->enqueue(ZTS_EVENT_STACK_DOWN, NULL);
} }
bool _lwip_is_up() bool zts_lwip_is_up()
{ {
Mutex::Lock _l(stackLock); Mutex::Lock _l(lwip_state_m);
return zts_events->getState(ZTS_STATE_STACK_RUNNING); return zts_events->getState(ZTS_STATE_STACK_RUNNING);
} }
void _lwip_driver_init() void zts_lwip_driver_init()
{ {
if (_lwip_is_up()) { if (zts_lwip_is_up()) {
return; return;
} }
if (_has_exited) { if (_has_exited) {
return; return;
} }
Mutex::Lock _l(stackLock); Mutex::Lock _l(lwip_state_m);
#if defined(__WINDOWS__) #if defined(__WINDOWS__)
sys_init(); // Required for win32 init of critical sections sys_init(); // Required for win32 init of critical sections
#endif #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,
zts_main_lwip_driver_loop,
NULL,
DEFAULT_THREAD_STACKSIZE,
DEFAULT_THREAD_PRIO);
} }
void _lwip_driver_shutdown() void zts_lwip_driver_shutdown()
{ {
if (_has_exited) { if (_has_exited) {
return; return;
} }
Mutex::Lock _l(stackLock); Mutex::Lock _l(lwip_state_m);
// Set flag to stop sending frames into the core // Set flag to stop sending frames into the core
zts_events->clrState(ZTS_STATE_STACK_RUNNING); zts_events->clrState(ZTS_STATE_STACK_RUNNING);
// Wait until the main lwIP thread has exited // Wait until the main lwIP thread has exited
@@ -395,7 +357,7 @@ void _lwip_driver_shutdown()
} }
} }
void _lwip_remove_netif(void* netif) void zts_lwip_remove_netif(void* netif)
{ {
if (! netif) { if (! netif) {
return; return;
@@ -408,7 +370,7 @@ void _lwip_remove_netif(void* netif)
UNLOCK_TCPIP_CORE(); UNLOCK_TCPIP_CORE();
} }
err_t _lwip_eth_tx(struct netif* n, struct pbuf* p) signed char zts_lwip_eth_tx(struct netif* n, struct pbuf* p)
{ {
if (! n) { if (! n) {
return ERR_IF; return ERR_IF;
@@ -441,7 +403,7 @@ err_t _lwip_eth_tx(struct netif* n, struct pbuf* p)
return ERR_OK; return ERR_OK;
} }
void _lwip_eth_rx( void zts_lwip_eth_rx(
VirtualTap* tap, VirtualTap* tap,
const MAC& from, const MAC& from,
const MAC& to, const MAC& to,
@@ -508,7 +470,7 @@ void _lwip_eth_rx(
} }
} }
bool _lwip_is_netif_up(void* n) bool zts_lwip_is_netif_up(void* n)
{ {
if (! n) { if (! n) {
return false; return false;
@@ -519,7 +481,7 @@ bool _lwip_is_netif_up(void* n)
return result; return result;
} }
static err_t _netif_init4(struct netif* n) static err_t zts_netif_init4(struct netif* n)
{ {
if (! n || ! n->state) { if (! n || ! n->state) {
return ERR_IF; return ERR_IF;
@@ -529,7 +491,7 @@ static err_t _netif_init4(struct netif* n)
n->hwaddr_len = 6; n->hwaddr_len = 6;
n->name[0] = '4'; n->name[0] = '4';
n->name[1] = 'a' + netifCount; n->name[1] = 'a' + netifCount;
n->linkoutput = _lwip_eth_tx; n->linkoutput = zts_lwip_eth_tx;
n->output = etharp_output; n->output = etharp_output;
n->mtu = std::min(LWIP_MTU, (int)tap->_mtu); 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 n->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP | NETIF_FLAG_MLD6
@@ -539,7 +501,7 @@ static err_t _netif_init4(struct netif* n)
return ERR_OK; return ERR_OK;
} }
static err_t _netif_init6(struct netif* n) static err_t zts_netif_init6(struct netif* n)
{ {
if (! n || ! n->state) { if (! n || ! n->state) {
return ERR_IF; return ERR_IF;
@@ -551,7 +513,7 @@ static err_t _netif_init6(struct netif* n)
n->hwaddr_len = 6; n->hwaddr_len = 6;
n->name[0] = '6'; n->name[0] = '6';
n->name[1] = 'a' + netifCount; n->name[1] = 'a' + netifCount;
n->linkoutput = _lwip_eth_tx; n->linkoutput = zts_lwip_eth_tx;
n->output_ip6 = ethip6_output; n->output_ip6 = ethip6_output;
n->mtu = std::min(LWIP_MTU, (int)tap->_mtu); 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 n->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP | NETIF_FLAG_MLD6
@@ -559,7 +521,7 @@ static err_t _netif_init6(struct netif* n)
return ERR_OK; return ERR_OK;
} }
void _lwip_init_interface(void* tapref, const InetAddress& ip) void zts_lwip_init_interface(void* tapref, const InetAddress& ip)
{ {
char macbuf[ZTS_MAC_ADDRSTRLEN] = { 0 }; char macbuf[ZTS_MAC_ADDRSTRLEN] = { 0 };
@@ -582,7 +544,7 @@ void _lwip_init_interface(void* tapref, const InetAddress& ip)
ip4.addr = *((u32_t*)ip.rawIpData()); ip4.addr = *((u32_t*)ip.rawIpData());
netmask.addr = *((u32_t*)ip.netmask().rawIpData()); netmask.addr = *((u32_t*)ip.netmask().rawIpData());
LOCK_TCPIP_CORE(); LOCK_TCPIP_CORE();
netif_add(n, &ip4, &netmask, &gw, (void*)vtap, _netif_init4, tcpip_input); netif_add(n, &ip4, &netmask, &gw, (void*)vtap, zts_netif_init4, tcpip_input);
vtap->netif4 = (void*)n; vtap->netif4 = (void*)n;
UNLOCK_TCPIP_CORE(); UNLOCK_TCPIP_CORE();
snprintf( snprintf(
@@ -610,7 +572,7 @@ void _lwip_init_interface(void* tapref, const InetAddress& ip)
LOCK_TCPIP_CORE(); LOCK_TCPIP_CORE();
if (isNewNetif) { if (isNewNetif) {
vtap->netif6 = (void*)n; vtap->netif6 = (void*)n;
netif_add(n, NULL, NULL, NULL, (void*)vtap, _netif_init6, ethernet_input); netif_add(n, NULL, NULL, NULL, (void*)vtap, zts_netif_init6, ethernet_input);
n->ip6_autoconfig_enabled = 1; n->ip6_autoconfig_enabled = 1;
vtap->_mac.copyTo(n->hwaddr, n->hwaddr_len); vtap->_mac.copyTo(n->hwaddr, n->hwaddr_len);
netif_create_ip6_linklocal_address(n, 1); netif_create_ip6_linklocal_address(n, 1);
@@ -634,7 +596,7 @@ void _lwip_init_interface(void* tapref, const InetAddress& ip)
} }
} }
void _lwip_remove_address_from_netif(void* tapref, const InetAddress& ip) void zts_lwip_remove_address_from_netif(void* tapref, const InetAddress& ip)
{ {
if (! tapref) { if (! tapref) {
return; return;
@@ -656,7 +618,7 @@ void _lwip_remove_address_from_netif(void* tapref, const InetAddress& ip)
if (! n) { if (! n) {
return; return;
} }
_lwip_remove_netif(n); zts_lwip_remove_netif(n);
} }
} // namespace ZeroTier } // namespace ZeroTier

View File

@@ -20,8 +20,6 @@
#ifndef ZTS_VIRTUAL_TAP_HPP #ifndef ZTS_VIRTUAL_TAP_HPP
#define ZTS_VIRTUAL_TAP_HPP #define ZTS_VIRTUAL_TAP_HPP
#include "lwip/err.h"
#define ZTS_LWIP_THREAD_NAME "ZTNetworkStackThread" #define ZTS_LWIP_THREAD_NAME "ZTNetworkStackThread"
#define VTAP_NAME_LEN 64 #define VTAP_NAME_LEN 64
@@ -32,9 +30,11 @@
namespace ZeroTier { namespace ZeroTier {
/* Forward declarations */
class Mutex; class Mutex;
class MAC; class MAC;
class MulticastGroup; class MulticastGroup;
class Events;
struct InetAddress; struct InetAddress;
/** /**
@@ -162,7 +162,6 @@ class VirtualTap {
MAC _mac; MAC _mac;
unsigned int _mtu; unsigned int _mtu;
uint64_t _net_id; uint64_t _net_id;
PhySocket* _unixListenSocket;
Phy<VirtualTap*> _phy; Phy<VirtualTap*> _phy;
Thread _thread; Thread _thread;
@@ -172,23 +171,18 @@ class VirtualTap {
std::vector<MulticastGroup> _multicastGroups; std::vector<MulticastGroup> _multicastGroups;
Mutex _multicastGroups_m; Mutex _multicastGroups_m;
//----------------------------------------------------------------------------// void phyOnTcpConnect(PhySocket* sock, void** uptr, bool success)
// Not used in this implementation // {
//----------------------------------------------------------------------------// }
void phyOnTcpAccept(PhySocket* sockL, PhySocket* sockN, void** uptrL, void** uptrN, const struct sockaddr* from)
void phyOnDatagram( {
PhySocket* sock, }
void** uptr, void phyOnTcpClose(PhySocket* sock, void** uptr)
const struct sockaddr* local_address, {
const struct sockaddr* from, }
void* data, void phyOnUnixClose(PhySocket* sock, void** uptr)
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 phyOnTcpClose(PhySocket* sock, void** uptr);
void phyOnTcpData(PhySocket* sock, void** uptr, void* data, unsigned long len);
void phyOnTcpWritable(PhySocket* sock, void** uptr);
void phyOnUnixClose(PhySocket* sock, void** uptr);
}; };
/** /**
@@ -196,7 +190,7 @@ class VirtualTap {
* *
* @usage This is a convenience function to encapsulate a macro * @usage This is a convenience function to encapsulate a macro
*/ */
bool _lwip_is_netif_up(void* netif); bool zts_lwip_is_netif_up(void* netif);
/** /**
* @brief Increase the delay multiplier for the main driver loop * @brief Increase the delay multiplier for the main driver loop
@@ -204,19 +198,19 @@ bool _lwip_is_netif_up(void* netif);
* @usage This should be called when we know the stack won't be used by any * @usage This should be called when we know the stack won't be used by any
* virtual taps * virtual taps
*/ */
void _lwip_hibernate_driver(); void zts_lwip_hibernate_driver();
/** /**
* @brief Decrease the delay multiplier for the main driver loop * @brief Decrease the delay multiplier for the main driver loop
* *
* @usage This should be called when at least one virtual tap is active * @usage This should be called when at least one virtual tap is active
*/ */
void _lwip_wake_driver(); void zts_lwip_wake_driver();
/** /**
* Returns whether the lwIP network stack is up and ready to process traffic * Returns whether the lwIP network stack is up and ready to process traffic
*/ */
bool _lwip_is_up(); bool zts_lwip_is_up();
/** /**
* @brief Initialize network stack semaphores, threads, and timers. * @brief Initialize network stack semaphores, threads, and timers.
@@ -224,7 +218,7 @@ bool _lwip_is_up();
* @usage This is called during the initial setup of each VirtualTap but is * @usage This is called during the initial setup of each VirtualTap but is
* only allowed to execute once * only allowed to execute once
*/ */
void _lwip_driver_init(); void zts_lwip_driver_init();
/** /**
* @brief Shutdown the stack as completely as possible (not officially * @brief Shutdown the stack as completely as possible (not officially
@@ -235,41 +229,17 @@ void _lwip_driver_init();
* interfaces will be brought down and all resources will be deallocated. A * interfaces will be brought down and all resources will be deallocated. A
* full application restart will be required to bring the stack back online. * full application restart will be required to bring the stack back online.
*/ */
void _lwip_driver_shutdown(); void zts_lwip_driver_shutdown();
/** /**
* @brief Requests that a netif be brought down and removed. * @brief Requests that a netif be brought down and removed.
*/ */
void _lwip_remove_netif(void* netif); void zts_lwip_remove_netif(void* netif);
/** /**
* @brief Starts DHCP timers * @brief Starts DHCP timers
*/ */
void _lwip_start_dhcp(void* netif); void zts_lwip_start_dhcp(void* netif);
/**
* @brief Called when the status of a netif changes:
* - Interface is up/down (ZTS_EVENT_NETIF_UP, ZTS_EVENT_NETIF_DOWN)
* - Address changes while up (ZTS_EVENT_NETIF_NEW_ADDRESS)
*/
#if LWIP_NETIF_STATUS_CALLBACK
static void _netif_status_callback(struct netif* netif);
#endif
/**
* @brief Called when a netif is removed (ZTS_EVENT_NETIF_INTERFACE_REMOVED)
*/
#if LWIP_NETIF_REMOVE_CALLBACK
static void _netif_remove_callback(struct netif* netif);
#endif
/**
* @brief Called when a link is brought up or down (ZTS_EVENT_NETIF_LINK_UP,
* ZTS_EVENT_NETIF_LINK_DOWN)
*/
#if LWIP_NETIF_LINK_CALLBACK
static void _netif_link_callback(struct netif* netif);
#endif
/** /**
* @brief Set up an interface in the network stack for the VirtualTap. * @brief Set up an interface in the network stack for the VirtualTap.
@@ -278,7 +248,7 @@ static void _netif_link_callback(struct netif* netif);
* sending and receiving data * sending and receiving data
* @param ip Virtual IP address for this ZeroTier VirtualTap interface * @param ip Virtual IP address for this ZeroTier VirtualTap interface
*/ */
void _lwip_init_interface(void* tapref, const InetAddress& ip); void zts_lwip_init_interface(void* tapref, const InetAddress& ip);
/** /**
* @brief Remove an assigned address from an lwIP netif * @brief Remove an assigned address from an lwIP netif
@@ -286,7 +256,7 @@ void _lwip_init_interface(void* tapref, const InetAddress& ip);
* @param tapref Reference to VirtualTap * @param tapref Reference to VirtualTap
* @param ip Virtual IP address to remove from this interface * @param ip Virtual IP address to remove from this interface
*/ */
void _lwip_remove_address_from_netif(void* tapref, const InetAddress& ip); void zts_lwip_remove_address_from_netif(void* tapref, const InetAddress& ip);
/** /**
* @brief Called from the stack, outbound Ethernet frames from the network * @brief Called from the stack, outbound Ethernet frames from the network
@@ -299,7 +269,7 @@ void _lwip_remove_address_from_netif(void* tapref, const InetAddress& ip);
* @param p A pointer to the beginning of a chain pf struct pbufs * @param p A pointer to the beginning of a chain pf struct pbufs
* @return * @return
*/ */
err_t _lwip_eth_tx(struct netif* netif, struct pbuf* p); signed char zts_lwip_eth_tx(struct netif* netif, struct pbuf* p);
/** /**
* @brief Receives incoming Ethernet frames from the ZeroTier virtual wire * @brief Receives incoming Ethernet frames from the ZeroTier virtual wire
@@ -314,7 +284,7 @@ err_t _lwip_eth_tx(struct netif* netif, struct pbuf* p);
* @param data Pointer to Ethernet frame * @param data Pointer to Ethernet frame
* @param len Length of Ethernet frame * @param len Length of Ethernet frame
*/ */
void _lwip_eth_rx( void zts_lwip_eth_rx(
VirtualTap* tap, VirtualTap* tap,
const MAC& from, const MAC& from,
const MAC& to, const MAC& to,