Format according to new ZeroTier standard

This commit is contained in:
Joseph Henry
2021-04-26 22:07:55 -07:00
parent 07b2a33447
commit a247552df1
23 changed files with 4991 additions and 4991 deletions

View File

@@ -35,62 +35,62 @@ be taken to avoid exposing vulnerable services or sharing unwanted files or othe
*/ */
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
if (argc != 3) { if (argc != 3) {
printf("\nUsage:\n"); printf("\nUsage:\n");
printf("adhoc <adhocStartPort> <adhocEndPort>\n"); printf("adhoc <adhocStartPort> <adhocEndPort>\n");
exit(0); exit(0);
} }
int err = ZTS_ERR_OK; int err = ZTS_ERR_OK;
uint16_t adhocStartPort = atoi(argv[1]); // Start of port range your application will use 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 uint16_t adhocEndPort = atoi(argv[2]); // End of port range your application will use
long long int net_id = zts_net_compute_adhoc_id(adhocStartPort, adhocEndPort); // At least 64 bits long long int net_id = zts_net_compute_adhoc_id(adhocStartPort, adhocEndPort); // At least 64 bits
// Start node and get identity // Start node and get identity
printf("Starting node...\n"); printf("Starting node...\n");
zts_node_start(); zts_node_start();
printf("Waiting for node to come online\n"); printf("Waiting for node to come online\n");
while (! zts_node_is_online()) { while (! zts_node_is_online()) {
zts_util_delay(50); zts_util_delay(50);
} }
uint64_t node_id = zts_node_get_id(); uint64_t node_id = zts_node_get_id();
printf("My public identity (node ID) is %llx\n", node_id); printf("My public identity (node ID) is %llx\n", node_id);
char keypair[ZTS_ID_STR_BUF_LEN] = { 0 }; char keypair[ZTS_ID_STR_BUF_LEN] = { 0 };
uint16_t len = ZTS_ID_STR_BUF_LEN; uint16_t len = ZTS_ID_STR_BUF_LEN;
if (zts_node_get_id_pair(keypair, &len) != ZTS_ERR_OK) { if (zts_node_get_id_pair(keypair, &len) != ZTS_ERR_OK) {
printf("Error getting identity keypair. Exiting.\n"); printf("Error getting identity keypair. Exiting.\n");
} }
printf("Identity [public/secret pair] = %s\n", keypair); printf("Identity [public/secret pair] = %s\n", keypair);
// Join the adhoc network // Join the adhoc network
printf("Joining network %llx\n", net_id); printf("Joining network %llx\n", net_id);
if (zts_net_join(net_id) != ZTS_ERR_OK) { if (zts_net_join(net_id) != ZTS_ERR_OK) {
printf("Unable to join network. Exiting.\n"); printf("Unable to join network. Exiting.\n");
exit(1); exit(1);
} }
printf("Waiting for join to complete\n"); printf("Waiting for join to complete\n");
while (! zts_net_transport_is_ready(net_id)) { while (! zts_net_transport_is_ready(net_id)) {
zts_util_delay(50); zts_util_delay(50);
} }
// Get address // Get address
char ipstr[ZTS_IP_MAX_STR_LEN] = { 0 }; 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); printf("Unable to compute address (error = %d). Exiting.\n", err);
exit(1); exit(1);
} }
printf("Join %llx from another machine and ping6 me at %s\n", net_id, ipstr); printf("Join %llx from another machine and ping6 me at %s\n", net_id, ipstr);
// Do network stuff! // Do network stuff!
// zts_socket, zts_connect, etc // zts_socket, zts_connect, etc
while (1) { while (1) {
zts_util_delay(500); // Idle indefinitely zts_util_delay(500); // Idle indefinitely
} }
printf("Stopping node\n"); printf("Stopping node\n");
return zts_node_stop(); return zts_node_stop();
} }

View File

@@ -12,97 +12,97 @@
void on_zts_event(void* msgPtr) void on_zts_event(void* msgPtr)
{ {
zts_event_msg_t* msg = (zts_event_msg_t*)msgPtr; zts_event_msg_t* msg = (zts_event_msg_t*)msgPtr;
// Node events // Node events
if (msg->event_code == ZTS_EVENT_NODE_ONLINE) { if (msg->event_code == ZTS_EVENT_NODE_ONLINE) {
printf("ZTS_EVENT_NODE_ONLINE --- This node's ID is %llx\n", msg->node->node_id); printf("ZTS_EVENT_NODE_ONLINE --- This node's ID is %llx\n", msg->node->node_id);
} }
if (msg->event_code == ZTS_EVENT_NODE_OFFLINE) { if (msg->event_code == ZTS_EVENT_NODE_OFFLINE) {
printf("ZTS_EVENT_NODE_OFFLINE --- Check your physical Internet connection, router, " printf("ZTS_EVENT_NODE_OFFLINE --- Check your physical Internet connection, router, "
"firewall, etc. What ports are you blocking?\n"); "firewall, etc. What ports are you blocking?\n");
} }
// Virtual network events // Virtual network events
if (msg->event_code == ZTS_EVENT_NETWORK_NOT_FOUND) { 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) { if (msg->event_code == ZTS_EVENT_NETWORK_ACCESS_DENIED) {
printf( printf(
"ZTS_EVENT_NETWORK_ACCESS_DENIED --- Access to virtual network %llx has been denied. " "ZTS_EVENT_NETWORK_ACCESS_DENIED --- Access to virtual network %llx has been denied. "
"Did you authorize the node yet?\n", "Did you authorize the node yet?\n",
msg->network->net_id); msg->network->net_id);
} }
if (msg->event_code == ZTS_EVENT_NETWORK_READY_IP6) { if (msg->event_code == ZTS_EVENT_NETWORK_READY_IP6) {
printf( printf(
"ZTS_EVENT_NETWORK_READY_IP6 --- Network config received. IPv6 traffic can now be sent " "ZTS_EVENT_NETWORK_READY_IP6 --- Network config received. IPv6 traffic can now be sent "
"over network %llx\n", "over network %llx\n",
msg->network->net_id); msg->network->net_id);
} }
// Address events // Address events
if (msg->event_code == ZTS_EVENT_ADDR_ADDED_IP6) { if (msg->event_code == ZTS_EVENT_ADDR_ADDED_IP6) {
char ipstr[ZTS_INET6_ADDRSTRLEN] = { 0 }; char ipstr[ZTS_INET6_ADDRSTRLEN] = { 0 };
struct zts_sockaddr_in6* in6 = (struct zts_sockaddr_in6*)&(msg->addr->addr); 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); 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 // To see more exhaustive examples look at test/selftest.c
} }
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
if (argc != 2) { if (argc != 2) {
printf("\nUsage:\n"); printf("\nUsage:\n");
printf("pingable-node <net_id>\n"); printf("pingable-node <net_id>\n");
exit(0); exit(0);
} }
long long int net_id = strtoull(argv[1], NULL, 16); // At least 64 bits long long int net_id = strtoull(argv[1], NULL, 16); // At least 64 bits
zts_init_set_event_handler(&on_zts_event); zts_init_set_event_handler(&on_zts_event);
printf("Starting node...\n"); printf("Starting node...\n");
zts_node_start(); zts_node_start();
printf("Waiting for node to come online\n"); printf("Waiting for node to come online\n");
while (! zts_node_is_online()) { while (! zts_node_is_online()) {
zts_util_delay(50); 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", zts_node_get_id());
char keypair[ZTS_ID_STR_BUF_LEN] = { 0 }; char keypair[ZTS_ID_STR_BUF_LEN] = { 0 };
uint16_t len = ZTS_ID_STR_BUF_LEN; uint16_t len = ZTS_ID_STR_BUF_LEN;
if (zts_node_get_id_pair(keypair, &len) != ZTS_ERR_OK) { if (zts_node_get_id_pair(keypair, &len) != ZTS_ERR_OK) {
printf("Error getting identity keypair. Exiting.\n"); printf("Error getting identity keypair. Exiting.\n");
} }
printf("Identity [public/secret pair] = %s\n", keypair); printf("Identity [public/secret pair] = %s\n", keypair);
printf("Joining network %llx\n", net_id); printf("Joining network %llx\n", net_id);
if (zts_net_join(net_id) != ZTS_ERR_OK) { if (zts_net_join(net_id) != ZTS_ERR_OK) {
printf("Unable to join network. Exiting.\n"); printf("Unable to join network. Exiting.\n");
exit(1); exit(1);
} }
printf("Waiting for join to complete\n"); printf("Waiting for join to complete\n");
while (! zts_net_transport_is_ready(net_id)) { while (! zts_net_transport_is_ready(net_id)) {
zts_util_delay(50); zts_util_delay(50);
} }
printf("Waiting for address assignment from network\n"); printf("Waiting for address assignment from network\n");
int err = 0; int err = 0;
while (! (err = zts_addr_is_assigned(net_id, ZTS_AF_INET))) { while (! (err = zts_addr_is_assigned(net_id, ZTS_AF_INET))) {
zts_util_delay(500); zts_util_delay(500);
} }
char ipstr[ZTS_IP_MAX_STR_LEN] = { 0 }; char ipstr[ZTS_IP_MAX_STR_LEN] = { 0 };
zts_addr_get_str(net_id, ZTS_AF_INET, ipstr, ZTS_IP_MAX_STR_LEN); zts_addr_get_str(net_id, ZTS_AF_INET, ipstr, ZTS_IP_MAX_STR_LEN);
printf("Join %llx from another machine and ping me at %s\n", net_id, ipstr); printf("Join %llx from another machine and ping me at %s\n", net_id, ipstr);
// Do network stuff! // Do network stuff!
// zts_socket, zts_connect, etc // zts_socket, zts_connect, etc
while (1) { while (1) {
zts_util_delay(500); // Idle indefinitely zts_util_delay(500); // Idle indefinitely
} }
printf("Stopping node\n"); printf("Stopping node\n");
return zts_node_stop(); return zts_node_stop();
} }

View File

@@ -12,94 +12,94 @@
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
if (argc != 5) { if (argc != 5) {
printf("\nlibzt example client\n"); printf("\nlibzt example client\n");
printf("client <id_storage_path> <net_id> <remote_addr> <remote_port>\n"); printf("client <id_storage_path> <net_id> <remote_addr> <remote_port>\n");
exit(0); exit(0);
} }
char* storage_path = argv[1]; char* storage_path = argv[1];
long long int net_id = strtoull(argv[2], NULL, 16); // At least 64 bits long long int net_id = strtoull(argv[2], NULL, 16); // At least 64 bits
char* remote_addr = argv[3]; char* remote_addr = argv[3];
int remote_port = atoi(argv[4]); int remote_port = atoi(argv[4]);
int err = ZTS_ERR_OK; int err = ZTS_ERR_OK;
// Initialize node // Initialize node
if ((err = zts_init_from_storage(storage_path)) != ZTS_ERR_OK) { if ((err = zts_init_from_storage(storage_path)) != ZTS_ERR_OK) {
printf("Unable to start service, error = %d. Exiting.\n", err); printf("Unable to start service, error = %d. Exiting.\n", err);
exit(1); exit(1);
} }
// Start node // Start node
if ((err = zts_node_start()) != ZTS_ERR_OK) { if ((err = zts_node_start()) != ZTS_ERR_OK) {
printf("Unable to start service, error = %d. Exiting.\n", err); printf("Unable to start service, error = %d. Exiting.\n", err);
exit(1); exit(1);
} }
printf("Waiting for node to come online\n"); printf("Waiting for node to come online\n");
while (! zts_node_is_online()) { while (! zts_node_is_online()) {
zts_util_delay(50); zts_util_delay(50);
} }
printf("Public identity (node ID) is %llx\n", (long long int)zts_node_get_id()); printf("Public identity (node ID) is %llx\n", (long long int)zts_node_get_id());
// Join network // Join network
printf("Joining network %llx\n", net_id); printf("Joining network %llx\n", net_id);
if (zts_net_join(net_id) != ZTS_ERR_OK) { if (zts_net_join(net_id) != ZTS_ERR_OK) {
printf("Unable to join network. Exiting.\n"); printf("Unable to join network. Exiting.\n");
exit(1); exit(1);
} }
printf("Don't forget to authorize this device in my.zerotier.com or the web API!\n"); printf("Don't forget to authorize this device in my.zerotier.com or the web API!\n");
printf("Waiting for join to complete\n"); printf("Waiting for join to complete\n");
while (! zts_net_transport_is_ready(net_id)) { while (! zts_net_transport_is_ready(net_id)) {
zts_util_delay(50); zts_util_delay(50);
} }
// Get assigned address (of the family type we care about) // Get assigned address (of the family type we care about)
int family = zts_util_get_ip_family(remote_addr); int family = zts_util_get_ip_family(remote_addr);
printf("Waiting for address assignment from network\n"); printf("Waiting for address assignment from network\n");
while (! (err = zts_addr_is_assigned(net_id, family))) { while (! (err = zts_addr_is_assigned(net_id, family))) {
zts_util_delay(50); zts_util_delay(50);
} }
char ipstr[ZTS_IP_MAX_STR_LEN] = { 0 }; char ipstr[ZTS_IP_MAX_STR_LEN] = { 0 };
zts_addr_get_str(net_id, family, ipstr, ZTS_IP_MAX_STR_LEN); zts_addr_get_str(net_id, family, ipstr, ZTS_IP_MAX_STR_LEN);
printf("IP address on network %llx is %s\n", net_id, ipstr); printf("IP address on network %llx is %s\n", net_id, ipstr);
// BEGIN Socket Stuff // BEGIN Socket Stuff
char* msgStr = (char*)"Welcome to the machine"; char* msgStr = (char*)"Welcome to the machine";
int bytes = 0, fd; int bytes = 0, fd;
char recvBuf[128] = { 0 }; char recvBuf[128] = { 0 };
memset(recvBuf, 0, sizeof(recvBuf)); memset(recvBuf, 0, sizeof(recvBuf));
// Connect to remote host // Connect to remote host
// Can also use traditional: zts_socket(), zts_connect(), etc // Can also use traditional: zts_socket(), zts_connect(), etc
printf("Attempting to connect...\n"); printf("Attempting to connect...\n");
while ((fd = zts_simple_tcp_client(remote_addr, remote_port)) < 0) { while ((fd = zts_simple_tcp_client(remote_addr, remote_port)) < 0) {
printf("Re-attempting to connect...\n"); printf("Re-attempting to connect...\n");
} }
// Data I/O // Data I/O
printf("Sending message string to server...\n"); printf("Sending message string to server...\n");
if ((bytes = zts_write(fd, msgStr, strlen(msgStr))) < 0) { if ((bytes = zts_write(fd, msgStr, strlen(msgStr))) < 0) {
printf("Error (fd=%d, ret=%d, zts_errno=%d). Exiting.\n", fd, bytes, zts_errno); printf("Error (fd=%d, ret=%d, zts_errno=%d). Exiting.\n", fd, bytes, zts_errno);
exit(1); exit(1);
} }
printf("Sent %d bytes: %s\n", bytes, msgStr); printf("Sent %d bytes: %s\n", bytes, msgStr);
printf("Reading message string from server...\n"); printf("Reading message string from server...\n");
if ((bytes = zts_read(fd, recvBuf, sizeof(recvBuf))) < 0) { if ((bytes = zts_read(fd, recvBuf, sizeof(recvBuf))) < 0) {
printf("Error (fd=%d, ret=%d, zts_errno=%d). Exiting.\n", fd, bytes, zts_errno); printf("Error (fd=%d, ret=%d, zts_errno=%d). Exiting.\n", fd, bytes, zts_errno);
exit(1); exit(1);
} }
printf("Read %d bytes: %s\n", bytes, recvBuf); printf("Read %d bytes: %s\n", bytes, recvBuf);
// Close // Close
zts_close(fd); zts_close(fd);
return zts_node_stop(); return zts_node_stop();
} }

View File

@@ -12,108 +12,108 @@
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->address);
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);
printf("\t- path_count : %d\n", d->path_count); printf("\t- path_count : %d\n", d->path_count);
printf("\t- paths:\n"); printf("\t- paths:\n");
// Print all known paths for each peer // Print all known paths for each peer
for (unsigned int j = 0; j < d->path_count; j++) { for (unsigned int j = 0; j < d->path_count; j++) {
char ipstr[ZTS_INET6_ADDRSTRLEN] = { 0 }; char ipstr[ZTS_INET6_ADDRSTRLEN] = { 0 };
int port = 0; int port = 0;
struct zts_sockaddr* sa = (struct zts_sockaddr*)&(d->paths[j].address); struct zts_sockaddr* sa = (struct zts_sockaddr*)&(d->paths[j].address);
if (sa->sa_family == ZTS_AF_INET) { if (sa->sa_family == ZTS_AF_INET) {
struct zts_sockaddr_in* in4 = (struct zts_sockaddr_in*)sa; struct zts_sockaddr_in* in4 = (struct zts_sockaddr_in*)sa;
zts_inet_ntop(ZTS_AF_INET, &(in4->sin_addr), ipstr, ZTS_INET_ADDRSTRLEN); zts_inet_ntop(ZTS_AF_INET, &(in4->sin_addr), ipstr, ZTS_INET_ADDRSTRLEN);
port = ntohs(in4->sin_port); port = ntohs(in4->sin_port);
} }
if (sa->sa_family == ZTS_AF_INET6) { if (sa->sa_family == ZTS_AF_INET6) {
struct zts_sockaddr_in6* in6 = (struct zts_sockaddr_in6*)sa; struct zts_sockaddr_in6* in6 = (struct zts_sockaddr_in6*)sa;
zts_inet_ntop(ZTS_AF_INET6, &(in6->sin6_addr), ipstr, ZTS_INET6_ADDRSTRLEN); zts_inet_ntop(ZTS_AF_INET6, &(in6->sin6_addr), ipstr, ZTS_INET6_ADDRSTRLEN);
} }
printf("\t - %15s : %6d\n", ipstr, port); printf("\t - %15s : %6d\n", ipstr, port);
} }
printf("\n\n"); printf("\n\n");
} }
void on_zts_event(void* msgPtr) void on_zts_event(void* msgPtr)
{ {
zts_event_msg_t* msg = (zts_event_msg_t*)msgPtr; zts_event_msg_t* msg = (zts_event_msg_t*)msgPtr;
printf("event_code = %d\n", msg->event_code); printf("event_code = %d\n", msg->event_code);
if (msg->peer) { if (msg->peer) {
if (msg->peer->role != ZTS_PEER_ROLE_PLANET) { if (msg->peer->role != ZTS_PEER_ROLE_PLANET) {
return; // Don't print controllers and ordinary nodes. return; // Don't print controllers and ordinary nodes.
} }
} }
if (msg->event_code == ZTS_EVENT_PEER_DIRECT) { if (msg->event_code == ZTS_EVENT_PEER_DIRECT) {
print_peer_details("ZTS_EVENT_PEER_DIRECT", msg->peer); print_peer_details("ZTS_EVENT_PEER_DIRECT", msg->peer);
} }
if (msg->event_code == ZTS_EVENT_PEER_RELAY) { if (msg->event_code == ZTS_EVENT_PEER_RELAY) {
print_peer_details("ZTS_EVENT_PEER_RELAY", msg->peer); print_peer_details("ZTS_EVENT_PEER_RELAY", msg->peer);
} }
} }
int main() int main()
{ {
// World generation // World generation
// Buffers that will be filled after generating the world // Buffers that will be filled after generating the world
char world_data_out[4096] = { 0 }; // (binary) Your new world definition char world_data_out[4096] = { 0 }; // (binary) Your new world definition
unsigned int world_len = 0; unsigned int world_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 a world
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 world 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_world_t world = { 0 };
world.public_id_str[0] = world.public_id_str[0] =
"992fcf1db7:0:" "992fcf1db7:0:"
"206ed59350b31916f749a1f85dffb3a8787dcbf83b8c6e9448d4e3ea0e3369301be716c3609344a9d1533850fb4460c5" "206ed59350b31916f749a1f85dffb3a8787dcbf83b8c6e9448d4e3ea0e3369301be716c3609344a9d1533850fb4460c5"
"0af43322bcfc8e13d3301a1f1003ceb6"; "0af43322bcfc8e13d3301a1f1003ceb6";
world.endpoint_ip_str[0][0] = "195.181.173.159/9993"; world.endpoint_ip_str[0][0] = "195.181.173.159/9993";
world.endpoint_ip_str[0][1] = "2a02:6ea0:c024::/9993"; world.endpoint_ip_str[0][1] = "2a02:6ea0:c024::/9993";
// Generate world // Generate world
zts_util_world_new(&world_data_out, &world_len, &prev_key, &prev_key_len, &curr_key, &curr_key_len, id, ts, &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= "); printf("world_data_out= ");
for (int i = 0; i < world_len; i++) { for (int i = 0; i < world_len; i++) {
if (i > 0) { if (i > 0) {
printf(","); printf(",");
} }
printf("0x%.2x", (unsigned char)world_data_out[i]); printf("0x%.2x", (unsigned char)world_data_out[i]);
} }
printf("\n"); printf("\n");
printf("world_len = %d\n", world_len); printf("world_len = %d\n", world_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 world definition
zts_init_set_world(&world_data_out, world_len); zts_init_set_world(&world_data_out, world_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(".");
// Start node // Start node
zts_node_start(); zts_node_start();
while (1) { while (1) {
zts_util_delay(500); zts_util_delay(500);
} }
return zts_node_stop(); return zts_node_stop();
} }

View File

@@ -12,85 +12,85 @@
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
if (argc != 5) { if (argc != 5) {
printf("\nlibzt example client\n"); printf("\nlibzt example client\n");
printf("client <id_storage_path> <net_id> <remote_addr> <remote_port>\n"); printf("client <id_storage_path> <net_id> <remote_addr> <remote_port>\n");
exit(0); exit(0);
} }
char* storage_path = argv[1]; char* storage_path = argv[1];
long long int net_id = strtoull(argv[2], NULL, 16); // At least 64 bits long long int net_id = strtoull(argv[2], NULL, 16); // At least 64 bits
char* remote_addr = argv[3]; char* remote_addr = argv[3];
int remote_port = atoi(argv[4]); int remote_port = atoi(argv[4]);
int err = ZTS_ERR_OK; int err = ZTS_ERR_OK;
// Initialize node // Initialize node
if ((err = zts_init_from_storage(storage_path)) != ZTS_ERR_OK) { if ((err = zts_init_from_storage(storage_path)) != ZTS_ERR_OK) {
printf("Unable to start service, error = %d. Exiting.\n", err); printf("Unable to start service, error = %d. Exiting.\n", err);
exit(1); exit(1);
} }
// Start node // Start node
if ((err = zts_node_start()) != ZTS_ERR_OK) { if ((err = zts_node_start()) != ZTS_ERR_OK) {
printf("Unable to start service, error = %d. Exiting.\n", err); printf("Unable to start service, error = %d. Exiting.\n", err);
exit(1); exit(1);
} }
printf("Waiting for node to come online\n"); printf("Waiting for node to come online\n");
while (! zts_node_is_online()) { while (! zts_node_is_online()) {
zts_util_delay(50); zts_util_delay(50);
} }
printf("Public identity (node ID) is %llx\n", (long long int)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); printf("Joining network %llx\n", net_id);
if (zts_net_join(net_id) != ZTS_ERR_OK) { if (zts_net_join(net_id) != ZTS_ERR_OK) {
printf("Unable to join network. Exiting.\n"); printf("Unable to join network. Exiting.\n");
exit(1); exit(1);
} }
printf("Don't forget to authorize this device in my.zerotier.com or the web API!\n"); printf("Don't forget to authorize this device in my.zerotier.com or the web API!\n");
printf("Waiting for join to complete\n"); printf("Waiting for join to complete\n");
while (! zts_net_transport_is_ready(net_id)) { while (! zts_net_transport_is_ready(net_id)) {
zts_util_delay(50); zts_util_delay(50);
} }
// Sockets // Sockets
char* msgStr = (char*)"Welcome to the machine"; char* msgStr = (char*)"Welcome to the machine";
int bytes = 0, fd; int bytes = 0, fd;
char recvBuf[128] = { 0 }; char recvBuf[128] = { 0 };
memset(recvBuf, 0, sizeof(recvBuf)); memset(recvBuf, 0, sizeof(recvBuf));
// Create socket // Create socket
if ((fd = zts_socket(ZTS_AF_INET, ZTS_SOCK_STREAM, 0)) < 0) { if ((fd = zts_socket(ZTS_AF_INET, ZTS_SOCK_STREAM, 0)) < 0) {
printf("Error (fd=%d, zts_errno=%d). Exiting.\n", fd, zts_errno); printf("Error (fd=%d, zts_errno=%d). Exiting.\n", fd, zts_errno);
exit(1); exit(1);
} }
// Connect // Connect
// Can also use: // Can also use:
// zts_connect(int fd, const struct zts_sockaddr* addr, zts_socklen_t addrlen); // zts_connect(int fd, const struct zts_sockaddr* addr, zts_socklen_t addrlen);
while (zts_simple_connect(fd, remote_addr, remote_port, 0) != ZTS_ERR_OK) { while (zts_simple_connect(fd, remote_addr, remote_port, 0) != ZTS_ERR_OK) {
printf("Attempting to connect...\n"); printf("Attempting to connect...\n");
} }
// Data I/O // Data I/O
// Wait random intervals to send a message to the server // Wait random intervals to send a message to the server
// The non-blocking aspect of this example is server-side // The non-blocking aspect of this example is server-side
while (1) { while (1) {
if ((bytes = zts_send(fd, msgStr, strlen(msgStr), 0)) < 0) { if ((bytes = zts_send(fd, msgStr, strlen(msgStr), 0)) < 0) {
printf("Error (fd=%d, ret=%d, zts_errno=%d). Exiting.\n", fd, bytes, zts_errno); printf("Error (fd=%d, ret=%d, zts_errno=%d). Exiting.\n", fd, bytes, zts_errno);
exit(1); exit(1);
} }
printf("zts_send()=%d\n", bytes); printf("zts_send()=%d\n", bytes);
zts_util_delay((rand() % 100) * 50); zts_util_delay((rand() % 100) * 50);
} }
zts_close(fd); zts_close(fd);
return zts_node_stop(); return zts_node_stop();
} }

View File

@@ -12,158 +12,158 @@
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
if (argc != 5) { if (argc != 5) {
printf("\nlibzt example server\n"); printf("\nlibzt example server\n");
printf("server <id_storage_path> <net_id> <local_addr> <local_port>\n"); printf("server <id_storage_path> <net_id> <local_addr> <local_port>\n");
exit(0); exit(0);
} }
char* storage_path = argv[1]; char* storage_path = argv[1];
long long int net_id = strtoull(argv[2], NULL, 16); // At least 64 bits long long int net_id = strtoull(argv[2], NULL, 16); // At least 64 bits
char* local_addr = argv[3]; char* local_addr = argv[3];
int local_port = atoi(argv[4]); int local_port = atoi(argv[4]);
int fd, accfd; int fd, accfd;
int err = ZTS_ERR_OK; int err = ZTS_ERR_OK;
// Initialize node // Initialize node
if ((err = zts_init_from_storage(storage_path)) != ZTS_ERR_OK) { if ((err = zts_init_from_storage(storage_path)) != ZTS_ERR_OK) {
printf("Unable to start service, error = %d. Exiting.\n", err); printf("Unable to start service, error = %d. Exiting.\n", err);
exit(1); exit(1);
} }
// Start node // Start node
if ((err = zts_node_start()) != ZTS_ERR_OK) { if ((err = zts_node_start()) != ZTS_ERR_OK) {
printf("Unable to start service, error = %d. Exiting.\n", err); printf("Unable to start service, error = %d. Exiting.\n", err);
exit(1); exit(1);
} }
printf("Waiting for node to come online\n"); printf("Waiting for node to come online\n");
while (! zts_node_is_online()) { while (! zts_node_is_online()) {
zts_util_delay(50); zts_util_delay(50);
} }
printf("Public identity (node ID) is %llx\n", zts_node_get_id()); printf("Public identity (node ID) is %llx\n", zts_node_get_id());
printf("Joining network %llx\n", net_id); printf("Joining network %llx\n", net_id);
if (zts_net_join(net_id) != ZTS_ERR_OK) { if (zts_net_join(net_id) != ZTS_ERR_OK) {
printf("Unable to join network. Exiting.\n"); printf("Unable to join network. Exiting.\n");
exit(1); exit(1);
} }
printf("Don't forget to authorize this device in my.zerotier.com or the web API!\n"); printf("Don't forget to authorize this device in my.zerotier.com or the web API!\n");
printf("Waiting for join to complete\n"); printf("Waiting for join to complete\n");
while (! zts_net_transport_is_ready(net_id)) { while (! zts_net_transport_is_ready(net_id)) {
zts_util_delay(50); zts_util_delay(50);
} }
printf("Waiting for address assignment from network\n"); printf("Waiting for address assignment from network\n");
while (! (err = zts_addr_is_assigned(net_id, ZTS_AF_INET))) { while (! (err = zts_addr_is_assigned(net_id, ZTS_AF_INET))) {
zts_util_delay(500); zts_util_delay(500);
} }
char ipstr[ZTS_IP_MAX_STR_LEN] = { 0 }; char ipstr[ZTS_IP_MAX_STR_LEN] = { 0 };
zts_addr_get_str(net_id, ZTS_AF_INET, ipstr, ZTS_IP_MAX_STR_LEN); zts_addr_get_str(net_id, ZTS_AF_INET, ipstr, ZTS_IP_MAX_STR_LEN);
printf("Assigned IP address: %s\n", ipstr); printf("Assigned IP address: %s\n", ipstr);
// Sockets // Sockets
printf("Creating socket...\n"); printf("Creating socket...\n");
if ((fd = zts_socket(ZTS_AF_INET, ZTS_SOCK_STREAM, 0)) < 0) { if ((fd = zts_socket(ZTS_AF_INET, ZTS_SOCK_STREAM, 0)) < 0) {
printf("Error (fd=%d, ret=%d, zts_errno=%d). Exiting.\n", fd, err, zts_errno); printf("Error (fd=%d, ret=%d, zts_errno=%d). Exiting.\n", fd, err, zts_errno);
exit(1); exit(1);
} }
printf("Binding...\n"); printf("Binding...\n");
// Can also use: // Can also use:
// zts_bind(int fd, const struct zts_sockaddr* addr, zts_socklen_t addrlen) // zts_bind(int fd, const struct zts_sockaddr* addr, zts_socklen_t addrlen)
if ((err = zts_simple_bind(fd, local_addr, local_port) < 0)) { if ((err = zts_simple_bind(fd, local_addr, local_port) < 0)) {
printf("Error (fd=%d, ret=%d, zts_errno=%d). Exiting.\n", fd, err, zts_errno); printf("Error (fd=%d, ret=%d, zts_errno=%d). Exiting.\n", fd, err, zts_errno);
exit(1); exit(1);
} }
printf("Listening...\n"); printf("Listening...\n");
int backlog = 100; int backlog = 100;
if ((err = zts_listen(fd, backlog)) < 0) { if ((err = zts_listen(fd, backlog)) < 0) {
printf("Error (fd=%d, ret=%d, zts_errno=%d). Exiting.\n", fd, err, zts_errno); printf("Error (fd=%d, ret=%d, zts_errno=%d). Exiting.\n", fd, err, zts_errno);
exit(1); exit(1);
} }
int bytes = 0; int bytes = 0;
char recvBuf[128] = { 0 }; char recvBuf[128] = { 0 };
while (1) { while (1) {
// Accept // Accept
// Can also use // Can also use
// zts_accept(int fd, struct zts_sockaddr* addr, zts_socklen_t* addrlen) // zts_accept(int fd, struct zts_sockaddr* addr, zts_socklen_t* addrlen)
char ipstr[ZTS_INET6_ADDRSTRLEN] = { 0 }; char ipstr[ZTS_INET6_ADDRSTRLEN] = { 0 };
int port = 0; int port = 0;
printf("Accepting on listening socket...\n"); printf("Accepting on listening socket...\n");
if ((accfd = zts_simple_accept(fd, ipstr, ZTS_INET6_ADDRSTRLEN, &port)) < 0) { if ((accfd = zts_simple_accept(fd, ipstr, ZTS_INET6_ADDRSTRLEN, &port)) < 0) {
printf("Error (fd=%d, ret=%d, zts_errno=%d). Exiting.\n", fd, err, zts_errno); printf("Error (fd=%d, ret=%d, zts_errno=%d). Exiting.\n", fd, err, zts_errno);
} }
printf("Accepted connection from %s:%d\n", ipstr, port); printf("Accepted connection from %s:%d\n", ipstr, port);
} }
// Data I/O // Data I/O
// Technique 1: ZTS_O_NONBLOCK // Technique 1: ZTS_O_NONBLOCK
if (0) { if (0) {
zts_fcntl(fd, ZTS_F_SETFL, ZTS_O_NONBLOCK); zts_fcntl(fd, ZTS_F_SETFL, ZTS_O_NONBLOCK);
zts_fcntl(accfd, ZTS_F_SETFL, ZTS_O_NONBLOCK); zts_fcntl(accfd, ZTS_F_SETFL, ZTS_O_NONBLOCK);
while (1) { while (1) {
bytes = zts_recv(accfd, recvBuf, sizeof(recvBuf), 0); bytes = zts_recv(accfd, recvBuf, sizeof(recvBuf), 0);
printf("zts_recv(%d, ...)=%d\n", accfd, bytes); printf("zts_recv(%d, ...)=%d\n", accfd, bytes);
zts_util_delay(100); zts_util_delay(100);
} }
} }
// Technique 2: zts_select // Technique 2: zts_select
if (0) { if (0) {
struct zts_timeval tv; struct zts_timeval tv;
tv.tv_sec = 0; tv.tv_sec = 0;
tv.tv_usec = 50000; tv.tv_usec = 50000;
int result = 0; int result = 0;
zts_fd_set active_fd_set, read_fd_set; zts_fd_set active_fd_set, read_fd_set;
ZTS_FD_ZERO(&active_fd_set); ZTS_FD_ZERO(&active_fd_set);
ZTS_FD_SET(accfd, &active_fd_set); ZTS_FD_SET(accfd, &active_fd_set);
while (1) { while (1) {
read_fd_set = active_fd_set; read_fd_set = active_fd_set;
if ((result = zts_select(ZTS_FD_SETSIZE, &read_fd_set, NULL, NULL, &tv) < 0)) { if ((result = zts_select(ZTS_FD_SETSIZE, &read_fd_set, NULL, NULL, &tv) < 0)) {
// perror ("select"); // perror ("select");
exit(1); exit(1);
} }
for (int i = 0; i < ZTS_FD_SETSIZE; i++) { for (int i = 0; i < ZTS_FD_SETSIZE; i++) {
if (ZTS_FD_ISSET(i, &read_fd_set)) { if (ZTS_FD_ISSET(i, &read_fd_set)) {
bytes = zts_recv(accfd, recvBuf, sizeof(recvBuf), 0); bytes = zts_recv(accfd, recvBuf, sizeof(recvBuf), 0);
printf("zts_recv(%d, ...)=%d\n", i, bytes); printf("zts_recv(%d, ...)=%d\n", i, bytes);
} }
// ZTS_FD_CLR(i, &active_fd_set); // ZTS_FD_CLR(i, &active_fd_set);
} }
} }
} }
// Technique 3: zts_poll // Technique 3: zts_poll
if (1) { if (1) {
int numfds = 0; int numfds = 0;
struct zts_pollfd poll_set[16]; struct zts_pollfd poll_set[16];
memset(poll_set, '\0', sizeof(poll_set)); memset(poll_set, '\0', sizeof(poll_set));
poll_set[0].fd = accfd; poll_set[0].fd = accfd;
poll_set[0].events = ZTS_POLLIN; poll_set[0].events = ZTS_POLLIN;
numfds++; numfds++;
int result = 0; int result = 0;
int timeout_ms = 50; int timeout_ms = 50;
while (1) { while (1) {
result = zts_poll(poll_set, numfds, timeout_ms); result = zts_poll(poll_set, numfds, timeout_ms);
printf("zts_poll()=%d\n", result); printf("zts_poll()=%d\n", result);
for (int i = 0; i < numfds; i++) { for (int i = 0; i < numfds; i++) {
if (poll_set[i].revents & ZTS_POLLIN) { if (poll_set[i].revents & ZTS_POLLIN) {
bytes = zts_recv(poll_set[i].fd, recvBuf, sizeof(recvBuf), 0); bytes = zts_recv(poll_set[i].fd, recvBuf, sizeof(recvBuf), 0);
printf("zts_recv(%d, ...)=%d\n", i, bytes); printf("zts_recv(%d, ...)=%d\n", i, bytes);
} }
} }
} }
} }
err = zts_close(fd); err = zts_close(fd);
return zts_node_stop(); return zts_node_stop();
} }

View File

@@ -18,92 +18,92 @@ char cache_data[ZTS_STORE_DATA_LEN];
void on_zts_event(void* msgPtr) void on_zts_event(void* msgPtr)
{ {
zts_event_msg_t* msg = (zts_event_msg_t*)msgPtr; zts_event_msg_t* msg = (zts_event_msg_t*)msgPtr;
int len = msg->len; // Length of message (or structure) int len = msg->len; // Length of message (or structure)
if (msg->event_code == ZTS_EVENT_NODE_ONLINE) { if (msg->event_code == ZTS_EVENT_NODE_ONLINE) {
printf("ZTS_EVENT_NODE_ONLINE\n"); printf("ZTS_EVENT_NODE_ONLINE\n");
} }
// Copy data to a buffer that you have allocated or write it to storage. // Copy data to a buffer that you have allocated or write it to storage.
// The data pointed to by msg->cache will be invalid after this function // The data pointed to by msg->cache will be invalid after this function
// returns. // returns.
memset(cache_data, 0, ZTS_STORE_DATA_LEN); memset(cache_data, 0, ZTS_STORE_DATA_LEN);
if (msg->event_code == ZTS_EVENT_STORE_IDENTITY_PUBLIC) { if (msg->event_code == ZTS_EVENT_STORE_IDENTITY_PUBLIC) {
printf("ZTS_EVENT_STORE_IDENTITY_PUBLIC (len=%d)\n", msg->len); printf("ZTS_EVENT_STORE_IDENTITY_PUBLIC (len=%d)\n", msg->len);
printf("identity.public = [ %.*s ]\n", len, msg->cache); printf("identity.public = [ %.*s ]\n", len, msg->cache);
memcpy(cache_data, msg->cache, len); memcpy(cache_data, msg->cache, len);
} }
if (msg->event_code == ZTS_EVENT_STORE_IDENTITY_SECRET) { if (msg->event_code == ZTS_EVENT_STORE_IDENTITY_SECRET) {
printf("ZTS_EVENT_STORE_IDENTITY_SECRET (len=%d)\n", msg->len); printf("ZTS_EVENT_STORE_IDENTITY_SECRET (len=%d)\n", msg->len);
printf("identity.secret = [ %.*s ]\n", len, msg->cache); printf("identity.secret = [ %.*s ]\n", len, msg->cache);
memcpy(cache_data, msg->cache, len); memcpy(cache_data, msg->cache, len);
// Same data can be retrieved via: zts_node_get_id_pair() // Same data can be retrieved via: zts_node_get_id_pair()
} }
if (msg->event_code == ZTS_EVENT_STORE_PLANET) { if (msg->event_code == ZTS_EVENT_STORE_PLANET) {
printf("ZTS_EVENT_STORE_PLANET (len=%d)\n", msg->len); printf("ZTS_EVENT_STORE_PLANET (len=%d)\n", msg->len);
// Binary data // Binary data
memcpy(cache_data, msg->cache, len); memcpy(cache_data, msg->cache, len);
} }
if (msg->event_code == ZTS_EVENT_STORE_PEER) { if (msg->event_code == ZTS_EVENT_STORE_PEER) {
printf("ZTS_EVENT_STORE_PEER (len=%d)\n", msg->len); printf("ZTS_EVENT_STORE_PEER (len=%d)\n", msg->len);
// Binary data // Binary data
memcpy(cache_data, msg->cache, len); memcpy(cache_data, msg->cache, len);
} }
if (msg->event_code == ZTS_EVENT_STORE_NETWORK) { if (msg->event_code == ZTS_EVENT_STORE_NETWORK) {
printf("ZTS_EVENT_STORE_NETWORK (len=%d)\n", msg->len); printf("ZTS_EVENT_STORE_NETWORK (len=%d)\n", msg->len);
// Binary data // Binary data
memcpy(cache_data, msg->cache, len); memcpy(cache_data, msg->cache, len);
} }
} }
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
int err = ZTS_ERR_OK; int err = ZTS_ERR_OK;
// Initialize node // Initialize node
zts_init_set_event_handler(&on_zts_event); zts_init_set_event_handler(&on_zts_event);
// Start node // Start node
printf("Starting node...\n"); printf("Starting node...\n");
int generate_new_id = 1; int generate_new_id = 1;
if (generate_new_id) { if (generate_new_id) {
// OPTION A // OPTION A
// Generate new automatically ID if no prior init called // Generate new automatically ID if no prior init called
zts_node_start(); zts_node_start();
} }
else { else {
// OPTION B // OPTION B
// Copy your key here // Copy your key here
char identity[ZTS_ID_STR_BUF_LEN] = { 0 }; char identity[ZTS_ID_STR_BUF_LEN] = { 0 };
int len = ZTS_ID_STR_BUF_LEN; int len = ZTS_ID_STR_BUF_LEN;
// Generate key (optional): // Generate key (optional):
// int key_len; // int key_len;
// zts_id_new(identity, &key_len); // zts_id_new(identity, &key_len);
// Load pre-existing identity from buffer // Load pre-existing identity from buffer
zts_init_from_memory(identity, len); zts_init_from_memory(identity, len);
zts_node_start(); zts_node_start();
} }
printf("Waiting for node to come online\n"); printf("Waiting for node to come online\n");
while (! zts_node_is_online()) { while (! zts_node_is_online()) {
zts_util_delay(50); zts_util_delay(50);
} }
// Do network stuff! // Do network stuff!
// zts_socket, zts_connect, etc // zts_socket, zts_connect, etc
printf("Node %llx is now online. Idling.\n", zts_node_get_id()); printf("Node %llx is now online. Idling.\n", zts_node_get_id());
while (1) { while (1) {
zts_util_delay(500); // Idle indefinitely zts_util_delay(500); // Idle indefinitely
} }
printf("Stopping node\n"); printf("Stopping node\n");
return zts_node_stop(); return zts_node_stop();
} }

View File

@@ -11,57 +11,57 @@
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
if (argc != 2) { if (argc != 2) {
printf("\nUsage:\n"); printf("\nUsage:\n");
printf("pingable-node <net_id>\n"); printf("pingable-node <net_id>\n");
exit(0); exit(0);
} }
long long int net_id = strtoull(argv[1], NULL, 16); // At least 64 bits long long int net_id = strtoull(argv[1], NULL, 16); // At least 64 bits
printf("Starting node...\n"); printf("Starting node...\n");
zts_node_start(); zts_node_start();
printf("Waiting for node to come online\n"); printf("Waiting for node to come online\n");
while (! zts_node_is_online()) { while (! zts_node_is_online()) {
zts_util_delay(50); zts_util_delay(50);
} }
printf("My public identity (node ID) is %llx\n", (long long int)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 }; char keypair[ZTS_ID_STR_BUF_LEN] = { 0 };
unsigned int 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) { if (zts_node_get_id_pair(keypair, &len) != ZTS_ERR_OK) {
printf("Error getting identity keypair. Exiting.\n"); printf("Error getting identity keypair. Exiting.\n");
} }
printf("Identity [public/secret pair] = %s\n", keypair); printf("Identity [public/secret pair] = %s\n", keypair);
printf("Joining network %llx\n", net_id); printf("Joining network %llx\n", net_id);
if (zts_net_join(net_id) != ZTS_ERR_OK) { if (zts_net_join(net_id) != ZTS_ERR_OK) {
printf("Unable to join network. Exiting.\n"); printf("Unable to join network. Exiting.\n");
exit(1); exit(1);
} }
printf("Waiting for join to complete\n"); printf("Waiting for join to complete\n");
while (! zts_net_transport_is_ready(net_id)) { while (! zts_net_transport_is_ready(net_id)) {
zts_util_delay(50); zts_util_delay(50);
} }
printf("Waiting for address assignment from network\n"); printf("Waiting for address assignment from network\n");
int err = 0; int err = 0;
while (! (err = zts_addr_is_assigned(net_id, ZTS_AF_INET))) { while (! (err = zts_addr_is_assigned(net_id, ZTS_AF_INET))) {
zts_util_delay(500); zts_util_delay(500);
} }
char ipstr[ZTS_IP_MAX_STR_LEN] = { 0 }; char ipstr[ZTS_IP_MAX_STR_LEN] = { 0 };
zts_addr_get_str(net_id, ZTS_AF_INET, ipstr, ZTS_IP_MAX_STR_LEN); zts_addr_get_str(net_id, ZTS_AF_INET, ipstr, ZTS_IP_MAX_STR_LEN);
printf("Join %llx from another machine and ping me at %s\n", net_id, ipstr); printf("Join %llx from another machine and ping me at %s\n", net_id, ipstr);
// Do network stuff! // Do network stuff!
// zts_socket, zts_connect, etc // zts_socket, zts_connect, etc
while (1) { while (1) {
zts_util_delay(500); // Idle indefinitely zts_util_delay(500); // Idle indefinitely
} }
printf("Stopping node\n"); printf("Stopping node\n");
return zts_node_stop(); return zts_node_stop();
} }

View File

@@ -12,99 +12,99 @@
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
if (argc != 5) { if (argc != 5) {
printf("\nlibzt example server\n"); printf("\nlibzt example server\n");
printf("server <id_storage_path> <net_id> <local_addr> <local_port>\n"); printf("server <id_storage_path> <net_id> <local_addr> <local_port>\n");
exit(0); exit(0);
} }
char* storage_path = argv[1]; char* storage_path = argv[1];
long long int net_id = strtoull(argv[2], NULL, 16); // At least 64 bits long long int net_id = strtoull(argv[2], NULL, 16); // At least 64 bits
char* local_addr = argv[3]; char* local_addr = argv[3];
int local_port = atoi(argv[4]); int local_port = atoi(argv[4]);
int fd, accfd; int fd, accfd;
int err = ZTS_ERR_OK; int err = ZTS_ERR_OK;
// Initialize node // Initialize node
if ((err = zts_init_from_storage(storage_path)) != ZTS_ERR_OK) { if ((err = zts_init_from_storage(storage_path)) != ZTS_ERR_OK) {
printf("Unable to start service, error = %d. Exiting.\n", err); printf("Unable to start service, error = %d. Exiting.\n", err);
exit(1); exit(1);
} }
// Start node // Start node
if ((err = zts_node_start()) != ZTS_ERR_OK) { if ((err = zts_node_start()) != ZTS_ERR_OK) {
printf("Unable to start service, error = %d. Exiting.\n", err); printf("Unable to start service, error = %d. Exiting.\n", err);
exit(1); exit(1);
} }
printf("Waiting for node to come online\n"); printf("Waiting for node to come online\n");
while (! zts_node_is_online()) { while (! zts_node_is_online()) {
zts_util_delay(50); zts_util_delay(50);
} }
printf("Public identity (node ID) is %llx\n", zts_node_get_id()); printf("Public identity (node ID) is %llx\n", zts_node_get_id());
// Join network // Join network
printf("Joining network %llx\n", net_id); printf("Joining network %llx\n", net_id);
if (zts_net_join(net_id) != ZTS_ERR_OK) { if (zts_net_join(net_id) != ZTS_ERR_OK) {
printf("Unable to join network. Exiting.\n"); printf("Unable to join network. Exiting.\n");
exit(1); exit(1);
} }
printf("Don't forget to authorize this device in my.zerotier.com or the web API!\n"); printf("Don't forget to authorize this device in my.zerotier.com or the web API!\n");
printf("Waiting for join to complete\n"); printf("Waiting for join to complete\n");
while (! zts_net_transport_is_ready(net_id)) { while (! zts_net_transport_is_ready(net_id)) {
zts_util_delay(50); zts_util_delay(50);
} }
// Get assigned address (of the family type we care about) // Get assigned address (of the family type we care about)
int family = zts_util_get_ip_family(local_addr); int family = zts_util_get_ip_family(local_addr);
printf("Waiting for address assignment from network\n"); printf("Waiting for address assignment from network\n");
while (! (err = zts_addr_is_assigned(net_id, family))) { while (! (err = zts_addr_is_assigned(net_id, family))) {
zts_util_delay(50); zts_util_delay(50);
} }
char ipstr[ZTS_IP_MAX_STR_LEN] = { 0 }; char ipstr[ZTS_IP_MAX_STR_LEN] = { 0 };
zts_addr_get_str(net_id, family, ipstr, ZTS_IP_MAX_STR_LEN); zts_addr_get_str(net_id, family, ipstr, ZTS_IP_MAX_STR_LEN);
printf("IP address on network %llx is %s\n", net_id, ipstr); printf("IP address on network %llx is %s\n", net_id, ipstr);
// BEGIN Socket Stuff // BEGIN Socket Stuff
// Accept incoming connection // Accept incoming connection
// Can also use traditional: zts_socket(), zts_bind(), zts_listen(), zts_accept(), etc. // Can also use traditional: zts_socket(), zts_bind(), zts_listen(), zts_accept(), etc.
char remote_addr[ZTS_INET6_ADDRSTRLEN] = { 0 }; char remote_addr[ZTS_INET6_ADDRSTRLEN] = { 0 };
int remote_port = 0; int remote_port = 0;
int len = ZTS_INET6_ADDRSTRLEN; 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); printf("Error (fd=%d, zts_errno=%d). Exiting.\n", accfd, zts_errno);
exit(1); exit(1);
} }
printf("Accepted connection from %s:%d\n", remote_addr, remote_port); printf("Accepted connection from %s:%d\n", remote_addr, remote_port);
// Data I/O // Data I/O
int bytes = 0; int bytes = 0;
char recvBuf[128] = { 0 }; char recvBuf[128] = { 0 };
printf("Reading message string from client...\n"); printf("Reading message string from client...\n");
if ((bytes = zts_read(accfd, recvBuf, sizeof(recvBuf))) < 0) { if ((bytes = zts_read(accfd, recvBuf, sizeof(recvBuf))) < 0) {
printf("Error (fd=%d, ret=%d, zts_errno=%d). Exiting.\n", fd, bytes, zts_errno); printf("Error (fd=%d, ret=%d, zts_errno=%d). Exiting.\n", fd, bytes, zts_errno);
exit(1); exit(1);
} }
printf("Read %d bytes: %s\n", bytes, recvBuf); printf("Read %d bytes: %s\n", bytes, recvBuf);
printf("Sending message string to client...\n"); printf("Sending message string to client...\n");
if ((bytes = zts_write(accfd, recvBuf, bytes)) < 0) { if ((bytes = zts_write(accfd, recvBuf, bytes)) < 0) {
printf("Error (fd=%d, ret=%d, zts_errno=%d). Exiting.\n", fd, bytes, zts_errno); printf("Error (fd=%d, ret=%d, zts_errno=%d). Exiting.\n", fd, bytes, zts_errno);
exit(1); exit(1);
} }
printf("Sent %d bytes: %s\n", bytes, recvBuf); printf("Sent %d bytes: %s\n", bytes, recvBuf);
// Close // Close
printf("Closing connection socket\n"); printf("Closing connection socket\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

@@ -12,119 +12,119 @@
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
if (argc != 2) { if (argc != 2) {
printf("\nUsage:\n"); printf("\nUsage:\n");
printf("pingable-node <net_id>\n"); printf("pingable-node <net_id>\n");
exit(0); exit(0);
} }
long long int net_id = strtoull(argv[1], NULL, 16); // At least 64 bits long long int net_id = strtoull(argv[1], NULL, 16); // At least 64 bits
printf("Starting node...\n"); printf("Starting node...\n");
zts_node_start(); zts_node_start();
printf("Waiting for node to come online\n"); printf("Waiting for node to come online\n");
while (! zts_node_is_online()) { while (! zts_node_is_online()) {
zts_util_delay(50); 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", zts_node_get_id());
char keypair[ZTS_ID_STR_BUF_LEN] = { 0 }; char keypair[ZTS_ID_STR_BUF_LEN] = { 0 };
uint16_t len = ZTS_ID_STR_BUF_LEN; uint16_t len = ZTS_ID_STR_BUF_LEN;
if (zts_node_get_id_pair(keypair, &len) != ZTS_ERR_OK) { if (zts_node_get_id_pair(keypair, &len) != ZTS_ERR_OK) {
printf("Error getting identity keypair. Exiting.\n"); printf("Error getting identity keypair. Exiting.\n");
} }
printf("Identity [public/secret pair] = %s\n", keypair); printf("Identity [public/secret pair] = %s\n", keypair);
printf("Joining network %llx\n", net_id); printf("Joining network %llx\n", net_id);
if (zts_net_join(net_id) != ZTS_ERR_OK) { if (zts_net_join(net_id) != ZTS_ERR_OK) {
printf("Unable to join network. Exiting.\n"); printf("Unable to join network. Exiting.\n");
exit(1); exit(1);
} }
printf("Waiting for join to complete\n"); printf("Waiting for join to complete\n");
while (! zts_net_transport_is_ready(net_id)) { while (! zts_net_transport_is_ready(net_id)) {
zts_util_delay(50); zts_util_delay(50);
} }
printf("Waiting for address assignment from network\n"); printf("Waiting for address assignment from network\n");
int err = 0; int err = 0;
while (! (err = zts_addr_is_assigned(net_id, ZTS_AF_INET))) { while (! (err = zts_addr_is_assigned(net_id, ZTS_AF_INET))) {
zts_util_delay(500); zts_util_delay(500);
} }
char ipstr[ZTS_IP_MAX_STR_LEN] = { 0 }; char ipstr[ZTS_IP_MAX_STR_LEN] = { 0 };
zts_addr_get_str(net_id, ZTS_AF_INET, ipstr, ZTS_IP_MAX_STR_LEN); zts_addr_get_str(net_id, ZTS_AF_INET, ipstr, ZTS_IP_MAX_STR_LEN);
printf("Join %llx from another machine and ping me at %s\n", net_id, ipstr); printf("Join %llx from another machine and ping me at %s\n", net_id, ipstr);
// Do network stuff! // Do network stuff!
// zts_socket, zts_connect, etc // zts_socket, zts_connect, etc
// Show protocol statistics // Show protocol statistics
zts_stats_counter_t s = { 0 }; zts_stats_counter_t s = { 0 };
while (1) { while (1) {
zts_util_delay(1000); zts_util_delay(1000);
if ((err = zts_stats_get_all(&s)) == ZTS_ERR_NO_RESULT) { if ((err = zts_stats_get_all(&s)) == ZTS_ERR_NO_RESULT) {
printf("no results\n"); printf("no results\n");
continue; continue;
} }
printf("\n\n"); printf("\n\n");
printf( printf(
" link_tx=%9d, link_rx=%9d, link_drop=%9d, link_err=%9d\n", " link_tx=%9d, link_rx=%9d, link_drop=%9d, link_err=%9d\n",
s.link_tx, s.link_tx,
s.link_rx, s.link_rx,
s.link_drop, s.link_drop,
s.link_err); s.link_err);
printf( printf(
"etharp_tx=%9d, etharp_rx=%9d, etharp_drop=%9d, etharp_err=%9d\n", "etharp_tx=%9d, etharp_rx=%9d, etharp_drop=%9d, etharp_err=%9d\n",
s.etharp_tx, s.etharp_tx,
s.etharp_rx, s.etharp_rx,
s.etharp_drop, s.etharp_drop,
s.etharp_err); s.etharp_err);
printf( printf(
" ip4_tx=%9d, ip4_rx=%9d, ip4_drop=%9d, ip4_err=%9d\n", " ip4_tx=%9d, ip4_rx=%9d, ip4_drop=%9d, ip4_err=%9d\n",
s.ip4_tx, s.ip4_tx,
s.ip4_rx, s.ip4_rx,
s.ip4_drop, s.ip4_drop,
s.ip4_err); s.ip4_err);
printf( printf(
" ip6_tx=%9d, ip6_rx=%9d, ip6_drop=%9d, ip6_err=%9d\n", " ip6_tx=%9d, ip6_rx=%9d, ip6_drop=%9d, ip6_err=%9d\n",
s.ip6_tx, s.ip6_tx,
s.ip6_rx, s.ip6_rx,
s.ip6_drop, s.ip6_drop,
s.ip6_err); s.ip6_err);
printf( printf(
" icmp4_tx=%9d, icmp4_rx=%9d, icmp4_drop=%9d, icmp4_err=%9d\n", " icmp4_tx=%9d, icmp4_rx=%9d, icmp4_drop=%9d, icmp4_err=%9d\n",
s.icmp4_tx, s.icmp4_tx,
s.icmp4_rx, s.icmp4_rx,
s.icmp4_drop, s.icmp4_drop,
s.icmp4_err); s.icmp4_err);
printf( printf(
" icmp6_tx=%9d, icmp6_rx=%9d, icmp6_drop=%9d, icmp6_err=%9d\n", " icmp6_tx=%9d, icmp6_rx=%9d, icmp6_drop=%9d, icmp6_err=%9d\n",
s.icmp6_tx, s.icmp6_tx,
s.icmp6_rx, s.icmp6_rx,
s.icmp6_drop, s.icmp6_drop,
s.icmp6_err); s.icmp6_err);
printf( printf(
" udp_tx=%9d, udp_rx=%9d, udp_drop=%9d, udp_err=%9d\n", " udp_tx=%9d, udp_rx=%9d, udp_drop=%9d, udp_err=%9d\n",
s.udp_tx, s.udp_tx,
s.udp_rx, s.udp_rx,
s.udp_drop, s.udp_drop,
s.udp_err); s.udp_err);
printf( printf(
" tcp_tx=%9d, tcp_rx=%9d, tcp_drop=%9d, tcp_err=%9d\n", " tcp_tx=%9d, tcp_rx=%9d, tcp_drop=%9d, tcp_err=%9d\n",
s.tcp_tx, s.tcp_tx,
s.tcp_rx, s.tcp_rx,
s.tcp_drop, s.tcp_drop,
s.tcp_err); s.tcp_err);
printf( printf(
" nd6_tx=%9d, nd6_rx=%9d, nd6_drop=%9d, nd6_err=%9d\n", " nd6_tx=%9d, nd6_rx=%9d, nd6_drop=%9d, nd6_err=%9d\n",
s.nd6_tx, s.nd6_tx,
s.nd6_rx, s.nd6_rx,
s.nd6_drop, s.nd6_drop,
s.nd6_err); s.nd6_err);
} }
return zts_node_stop(); return zts_node_stop();
} }

File diff suppressed because it is too large Load Diff

View File

@@ -47,80 +47,80 @@ extern "C" {
size_t on_data(void* buffer, size_t size, size_t nmemb, void* userp) size_t on_data(void* buffer, size_t size, size_t nmemb, void* userp)
{ {
DEBUG_INFO("buf=%p,size=%zu,nmemb=%zu,userp=%p", buffer, size, nmemb, userp); DEBUG_INFO("buf=%p,size=%zu,nmemb=%zu,userp=%p", buffer, size, nmemb, userp);
int byte_count = (size * nmemb); int byte_count = (size * nmemb);
if (_resp_buf_offset + byte_count >= _resp_buf_len) { if (_resp_buf_offset + byte_count >= _resp_buf_len) {
DEBUG_INFO("Out of buffer space. Cannot store response from server"); DEBUG_INFO("Out of buffer space. Cannot store response from server");
return 0; // Signal to libcurl that our buffer is full (triggers a return 0; // Signal to libcurl that our buffer is full (triggers a
// write error.) // write error.)
} }
memcpy(_resp_buf + _resp_buf_offset, buffer, byte_count); memcpy(_resp_buf + _resp_buf_offset, buffer, byte_count);
_resp_buf_offset += byte_count; _resp_buf_offset += byte_count;
return byte_count; return byte_count;
} }
int zts_central_set_access_mode(int8_t modes) int zts_central_set_access_mode(int8_t modes)
{ {
if (! (modes & ZTS_CENTRAL_READ) && ! (modes & ZTS_CENTRAL_WRITE)) { if (! (modes & ZTS_CENTRAL_READ) && ! (modes & ZTS_CENTRAL_WRITE)) {
return ZTS_ERR_ARG; return ZTS_ERR_ARG;
} }
_access_modes = modes; _access_modes = modes;
return ZTS_ERR_OK; return ZTS_ERR_OK;
} }
int zts_central_set_verbose(int8_t is_verbose) int zts_central_set_verbose(int8_t is_verbose)
{ {
if (is_verbose != 1 && is_verbose != 0) { if (is_verbose != 1 && is_verbose != 0) {
return ZTS_ERR_ARG; return ZTS_ERR_ARG;
} }
_bIsVerbose = is_verbose; _bIsVerbose = is_verbose;
return ZTS_ERR_OK; return ZTS_ERR_OK;
} }
void zts_central_clear_resp_buf() void zts_central_clear_resp_buf()
{ {
Mutex::Lock _l(_responseBuffer_m); Mutex::Lock _l(_responseBuffer_m);
memset(_resp_buf, 0, _resp_buf_len); memset(_resp_buf, 0, _resp_buf_len);
_resp_buf_offset = 0; _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 _access_modes = ZTS_CENTRAL_READ; // Default read-only
_bIsVerbose = 0; // Default disable libcurl verbose output _bIsVerbose = 0; // Default disable libcurl verbose output
Mutex::Lock _l(_responseBuffer_m); Mutex::Lock _l(_responseBuffer_m);
if (resp_buf_len == 0) { if (resp_buf_len == 0) {
return ZTS_ERR_ARG; return ZTS_ERR_ARG;
} }
_resp_buf = resp_buf; _resp_buf = resp_buf;
_resp_buf_len = resp_buf_len; _resp_buf_len = resp_buf_len;
_resp_buf_offset = 0; _resp_buf_offset = 0;
// 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 = strlen(url_str);
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;
} }
else { else {
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 = strlen(token_str);
if (token_len != ZTS_CENTRAL_TOKEN_LEN) { if (token_len != ZTS_CENTRAL_TOKEN_LEN) {
return ZTS_ERR_ARG; return ZTS_ERR_ARG;
} }
else { else {
memset(api_token, 0, ZTS_CENTRAL_TOKEN_LEN); memset(api_token, 0, ZTS_CENTRAL_TOKEN_LEN);
strncpy(api_token, token_str, token_len); strncpy(api_token, token_str, token_len);
} }
_bInit = true; _bInit = true;
return ZTS_ERR_OK; return ZTS_ERR_OK;
} }
void zts_central_cleanup() void zts_central_cleanup()
{ {
curl_global_cleanup(); curl_global_cleanup();
} }
int central_req( int central_req(
@@ -131,183 +131,183 @@ int central_req(
int* response_code, int* response_code,
char* post_data) char* post_data)
{ {
int err = ZTS_ERR_OK; int err = ZTS_ERR_OK;
if (! _bInit) { if (! _bInit) {
DEBUG_INFO("Error: Central API must be initialized first. Call " DEBUG_INFO("Error: Central API must be initialized first. Call "
"zts_central_init()"); "zts_central_init()");
return ZTS_ERR_SERVICE; return ZTS_ERR_SERVICE;
} }
if (request_type == ZTS_HTTP_GET && ! (_access_modes & ZTS_CENTRAL_READ)) { if (request_type == ZTS_HTTP_GET && ! (_access_modes & ZTS_CENTRAL_READ)) {
DEBUG_INFO("Error: Incorrect access mode. Need (ZTS_CENTRAL_READ) permission"); DEBUG_INFO("Error: Incorrect access mode. Need (ZTS_CENTRAL_READ) permission");
return ZTS_ERR_SERVICE; return ZTS_ERR_SERVICE;
} }
if (request_type == ZTS_HTTP_POST && ! (_access_modes & ZTS_CENTRAL_WRITE)) { if (request_type == ZTS_HTTP_POST && ! (_access_modes & ZTS_CENTRAL_WRITE)) {
DEBUG_INFO("Error: Incorrect access mode. Need (ZTS_CENTRAL_WRITE) " DEBUG_INFO("Error: Incorrect access mode. Need (ZTS_CENTRAL_WRITE) "
"permission"); "permission");
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 = strlen(central_str);
int api_route_strlen = strlen(api_route_str); int api_route_strlen = strlen(api_route_str);
int token_strlen = strlen(token_str); int token_strlen = strlen(token_str);
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;
} }
if (url_len > ZTS_CENRTAL_MAX_URL_LEN) { if (url_len > ZTS_CENRTAL_MAX_URL_LEN) {
return ZTS_ERR_ARG; return ZTS_ERR_ARG;
} }
char req_url[ZTS_CENRTAL_MAX_URL_LEN] = { 0 }; char req_url[ZTS_CENRTAL_MAX_URL_LEN] = { 0 };
strncpy(req_url, central_str, ZTS_CENRTAL_MAX_URL_LEN); strncpy(req_url, central_str, ZTS_CENRTAL_MAX_URL_LEN);
strncat(req_url, api_route_str, ZTS_CENRTAL_MAX_URL_LEN); strncat(req_url, api_route_str, ZTS_CENRTAL_MAX_URL_LEN);
CURL* curl; CURL* curl;
CURLcode res; CURLcode res;
curl = curl_easy_init(); curl = curl_easy_init();
if (! curl) { if (! curl) {
return ZTS_ERR_GENERAL; return ZTS_ERR_GENERAL;
} }
struct curl_slist* hs = NULL; struct curl_slist* hs = NULL;
char auth_str[ZTS_CENTRAL_TOKEN_LEN + 32] = { 0 }; // + Authorization: Bearer char auth_str[ZTS_CENTRAL_TOKEN_LEN + 32] = { 0 }; // + Authorization: Bearer
if (token_strlen == ZTS_CENTRAL_TOKEN_LEN) { 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); hs = curl_slist_append(hs, auth_str);
hs = curl_slist_append(hs, "Content-Type: application/json"); hs = curl_slist_append(hs, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, hs); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, hs);
curl_easy_setopt(curl, CURLOPT_URL, req_url); curl_easy_setopt(curl, CURLOPT_URL, req_url);
// example.com is redirected, so we tell libcurl to follow redirection // example.com is redirected, so we tell libcurl to follow redirection
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
if (_bIsVerbose) { if (_bIsVerbose) {
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
} }
// Tell curl to use our write function // Tell curl to use our write function
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, on_data); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, on_data);
if (request_type == ZTS_HTTP_GET) { if (request_type == ZTS_HTTP_GET) {
// Nothing // Nothing
DEBUG_INFO("Request (GET) = %s", api_route_str); DEBUG_INFO("Request (GET) = %s", api_route_str);
} }
if (request_type == ZTS_HTTP_POST) { if (request_type == ZTS_HTTP_POST) {
DEBUG_INFO("Request (POST) = %s", api_route_str); DEBUG_INFO("Request (POST) = %s", api_route_str);
if (post_data) { if (post_data) {
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data);
} }
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST"); curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
} }
if (request_type == ZTS_HTTP_DELETE) { if (request_type == ZTS_HTTP_DELETE) {
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE"); curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE");
} }
// curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L); // Consider 400-500 // curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L); // Consider 400-500
// series code as failures // series code as failures
// Perform request // Perform request
res = curl_easy_perform(curl); res = curl_easy_perform(curl);
if (res == CURLE_OK) { if (res == CURLE_OK) {
// char* url; // char* url;
double elapsed_time = 0.0; double elapsed_time = 0.0;
long hrc = 0; long hrc = 0;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &hrc); curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &hrc);
curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &elapsed_time); curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &elapsed_time);
DEBUG_INFO("Req. took %f second(s). HTTP code (%ld)", elapsed_time, hrc); DEBUG_INFO("Req. took %f second(s). HTTP code (%ld)", elapsed_time, hrc);
*response_code = hrc; *response_code = hrc;
// curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &url); // curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &url);
} }
else { else {
DEBUG_INFO("%s", curl_easy_strerror(res)); DEBUG_INFO("%s", curl_easy_strerror(res));
err = ZTS_ERR_SERVICE; err = ZTS_ERR_SERVICE;
} }
curl_easy_cleanup(curl); curl_easy_cleanup(curl);
return err; return err;
} }
int zts_central_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) { if (dest_buf_len <= _resp_buf_offset) {
return ZTS_ERR_ARG; return ZTS_ERR_ARG;
} }
int sz = dest_buf_len < _resp_buf_len ? dest_buf_len : _resp_buf_len; int sz = dest_buf_len < _resp_buf_len ? dest_buf_len : _resp_buf_len;
memcpy(dest_buffer, _resp_buf, sz); memcpy(dest_buffer, _resp_buf, sz);
return ZTS_ERR_OK; return ZTS_ERR_OK;
} }
int zts_central_status_get(int* resp_code) int zts_central_status_get(int* resp_code)
{ {
return central_req(ZTS_HTTP_GET, api_url, (char*)"/api/status", api_token, resp_code, NULL); return central_req(ZTS_HTTP_GET, api_url, (char*)"/api/status", api_token, resp_code, NULL);
} }
int zts_central_self_get(int* resp_code) int zts_central_self_get(int* resp_code)
{ {
return central_req(ZTS_HTTP_GET, api_url, (char*)"/api/self", api_token, resp_code, NULL); return central_req(ZTS_HTTP_GET, api_url, (char*)"/api/self", api_token, resp_code, NULL);
} }
int zts_central_net_get(int* resp_code, uint64_t net_id) int zts_central_net_get(int* resp_code, uint64_t net_id)
{ {
char req[REQ_LEN] = { 0 }; char req[REQ_LEN] = { 0 };
OSUtils::ztsnprintf(req, REQ_LEN, "/api/network/%llx", net_id); OSUtils::ztsnprintf(req, REQ_LEN, "/api/network/%llx", net_id);
return central_req(ZTS_HTTP_GET, api_url, req, api_token, resp_code, NULL); return central_req(ZTS_HTTP_GET, api_url, req, api_token, resp_code, NULL);
} }
int zts_central_net_update(int* resp_code, uint64_t net_id) int zts_central_net_update(int* resp_code, uint64_t net_id)
{ {
char req[REQ_LEN] = { 0 }; char req[REQ_LEN] = { 0 };
OSUtils::ztsnprintf(req, REQ_LEN, "/api/network/%llx", net_id); OSUtils::ztsnprintf(req, REQ_LEN, "/api/network/%llx", net_id);
return central_req(ZTS_HTTP_POST, api_url, req, api_token, resp_code, NULL); return central_req(ZTS_HTTP_POST, api_url, req, api_token, resp_code, NULL);
} }
int zts_central_net_delete(int* resp_code, uint64_t net_id) int zts_central_net_delete(int* resp_code, uint64_t net_id)
{ {
char req[REQ_LEN] = { 0 }; char req[REQ_LEN] = { 0 };
OSUtils::ztsnprintf(req, REQ_LEN, "/api/network/%llx", net_id); OSUtils::ztsnprintf(req, REQ_LEN, "/api/network/%llx", net_id);
return central_req(ZTS_HTTP_DELETE, api_url, req, api_token, resp_code, NULL); return central_req(ZTS_HTTP_DELETE, api_url, req, api_token, resp_code, NULL);
} }
int zts_central_net_get_all(int* resp_code) int zts_central_net_get_all(int* resp_code)
{ {
return central_req(ZTS_HTTP_GET, api_url, (char*)"/api/network", api_token, resp_code, NULL); return central_req(ZTS_HTTP_GET, api_url, (char*)"/api/network", api_token, resp_code, NULL);
} }
int zts_central_member_get(int* resp_code, uint64_t net_id, uint64_t node_id) int zts_central_member_get(int* resp_code, uint64_t net_id, uint64_t node_id)
{ {
if (net_id == 0 || node_id == 0) { if (net_id == 0 || node_id == 0) {
return ZTS_ERR_ARG; return ZTS_ERR_ARG;
} }
char req[REQ_LEN] = { 0 }; char req[REQ_LEN] = { 0 };
OSUtils::ztsnprintf(req, REQ_LEN, "/api/network/%llx/member/%llx", net_id, node_id); OSUtils::ztsnprintf(req, REQ_LEN, "/api/network/%llx/member/%llx", net_id, node_id);
return central_req(ZTS_HTTP_GET, api_url, req, api_token, resp_code, NULL); return central_req(ZTS_HTTP_GET, api_url, req, api_token, resp_code, NULL);
} }
int zts_central_member_update(int* resp_code, uint64_t net_id, uint64_t node_id, char* post_data) int zts_central_member_update(int* resp_code, uint64_t net_id, uint64_t node_id, char* post_data)
{ {
if (net_id == 0 || node_id == 0 || post_data == NULL) { if (net_id == 0 || node_id == 0 || post_data == NULL) {
return ZTS_ERR_ARG; return ZTS_ERR_ARG;
} }
char req[REQ_LEN] = { 0 }; char req[REQ_LEN] = { 0 };
OSUtils::ztsnprintf(req, REQ_LEN, "/api/network/%llx/member/%llx", net_id, node_id); OSUtils::ztsnprintf(req, REQ_LEN, "/api/network/%llx/member/%llx", net_id, node_id);
return central_req(ZTS_HTTP_POST, api_url, req, api_token, resp_code, post_data); return central_req(ZTS_HTTP_POST, api_url, req, api_token, resp_code, post_data);
} }
int zts_central_node_auth(int* resp_code, uint64_t net_id, uint64_t node_id, uint8_t is_authed) int zts_central_node_auth(int* resp_code, uint64_t net_id, uint64_t node_id, uint8_t is_authed)
{ {
if (is_authed != 0 && is_authed != 1) { if (is_authed != 0 && is_authed != 1) {
return ZTS_ERR_ARG; return ZTS_ERR_ARG;
} }
char config_data[REQ_LEN] = { 0 }; char config_data[REQ_LEN] = { 0 };
if (is_authed == ZTS_CENTRAL_NODE_AUTH_TRUE) { if (is_authed == ZTS_CENTRAL_NODE_AUTH_TRUE) {
OSUtils::ztsnprintf(config_data, REQ_LEN, "{\"config\": {\"authorized\": true} }"); OSUtils::ztsnprintf(config_data, REQ_LEN, "{\"config\": {\"authorized\": true} }");
} }
if (is_authed == ZTS_CENTRAL_NODE_AUTH_FALSE) { if (is_authed == ZTS_CENTRAL_NODE_AUTH_FALSE) {
OSUtils::ztsnprintf(config_data, REQ_LEN, "{\"config\": {\"authorized\": false} }"); OSUtils::ztsnprintf(config_data, REQ_LEN, "{\"config\": {\"authorized\": false} }");
} }
return zts_central_member_update(resp_code, net_id, node_id, config_data); return zts_central_member_update(resp_code, net_id, node_id, config_data);
} }
int zts_central_net_get_members(int* resp_code, uint64_t net_id) int zts_central_net_get_members(int* resp_code, uint64_t net_id)
{ {
char req[REQ_LEN] = { 0 }; char req[REQ_LEN] = { 0 };
OSUtils::ztsnprintf(req, REQ_LEN, "/api/network/%llx/member", net_id); OSUtils::ztsnprintf(req, REQ_LEN, "/api/network/%llx/member", net_id);
return central_req(ZTS_HTTP_GET, api_url, req, api_token, resp_code, NULL); return central_req(ZTS_HTTP_GET, api_url, req, api_token, resp_code, NULL);
} }
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -69,20 +69,20 @@ Mutex service_m;
*/ */
int init_subsystems() int init_subsystems()
{ {
if (! zts_events) { if (! zts_events) {
zts_events = new Events(); zts_events = new Events();
} }
if (zts_events->getState(ZTS_STATE_FREE_CALLED)) { if (zts_events->getState(ZTS_STATE_FREE_CALLED)) {
return ZTS_ERR_SERVICE; return ZTS_ERR_SERVICE;
} }
#ifdef ZTS_ENABLE_CUSTOM_SIGNAL_HANDLERS #ifdef ZTS_ENABLE_CUSTOM_SIGNAL_HANDLERS
_install_signal_handlers(); _install_signal_handlers();
#endif // ZTS_ENABLE_CUSTOM_SIGNAL_HANDLERS #endif // ZTS_ENABLE_CUSTOM_SIGNAL_HANDLERS
if (! zts_service) { if (! zts_service) {
zts_service = new NodeService(); zts_service = new NodeService();
zts_service->setUserEventSystem(zts_events); zts_service->setUserEventSystem(zts_events);
} }
return ZTS_ERR_OK; return ZTS_ERR_OK;
} }
#ifdef __cplusplus #ifdef __cplusplus
@@ -91,15 +91,15 @@ extern "C" {
int zts_init_from_storage(const char* path) int zts_init_from_storage(const char* path)
{ {
ACQUIRE_SERVICE_OFFLINE(); ACQUIRE_SERVICE_OFFLINE();
zts_service->setHomePath(path); zts_service->setHomePath(path);
return ZTS_ERR_OK; return ZTS_ERR_OK;
} }
int zts_init_from_memory(const char* keypair, unsigned int len) int zts_init_from_memory(const char* keypair, unsigned int len)
{ {
ACQUIRE_SERVICE_OFFLINE(); ACQUIRE_SERVICE_OFFLINE();
return zts_service->setIdentity(keypair, len); return zts_service->setIdentity(keypair, len);
} }
#ifdef ZTS_ENABLE_PYTHON #ifdef ZTS_ENABLE_PYTHON
@@ -112,154 +112,154 @@ int zts_init_set_event_handler(PythonDirectorCallbackClass* callback)
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();
if (! callback) { if (! callback) {
return ZTS_ERR_ARG; return ZTS_ERR_ARG;
} }
_userEventCallback = callback; _userEventCallback = callback;
zts_service->enableEvents(); zts_service->enableEvents();
return ZTS_ERR_OK; return ZTS_ERR_OK;
} }
int zts_init_blacklist_if(const char* prefix, unsigned int len) int zts_init_blacklist_if(const char* prefix, unsigned int len)
{ {
ACQUIRE_SERVICE_OFFLINE(); ACQUIRE_SERVICE_OFFLINE();
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_world(const void* world_data, unsigned int len)
{ {
ACQUIRE_SERVICE_OFFLINE(); ACQUIRE_SERVICE_OFFLINE();
return zts_service->setWorld(world_data, len); return zts_service->setWorld(world_data, len);
} }
int zts_init_set_port(unsigned short port) int zts_init_set_port(unsigned short port)
{ {
ACQUIRE_SERVICE_OFFLINE(); ACQUIRE_SERVICE_OFFLINE();
zts_service->setPrimaryPort(port); zts_service->setPrimaryPort(port);
return ZTS_ERR_OK; return ZTS_ERR_OK;
} }
int zts_init_allow_peer_cache(unsigned int allowed) int zts_init_allow_peer_cache(unsigned int allowed)
{ {
ACQUIRE_SERVICE_OFFLINE(); ACQUIRE_SERVICE_OFFLINE();
return zts_service->allowPeerCaching(allowed); return zts_service->allowPeerCaching(allowed);
} }
int zts_init_allow_net_cache(unsigned int allowed) int zts_init_allow_net_cache(unsigned int allowed)
{ {
ACQUIRE_SERVICE_OFFLINE(); ACQUIRE_SERVICE_OFFLINE();
return zts_service->allowNetworkCaching(allowed); return zts_service->allowNetworkCaching(allowed);
} }
int zts_init_allow_world_cache(unsigned int allowed) int zts_init_allow_world_cache(unsigned int allowed)
{ {
ACQUIRE_SERVICE_OFFLINE(); ACQUIRE_SERVICE_OFFLINE();
return zts_service->allowWorldCaching(allowed); return zts_service->allowWorldCaching(allowed);
} }
int zts_init_allow_id_cache(unsigned int allowed) int zts_init_allow_id_cache(unsigned int allowed)
{ {
ACQUIRE_SERVICE_OFFLINE(); ACQUIRE_SERVICE_OFFLINE();
return zts_service->allowIdentityCaching(allowed); 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) { if (! addr || ! net_id || ! node_id) {
return ZTS_ERR_ARG; return ZTS_ERR_ARG;
} }
InetAddress _6planeAddr = InetAddress::makeIpv66plane(net_id, node_id); InetAddress _6planeAddr = InetAddress::makeIpv66plane(net_id, node_id);
struct sockaddr_in6* in6 = (struct sockaddr_in6*)addr; struct sockaddr_in6* in6 = (struct sockaddr_in6*)addr;
memcpy(in6->sin6_addr.s6_addr, _6planeAddr.rawIpData(), sizeof(struct in6_addr)); memcpy(in6->sin6_addr.s6_addr, _6planeAddr.rawIpData(), sizeof(struct in6_addr));
return ZTS_ERR_OK; 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) { if (! addr || ! net_id || ! node_id) {
return ZTS_ERR_ARG; return ZTS_ERR_ARG;
} }
InetAddress _rfc4193Addr = InetAddress::makeIpv6rfc4193(net_id, node_id); InetAddress _rfc4193Addr = InetAddress::makeIpv6rfc4193(net_id, node_id);
struct sockaddr_in6* in6 = (struct sockaddr_in6*)addr; struct sockaddr_in6* in6 = (struct sockaddr_in6*)addr;
memcpy(in6->sin6_addr.s6_addr, _rfc4193Addr.rawIpData(), sizeof(struct in6_addr)); memcpy(in6->sin6_addr.s6_addr, _rfc4193Addr.rawIpData(), sizeof(struct in6_addr));
return ZTS_ERR_OK; return ZTS_ERR_OK;
} }
int zts_addr_compute_rfc4193_str(uint64_t net_id, uint64_t node_id, char* dst, unsigned 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) { if (! net_id || ! node_id || ! dst || len != ZTS_IP_MAX_STR_LEN) {
return ZTS_ERR_ARG; return ZTS_ERR_ARG;
} }
struct zts_sockaddr_storage ss; struct zts_sockaddr_storage ss;
int err = ZTS_ERR_OK; int err = ZTS_ERR_OK;
if ((err = zts_addr_compute_rfc4193(net_id, node_id, &ss)) != ZTS_ERR_OK) { if ((err = zts_addr_compute_rfc4193(net_id, node_id, &ss)) != ZTS_ERR_OK) {
return err; return err;
} }
struct zts_sockaddr_in6* in6 = (struct zts_sockaddr_in6*)&ss; struct zts_sockaddr_in6* in6 = (struct zts_sockaddr_in6*)&ss;
zts_inet_ntop(ZTS_AF_INET6, &(in6->sin6_addr), dst, ZTS_IP_MAX_STR_LEN); zts_inet_ntop(ZTS_AF_INET6, &(in6->sin6_addr), dst, ZTS_IP_MAX_STR_LEN);
return ZTS_ERR_OK; return ZTS_ERR_OK;
} }
int zts_addr_compute_6plane_str(uint64_t net_id, uint64_t node_id, char* dst, unsigned 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) { if (! net_id || ! node_id || ! dst || len != ZTS_IP_MAX_STR_LEN) {
return ZTS_ERR_ARG; return ZTS_ERR_ARG;
} }
struct zts_sockaddr_storage ss; struct zts_sockaddr_storage ss;
int err = ZTS_ERR_OK; int err = ZTS_ERR_OK;
if ((err = zts_addr_compute_6plane(net_id, node_id, &ss)) != ZTS_ERR_OK) { if ((err = zts_addr_compute_6plane(net_id, node_id, &ss)) != ZTS_ERR_OK) {
return err; return err;
} }
struct zts_sockaddr_in6* in6 = (struct zts_sockaddr_in6*)&ss; struct zts_sockaddr_in6* in6 = (struct zts_sockaddr_in6*)&ss;
zts_inet_ntop(ZTS_AF_INET6, &(in6->sin6_addr), dst, ZTS_IP_MAX_STR_LEN); zts_inet_ntop(ZTS_AF_INET6, &(in6->sin6_addr), dst, ZTS_IP_MAX_STR_LEN);
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(uint16_t start_port, uint16_t 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);
return strtoull(net_id_str, NULL, 16); return strtoull(net_id_str, NULL, 16);
} }
int zts_id_new(char* key, unsigned int* dst_len) int zts_id_new(char* key, unsigned int* dst_len)
{ {
if (key == NULL || *dst_len != ZT_IDENTITY_STRING_BUFFER_LENGTH) { if (key == NULL || *dst_len != ZT_IDENTITY_STRING_BUFFER_LENGTH) {
return ZTS_ERR_ARG; return ZTS_ERR_ARG;
} }
Identity id; Identity id;
id.generate(); id.generate();
char idtmp[1024] = { 0 }; char idtmp[1024] = { 0 };
std::string idser = id.toString(true, idtmp); std::string idser = id.toString(true, idtmp);
unsigned int key_pair_len = idser.length(); unsigned int key_pair_len = idser.length();
if (key_pair_len > *dst_len) { if (key_pair_len > *dst_len) {
return ZTS_ERR_ARG; return ZTS_ERR_ARG;
} }
memcpy(key, idser.c_str(), key_pair_len); memcpy(key, idser.c_str(), key_pair_len);
*dst_len = key_pair_len; *dst_len = key_pair_len;
return ZTS_ERR_OK; return ZTS_ERR_OK;
} }
int zts_id_pair_is_valid(const char* key, unsigned int len) int zts_id_pair_is_valid(const char* key, unsigned int len)
{ {
if (key == NULL || len != ZT_IDENTITY_STRING_BUFFER_LENGTH) { if (key == NULL || len != ZT_IDENTITY_STRING_BUFFER_LENGTH) {
return false; return false;
} }
Identity id; Identity id;
if ((strlen(key) > 32) && (key[10] == ':')) { if ((strlen(key) > 32) && (key[10] == ':')) {
if (id.fromString(key)) { if (id.fromString(key)) {
return id.locallyValidate(); return id.locallyValidate();
} }
} }
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* dst_len)
{ {
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); ACQUIRE_SERVICE(ZTS_ERR_SERVICE);
zts_service->getIdentity(key, dst_len); zts_service->getIdentity(key, dst_len);
return *dst_len > 0 ? ZTS_ERR_OK : ZTS_ERR_GENERAL; return *dst_len > 0 ? ZTS_ERR_OK : ZTS_ERR_GENERAL;
} }
#if defined(__WINDOWS__) #if defined(__WINDOWS__)
@@ -269,95 +269,95 @@ void* cbRun(void* arg)
#endif #endif
{ {
#if defined(__APPLE__) #if defined(__APPLE__)
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;
} }
int zts_addr_is_assigned(uint64_t net_id, unsigned int family) int zts_addr_is_assigned(uint64_t net_id, unsigned int family)
{ {
ACQUIRE_SERVICE(0); ACQUIRE_SERVICE(0);
return zts_service->addrIsAssigned(net_id, family); return zts_service->addrIsAssigned(net_id, family);
} }
int zts_addr_get(uint64_t net_id, unsigned 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); ACQUIRE_SERVICE(ZTS_ERR_SERVICE);
return zts_service->getFirstAssignedAddr(net_id, family, addr); return zts_service->getFirstAssignedAddr(net_id, family, addr);
} }
int zts_addr_get_str(uint64_t net_id, unsigned int family, char* dst, unsigned int len) 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 // No service lock required since zts_addr_get will lock it
if (net_id == 0) { if (net_id == 0) {
return ZTS_ERR_ARG; return ZTS_ERR_ARG;
} }
if (len < ZTS_INET6_ADDRSTRLEN) { if (len < ZTS_INET6_ADDRSTRLEN) {
return ZTS_ERR_ARG; return ZTS_ERR_ARG;
} }
if (family == ZTS_AF_INET) { if (family == ZTS_AF_INET) {
struct zts_sockaddr_storage ss; struct zts_sockaddr_storage ss;
int err = ZTS_ERR_OK; int err = ZTS_ERR_OK;
if ((err = zts_addr_get(net_id, family, &ss)) != ZTS_ERR_OK) { if ((err = zts_addr_get(net_id, family, &ss)) != ZTS_ERR_OK) {
return err; return err;
} }
struct zts_sockaddr_in* in4 = (struct zts_sockaddr_in*)&ss; struct zts_sockaddr_in* in4 = (struct zts_sockaddr_in*)&ss;
zts_inet_ntop(family, &(in4->sin_addr), dst, ZTS_INET6_ADDRSTRLEN); zts_inet_ntop(family, &(in4->sin_addr), dst, ZTS_INET6_ADDRSTRLEN);
} }
if (family == ZTS_AF_INET6) { if (family == ZTS_AF_INET6) {
struct zts_sockaddr_storage ss; struct zts_sockaddr_storage ss;
int err = ZTS_ERR_OK; int err = ZTS_ERR_OK;
if ((err = zts_addr_get(net_id, family, &ss)) != ZTS_ERR_OK) { if ((err = zts_addr_get(net_id, family, &ss)) != ZTS_ERR_OK) {
return err; return err;
} }
struct zts_sockaddr_in6* in6 = (struct zts_sockaddr_in6*)&ss; struct zts_sockaddr_in6* in6 = (struct zts_sockaddr_in6*)&ss;
zts_inet_ntop(family, &(in6->sin6_addr), dst, ZTS_INET6_ADDRSTRLEN); zts_inet_ntop(family, &(in6->sin6_addr), dst, ZTS_INET6_ADDRSTRLEN);
} }
return ZTS_ERR_OK; return ZTS_ERR_OK;
} }
int zts_addr_get_all(uint64_t net_id, struct zts_sockaddr_storage* addr, unsigned int* count) int zts_addr_get_all(uint64_t net_id, struct zts_sockaddr_storage* addr, unsigned int* count)
{ {
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); ACQUIRE_SERVICE(ZTS_ERR_SERVICE);
return zts_service->getAllAssignedAddr(net_id, addr, count); return zts_service->getAllAssignedAddr(net_id, addr, count);
} }
int zts_core_lock_obtain() int zts_core_lock_obtain()
{ {
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); ACQUIRE_SERVICE(ZTS_ERR_SERVICE);
zts_service->obtainLock(); zts_service->obtainLock();
return ZTS_ERR_OK; return ZTS_ERR_OK;
} }
int zts_core_lock_release() int zts_core_lock_release()
{ {
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); ACQUIRE_SERVICE(ZTS_ERR_SERVICE);
zts_service->releaseLock(); zts_service->releaseLock();
return ZTS_ERR_OK; return ZTS_ERR_OK;
} }
int zts_core_query_addr_count(uint64_t net_id) int zts_core_query_addr_count(uint64_t net_id)
{ {
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); ACQUIRE_SERVICE(ZTS_ERR_SERVICE);
return zts_service->addressCount(net_id); return zts_service->addressCount(net_id);
} }
int zts_core_query_addr(uint64_t net_id, unsigned int idx, char* addr, unsigned int len) int zts_core_query_addr(uint64_t net_id, unsigned int idx, char* addr, unsigned int len)
{ {
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); ACQUIRE_SERVICE(ZTS_ERR_SERVICE);
return zts_service->getAddrAtIdx(net_id, idx, addr, len); return zts_service->getAddrAtIdx(net_id, idx, addr, len);
} }
int zts_core_query_route_count(uint64_t net_id) int zts_core_query_route_count(uint64_t net_id)
{ {
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); ACQUIRE_SERVICE(ZTS_ERR_SERVICE);
return zts_service->routeCount(net_id); return zts_service->routeCount(net_id);
} }
int zts_core_query_route( int zts_core_query_route(
@@ -369,110 +369,110 @@ int zts_core_query_route(
uint16_t* flags, uint16_t* flags,
uint16_t* metric) uint16_t* metric)
{ {
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); ACQUIRE_SERVICE(ZTS_ERR_SERVICE);
return zts_service->getRouteAtIdx(net_id, idx, target, via, len, flags, metric); return zts_service->getRouteAtIdx(net_id, idx, target, via, len, flags, metric);
} }
int zts_core_query_path_count(uint64_t peer_id) int zts_core_query_path_count(uint64_t peer_id)
{ {
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); ACQUIRE_SERVICE(ZTS_ERR_SERVICE);
return zts_service->pathCount(peer_id); return zts_service->pathCount(peer_id);
} }
int zts_core_query_path(uint64_t peer_id, unsigned int idx, char* path, unsigned int len) int zts_core_query_path(uint64_t peer_id, unsigned int idx, char* path, unsigned int len)
{ {
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); ACQUIRE_SERVICE(ZTS_ERR_SERVICE);
return zts_service->getPathAtIdx(peer_id, idx, path, len); return zts_service->getPathAtIdx(peer_id, idx, path, len);
} }
int zts_core_query_mc_count(uint64_t net_id) int zts_core_query_mc_count(uint64_t net_id)
{ {
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); ACQUIRE_SERVICE(ZTS_ERR_SERVICE);
return zts_service->multicastSubCount(net_id); return zts_service->multicastSubCount(net_id);
} }
int zts_core_query_mc(uint64_t net_id, unsigned int idx, uint64_t* mac, uint32_t* adi) int zts_core_query_mc(uint64_t net_id, unsigned int idx, uint64_t* mac, uint32_t* adi)
{ {
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); ACQUIRE_SERVICE(ZTS_ERR_SERVICE);
return zts_service->getMulticastSubAtIdx(net_id, idx, mac, adi); return zts_service->getMulticastSubAtIdx(net_id, idx, mac, adi);
} }
int zts_net_join(const uint64_t net_id) int zts_net_join(const uint64_t net_id)
{ {
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); ACQUIRE_SERVICE(ZTS_ERR_SERVICE);
return zts_service->join(net_id); return zts_service->join(net_id);
} }
int zts_net_leave(const uint64_t net_id) int zts_net_leave(const uint64_t net_id)
{ {
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); ACQUIRE_SERVICE(ZTS_ERR_SERVICE);
return zts_service->leave(net_id); return zts_service->leave(net_id);
} }
int zts_net_transport_is_ready(const uint64_t net_id) int zts_net_transport_is_ready(const uint64_t net_id)
{ {
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); ACQUIRE_SERVICE(ZTS_ERR_SERVICE);
return zts_service->networkIsReady(net_id); return zts_service->networkIsReady(net_id);
} }
uint64_t zts_net_get_mac(uint64_t net_id) uint64_t zts_net_get_mac(uint64_t net_id)
{ {
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); ACQUIRE_SERVICE(ZTS_ERR_SERVICE);
return zts_service->getMACAddress(net_id); return zts_service->getMACAddress(net_id);
} }
ZTS_API int ZTCALL zts_net_get_mac_str(uint64_t net_id, char* dst, unsigned 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); ACQUIRE_SERVICE(ZTS_ERR_SERVICE);
if (! dst || len < ZTS_MAC_ADDRSTRLEN) { if (! dst || len < ZTS_MAC_ADDRSTRLEN) {
return ZTS_ERR_ARG; return ZTS_ERR_ARG;
} }
uint64_t mac = zts_service->getMACAddress(net_id); uint64_t mac = zts_service->getMACAddress(net_id);
OSUtils::ztsnprintf( OSUtils::ztsnprintf(
dst, dst,
ZTS_MAC_ADDRSTRLEN, ZTS_MAC_ADDRSTRLEN,
"%x:%x:%x:%x:%x:%x", "%x:%x:%x:%x:%x:%x",
(mac >> 48) & 0xFF, (mac >> 48) & 0xFF,
(mac >> 32) & 0xFF, (mac >> 32) & 0xFF,
(mac >> 24) & 0xFF, (mac >> 24) & 0xFF,
(mac >> 16) & 0xFF, (mac >> 16) & 0xFF,
(mac >> 8) & 0xFF, (mac >> 8) & 0xFF,
(mac >> 0) & 0xFF); (mac >> 0) & 0xFF);
return ZTS_ERR_OK; return ZTS_ERR_OK;
} }
int zts_net_get_broadcast(uint64_t net_id) int zts_net_get_broadcast(uint64_t net_id)
{ {
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); ACQUIRE_SERVICE(ZTS_ERR_SERVICE);
return zts_service->getNetworkBroadcast(net_id); return zts_service->getNetworkBroadcast(net_id);
} }
int zts_net_get_mtu(uint64_t net_id) int zts_net_get_mtu(uint64_t net_id)
{ {
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); ACQUIRE_SERVICE(ZTS_ERR_SERVICE);
return zts_service->getNetworkMTU(net_id); return zts_service->getNetworkMTU(net_id);
} }
int zts_net_get_name(uint64_t net_id, char* dst, unsigned int len) int zts_net_get_name(uint64_t net_id, char* dst, unsigned int len)
{ {
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); ACQUIRE_SERVICE(ZTS_ERR_SERVICE);
return zts_service->getNetworkName(net_id, dst, len); return zts_service->getNetworkName(net_id, dst, len);
} }
int zts_net_get_status(uint64_t net_id) int zts_net_get_status(uint64_t net_id)
{ {
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); ACQUIRE_SERVICE(ZTS_ERR_SERVICE);
return zts_service->getNetworkStatus(net_id); return zts_service->getNetworkStatus(net_id);
} }
int zts_net_get_type(uint64_t net_id) int zts_net_get_type(uint64_t net_id)
{ {
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); ACQUIRE_SERVICE(ZTS_ERR_SERVICE);
return zts_service->getNetworkType(net_id); return zts_service->getNetworkType(net_id);
} }
int zts_route_is_assigned(uint64_t net_id, unsigned int family) int zts_route_is_assigned(uint64_t net_id, unsigned int family)
{ {
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); ACQUIRE_SERVICE(ZTS_ERR_SERVICE);
return zts_service->networkHasRoute(net_id, family); return zts_service->networkHasRoute(net_id, family);
} }
// Start a ZeroTier NodeService background thread // Start a ZeroTier NodeService background thread
@@ -483,211 +483,211 @@ void* _runNodeService(void* arg)
#endif #endif
{ {
#if defined(__APPLE__) #if defined(__APPLE__)
pthread_setname_np(ZTS_SERVICE_THREAD_NAME); pthread_setname_np(ZTS_SERVICE_THREAD_NAME);
#endif #endif
try { try {
zts_service->run(); zts_service->run();
// Begin shutdown // Begin shutdown
service_m.lock(); service_m.lock();
zts_events->clrState(ZTS_STATE_NODE_RUNNING); zts_events->clrState(ZTS_STATE_NODE_RUNNING);
delete zts_service; delete zts_service;
zts_service = (NodeService*)0; zts_service = (NodeService*)0;
service_m.unlock(); service_m.unlock();
events_m.lock(); events_m.lock();
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; delete zts_events;
zts_events = (Events*)0; zts_events = (Events*)0;
} }
events_m.unlock(); events_m.unlock();
} }
catch (...) { catch (...) {
} }
#ifndef __WINDOWS__ #ifndef __WINDOWS__
pthread_exit(0); pthread_exit(0);
#endif #endif
return NULL; return NULL;
} }
int zts_node_start() int zts_node_start()
{ {
ACQUIRE_SERVICE_OFFLINE(); ACQUIRE_SERVICE_OFFLINE();
// Start TCP/IP stack // Start TCP/IP stack
_lwip_driver_init(); _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()) {
#if defined(__WINDOWS__) #if defined(__WINDOWS__)
HANDLE callbackThread = CreateThread(NULL, 0, cbRun, NULL, 0, NULL); HANDLE callbackThread = CreateThread(NULL, 0, cbRun, NULL, 0, NULL);
// TODO: Check success // TODO: Check success
#else #else
pthread_t cbThread; pthread_t cbThread;
if ((res = pthread_create(&cbThread, NULL, cbRun, NULL)) != 0) {} if ((res = pthread_create(&cbThread, NULL, cbRun, NULL)) != 0) {}
#endif #endif
#if defined(__linux__) #if defined(__linux__)
pthread_setname_np(cbThread, ZTS_EVENT_CALLBACK_THREAD_NAME); pthread_setname_np(cbThread, ZTS_EVENT_CALLBACK_THREAD_NAME);
#endif #endif
if (res != ZTS_ERR_OK) { if (res != ZTS_ERR_OK) {
zts_events->clrState(ZTS_STATE_CALLBACKS_RUNNING); zts_events->clrState(ZTS_STATE_CALLBACKS_RUNNING);
zts_events->clrCallback(); zts_events->clrCallback();
} }
zts_events->setState(ZTS_STATE_CALLBACKS_RUNNING); zts_events->setState(ZTS_STATE_CALLBACKS_RUNNING);
} }
// Start ZeroTier service // Start ZeroTier service
#if defined(__WINDOWS__) #if defined(__WINDOWS__)
WSAStartup(MAKEWORD(2, 2), &wsaData); WSAStartup(MAKEWORD(2, 2), &wsaData);
HANDLE serviceThread = CreateThread(NULL, 0, _runNodeService, (void*)NULL, 0, NULL); HANDLE serviceThread = CreateThread(NULL, 0, _runNodeService, (void*)NULL, 0, NULL);
// TODO: Check success // TODO: Check success
#else #else
pthread_t service_thread; pthread_t service_thread;
if ((res = pthread_create(&service_thread, NULL, _runNodeService, (void*)NULL)) != 0) {} if ((res = pthread_create(&service_thread, NULL, _runNodeService, (void*)NULL)) != 0) {}
#endif #endif
#if defined(__linux__) #if defined(__linux__)
pthread_setname_np(service_thread, ZTS_SERVICE_THREAD_NAME); pthread_setname_np(service_thread, ZTS_SERVICE_THREAD_NAME);
#endif #endif
if (res != ZTS_ERR_OK) { if (res != ZTS_ERR_OK) {
zts_events->clrState(ZTS_STATE_NODE_RUNNING); zts_events->clrState(ZTS_STATE_NODE_RUNNING);
} }
zts_events->setState(ZTS_STATE_NODE_RUNNING); zts_events->setState(ZTS_STATE_NODE_RUNNING);
return ZTS_ERR_OK; return ZTS_ERR_OK;
} }
int zts_node_is_online() int zts_node_is_online()
{ {
ACQUIRE_SERVICE(0); ACQUIRE_SERVICE(0);
return zts_service->nodeIsOnline(); return zts_service->nodeIsOnline();
} }
uint64_t zts_node_get_id() uint64_t zts_node_get_id()
{ {
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); ACQUIRE_SERVICE(ZTS_ERR_SERVICE);
return zts_service->getNodeId(); return zts_service->getNodeId();
} }
int zts_node_get_port() int zts_node_get_port()
{ {
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); ACQUIRE_SERVICE(ZTS_ERR_SERVICE);
return zts_service->getPrimaryPort(); return zts_service->getPrimaryPort();
} }
int zts_node_stop() int zts_node_stop()
{ {
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); ACQUIRE_SERVICE(ZTS_ERR_SERVICE);
zts_events->clrState(ZTS_STATE_NODE_RUNNING); zts_events->clrState(ZTS_STATE_NODE_RUNNING);
zts_service->terminate(); zts_service->terminate();
#if defined(__WINDOWS__) #if defined(__WINDOWS__)
WSACleanup(); WSACleanup();
#endif #endif
return ZTS_ERR_OK; return ZTS_ERR_OK;
} }
int zts_node_free() int zts_node_free()
{ {
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); ACQUIRE_SERVICE(ZTS_ERR_SERVICE);
zts_events->setState(ZTS_STATE_FREE_CALLED); zts_events->setState(ZTS_STATE_FREE_CALLED);
zts_events->clrState(ZTS_STATE_NODE_RUNNING); zts_events->clrState(ZTS_STATE_NODE_RUNNING);
zts_service->terminate(); zts_service->terminate();
#if defined(__WINDOWS__) #if defined(__WINDOWS__)
WSACleanup(); WSACleanup();
#endif #endif
_lwip_driver_shutdown(); _lwip_driver_shutdown();
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_world_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_world_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_world_id)
{ {
ACQUIRE_SERVICE(ZTS_ERR_SERVICE); ACQUIRE_SERVICE(ZTS_ERR_SERVICE);
zts_service->deorbit(NULL, moon_world_id); zts_service->deorbit(NULL, moon_world_id);
return ZTS_ERR_OK; return ZTS_ERR_OK;
} }
int zts_stats_get_all(zts_stats_counter_t* dst) int zts_stats_get_all(zts_stats_counter_t* dst)
{ {
if (! dst) { if (! dst) {
return ZTS_ERR_ARG; return ZTS_ERR_ARG;
} }
if (! transport_ok()) { if (! transport_ok()) {
return ZTS_ERR_SERVICE; return ZTS_ERR_SERVICE;
} }
#if LWIP_STATS #if LWIP_STATS
extern struct stats_ lwip_stats; extern struct stats_ lwip_stats;
#define lws lwip_stats #define lws lwip_stats
/* Here we summarize lwIP's statistics for simplicity at the expense of specificity */ /* Here we 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;
dst->link_rx = lws.link.recv; dst->link_rx = lws.link.recv;
dst->link_drop = lws.link.drop; dst->link_drop = lws.link.drop;
dst->link_err = lws.link.chkerr + lws.link.lenerr + lws.link.memerr + lws.link.rterr + lws.link.proterr dst->link_err = lws.link.chkerr + lws.link.lenerr + lws.link.memerr + lws.link.rterr + lws.link.proterr
+ lws.link.opterr + lws.link.err; + lws.link.opterr + lws.link.err;
// etharp // etharp
dst->etharp_tx = lws.etharp.xmit; dst->etharp_tx = lws.etharp.xmit;
dst->etharp_rx = lws.etharp.recv; dst->etharp_rx = lws.etharp.recv;
dst->etharp_drop = lws.etharp.drop; dst->etharp_drop = lws.etharp.drop;
dst->etharp_err = lws.etharp.chkerr + lws.etharp.lenerr + lws.etharp.memerr + lws.etharp.rterr + lws.etharp.proterr dst->etharp_err = lws.etharp.chkerr + lws.etharp.lenerr + lws.etharp.memerr + lws.etharp.rterr + lws.etharp.proterr
+ lws.etharp.opterr + lws.etharp.err; + lws.etharp.opterr + lws.etharp.err;
// ip4 // ip4
dst->ip4_tx = lws.ip.xmit; dst->ip4_tx = lws.ip.xmit;
dst->ip4_rx = lws.ip.recv; dst->ip4_rx = lws.ip.recv;
dst->ip4_drop = lws.ip.drop; 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 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.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; + lws.ip_frag.proterr + lws.ip_frag.opterr + lws.ip_frag.err;
// ip6 // ip6
dst->ip6_tx = lws.ip6.xmit; dst->ip6_tx = lws.ip6.xmit;
dst->ip6_rx = lws.ip6.recv; dst->ip6_rx = lws.ip6.recv;
dst->ip6_drop = lws.ip6.drop; 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 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.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; + lws.ip6_frag.proterr + lws.ip6_frag.opterr + lws.ip6_frag.err;
// icmp4 // icmp4
dst->icmp4_tx = lws.icmp.xmit; dst->icmp4_tx = lws.icmp.xmit;
dst->icmp4_rx = lws.icmp.recv; dst->icmp4_rx = lws.icmp.recv;
dst->icmp4_drop = lws.icmp.drop; dst->icmp4_drop = lws.icmp.drop;
dst->icmp4_err = lws.icmp.chkerr + lws.icmp.lenerr + lws.icmp.memerr + lws.icmp.rterr + lws.icmp.proterr dst->icmp4_err = lws.icmp.chkerr + lws.icmp.lenerr + lws.icmp.memerr + lws.icmp.rterr + lws.icmp.proterr
+ lws.icmp.opterr + lws.icmp.err; + lws.icmp.opterr + lws.icmp.err;
// icmp6 // icmp6
dst->icmp6_tx = lws.icmp6.xmit; dst->icmp6_tx = lws.icmp6.xmit;
dst->icmp6_rx = lws.icmp6.recv; dst->icmp6_rx = lws.icmp6.recv;
dst->icmp6_drop = lws.icmp6.drop; dst->icmp6_drop = lws.icmp6.drop;
dst->icmp6_err = lws.icmp6.chkerr + lws.icmp6.lenerr + lws.icmp6.memerr + lws.icmp6.rterr + lws.icmp6.proterr dst->icmp6_err = lws.icmp6.chkerr + lws.icmp6.lenerr + lws.icmp6.memerr + lws.icmp6.rterr + lws.icmp6.proterr
+ lws.icmp6.opterr + lws.icmp6.err; + lws.icmp6.opterr + lws.icmp6.err;
// udp // udp
dst->udp_tx = lws.udp.xmit; dst->udp_tx = lws.udp.xmit;
dst->udp_rx = lws.udp.recv; dst->udp_rx = lws.udp.recv;
dst->udp_drop = lws.udp.drop; 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 dst->udp_err = lws.udp.chkerr + lws.udp.lenerr + lws.udp.memerr + lws.udp.rterr + lws.udp.proterr + lws.udp.opterr
+ lws.udp.err; + lws.udp.err;
// tcp // tcp
dst->tcp_tx = lws.tcp.xmit; dst->tcp_tx = lws.tcp.xmit;
dst->tcp_rx = lws.tcp.recv; dst->tcp_rx = lws.tcp.recv;
dst->tcp_drop = lws.tcp.drop; 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 dst->tcp_err = lws.tcp.chkerr + lws.tcp.lenerr + lws.tcp.memerr + lws.tcp.rterr + lws.tcp.proterr + lws.tcp.opterr
+ lws.tcp.err; + lws.tcp.err;
// nd6 // nd6
dst->nd6_tx = lws.nd6.xmit; dst->nd6_tx = lws.nd6.xmit;
dst->nd6_rx = lws.nd6.recv; dst->nd6_rx = lws.nd6.recv;
dst->nd6_drop = lws.nd6.drop; 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 dst->nd6_err = lws.nd6.chkerr + lws.nd6.lenerr + lws.nd6.memerr + lws.nd6.rterr + lws.nd6.proterr + lws.nd6.opterr
+ lws.nd6.err; + lws.nd6.err;
// TODO: Add mem and sys stats // TODO: Add mem and sys stats
return ZTS_ERR_OK; return ZTS_ERR_OK;
#else #else
return ZTS_ERR_NO_RESULT; return ZTS_ERR_NO_RESULT;
#endif #endif
#undef lws #undef lws
} }

View File

@@ -62,20 +62,20 @@
#if defined(LIBZT_DEBUG) #if defined(LIBZT_DEBUG)
#if defined(__ANDROID__) #if defined(__ANDROID__)
#define DEBUG_INFO(fmt, args...) \ #define DEBUG_INFO(fmt, args...) \
((void)__android_log_print( \ ((void)__android_log_print( \
ANDROID_LOG_VERBOSE, \ ANDROID_LOG_VERBOSE, \
ZT_LOG_TAG, \ ZT_LOG_TAG, \
"%17s:%5d:%20s: " fmt "\n", \ "%17s:%5d:%20s: " fmt "\n", \
ZT_FILENAME, \ ZT_FILENAME, \
__LINE__, \ __LINE__, \
__FUNCTION__, \ __FUNCTION__, \
##args)) ##args))
#elif defined(_WIN32) #elif defined(_WIN32)
#define DEBUG_INFO(fmt, ...) \ #define DEBUG_INFO(fmt, ...) \
fprintf(stderr, ZT_WHT "%17s:%5d:%25s: " fmt "\n" ZT_RESET, ZT_FILENAME, __LINE__, __FUNCTION__, __VA_ARGS__) fprintf(stderr, ZT_WHT "%17s:%5d:%25s: " fmt "\n" ZT_RESET, ZT_FILENAME, __LINE__, __FUNCTION__, __VA_ARGS__)
#else #else
#define DEBUG_INFO(fmt, args...) \ #define DEBUG_INFO(fmt, args...) \
fprintf(stderr, ZT_WHT "%17s:%5d:%25s: " fmt "\n" ZT_RESET, ZT_FILENAME, __LINE__, __FUNCTION__, ##args) fprintf(stderr, ZT_WHT "%17s:%5d:%25s: " fmt "\n" ZT_RESET, ZT_FILENAME, __LINE__, __FUNCTION__, ##args)
#endif #endif
#else // !LIBZT_DEBUG #else // !LIBZT_DEBUG
#if defined(_WIN32) #if defined(_WIN32)

View File

@@ -75,218 +75,218 @@ moodycamel::ConcurrentQueue<zts_event_msg_t*> _callbackMsgQueue;
void Events::run() void Events::run()
{ {
while (getState(ZTS_STATE_CALLBACKS_RUNNING) || _callbackMsgQueue.size_approx() > 0) { while (getState(ZTS_STATE_CALLBACKS_RUNNING) || _callbackMsgQueue.size_approx() > 0) {
zts_event_msg_t* msg; zts_event_msg_t* msg;
size_t sz = _callbackMsgQueue.size_approx(); size_t sz = _callbackMsgQueue.size_approx();
for (size_t j = 0; j < sz; j++) { for (size_t j = 0; j < sz; j++) {
if (_callbackMsgQueue.try_dequeue(msg)) { if (_callbackMsgQueue.try_dequeue(msg)) {
events_m.lock(); events_m.lock();
sendToUser(msg); sendToUser(msg);
events_m.unlock(); events_m.unlock();
} }
} }
zts_util_delay(ZTS_CALLBACK_PROCESSING_INTERVAL); zts_util_delay(ZTS_CALLBACK_PROCESSING_INTERVAL);
} }
} }
void Events::enqueue(unsigned int event_code, const void* arg, int len) void Events::enqueue(unsigned int event_code, const void* arg, int len)
{ {
if (! _enabled) { if (! _enabled) {
return; return;
} }
zts_event_msg_t* msg = new zts_event_msg_t(); zts_event_msg_t* msg = new zts_event_msg_t();
msg->event_code = event_code; msg->event_code = event_code;
if (ZTS_NODE_EVENT(event_code)) { if (ZTS_NODE_EVENT(event_code)) {
msg->node = (zts_node_info_t*)arg; msg->node = (zts_node_info_t*)arg;
msg->len = sizeof(zts_node_info_t); msg->len = sizeof(zts_node_info_t);
} }
if (ZTS_NETWORK_EVENT(event_code)) { if (ZTS_NETWORK_EVENT(event_code)) {
msg->network = (zts_net_info_t*)arg; msg->network = (zts_net_info_t*)arg;
msg->len = sizeof(zts_net_info_t); msg->len = sizeof(zts_net_info_t);
} }
if (ZTS_STACK_EVENT(event_code)) { if (ZTS_STACK_EVENT(event_code)) {
/* nothing to convey to user */ /* nothing to convey to user */
} }
if (ZTS_NETIF_EVENT(event_code)) { if (ZTS_NETIF_EVENT(event_code)) {
msg->netif = (zts_netif_info_t*)arg; msg->netif = (zts_netif_info_t*)arg;
msg->len = sizeof(zts_netif_info_t); msg->len = sizeof(zts_netif_info_t);
} }
if (ZTS_ROUTE_EVENT(event_code)) { if (ZTS_ROUTE_EVENT(event_code)) {
msg->route = (zts_route_info_t*)arg; msg->route = (zts_route_info_t*)arg;
msg->len = sizeof(zts_route_info_t); msg->len = sizeof(zts_route_info_t);
} }
if (ZTS_PEER_EVENT(event_code)) { if (ZTS_PEER_EVENT(event_code)) {
msg->peer = (zts_peer_info_t*)arg; msg->peer = (zts_peer_info_t*)arg;
msg->len = sizeof(zts_peer_info_t); msg->len = sizeof(zts_peer_info_t);
} }
if (ZTS_ADDR_EVENT(event_code)) { if (ZTS_ADDR_EVENT(event_code)) {
msg->addr = (zts_addr_info_t*)arg; msg->addr = (zts_addr_info_t*)arg;
msg->len = sizeof(zts_addr_info_t); msg->len = sizeof(zts_addr_info_t);
} }
if (ZTS_STORE_EVENT(event_code)) { if (ZTS_STORE_EVENT(event_code)) {
msg->cache = (void*)arg; msg->cache = (void*)arg;
msg->len = len; msg->len = len;
} }
if (msg && _callbackMsgQueue.size_approx() > 1024) { if (msg && _callbackMsgQueue.size_approx() > 1024) {
/* Rate-limit number of events. This value should only grow if the /* 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. user application isn't returning from the event handler in a timely manner.
For most applications it should hover around 1 to 2 */ For most applications it should hover around 1 to 2 */
destroy(msg); destroy(msg);
} }
else { else {
_callbackMsgQueue.enqueue(msg); _callbackMsgQueue.enqueue(msg);
} }
} }
void Events::destroy(zts_event_msg_t* msg) void Events::destroy(zts_event_msg_t* msg)
{ {
if (! msg) { if (! msg) {
return; return;
} }
if (msg->node) { if (msg->node) {
delete msg->node; delete msg->node;
} }
if (msg->network) { if (msg->network) {
delete msg->network; delete msg->network;
} }
if (msg->netif) { if (msg->netif) {
delete msg->netif; delete msg->netif;
} }
if (msg->route) { if (msg->route) {
delete msg->route; delete msg->route;
} }
if (msg->peer) { if (msg->peer) {
delete msg->peer; delete msg->peer;
} }
if (msg->addr) { if (msg->addr) {
delete msg->addr; delete msg->addr;
} }
delete msg; delete msg;
msg = NULL; msg = NULL;
} }
void Events::sendToUser(zts_event_msg_t* msg) void Events::sendToUser(zts_event_msg_t* msg)
{ {
bool bShouldStopCallbackThread = (msg->event_code == ZTS_EVENT_STACK_DOWN); bool bShouldStopCallbackThread = (msg->event_code == ZTS_EVENT_STACK_DOWN);
#ifdef ZTS_ENABLE_PYTHON #ifdef ZTS_ENABLE_PYTHON
PyGILState_STATE state = PyGILState_Ensure(); PyGILState_STATE state = PyGILState_Ensure();
_userEventCallback->on_zerotier_event(msg); _userEventCallback->on_zerotier_event(msg);
PyGILState_Release(state); PyGILState_Release(state);
#endif #endif
#ifdef ZTS_ENABLE_JAVA #ifdef ZTS_ENABLE_JAVA
if (_userCallbackMethodRef) { if (_userCallbackMethodRef) {
JNIEnv* env; JNIEnv* env;
#if defined(__ANDROID__) #if defined(__ANDROID__)
jint rs = jvm->AttachCurrentThread(&env, NULL); jint rs = jvm->AttachCurrentThread(&env, NULL);
#else #else
jint rs = jvm->AttachCurrentThread((void**)&env, NULL); jint rs = jvm->AttachCurrentThread((void**)&env, NULL);
#endif #endif
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->address : 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->nwid : 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->address : 0;
} }
env->CallVoidMethod(objRef, _userCallbackMethodRef, id, msg->event_code); env->CallVoidMethod(objRef, _userCallbackMethodRef, id, msg->event_code);
} }
#endif // ZTS_ENABLE_JAVA #endif // ZTS_ENABLE_JAVA
#ifdef ZTS_ENABLE_PINVOKE #ifdef ZTS_ENABLE_PINVOKE
if (_userEventCallback) { if (_userEventCallback) {
_userEventCallback(msg); _userEventCallback(msg);
} }
#endif #endif
#ifdef ZTS_C_API_ONLY #ifdef ZTS_C_API_ONLY
if (_userEventCallback) { if (_userEventCallback) {
_userEventCallback(msg); _userEventCallback(msg);
} }
#endif #endif
destroy(msg); destroy(msg);
if (bShouldStopCallbackThread) { if (bShouldStopCallbackThread) {
/* Ensure last possible callback ZTS_EVENT_STACK_DOWN is /* Ensure last possible callback ZTS_EVENT_STACK_DOWN is
delivered before callback thread is finally stopped. */ delivered before callback thread is finally stopped. */
clrState(ZTS_STATE_CALLBACKS_RUNNING); clrState(ZTS_STATE_CALLBACKS_RUNNING);
} }
} }
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 && objRef && _userCallbackMethodRef);
#else #else
retval = _userEventCallback; retval = _userEventCallback;
#endif #endif
events_m.unlock(); events_m.unlock();
return retval; return retval;
} }
void Events::clrCallback() void Events::clrCallback()
{ {
events_m.lock(); events_m.lock();
#ifdef ZTS_ENABLE_JAVA #ifdef ZTS_ENABLE_JAVA
objRef = NULL; objRef = NULL;
_userCallbackMethodRef = NULL; _userCallbackMethodRef = NULL;
#else #else
_userEventCallback = NULL; _userEventCallback = NULL;
#endif #endif
events_m.unlock(); events_m.unlock();
} }
int Events::canPerformServiceOperation() int Events::canPerformServiceOperation()
{ {
return zts_service && zts_service->isRunning() && ! getState(ZTS_STATE_FREE_CALLED); return zts_service && zts_service->isRunning() && ! getState(ZTS_STATE_FREE_CALLED);
} }
void Events::setState(uint8_t newFlags) void Events::setState(uint8_t newFlags)
{ {
if ((newFlags ^ service_state) & ZTS_STATE_NET_SERVICE_RUNNING) { if ((newFlags ^ service_state) & ZTS_STATE_NET_SERVICE_RUNNING) {
return; // No effect. Not allowed to set this flag manually return; // No effect. Not allowed to set this flag manually
} }
SET_FLAGS(newFlags); SET_FLAGS(newFlags);
if (GET_FLAGS(ZTS_STATE_NODE_RUNNING) && GET_FLAGS(ZTS_STATE_STACK_RUNNING) if (GET_FLAGS(ZTS_STATE_NODE_RUNNING) && GET_FLAGS(ZTS_STATE_STACK_RUNNING)
&& ! (GET_FLAGS(ZTS_STATE_FREE_CALLED))) { && ! (GET_FLAGS(ZTS_STATE_FREE_CALLED))) {
SET_FLAGS(ZTS_STATE_NET_SERVICE_RUNNING); SET_FLAGS(ZTS_STATE_NET_SERVICE_RUNNING);
} }
else { else {
CLR_FLAGS(ZTS_STATE_NET_SERVICE_RUNNING); CLR_FLAGS(ZTS_STATE_NET_SERVICE_RUNNING);
} }
} }
void Events::clrState(uint8_t newFlags) void Events::clrState(uint8_t newFlags)
{ {
if (newFlags & ZTS_STATE_NET_SERVICE_RUNNING) { if (newFlags & ZTS_STATE_NET_SERVICE_RUNNING) {
return; // No effect. Not allowed to set this flag manually return; // No effect. Not allowed to set this flag manually
} }
CLR_FLAGS(newFlags); CLR_FLAGS(newFlags);
if (GET_FLAGS(ZTS_STATE_NODE_RUNNING) && GET_FLAGS(ZTS_STATE_STACK_RUNNING) if (GET_FLAGS(ZTS_STATE_NODE_RUNNING) && GET_FLAGS(ZTS_STATE_STACK_RUNNING)
&& ! (GET_FLAGS(ZTS_STATE_FREE_CALLED))) { && ! (GET_FLAGS(ZTS_STATE_FREE_CALLED))) {
SET_FLAGS(ZTS_STATE_NET_SERVICE_RUNNING); SET_FLAGS(ZTS_STATE_NET_SERVICE_RUNNING);
} }
else { else {
CLR_FLAGS(ZTS_STATE_NET_SERVICE_RUNNING); CLR_FLAGS(ZTS_STATE_NET_SERVICE_RUNNING);
} }
} }
bool Events::getState(uint8_t testFlags) bool Events::getState(uint8_t testFlags)
{ {
return testFlags & service_state; return testFlags & service_state;
} }
void Events::enable() void Events::enable()
{ {
_enabled = true; _enabled = true;
} }
void Events::disable() void Events::disable()
{ {
_enabled = false; _enabled = false;
} }
} // namespace ZeroTier } // namespace ZeroTier

View File

@@ -34,33 +34,33 @@
// Lock service and check that it is running // Lock service and check that it is running
#define ACQUIRE_SERVICE(x) \ #define ACQUIRE_SERVICE(x) \
Mutex::Lock _ls(service_m); \ Mutex::Lock _ls(service_m); \
if (! zts_service || ! zts_service->isRunning()) { \ if (! zts_service || ! zts_service->isRunning()) { \
return x; \ return x; \
} }
// Lock service and check that it is not currently running // Lock service and check that it is not currently running
#define ACQUIRE_SERVICE_OFFLINE() \ #define ACQUIRE_SERVICE_OFFLINE() \
Mutex::Lock _ls(service_m); \ Mutex::Lock _ls(service_m); \
if (zts_service && zts_service->isRunning()) { \ if (zts_service && zts_service->isRunning()) { \
return ZTS_ERR_SERVICE; \ return ZTS_ERR_SERVICE; \
} \ } \
if (! zts_service) { \ if (! zts_service) { \
init_subsystems(); \ init_subsystems(); \
} }
// Unlock service // Unlock service
#define RELEASE_SERVICE() service_m.unlock(); #define RELEASE_SERVICE() service_m.unlock();
// Lock service, ensure node is online // Lock service, ensure node is online
#define ACQUIRE_ONLINE_NODE() \ #define ACQUIRE_ONLINE_NODE() \
ACQUIRE_SERVICE() if (! zts_service->nodeIsOnline()) \ ACQUIRE_SERVICE() if (! zts_service->nodeIsOnline()) \
{ \ { \
return ZTS_ERR_SERVICE; \ return ZTS_ERR_SERVICE; \
} }
// Lock event callback // Lock event callback
#define ACQUIRE_EVENTS() \ #define ACQUIRE_EVENTS() \
Mutex::Lock _lc(events_m); \ Mutex::Lock _lc(events_m); \
if (! zts_events) { \ if (! zts_events) { \
return ZTS_ERR_SERVICE; \ return ZTS_ERR_SERVICE; \
} }
namespace ZeroTier { namespace ZeroTier {
@@ -83,8 +83,8 @@ extern int last_state_check;
inline int transport_ok() inline int transport_ok()
{ {
last_state_check = service_state & ZTS_STATE_NET_SERVICE_RUNNING; last_state_check = service_state & ZTS_STATE_NET_SERVICE_RUNNING;
return last_state_check; return last_state_check;
} }
/** /**
@@ -93,72 +93,72 @@ inline int transport_ok()
#define ZTS_CALLBACK_PROCESSING_INTERVAL 25 #define ZTS_CALLBACK_PROCESSING_INTERVAL 25
class Events { class Events {
bool _enabled; bool _enabled;
public: public:
Events() : _enabled(false) Events() : _enabled(false)
{ {
} }
/** /**
* Perform one iteration of callback processing * Perform one iteration of callback processing
*/ */
void run(); void run();
/** /**
* Enable callback event processing * Enable callback event processing
*/ */
void enable(); void enable();
/** /**
* Disable callback event processing * Disable callback event processing
*/ */
void disable(); void disable();
/** /**
* Enqueue an event to be sent to the user application * Enqueue an event to be sent to the user application
*/ */
void enqueue(unsigned int 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 * Send callback message to user application
*/ */
void sendToUser(zts_event_msg_t* msg); void sendToUser(zts_event_msg_t* msg);
/** /**
* Free memory occupied by callback structures * Free memory occupied by callback structures
*/ */
void destroy(zts_event_msg_t* msg); void destroy(zts_event_msg_t* msg);
/** /**
* Return whether a callback method has been set * Return whether a callback method has been set
*/ */
bool hasCallback(); bool hasCallback();
/** /**
* Clear pointer reference to user-provided callback function * Clear pointer reference to user-provided callback function
*/ */
void clrCallback(); void clrCallback();
/** /**
* Return whether service operation can be performed at this time * Return whether service operation can be performed at this time
*/ */
int canPerformServiceOperation(); int canPerformServiceOperation();
/** /**
* Set internal state flags * Set internal state flags
*/ */
void setState(uint8_t newFlags); void setState(uint8_t newFlags);
/** /**
* Clear internal state flags * Clear internal state flags
*/ */
void clrState(uint8_t newFlags); void clrState(uint8_t newFlags);
/** /**
* Get internal state flags * Get internal state flags
*/ */
bool getState(uint8_t testFlags); bool getState(uint8_t testFlags);
}; };
} // namespace ZeroTier } // namespace ZeroTier

File diff suppressed because it is too large Load Diff

View File

@@ -55,412 +55,412 @@ namespace ZeroTier {
*/ */
class NodeService { class NodeService {
public: public:
/** /**
* Returned by node main if/when it terminates * Returned by node main if/when it terminates
*/ */
enum ReasonForTermination { enum ReasonForTermination {
/** /**
* Instance is still running * Instance is still running
*/ */
ONE_STILL_RUNNING = 0, ONE_STILL_RUNNING = 0,
/** /**
* Normal shutdown * Normal shutdown
*/ */
ONE_NORMAL_TERMINATION = 1, ONE_NORMAL_TERMINATION = 1,
/** /**
* A serious unrecoverable error has occurred * A serious unrecoverable error has occurred
*/ */
ONE_UNRECOVERABLE_ERROR = 2, ONE_UNRECOVERABLE_ERROR = 2,
/** /**
* Your identity has collided with another * Your identity has collided with another
*/ */
ONE_IDENTITY_COLLISION = 3 ONE_IDENTITY_COLLISION = 3
}; };
/** /**
* Local settings for each network * Local settings for each network
*/ */
struct NetworkSettings { struct NetworkSettings {
/** /**
* Allow this network to configure IP addresses and routes? * Allow this network to configure IP addresses and routes?
*/ */
bool allowManaged; bool allowManaged;
/** /**
* Whitelist of addresses that can be configured by this network. * Whitelist of addresses that can be configured by this network.
* If empty and allowManaged is true, allow all * If empty and allowManaged is true, allow all
* private/pseudoprivate addresses. * private/pseudoprivate addresses.
*/ */
std::vector<InetAddress> allowManagedWhitelist; std::vector<InetAddress> allowManagedWhitelist;
/** /**
* Allow configuration of IPs and routes within global (Internet) IP * Allow configuration of IPs and routes within global (Internet) IP
* space? * space?
*/ */
bool allowGlobal; bool allowGlobal;
/** /**
* Allow overriding of system default routes for "full tunnel" * Allow overriding of system default routes for "full tunnel"
* operation? * operation?
*/ */
bool allowDefault; bool allowDefault;
}; };
Phy<NodeService*> _phy; Phy<NodeService*> _phy;
Node* _node; Node* _node;
unsigned int _primaryPort = 0; unsigned int _primaryPort = 0;
unsigned int _secondaryPort = 0; unsigned int _secondaryPort = 0;
unsigned int _tertiaryPort = 0; unsigned int _tertiaryPort = 0;
volatile unsigned int _udpPortPickerCounter; volatile unsigned int _udpPortPickerCounter;
std::map<uint64_t, unsigned int> peerCache; std::map<uint64_t, unsigned int> peerCache;
// Local configuration and memo-ized information from it // Local configuration and memo-ized information from it
Hashtable<uint64_t, std::vector<InetAddress> > _v4Hints; Hashtable<uint64_t, std::vector<InetAddress> > _v4Hints;
Hashtable<uint64_t, std::vector<InetAddress> > _v6Hints; Hashtable<uint64_t, std::vector<InetAddress> > _v6Hints;
Hashtable<uint64_t, std::vector<InetAddress> > _v4Blacklists; Hashtable<uint64_t, std::vector<InetAddress> > _v4Blacklists;
Hashtable<uint64_t, std::vector<InetAddress> > _v6Blacklists; Hashtable<uint64_t, std::vector<InetAddress> > _v6Blacklists;
std::vector<InetAddress> _globalV4Blacklist; std::vector<InetAddress> _globalV4Blacklist;
std::vector<InetAddress> _globalV6Blacklist; std::vector<InetAddress> _globalV6Blacklist;
std::vector<InetAddress> _allowManagementFrom; std::vector<InetAddress> _allowManagementFrom;
std::vector<std::string> _interfacePrefixBlacklist; std::vector<std::string> _interfacePrefixBlacklist;
Mutex _localConfig_m; Mutex _localConfig_m;
std::vector<InetAddress> explicitBind; std::vector<InetAddress> explicitBind;
/* /*
* To attempt to handle NAT/gateway craziness we use three local UDP * To attempt to handle NAT/gateway craziness we use three local UDP
* ports: * ports:
* *
* [0] is the normal/default port, usually 9993 * [0] is the normal/default port, usually 9993
* [1] is a port derived from our ZeroTier address * [1] is a port derived from our ZeroTier address
* [2] is a port computed from the normal/default for use with * [2] is a port computed from the normal/default for use with
* uPnP/NAT-PMP mappings * uPnP/NAT-PMP mappings
* *
* [2] exists because on some gateways trying to do regular NAT-t * [2] exists because on some gateways trying to do regular NAT-t
* interferes destructively with uPnP port mapping behavior in very * interferes destructively with uPnP port mapping behavior in very
* weird buggy ways. It's only used if uPnP/NAT-PMP is enabled in this * weird buggy ways. It's only used if uPnP/NAT-PMP is enabled in this
* build. * build.
*/ */
unsigned int _ports[3] = { 0 }; unsigned int _ports[3] = { 0 };
Binder _binder; Binder _binder;
// Time we last received a packet from a global address // Time we last received a packet from a global address
uint64_t _lastDirectReceiveFromGlobal; uint64_t _lastDirectReceiveFromGlobal;
// Last potential sleep/wake event // Last potential sleep/wake event
uint64_t _lastRestart; uint64_t _lastRestart;
// Deadline for the next background task service function // Deadline for the next background task service function
volatile int64_t _nextBackgroundTaskDeadline; volatile int64_t _nextBackgroundTaskDeadline;
// Configured networks // Configured networks
struct NetworkState { struct NetworkState {
NetworkState() : tap((VirtualTap*)0) NetworkState() : tap((VirtualTap*)0)
{ {
// Real defaults are in network 'up' code in network event // Real defaults are in network 'up' code in network event
// handler // handler
settings.allowManaged = true; settings.allowManaged = true;
settings.allowGlobal = false; settings.allowGlobal = false;
settings.allowDefault = false; settings.allowDefault = false;
} }
VirtualTap* tap; VirtualTap* tap;
ZT_VirtualNetworkConfig config; // memcpy() of raw config from core ZT_VirtualNetworkConfig config; // memcpy() of raw config from core
std::vector<InetAddress> managedIps; std::vector<InetAddress> managedIps;
NetworkSettings settings; NetworkSettings settings;
}; };
std::map<uint64_t, NetworkState> _nets; std::map<uint64_t, NetworkState> _nets;
/** Lock to control access to network configuration data */ /** Lock to control access to network configuration data */
Mutex _nets_m; Mutex _nets_m;
/** Lock to control access to storage data */ /** Lock to control access to storage data */
Mutex _store_m; Mutex _store_m;
/** Lock to control access to service run state */ /** Lock to control access to service run state */
Mutex _run_m; Mutex _run_m;
// Set to false to force service to stop // Set to false to force service to stop
volatile bool _run; volatile bool _run;
/** Lock to control access to termination reason */ /** Lock to control access to termination reason */
Mutex _termReason_m; Mutex _termReason_m;
// Termination status information // Termination status information
ReasonForTermination _termReason; ReasonForTermination _termReason;
std::string _fatalErrorMessage; std::string _fatalErrorMessage;
// uPnP/NAT-PMP port mapper if enabled // uPnP/NAT-PMP port mapper if enabled
bool _portMappingEnabled; // local.conf settings bool _portMappingEnabled; // local.conf settings
#ifdef ZT_USE_MINIUPNPC #ifdef ZT_USE_MINIUPNPC
PortMapper* _portMapper; PortMapper* _portMapper;
#endif #endif
uint8_t _allowNetworkCaching; uint8_t _allowNetworkCaching;
uint8_t _allowPeerCaching; uint8_t _allowPeerCaching;
uint8_t _allowIdentityCaching; uint8_t _allowIdentityCaching;
uint8_t _allowWorldCaching; uint8_t _allowWorldCaching;
char _publicIdStr[ZT_IDENTITY_STRING_BUFFER_LENGTH] = { 0 }; char _publicIdStr[ZT_IDENTITY_STRING_BUFFER_LENGTH] = { 0 };
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 _worldData[ZTS_STORE_DATA_LEN] = { 0 };
int _worldDataLen = 0; int _worldDataLen = 0;
/** Whether the node has successfully come online */ /** Whether the node has successfully come online */
bool _nodeIsOnline; bool _nodeIsOnline;
/** Whether we allow the NodeService to generate events for the user */ /** Whether we allow the NodeService to generate events for the user */
bool _eventsEnabled; bool _eventsEnabled;
/** Storage path defined by the user */ /** Storage path defined by the user */
std::string _homePath; std::string _homePath;
/** System to ingest events from this class and emit them to the user */ /** System to ingest events from this class and emit them to the user */
Events* _events; Events* _events;
NodeService(); NodeService();
~NodeService(); ~NodeService();
/** Main service loop */ /** Main service loop */
ReasonForTermination run(); ReasonForTermination run();
ReasonForTermination reasonForTermination() const; ReasonForTermination reasonForTermination() const;
std::string fatalErrorMessage() const; std::string fatalErrorMessage() const;
/** Stop the node and service */ /** Stop the node and service */
void terminate(); void terminate();
/** Apply or update managed IPs for a configured network */ /** Apply or update managed IPs for a configured network */
void syncManagedStuff(NetworkState& n); void syncManagedStuff(NetworkState& n);
void phyOnDatagram( void phyOnDatagram(
PhySocket* sock, PhySocket* sock,
void** uptr, void** uptr,
const struct sockaddr* localAddr, const struct sockaddr* localAddr,
const struct sockaddr* from, const struct sockaddr* from,
void* data, void* data,
unsigned long len); unsigned long len);
int nodeVirtualNetworkConfigFunction( int nodeVirtualNetworkConfigFunction(
uint64_t net_id, uint64_t net_id,
void** nuptr, void** nuptr,
enum ZT_VirtualNetworkConfigOperation op, enum ZT_VirtualNetworkConfigOperation op,
const ZT_VirtualNetworkConfig* nwc); const ZT_VirtualNetworkConfig* nwc);
void nodeEventCallback(enum ZT_Event event, const void* metaData); void nodeEventCallback(enum ZT_Event event, const void* metaData);
zts_net_info_t* prepare_network_details_msg(const NetworkState& n); zts_net_info_t* prepare_network_details_msg(const NetworkState& n);
void generateEventMsgs(); void generateEventMsgs();
void sendEventToUser(unsigned int event_code, const void* arg, unsigned int len = 0); void sendEventToUser(unsigned int event_code, const void* arg, unsigned int len = 0);
/** Join a network */ /** Join a network */
int join(uint64_t net_id); int join(uint64_t net_id);
/** Leave a network */ /** Leave a network */
int leave(uint64_t net_id); int leave(uint64_t net_id);
/** Return whether the network is ready for transport services */ /** Return whether the network is ready for transport services */
bool networkIsReady(uint64_t net_id) const; bool networkIsReady(uint64_t net_id) const;
/** Lock the service so we can perform queries */ /** Lock the service so we can perform queries */
void obtainLock() const; void obtainLock() const;
/** Unlock the service */ /** Unlock the service */
void releaseLock() const; void releaseLock() const;
/** Return number of assigned addresses on the network. Service must be locked. */ /** Return number of assigned addresses on the network. Service must be locked. */
int addressCount(uint64_t net_id) const; int addressCount(uint64_t net_id) const;
/** Return number of managed routes on the network. Service must be locked. */ /** Return number of managed routes on the network. Service must be locked. */
int routeCount(uint64_t net_id) const; int routeCount(uint64_t net_id) const;
/** Return number of multicast subscriptions on the network. Service must be locked. */ /** Return number of multicast subscriptions on the network. Service must be locked. */
int multicastSubCount(uint64_t net_id) const; int multicastSubCount(uint64_t net_id) const;
/** Return number of known physical paths to the peer. Service must be locked. */ /** Return number of known physical paths to the peer. Service must be locked. */
int pathCount(uint64_t peer_id) const; int pathCount(uint64_t peer_id) const;
int getAddrAtIdx(uint64_t net_id, unsigned int idx, char* dst, unsigned int len); int getAddrAtIdx(uint64_t net_id, unsigned int idx, char* dst, unsigned int len);
int getRouteAtIdx( int getRouteAtIdx(
uint64_t net_id, uint64_t net_id,
unsigned int idx, unsigned int idx,
char* target, char* target,
char* via, char* via,
unsigned int len, unsigned int len,
uint16_t* flags, uint16_t* flags,
uint16_t* metric); uint16_t* metric);
int getMulticastSubAtIdx(uint64_t net_id, unsigned int idx, uint64_t* mac, uint32_t* adi); 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); int getPathAtIdx(uint64_t peer_id, unsigned int idx, char* path, unsigned int len);
/** Orbit a moon */ /** Orbit a moon */
int orbit(void* tptr, uint64_t moonWorldId, uint64_t moonSeed); int orbit(void* tptr, uint64_t moonWorldId, uint64_t moonSeed);
/** De-orbit a moon */ /** De-orbit a moon */
int deorbit(void* tptr, uint64_t moonWorldId); int deorbit(void* tptr, uint64_t moonWorldId);
/** Return the integer-form of the node's identity */ /** Return the integer-form of the node's identity */
uint64_t getNodeId(); uint64_t getNodeId();
/** Gets the node's identity */ /** Gets the node's identity */
int getIdentity(char* keypair, unsigned int* len); int getIdentity(char* keypair, unsigned int* len);
/** Set the node's identity */ /** Set the node's identity */
int setIdentity(const char* keypair, unsigned int len); int setIdentity(const char* keypair, unsigned int len);
void nodeStatePutFunction(enum ZT_StateObjectType type, const uint64_t id[2], const void* data, unsigned 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( int nodeWirePacketSendFunction(
const int64_t localSocket, const int64_t localSocket,
const struct sockaddr_storage* addr, const struct sockaddr_storage* addr,
const void* data, const void* data,
unsigned int len, unsigned int len,
unsigned int ttl); unsigned int ttl);
void nodeVirtualNetworkFrameFunction( void nodeVirtualNetworkFrameFunction(
uint64_t net_id, uint64_t net_id,
void** nuptr, void** nuptr,
uint64_t sourceMac, uint64_t sourceMac,
uint64_t destMac, uint64_t destMac,
unsigned int etherType, unsigned int etherType,
unsigned int vlanId, unsigned int vlanId,
const void* data, const void* data,
unsigned int len); 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, unsigned int family, struct sockaddr_storage* result); int nodePathLookupFunction(uint64_t ztaddr, unsigned int family, struct sockaddr_storage* result);
void tapFrameHandler( void tapFrameHandler(
uint64_t net_id, uint64_t net_id,
const MAC& from, const MAC& from,
const MAC& to, const MAC& to,
unsigned int etherType, unsigned int etherType,
unsigned int vlanId, unsigned int vlanId,
const void* data, const void* data,
unsigned int len); unsigned int len);
int shouldBindInterface(const char* ifname, const InetAddress& ifaddr); int shouldBindInterface(const char* ifname, const InetAddress& ifaddr);
int _trialBind(unsigned int port); int _trialBind(unsigned int port);
/** Return whether the NodeService is running */ /** Return whether the NodeService is running */
int isRunning() const; int isRunning() const;
/** Return whether the node is online */ /** Return whether the node is online */
int nodeIsOnline() const; int nodeIsOnline() const;
/** Instruct the NodeService on where to look for identity files and caches */ /** Instruct the NodeService on where to look for identity files and caches */
int setHomePath(const char* homePath); int setHomePath(const char* homePath);
/** Set the NodeService's primary port */ /** Set the NodeService's primary port */
int setPrimaryPort(unsigned short primaryPort); int setPrimaryPort(unsigned short primaryPort);
/** Get the NodeService's primary port */ /** Get the NodeService's primary port */
unsigned short getPrimaryPort() const; unsigned short getPrimaryPort() const;
/** Set the event system instance used to convey messages to the user */ /** Set the event system instance used to convey messages to the user */
int setUserEventSystem(Events* events); int setUserEventSystem(Events* events);
void enableEvents(); void enableEvents();
/** Set the world definition */ /** Set the world 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) */
int addInterfacePrefixToBlacklist(const char* prefix, unsigned int len); int addInterfacePrefixToBlacklist(const char* prefix, unsigned int len);
/** Return the MAC Address of the node in the given network */ /** Return the MAC Address of the node in the given network */
uint64_t getMACAddress(uint64_t net_id) const; uint64_t getMACAddress(uint64_t net_id) const;
/** Get the string format name of a network */ /** Get the string format name of a network */
int getNetworkName(uint64_t net_id, char* dst, unsigned int len) const; int getNetworkName(uint64_t net_id, char* dst, unsigned int len) const;
/** Allow ZeroTier to cache peer hints to storage */ /** Allow ZeroTier to cache peer hints to storage */
int allowPeerCaching(unsigned int allowed); int allowPeerCaching(unsigned int allowed);
/** Allow ZeroTier to cache network info to storage */ /** Allow ZeroTier to cache network info to storage */
int allowNetworkCaching(unsigned int allowed); int allowNetworkCaching(unsigned int allowed);
/** 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 world 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 */
int getNetworkBroadcast(uint64_t net_id); int getNetworkBroadcast(uint64_t net_id);
/** Return the MTU of the given network */ /** Return the MTU of the given network */
int getNetworkMTU(uint64_t net_id); int getNetworkMTU(uint64_t net_id);
/** Return whether the network is public or private */ /** Return whether the network is public or private */
int getNetworkType(uint64_t net_id); int getNetworkType(uint64_t net_id);
/** Return the status of the network join */ /** Return the status of the network join */
int getNetworkStatus(uint64_t net_id); int getNetworkStatus(uint64_t net_id);
/** Get the first address assigned by the network */ /** Get the first address assigned by the network */
int getFirstAssignedAddr(uint64_t net_id, unsigned int family, struct zts_sockaddr_storage* addr); int getFirstAssignedAddr(uint64_t net_id, unsigned int family, struct zts_sockaddr_storage* addr);
/** Get an array of assigned addresses for the given network */ /** 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 getAllAssignedAddr(uint64_t net_id, struct zts_sockaddr_storage* addr, unsigned int* count);
/** Return whether a managed route of the given family has been assigned by the network */ /** 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 networkHasRoute(uint64_t net_id, unsigned int family);
/** Return whether an address of the given family has been assigned by the network */ /** Return whether an address of the given family has been assigned by the network */
int addrIsAssigned(uint64_t net_id, unsigned int family); int addrIsAssigned(uint64_t net_id, unsigned int family);
void phyOnTcpConnect(PhySocket* sock, void** uptr, bool success) void phyOnTcpConnect(PhySocket* sock, void** uptr, bool success)
{ {
// Intentionally left empty // 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 // Intentionally left empty
} }
void phyOnTcpClose(PhySocket* sock, void** uptr) void phyOnTcpClose(PhySocket* sock, void** uptr)
{ {
// Intentionally left empty // Intentionally left empty
} }
void phyOnTcpData(PhySocket* sock, void** uptr, void* data, unsigned long len) void phyOnTcpData(PhySocket* sock, void** uptr, void* data, unsigned long len)
{ {
// Intentionally left empty // Intentionally left empty
} }
void phyOnTcpWritable(PhySocket* sock, void** uptr) void phyOnTcpWritable(PhySocket* sock, void** uptr)
{ {
// Intentionally left empty // Intentionally left empty
} }
void phyOnFileDescriptorActivity(PhySocket* sock, void** uptr, bool readable, bool writable) void phyOnFileDescriptorActivity(PhySocket* sock, void** uptr, bool readable, bool writable)
{ {
// Intentionally left empty // Intentionally left empty
} }
void phyOnUnixAccept(PhySocket* sockL, PhySocket* sockN, void** uptrL, void** uptrN) void phyOnUnixAccept(PhySocket* sockL, PhySocket* sockN, void** uptrL, void** uptrN)
{ {
// Intentionally left empty // Intentionally left empty
} }
void phyOnUnixClose(PhySocket* sock, void** uptr) void phyOnUnixClose(PhySocket* sock, void** uptr)
{ {
// Intentionally left empty // Intentionally left empty
} }
void phyOnUnixData(PhySocket* sock, void** uptr, void* data, unsigned long len) void phyOnUnixData(PhySocket* sock, void** uptr, void* data, unsigned long len)
{ {
// Intentionally left empty // Intentionally left empty
} }
void phyOnUnixWritable(PhySocket* sock, void** uptr) void phyOnUnixWritable(PhySocket* sock, void** uptr)
{ {
// Intentionally left empty // Intentionally left empty
} }
}; };
static int SnodeVirtualNetworkConfigFunction( static int SnodeVirtualNetworkConfigFunction(
@@ -472,12 +472,12 @@ static int SnodeVirtualNetworkConfigFunction(
enum ZT_VirtualNetworkConfigOperation op, enum ZT_VirtualNetworkConfigOperation op,
const ZT_VirtualNetworkConfig* nwconf) const ZT_VirtualNetworkConfig* nwconf)
{ {
return reinterpret_cast<NodeService*>(uptr)->nodeVirtualNetworkConfigFunction(net_id, nuptr, op, nwconf); return reinterpret_cast<NodeService*>(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<NodeService*>(uptr)->nodeEventCallback(event, metaData); reinterpret_cast<NodeService*>(uptr)->nodeEventCallback(event, metaData);
} }
static void SnodeStatePutFunction( static void SnodeStatePutFunction(
@@ -489,7 +489,7 @@ static void SnodeStatePutFunction(
const void* data, const void* data,
int len) int len)
{ {
reinterpret_cast<NodeService*>(uptr)->nodeStatePutFunction(type, id, data, len); reinterpret_cast<NodeService*>(uptr)->nodeStatePutFunction(type, id, data, len);
} }
static int SnodeStateGetFunction( static int SnodeStateGetFunction(
@@ -501,7 +501,7 @@ static int SnodeStateGetFunction(
void* data, void* data,
unsigned int maxlen) unsigned int maxlen)
{ {
return reinterpret_cast<NodeService*>(uptr)->nodeStateGetFunction(type, id, data, maxlen); return reinterpret_cast<NodeService*>(uptr)->nodeStateGetFunction(type, id, data, maxlen);
} }
static int SnodeWirePacketSendFunction( static int SnodeWirePacketSendFunction(
@@ -514,7 +514,7 @@ static int SnodeWirePacketSendFunction(
unsigned int len, unsigned int len,
unsigned int ttl) unsigned int ttl)
{ {
return reinterpret_cast<NodeService*>(uptr)->nodeWirePacketSendFunction(localSocket, addr, data, len, ttl); return reinterpret_cast<NodeService*>(uptr)->nodeWirePacketSendFunction(localSocket, addr, data, len, ttl);
} }
static void SnodeVirtualNetworkFrameFunction( static void SnodeVirtualNetworkFrameFunction(
@@ -530,8 +530,8 @@ static void SnodeVirtualNetworkFrameFunction(
const void* data, const void* data,
unsigned int len) unsigned int len)
{ {
reinterpret_cast<NodeService*>(uptr) reinterpret_cast<NodeService*>(uptr)
->nodeVirtualNetworkFrameFunction(net_id, nuptr, sourceMac, destMac, etherType, vlanId, data, len); ->nodeVirtualNetworkFrameFunction(net_id, nuptr, sourceMac, destMac, etherType, vlanId, data, len);
} }
static int SnodePathCheckFunction( static int SnodePathCheckFunction(
@@ -542,7 +542,7 @@ static int SnodePathCheckFunction(
int64_t localSocket, int64_t localSocket,
const struct sockaddr_storage* remoteAddr) const struct sockaddr_storage* remoteAddr)
{ {
return reinterpret_cast<NodeService*>(uptr)->nodePathCheckFunction(ztaddr, localSocket, remoteAddr); return reinterpret_cast<NodeService*>(uptr)->nodePathCheckFunction(ztaddr, localSocket, remoteAddr);
} }
static int SnodePathLookupFunction( static int SnodePathLookupFunction(
@@ -553,7 +553,7 @@ static int SnodePathLookupFunction(
int family, int family,
struct sockaddr_storage* result) struct sockaddr_storage* result)
{ {
return reinterpret_cast<NodeService*>(uptr)->nodePathLookupFunction(ztaddr, family, result); return reinterpret_cast<NodeService*>(uptr)->nodePathLookupFunction(ztaddr, family, result);
} }
static void StapFrameHandler( static void StapFrameHandler(
@@ -567,7 +567,7 @@ static void StapFrameHandler(
const void* data, const void* data,
unsigned int len) unsigned int len)
{ {
reinterpret_cast<NodeService*>(uptr)->tapFrameHandler(net_id, from, to, etherType, vlanId, data, len); reinterpret_cast<NodeService*>(uptr)->tapFrameHandler(net_id, from, to, etherType, vlanId, data, len);
} }
} // namespace ZeroTier } // namespace ZeroTier

View File

@@ -38,43 +38,43 @@
void _signal_handler(int signal) void _signal_handler(int signal)
{ {
/* /*
switch(signal) switch(signal)
{ {
case SIGINT: case SIGINT:
fprintf(stderr, "SIGINT\n"); fprintf(stderr, "SIGINT\n");
break; break;
case SIGABRT: case SIGABRT:
fprintf(stderr, "SIGABRT\n"); fprintf(stderr, "SIGABRT\n");
break; break;
case SIGILL: case SIGILL:
fprintf(stderr, "SIGILL\n"); fprintf(stderr, "SIGILL\n");
break; break;
case SIGSEGV: case SIGSEGV:
fprintf(stderr, "SIGSEGV\n"); fprintf(stderr, "SIGSEGV\n");
break; break;
case SIGFPE: case SIGFPE:
fprintf(stderr, "SIGFPE\n"); fprintf(stderr, "SIGFPE\n");
break; break;
case SIGTERM: case SIGTERM:
default: default:
fprintf(stderr, "SIGTERM\n"); fprintf(stderr, "SIGTERM\n");
break; break;
} }
*/ */
exit(signal); exit(signal);
} }
void _install_signal_handlers() void _install_signal_handlers()
{ {
signal(SIGINT, &_signal_handler); signal(SIGINT, &_signal_handler);
/* /*
signal(SIGABRT, &_signal_handler); signal(SIGABRT, &_signal_handler);
signal(SIGFPE, &_signal_handler); signal(SIGFPE, &_signal_handler);
signal(SIGILL, &_signal_handler); signal(SIGILL, &_signal_handler);
signal(SIGSEGV, &_signal_handler); signal(SIGSEGV, &_signal_handler);
signal(SIGTERM, &_signal_handler); signal(SIGTERM, &_signal_handler);
*/ */
} }
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@@ -46,32 +46,32 @@ extern "C" {
int zts_util_get_ip_family(const char* ipstr) int zts_util_get_ip_family(const char* ipstr)
{ {
if (! ipstr) { if (! ipstr) {
return ZTS_ERR_ARG; return ZTS_ERR_ARG;
} }
int family = -1; int family = -1;
struct zts_sockaddr_in sa4; struct zts_sockaddr_in sa4;
if (zts_inet_pton(ZTS_AF_INET, ipstr, &(sa4.sin_addr)) == 1) { if (zts_inet_pton(ZTS_AF_INET, ipstr, &(sa4.sin_addr)) == 1) {
family = ZTS_AF_INET; family = ZTS_AF_INET;
} }
struct zts_sockaddr_in6 sa6; struct zts_sockaddr_in6 sa6;
if (zts_inet_pton(ZTS_AF_INET6, ipstr, &(sa6.sin6_addr)) == 1) { if (zts_inet_pton(ZTS_AF_INET6, ipstr, &(sa6.sin6_addr)) == 1) {
family = ZTS_AF_INET6; family = ZTS_AF_INET6;
} }
return family; return family;
} }
void zts_util_delay(unsigned long milliseconds) void zts_util_delay(unsigned long milliseconds)
{ {
#ifdef __WINDOWS__ #ifdef __WINDOWS__
Sleep(milliseconds); Sleep(milliseconds);
#elif _POSIX_C_SOURCE >= 199309L #elif _POSIX_C_SOURCE >= 199309L
struct timespec ts; struct timespec ts;
ts.tv_sec = milliseconds / 1000; ts.tv_sec = milliseconds / 1000;
ts.tv_nsec = (milliseconds % 1000) * 1000000; ts.tv_nsec = (milliseconds % 1000) * 1000000;
nanosleep(&ts, NULL); nanosleep(&ts, NULL);
#else #else
usleep(milliseconds * 1000); usleep(milliseconds * 1000);
#endif #endif
} }
@@ -86,97 +86,97 @@ int zts_util_world_new(
uint64_t ts, uint64_t ts,
zts_world_t* world_spec) zts_world_t* world_spec)
{ {
if (! world_spec || ! prev_key || ! curr_key || ! prev_key_len || ! curr_key_len) { if (! world_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
std::string previous, current; std::string previous, current;
if ((! OSUtils::readFile("previous.c25519", previous)) || (! OSUtils::readFile("current.c25519", current))) { if ((! OSUtils::readFile("previous.c25519", previous)) || (! OSUtils::readFile("current.c25519", current))) {
C25519::Pair np(C25519::generate()); C25519::Pair np(C25519::generate());
previous = std::string(); previous = std::string();
previous.append((const char*)np.pub.data, ZT_C25519_PUBLIC_KEY_LEN); previous.append((const char*)np.pub.data, ZT_C25519_PUBLIC_KEY_LEN);
previous.append((const char*)np.priv.data, ZT_C25519_PRIVATE_KEY_LEN); previous.append((const char*)np.priv.data, ZT_C25519_PRIVATE_KEY_LEN);
current = previous; current = previous;
} }
if ((previous.length() != (ZT_C25519_PUBLIC_KEY_LEN + ZT_C25519_PRIVATE_KEY_LEN)) 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))) { || (current.length() != (ZT_C25519_PUBLIC_KEY_LEN + ZT_C25519_PRIVATE_KEY_LEN))) {
// Previous.c25519 or current.c25519 empty or invalid // Previous.c25519 or current.c25519 empty or invalid
return ZTS_ERR_ARG; return ZTS_ERR_ARG;
} }
C25519::Pair previousKP; C25519::Pair previousKP;
memcpy(previousKP.pub.data, previous.data(), ZT_C25519_PUBLIC_KEY_LEN); 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); memcpy(previousKP.priv.data, previous.data() + ZT_C25519_PUBLIC_KEY_LEN, ZT_C25519_PRIVATE_KEY_LEN);
C25519::Pair currentKP; C25519::Pair currentKP;
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 world 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 (! world_spec->public_id_str[i]) {
break; break;
} }
if (strlen(world_spec->public_id_str[i])) { if (strlen(world_spec->public_id_str[i])) {
// printf("id = %s\n", world_spec->public_id_str[i]); // printf("id = %s\n", world_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(world_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 (! world_spec->endpoint_ip_str[i][j]) {
break; break;
} }
if (strlen(world_spec->endpoint_ip_str[i][j])) { if (strlen(world_spec->endpoint_ip_str[i][j])) {
roots.back().stableEndpoints.push_back(InetAddress(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]); // printf(" ep = %s\n", world_spec->endpoint_ip_str[i][j]);
} }
} }
} }
} }
// Generate // Generate
World nw = World::make(World::TYPE_PLANET, id, ts, currentKP.pub, roots, previousKP); World nw = World::make(World::TYPE_PLANET, id, ts, currentKP.pub, roots, previousKP);
// Test // Test
Buffer<ZT_WORLD_MAX_SERIALIZED_LENGTH> outtmp; Buffer<ZT_WORLD_MAX_SERIALIZED_LENGTH> outtmp;
nw.serialize(outtmp, false); nw.serialize(outtmp, false);
World testw; World testw;
testw.deserialize(outtmp, 0); testw.deserialize(outtmp, 0);
if (testw != nw) { if (testw != nw) {
// Serialization test failed // Serialization test failed
return ZTS_ERR_GENERAL; return ZTS_ERR_GENERAL;
} }
// Write output // Write output
memcpy(world_out, (char*)outtmp.data(), outtmp.size()); memcpy(world_out, (char*)outtmp.data(), outtmp.size());
*world_len = outtmp.size(); *world_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());
*curr_key_len = ZT_C25519_PRIVATE_KEY_LEN + ZT_C25519_PUBLIC_KEY_LEN; *curr_key_len = ZT_C25519_PRIVATE_KEY_LEN + ZT_C25519_PUBLIC_KEY_LEN;
return ZTS_ERR_OK; return ZTS_ERR_OK;
} }
void native_ss_to_zts_ss(struct zts_sockaddr_storage* ss_out, const struct sockaddr_storage* ss_in) 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) { if (ss_in->ss_family == AF_INET) {
struct sockaddr_in* s_in4 = (struct sockaddr_in*)ss_in; struct sockaddr_in* s_in4 = (struct sockaddr_in*)ss_in;
struct zts_sockaddr_in* d_in4 = (struct zts_sockaddr_in*)ss_out; struct zts_sockaddr_in* d_in4 = (struct zts_sockaddr_in*)ss_out;
#ifndef __WINDOWS__ #ifndef __WINDOWS__
d_in4->sin_len = 0; // s_in4->sin_len; d_in4->sin_len = 0; // s_in4->sin_len;
#endif #endif
d_in4->sin_family = ZTS_AF_INET; d_in4->sin_family = ZTS_AF_INET;
d_in4->sin_port = s_in4->sin_port; d_in4->sin_port = s_in4->sin_port;
memcpy(&(d_in4->sin_addr), &(s_in4->sin_addr), sizeof(s_in4->sin_addr)); memcpy(&(d_in4->sin_addr), &(s_in4->sin_addr), sizeof(s_in4->sin_addr));
} }
if (ss_in->ss_family == AF_INET6) { if (ss_in->ss_family == AF_INET6) {
struct sockaddr_in6* s_in6 = (struct sockaddr_in6*)ss_in; struct sockaddr_in6* s_in6 = (struct sockaddr_in6*)ss_in;
struct zts_sockaddr_in6* d_in6 = (struct zts_sockaddr_in6*)ss_out; struct zts_sockaddr_in6* d_in6 = (struct zts_sockaddr_in6*)ss_out;
#ifndef __WINDOWS__ #ifndef __WINDOWS__
d_in6->sin6_len = 0; // s_in6->sin6_len; d_in6->sin6_len = 0; // s_in6->sin6_len;
#endif #endif
d_in6->sin6_family = ZTS_AF_INET6; d_in6->sin6_family = ZTS_AF_INET6;
d_in6->sin6_port = s_in6->sin6_port; d_in6->sin6_port = s_in6->sin6_port;
d_in6->sin6_flowinfo = s_in6->sin6_flowinfo; d_in6->sin6_flowinfo = s_in6->sin6_flowinfo;
memcpy(&(d_in6->sin6_addr), &(s_in6->sin6_addr), sizeof(s_in6->sin6_addr)); memcpy(&(d_in6->sin6_addr), &(s_in6->sin6_addr), sizeof(s_in6->sin6_addr));
d_in6->sin6_scope_id = s_in6->sin6_scope_id; d_in6->sin6_scope_id = s_in6->sin6_scope_id;
} }
} }
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -84,191 +84,191 @@ VirtualTap::VirtualTap(
, _unixListenSocket((PhySocket*)0) , _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);
#ifndef __WINDOWS__ #ifndef __WINDOWS__
::pipe(_shutdownSignalPipe); ::pipe(_shutdownSignalPipe);
#endif #endif
// Start virtual tap thread and stack I/O loops // Start virtual tap thread and stack I/O loops
_thread = Thread::start(this); _thread = Thread::start(this);
} }
VirtualTap::~VirtualTap() VirtualTap::~VirtualTap()
{ {
_run = false; _run = false;
#ifndef __WINDOWS__ #ifndef __WINDOWS__
::write(_shutdownSignalPipe[1], "\0", 1); ::write(_shutdownSignalPipe[1], "\0", 1);
#endif #endif
_phy.whack(); _phy.whack();
_lwip_remove_netif(netif4); _lwip_remove_netif(netif4);
netif4 = NULL; netif4 = NULL;
_lwip_remove_netif(netif6); _lwip_remove_netif(netif6);
netif6 = NULL; netif6 = NULL;
Thread::join(_thread); Thread::join(_thread);
#ifndef __WINDOWS__ #ifndef __WINDOWS__
::close(_shutdownSignalPipe[0]); ::close(_shutdownSignalPipe[0]);
::close(_shutdownSignalPipe[1]); ::close(_shutdownSignalPipe[1]);
#endif #endif
} }
void VirtualTap::lastConfigUpdate(uint64_t lastConfigUpdateTime) void VirtualTap::lastConfigUpdate(uint64_t lastConfigUpdateTime)
{ {
_lastConfigUpdateTime = lastConfigUpdateTime; _lastConfigUpdateTime = lastConfigUpdateTime;
} }
void VirtualTap::setEnabled(bool en) void VirtualTap::setEnabled(bool en)
{ {
_enabled = en; _enabled = en;
} }
bool VirtualTap::enabled() const bool VirtualTap::enabled() const
{ {
return _enabled; return _enabled;
} }
void VirtualTap::setUserEventSystem(Events* events) void VirtualTap::setUserEventSystem(Events* events)
{ {
_events = events; _events = events;
} }
bool VirtualTap::hasIpv4Addr() bool VirtualTap::hasIpv4Addr()
{ {
Mutex::Lock _l(_ips_m); Mutex::Lock _l(_ips_m);
std::vector<InetAddress>::iterator it(_ips.begin()); std::vector<InetAddress>::iterator it(_ips.begin());
while (it != _ips.end()) { while (it != _ips.end()) {
if ((*it).isV4()) { if ((*it).isV4()) {
return true; return true;
} }
++it; ++it;
} }
return false; return false;
} }
bool VirtualTap::hasIpv6Addr() bool VirtualTap::hasIpv6Addr()
{ {
Mutex::Lock _l(_ips_m); Mutex::Lock _l(_ips_m);
std::vector<InetAddress>::iterator it(_ips.begin()); std::vector<InetAddress>::iterator it(_ips.begin());
while (it != _ips.end()) { while (it != _ips.end()) {
if ((*it).isV6()) { if ((*it).isV6()) {
return true; return true;
} }
++it; ++it;
} }
return false; return false;
} }
bool VirtualTap::addIp(const InetAddress& ip) bool VirtualTap::addIp(const InetAddress& ip)
{ {
// TODO: Rewrite to allow for more addresses // TODO: Rewrite to allow for more addresses
char ipbuf[128] = { 0 }; char ipbuf[128] = { 0 };
/* Limit address assignments to one per type. /* Limit address assignments to one per type.
This limitation can be removed if some changes This limitation can be removed if some changes
are made in the netif driver. */ are made in the netif driver. */
if (ip.isV4() && hasIpv4Addr()) { if (ip.isV4() && hasIpv4Addr()) {
ip.toString(ipbuf); ip.toString(ipbuf);
// DEBUG_INFO("failed to add IP (%s), only one per type per netif // DEBUG_INFO("failed to add IP (%s), only one per type per netif
// allowed\n", ipbuf); // allowed\n", ipbuf);
return false; return false;
} }
if (ip.isV6() && hasIpv6Addr()) { if (ip.isV6() && hasIpv6Addr()) {
ip.toString(ipbuf); ip.toString(ipbuf);
// DEBUG_INFO("failed to add IP (%s), only one per type per netif // DEBUG_INFO("failed to add IP (%s), only one per type per netif
// allowed\n", ipbuf); // allowed\n", ipbuf);
return false; return false;
} }
Mutex::Lock _l(_ips_m); Mutex::Lock _l(_ips_m);
if (_ips.size() >= ZT_MAX_ZT_ASSIGNED_ADDRESSES) { if (_ips.size() >= ZT_MAX_ZT_ASSIGNED_ADDRESSES) {
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); _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());
} }
return true; return true;
} }
bool VirtualTap::removeIp(const InetAddress& ip) 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); _lwip_remove_address_from_netif((void*)this, ip);
_ips.erase(i); _ips.erase(i);
} }
return true; return true;
} }
std::vector<InetAddress> VirtualTap::ips() const std::vector<InetAddress> VirtualTap::ips() const
{ {
Mutex::Lock _l(_ips_m); Mutex::Lock _l(_ips_m);
return _ips; 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) { if (len && _enabled) {
_lwip_eth_rx(this, from, to, etherType, data, len); _lwip_eth_rx(this, from, to, etherType, data, len);
} }
} }
void VirtualTap::scanMulticastGroups(std::vector<MulticastGroup>& added, std::vector<MulticastGroup>& removed) void VirtualTap::scanMulticastGroups(std::vector<MulticastGroup>& added, std::vector<MulticastGroup>& removed)
{ {
std::vector<MulticastGroup> newGroups; std::vector<MulticastGroup> newGroups;
Mutex::Lock _l(_multicastGroups_m); Mutex::Lock _l(_multicastGroups_m);
// TODO: get multicast subscriptions // TODO: get multicast subscriptions
std::vector<InetAddress> allIps(ips()); std::vector<InetAddress> allIps(ips());
for (std::vector<InetAddress>::iterator ip(allIps.begin()); ip != allIps.end(); ++ip) for (std::vector<InetAddress>::iterator ip(allIps.begin()); ip != allIps.end(); ++ip)
newGroups.push_back(MulticastGroup::deriveMulticastGroupForAddressResolution(*ip)); newGroups.push_back(MulticastGroup::deriveMulticastGroupForAddressResolution(*ip));
std::sort(newGroups.begin(), newGroups.end()); std::sort(newGroups.begin(), newGroups.end());
for (std::vector<MulticastGroup>::iterator m(newGroups.begin()); m != newGroups.end(); ++m) { for (std::vector<MulticastGroup>::iterator m(newGroups.begin()); m != newGroups.end(); ++m) {
if (! std::binary_search(_multicastGroups.begin(), _multicastGroups.end(), *m)) if (! std::binary_search(_multicastGroups.begin(), _multicastGroups.end(), *m))
added.push_back(*m); added.push_back(*m);
} }
for (std::vector<MulticastGroup>::iterator m(_multicastGroups.begin()); m != _multicastGroups.end(); ++m) { for (std::vector<MulticastGroup>::iterator m(_multicastGroups.begin()); m != _multicastGroups.end(); ++m) {
if (! std::binary_search(newGroups.begin(), newGroups.end(), *m)) if (! std::binary_search(newGroups.begin(), newGroups.end(), *m))
removed.push_back(*m); removed.push_back(*m);
} }
_multicastGroups.swap(newGroups); _multicastGroups.swap(newGroups);
} }
void VirtualTap::setMtu(unsigned int mtu) void VirtualTap::setMtu(unsigned int mtu)
{ {
_mtu = mtu; _mtu = mtu;
} }
void VirtualTap::threadMain() throw() void VirtualTap::threadMain() throw()
{ {
fd_set readfds, nullfds; fd_set readfds, nullfds;
struct timeval tv; struct timeval tv;
tv.tv_sec = 0; tv.tv_sec = 0;
tv.tv_usec = 0; tv.tv_usec = 0;
FD_ZERO(&readfds); FD_ZERO(&readfds);
FD_ZERO(&nullfds); FD_ZERO(&nullfds);
int nfds = (int)std::max(_shutdownSignalPipe[0], 0) + 1; int nfds = (int)std::max(_shutdownSignalPipe[0], 0) + 1;
#if defined(__linux__) #if defined(__linux__)
pthread_setname_np(pthread_self(), vtap_full_name); pthread_setname_np(pthread_self(), vtap_full_name);
#endif #endif
#if defined(__APPLE__) #if defined(__APPLE__)
pthread_setname_np(vtap_full_name); pthread_setname_np(vtap_full_name);
#endif #endif
while (true) { while (true) {
FD_SET(_shutdownSignalPipe[0], &readfds); FD_SET(_shutdownSignalPipe[0], &readfds);
select(nfds, &readfds, &nullfds, &nullfds, &tv); select(nfds, &readfds, &nullfds, &nullfds, &tv);
// writes to shutdown pipe terminate thread // writes to shutdown pipe terminate thread
if (FD_ISSET(_shutdownSignalPipe[0], &readfds)) { if (FD_ISSET(_shutdownSignalPipe[0], &readfds)) {
break; break;
} }
#if defined(__WINDOWS__) #if defined(__WINDOWS__)
Sleep(ZTS_TAP_THREAD_POLLING_INTERVAL); Sleep(ZTS_TAP_THREAD_POLLING_INTERVAL);
#else #else
struct timespec sleepValue = { 0 }; struct timespec sleepValue = { 0 };
sleepValue.tv_nsec = ZTS_TAP_THREAD_POLLING_INTERVAL * 500000; sleepValue.tv_nsec = ZTS_TAP_THREAD_POLLING_INTERVAL * 500000;
nanosleep(&sleepValue, NULL); nanosleep(&sleepValue, NULL);
#endif #endif
} }
} }
void VirtualTap::phyOnDatagram( void VirtualTap::phyOnDatagram(
@@ -279,7 +279,7 @@ void VirtualTap::phyOnDatagram(
void* data, void* data,
unsigned long len) unsigned long len)
{ {
// Intentionally empty // Intentionally empty
} }
void VirtualTap::phyOnTcpConnect(PhySocket* sock, void** uptr, bool success) void VirtualTap::phyOnTcpConnect(PhySocket* sock, void** uptr, bool success)
@@ -327,118 +327,118 @@ Mutex stackLock;
// 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 _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 _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);
#endif #endif
#if defined(__APPLE__) #if defined(__APPLE__)
pthread_setname_np(ZTS_LWIP_THREAD_NAME); pthread_setname_np(ZTS_LWIP_THREAD_NAME);
#endif #endif
sys_sem_t sem; sys_sem_t sem;
LWIP_UNUSED_ARG(arg); LWIP_UNUSED_ARG(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(_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)) {
zts_util_delay(LWIP_DRIVER_LOOP_INTERVAL); zts_util_delay(LWIP_DRIVER_LOOP_INTERVAL);
} }
_has_exited = true; _has_exited = true;
zts_events->enqueue(ZTS_EVENT_STACK_DOWN, NULL); zts_events->enqueue(ZTS_EVENT_STACK_DOWN, NULL);
} }
bool _lwip_is_up() bool _lwip_is_up()
{ {
Mutex::Lock _l(stackLock); Mutex::Lock _l(stackLock);
return zts_events->getState(ZTS_STATE_STACK_RUNNING); return zts_events->getState(ZTS_STATE_STACK_RUNNING);
} }
void _lwip_driver_init() void _lwip_driver_init()
{ {
if (_lwip_is_up()) { if (_lwip_is_up()) {
return; return;
} }
if (_has_exited) { if (_has_exited) {
return; return;
} }
Mutex::Lock _l(stackLock); Mutex::Lock _l(stackLock);
#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, _main_lwip_driver_loop, NULL, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO);
} }
void _lwip_driver_shutdown() void _lwip_driver_shutdown()
{ {
if (_has_exited) { if (_has_exited) {
return; return;
} }
Mutex::Lock _l(stackLock); Mutex::Lock _l(stackLock);
// 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
if (_has_started) { if (_has_started) {
while (! _has_exited) { while (! _has_exited) {
zts_util_delay(LWIP_DRIVER_LOOP_INTERVAL); zts_util_delay(LWIP_DRIVER_LOOP_INTERVAL);
} }
} }
} }
void _lwip_remove_netif(void* netif) void _lwip_remove_netif(void* netif)
{ {
if (! netif) { if (! netif) {
return; return;
} }
struct netif* n = (struct netif*)netif; struct netif* n = (struct netif*)netif;
LOCK_TCPIP_CORE(); LOCK_TCPIP_CORE();
netif_remove(n); netif_remove(n);
netif_set_down(n); netif_set_down(n);
netif_set_link_down(n); netif_set_link_down(n);
UNLOCK_TCPIP_CORE(); UNLOCK_TCPIP_CORE();
} }
err_t _lwip_eth_tx(struct netif* n, struct pbuf* p) err_t _lwip_eth_tx(struct netif* n, struct pbuf* p)
{ {
if (! n) { if (! n) {
return ERR_IF; return ERR_IF;
} }
struct pbuf* q; struct pbuf* q;
char buf[ZT_MAX_MTU + 32] = { 0 }; char buf[ZT_MAX_MTU + 32] = { 0 };
char* bufptr; char* bufptr;
int totalLength = 0; int totalLength = 0;
VirtualTap* tap = (VirtualTap*)n->state; VirtualTap* tap = (VirtualTap*)n->state;
bufptr = buf; bufptr = buf;
for (q = p; q != NULL; q = q->next) { for (q = p; q != NULL; q = q->next) {
memcpy(bufptr, q->payload, q->len); memcpy(bufptr, q->payload, q->len);
bufptr += q->len; bufptr += q->len;
totalLength += q->len; totalLength += q->len;
} }
struct eth_hdr* ethhdr; struct eth_hdr* ethhdr;
ethhdr = (struct eth_hdr*)buf; ethhdr = (struct eth_hdr*)buf;
MAC src_mac; MAC src_mac;
MAC dest_mac; MAC dest_mac;
src_mac.setTo(ethhdr->src.addr, 6); src_mac.setTo(ethhdr->src.addr, 6);
dest_mac.setTo(ethhdr->dest.addr, 6); dest_mac.setTo(ethhdr->dest.addr, 6);
char* data = buf + sizeof(struct eth_hdr); char* data = buf + sizeof(struct eth_hdr);
int len = totalLength - sizeof(struct eth_hdr); int len = totalLength - sizeof(struct eth_hdr);
int proto = Utils::ntoh((uint16_t)ethhdr->type); int proto = Utils::ntoh((uint16_t)ethhdr->type);
tap->_handler(tap->_arg, NULL, tap->_net_id, src_mac, dest_mac, proto, 0, data, len); tap->_handler(tap->_arg, NULL, tap->_net_id, src_mac, dest_mac, proto, 0, data, len);
return ERR_OK; return ERR_OK;
} }
void _lwip_eth_rx( void _lwip_eth_rx(
@@ -450,213 +450,213 @@ void _lwip_eth_rx(
unsigned int len) unsigned int len)
{ {
#ifdef LWIP_STATS #ifdef LWIP_STATS
stats_display(); stats_display();
#endif #endif
if (! zts_events->getState(ZTS_STATE_STACK_RUNNING)) { if (! zts_events->getState(ZTS_STATE_STACK_RUNNING)) {
return; return;
} }
struct pbuf *p, *q; struct pbuf *p, *q;
struct eth_hdr ethhdr; struct eth_hdr ethhdr;
from.copyTo(ethhdr.src.addr, 6); from.copyTo(ethhdr.src.addr, 6);
to.copyTo(ethhdr.dest.addr, 6); to.copyTo(ethhdr.dest.addr, 6);
ethhdr.type = Utils::hton((uint16_t)etherType); ethhdr.type = Utils::hton((uint16_t)etherType);
p = pbuf_alloc(PBUF_RAW, (uint16_t)len + sizeof(struct eth_hdr), PBUF_RAM); p = pbuf_alloc(PBUF_RAW, (uint16_t)len + sizeof(struct eth_hdr), PBUF_RAM);
if (! p) { if (! p) {
// DEBUG_ERROR("dropped packet: unable to allocate memory for // DEBUG_ERROR("dropped packet: unable to allocate memory for
// pbuf"); // pbuf");
return; return;
} }
// First pbuf gets Ethernet header at start // First pbuf gets Ethernet header at start
q = p; q = p;
if (q->len < sizeof(ethhdr)) { if (q->len < sizeof(ethhdr)) {
pbuf_free(p); pbuf_free(p);
p = NULL; p = NULL;
// DEBUG_ERROR("dropped packet: first pbuf smaller than Ethernet // DEBUG_ERROR("dropped packet: first pbuf smaller than Ethernet
// header"); // header");
return; return;
} }
// Copy frame data into pbuf // Copy frame data into pbuf
const char* dataptr = reinterpret_cast<const char*>(data); const char* dataptr = reinterpret_cast<const char*>(data);
memcpy(q->payload, &ethhdr, sizeof(ethhdr)); memcpy(q->payload, &ethhdr, sizeof(ethhdr));
int remainingPayloadSpace = q->len - sizeof(ethhdr); int remainingPayloadSpace = q->len - sizeof(ethhdr);
memcpy((char*)q->payload + sizeof(ethhdr), dataptr, remainingPayloadSpace); memcpy((char*)q->payload + sizeof(ethhdr), dataptr, remainingPayloadSpace);
dataptr += remainingPayloadSpace; dataptr += remainingPayloadSpace;
// Remaining pbufs (if any) get rest of data // Remaining pbufs (if any) get rest of data
while ((q = q->next)) { while ((q = q->next)) {
memcpy(q->payload, dataptr, q->len); memcpy(q->payload, dataptr, q->len);
dataptr += q->len; dataptr += q->len;
} }
// Feed packet into stack // Feed packet into stack
int err; int err;
if (Utils::ntoh(ethhdr.type) == 0x800 || Utils::ntoh(ethhdr.type) == 0x806) { if (Utils::ntoh(ethhdr.type) == 0x800 || Utils::ntoh(ethhdr.type) == 0x806) {
if (tap->netif4) { 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); // DEBUG_ERROR("packet input error (%d)", err);
pbuf_free(p); pbuf_free(p);
} }
} }
} }
if (Utils::ntoh(ethhdr.type) == 0x86DD) { if (Utils::ntoh(ethhdr.type) == 0x86DD) {
if (tap->netif6) { 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); // DEBUG_ERROR("packet input error (%d)", err);
pbuf_free(p); pbuf_free(p);
} }
} }
} }
} }
bool _lwip_is_netif_up(void* n) bool _lwip_is_netif_up(void* n)
{ {
if (! n) { if (! n) {
return false; return false;
} }
LOCK_TCPIP_CORE(); LOCK_TCPIP_CORE();
bool result = netif_is_up((struct netif*)n); bool result = netif_is_up((struct netif*)n);
UNLOCK_TCPIP_CORE(); UNLOCK_TCPIP_CORE();
return result; return result;
} }
static err_t _netif_init4(struct netif* n) static err_t _netif_init4(struct netif* n)
{ {
if (! n || ! n->state) { if (! n || ! n->state) {
return ERR_IF; return ERR_IF;
} }
// Called from core, no need to lock // Called from core, no need to lock
VirtualTap* tap = (VirtualTap*)(n->state); VirtualTap* tap = (VirtualTap*)(n->state);
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 = _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
| NETIF_FLAG_LINK_UP | NETIF_FLAG_UP; | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP;
n->hwaddr_len = sizeof(n->hwaddr); n->hwaddr_len = sizeof(n->hwaddr);
tap->_mac.copyTo(n->hwaddr, n->hwaddr_len); tap->_mac.copyTo(n->hwaddr, n->hwaddr_len);
return ERR_OK; return ERR_OK;
} }
static err_t _netif_init6(struct netif* n) static err_t _netif_init6(struct netif* n)
{ {
if (! n || ! n->state) { if (! n || ! n->state) {
return ERR_IF; return ERR_IF;
} }
n->hwaddr_len = sizeof(n->hwaddr); n->hwaddr_len = sizeof(n->hwaddr);
VirtualTap* tap = (VirtualTap*)(n->state); VirtualTap* tap = (VirtualTap*)(n->state);
tap->_mac.copyTo(n->hwaddr, n->hwaddr_len); tap->_mac.copyTo(n->hwaddr, n->hwaddr_len);
// Called from core, no need to lock // Called from core, no need to lock
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 = _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
| NETIF_FLAG_LINK_UP | NETIF_FLAG_UP; | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP;
return ERR_OK; return ERR_OK;
} }
void _lwip_init_interface(void* tapref, const InetAddress& ip) void _lwip_init_interface(void* tapref, const InetAddress& ip)
{ {
char macbuf[ZTS_MAC_ADDRSTRLEN] = { 0 }; char macbuf[ZTS_MAC_ADDRSTRLEN] = { 0 };
VirtualTap* vtap = (VirtualTap*)tapref; VirtualTap* vtap = (VirtualTap*)tapref;
struct netif* n = NULL; struct netif* n = NULL;
bool isNewNetif = false; bool isNewNetif = false;
if (ip.isV4()) { if (ip.isV4()) {
if (vtap->netif4) { if (vtap->netif4) {
n = (struct netif*)vtap->netif4; n = (struct netif*)vtap->netif4;
} }
else { else {
n = new struct netif; n = new struct netif;
isNewNetif = true; isNewNetif = true;
netifCount++; netifCount++;
} }
static ip4_addr_t ip4, netmask, gw; static ip4_addr_t ip4, netmask, gw;
IP4_ADDR(&gw, 127, 0, 0, 1); IP4_ADDR(&gw, 127, 0, 0, 1);
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, _netif_init4, tcpip_input);
vtap->netif4 = (void*)n; vtap->netif4 = (void*)n;
UNLOCK_TCPIP_CORE(); UNLOCK_TCPIP_CORE();
snprintf( snprintf(
macbuf, macbuf,
ZTS_MAC_ADDRSTRLEN, ZTS_MAC_ADDRSTRLEN,
"%02x:%02x:%02x:%02x:%02x:%02x", "%02x:%02x:%02x:%02x:%02x:%02x",
n->hwaddr[0], n->hwaddr[0],
n->hwaddr[1], n->hwaddr[1],
n->hwaddr[2], n->hwaddr[2],
n->hwaddr[3], n->hwaddr[3],
n->hwaddr[4], n->hwaddr[4],
n->hwaddr[5]); n->hwaddr[5]);
} }
if (ip.isV6()) { if (ip.isV6()) {
if (vtap->netif6) { if (vtap->netif6) {
n = (struct netif*)vtap->netif6; n = (struct netif*)vtap->netif6;
} }
else { else {
n = new struct netif; n = new struct netif;
isNewNetif = true; isNewNetif = true;
netifCount++; netifCount++;
} }
static ip6_addr_t ip6; static ip6_addr_t ip6;
memcpy(&(ip6.addr), ip.rawIpData(), sizeof(ip6.addr)); memcpy(&(ip6.addr), ip.rawIpData(), sizeof(ip6.addr));
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, _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);
netif_set_link_up(n); netif_set_link_up(n);
netif_set_up(n); netif_set_up(n);
netif_set_default(n); netif_set_default(n);
} }
netif_add_ip6_address(n, &ip6, NULL); netif_add_ip6_address(n, &ip6, NULL);
n->output_ip6 = ethip6_output; n->output_ip6 = ethip6_output;
UNLOCK_TCPIP_CORE(); UNLOCK_TCPIP_CORE();
snprintf( snprintf(
macbuf, macbuf,
ZTS_MAC_ADDRSTRLEN, ZTS_MAC_ADDRSTRLEN,
"%02x:%02x:%02x:%02x:%02x:%02x", "%02x:%02x:%02x:%02x:%02x:%02x",
n->hwaddr[0], n->hwaddr[0],
n->hwaddr[1], n->hwaddr[1],
n->hwaddr[2], n->hwaddr[2],
n->hwaddr[3], n->hwaddr[3],
n->hwaddr[4], n->hwaddr[4],
n->hwaddr[5]); n->hwaddr[5]);
} }
} }
void _lwip_remove_address_from_netif(void* tapref, const InetAddress& ip) void _lwip_remove_address_from_netif(void* tapref, const InetAddress& ip)
{ {
if (! tapref) { if (! tapref) {
return; return;
} }
VirtualTap* vtap = (VirtualTap*)tapref; VirtualTap* vtap = (VirtualTap*)tapref;
struct netif* n = NULL; struct netif* n = NULL;
/* When true multi-homing is implemented this will need to /* When true multi-homing is implemented this will need to
be a bit more sophisticated */ be a bit more sophisticated */
if (ip.isV4()) { if (ip.isV4()) {
if (vtap->netif4) { if (vtap->netif4) {
n = (struct netif*)vtap->netif4; n = (struct netif*)vtap->netif4;
} }
} }
if (ip.isV6()) { if (ip.isV6()) {
if (vtap->netif6) { if (vtap->netif6) {
n = (struct netif*)vtap->netif6; n = (struct netif*)vtap->netif6;
} }
} }
if (! n) { if (! n) {
return; return;
} }
_lwip_remove_netif(n); _lwip_remove_netif(n);
} }
} // namespace ZeroTier } // namespace ZeroTier

View File

@@ -42,153 +42,153 @@ struct InetAddress;
* then be destroyed upon leaving the network. * then be destroyed upon leaving the network.
*/ */
class VirtualTap { class VirtualTap {
friend class Phy<VirtualTap*>; friend class Phy<VirtualTap*>;
public: public:
VirtualTap( VirtualTap(
const char* homePath, const char* homePath,
const MAC& mac, const MAC& mac,
unsigned int mtu, unsigned int mtu,
unsigned int metric, unsigned int metric,
uint64_t net_id, uint64_t net_id,
void (*handler)( void (*handler)(
void*, void*,
void*, void*,
uint64_t, uint64_t,
const MAC&, const MAC&,
const MAC&, const MAC&,
unsigned int, unsigned int,
unsigned int, unsigned int,
const void*, const void*,
unsigned int), unsigned int),
void* arg); void* arg);
~VirtualTap(); ~VirtualTap();
void setEnabled(bool en); void setEnabled(bool en);
bool enabled() const; bool enabled() const;
/** /**
* System to ingest events from this class and emit them to the user * System to ingest events from this class and emit them to the user
*/ */
Events* _events; Events* _events;
/** /**
* Mutex for protecting IP address container for this tap. * Mutex for protecting IP address container for this tap.
*/ */
Mutex _ips_m; // Public because we want it accessible by the driver Mutex _ips_m; // Public because we want it accessible by the driver
// layer // layer
void setUserEventSystem(Events* events); void setUserEventSystem(Events* events);
/** /**
* Return whether this tap has been assigned an IPv4 address. * Return whether this tap has been assigned an IPv4 address.
*/ */
bool hasIpv4Addr(); bool hasIpv4Addr();
/** /**
* Return whether this tap has been assigned an IPv6 address. * Return whether this tap has been assigned an IPv6 address.
*/ */
bool hasIpv6Addr(); bool hasIpv6Addr();
/** /**
* Adds an address to the user-space stack interface associated with * Adds an address to the user-space stack interface associated with
* this VirtualTap * this VirtualTap
* - Starts VirtualTap main thread ONLY if successful * - Starts VirtualTap main thread ONLY if successful
*/ */
bool addIp(const InetAddress& ip); bool addIp(const InetAddress& ip);
/** /**
* Removes an address from the user-space stack interface associated * Removes an address from the user-space stack interface associated
* with this VirtualTap * with this VirtualTap
*/ */
bool removeIp(const InetAddress& ip); bool removeIp(const InetAddress& ip);
/** /**
* Presents data to the user-space stack * 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 * Scan multicast groups
*/ */
void scanMulticastGroups(std::vector<MulticastGroup>& added, std::vector<MulticastGroup>& removed); void scanMulticastGroups(std::vector<MulticastGroup>& added, std::vector<MulticastGroup>& removed);
/** /**
* Set MTU * Set MTU
*/ */
void setMtu(unsigned int mtu); void setMtu(unsigned int mtu);
/** /**
* Calls main network stack loops * Calls main network stack loops
*/ */
void threadMain() throw(); void threadMain() throw();
/** /**
* For moving data onto the ZeroTier virtual wire * For moving data onto the ZeroTier virtual wire
*/ */
void (*_handler)( void (*_handler)(
void*, void*,
void*, void*,
uint64_t, uint64_t,
const MAC&, const MAC&,
const MAC&, const MAC&,
unsigned int, unsigned int,
unsigned int, unsigned int,
const void*, const void*,
unsigned int); unsigned int);
void* netif4 = NULL; void* netif4 = NULL;
void* netif6 = NULL; void* netif6 = NULL;
// The last time that this virtual tap received a network config update // The last time that this virtual tap received a network config update
// from the core // from the core
uint64_t _lastConfigUpdateTime = 0; uint64_t _lastConfigUpdateTime = 0;
void lastConfigUpdate(uint64_t lastConfigUpdateTime); void lastConfigUpdate(uint64_t lastConfigUpdateTime);
int _networkStatus = 0; int _networkStatus = 0;
char vtap_full_name[VTAP_NAME_LEN] = { 0 }; char vtap_full_name[VTAP_NAME_LEN] = { 0 };
std::vector<InetAddress> ips() const; std::vector<InetAddress> ips() const;
std::vector<InetAddress> _ips; std::vector<InetAddress> _ips;
std::string _homePath; std::string _homePath;
void* _arg; void* _arg;
volatile bool _initialized; volatile bool _initialized;
volatile bool _enabled; volatile bool _enabled;
volatile bool _run; volatile bool _run;
MAC _mac; MAC _mac;
unsigned int _mtu; unsigned int _mtu;
uint64_t _net_id; uint64_t _net_id;
PhySocket* _unixListenSocket; PhySocket* _unixListenSocket;
Phy<VirtualTap*> _phy; Phy<VirtualTap*> _phy;
Thread _thread; Thread _thread;
int _shutdownSignalPipe[2] = { 0 }; int _shutdownSignalPipe[2] = { 0 };
std::vector<MulticastGroup> _multicastGroups; std::vector<MulticastGroup> _multicastGroups;
Mutex _multicastGroups_m; Mutex _multicastGroups_m;
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
// Not used in this implementation // // Not used in this implementation //
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
void phyOnDatagram( void phyOnDatagram(
PhySocket* sock, PhySocket* sock,
void** uptr, void** uptr,
const struct sockaddr* local_address, const struct sockaddr* local_address,
const struct sockaddr* from, const struct sockaddr* from,
void* data, void* data,
unsigned long len); unsigned long len);
void phyOnTcpConnect(PhySocket* sock, void** uptr, bool success); 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 phyOnTcpClose(PhySocket* sock, void** uptr);
void phyOnTcpData(PhySocket* sock, void** uptr, void* data, unsigned long len); void phyOnTcpData(PhySocket* sock, void** uptr, void* data, unsigned long len);
void phyOnTcpWritable(PhySocket* sock, void** uptr); void phyOnTcpWritable(PhySocket* sock, void** uptr);
void phyOnUnixClose(PhySocket* sock, void** uptr); void phyOnUnixClose(PhySocket* sock, void** uptr);
}; };
/** /**