#include #include #include #include #include "ZeroTier.h" bool node_ready = false; bool network_ready = false; // Example callbacks void myZeroTierEventCallback(struct zts_callback_msg *msg) { // // Node events // if (msg->eventCode == ZTS_EVENT_NODE_ONLINE) { printf("ZTS_EVENT_NODE_ONLINE, node=%llx\n", msg->node->address); node_ready = true; // ZeroTier service is running and online } if (msg->eventCode == ZTS_EVENT_NODE_OFFLINE) { printf("ZTS_EVENT_NODE_OFFLINE\n"); node_ready = false; // ZeroTier service is running and online } if (msg->eventCode == ZTS_EVENT_NODE_NORMAL_TERMINATION) { printf("ZTS_EVENT_NODE_NORMAL_TERMINATION\n"); // ZeroTier service has stopped } // // Virtual network events // if (msg->eventCode == ZTS_EVENT_NETWORK_NOT_FOUND) { printf("ZTS_EVENT_NETWORK_NOT_FOUND --- network=%llx\n", msg->network->nwid); // Is your nwid incorrect? } if (msg->eventCode == ZTS_EVENT_NETWORK_REQUESTING_CONFIG) { printf("ZTS_EVENT_NETWORK_REQUESTING_CONFIG --- network=%llx\n", msg->network->nwid); // Node is requesting network config details from controller, please wait } if (msg->eventCode == ZTS_EVENT_NETWORK_ACCESS_DENIED) { printf("ZTS_EVENT_NETWORK_ACCESS_DENIED --- network=%llx\n", msg->network->nwid); // This node is not authorized to join nwid } if (msg->eventCode == ZTS_EVENT_NETWORK_READY_IP4) { printf("ZTS_EVENT_NETWORK_READY_IP4 --- network=%llx\n", msg->network->nwid); network_ready = true; // IPv4 traffic can now be processed for nwid } if (msg->eventCode == ZTS_EVENT_NETWORK_READY_IP6) { printf("ZTS_EVENT_NETWORK_READY_IP6 --- network=%llx\n", msg->network->nwid); network_ready = true; } if (msg->eventCode == ZTS_EVENT_NETWORK_DOWN) { printf("ZTS_EVENT_NETWORK_DOWN --- network=%llx\n", msg->network->nwid); // Can happen if another thread called zts_leave() } // // Network stack events // if (msg->eventCode == ZTS_EVENT_NETIF_UP) { printf("ZTS_EVENT_NETIF_UP --- network=%llx, mac=%llx, mtu=%d\n", msg->netif->nwid, msg->netif->mac, msg->netif->mtu); network_ready = true; } if (msg->eventCode == ZTS_EVENT_NETIF_DOWN) { printf("ZTS_EVENT_NETIF_DOWN --- network=%llx, mac=%llx\n", msg->netif->nwid, msg->netif->mac); network_ready = true; } // // Address events // if (msg->eventCode == ZTS_EVENT_ADDR_ADDED_IP4) { char ipstr[INET_ADDRSTRLEN]; struct sockaddr_in *in4 = (struct sockaddr_in*)&(msg->addr->addr); inet_ntop(AF_INET, &(in4->sin_addr), ipstr, INET_ADDRSTRLEN); printf("ZTS_EVENT_ADDR_NEW_IP4 --- addr=%s (on network=%llx)\n", ipstr, msg->addr->nwid); } if (msg->eventCode == ZTS_EVENT_ADDR_ADDED_IP6) { char ipstr[INET6_ADDRSTRLEN]; struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&(msg->addr->addr); inet_ntop(AF_INET6, &(in6->sin6_addr), ipstr, INET6_ADDRSTRLEN); printf("ZTS_EVENT_ADDR_NEW_IP6 --- addr=%s (on network=%llx)\n", ipstr, msg->addr->nwid); } if (msg->eventCode == ZTS_EVENT_ADDR_REMOVED_IP4) { char ipstr[INET_ADDRSTRLEN]; struct sockaddr_in *in4 = (struct sockaddr_in*)&(msg->addr->addr); inet_ntop(AF_INET, &(in4->sin_addr), ipstr, INET_ADDRSTRLEN); printf("ZTS_EVENT_ADDR_REMOVED_IP4 --- addr=%s (on network=%llx)\n", ipstr, msg->addr->nwid); } if (msg->eventCode == ZTS_EVENT_ADDR_REMOVED_IP6) { char ipstr[INET6_ADDRSTRLEN]; struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&(msg->addr->addr); inet_ntop(AF_INET6, &(in6->sin6_addr), ipstr, INET6_ADDRSTRLEN); printf("ZTS_EVENT_ADDR_REMOVED_IP6 --- addr=%s (on network=%llx)\n", ipstr, msg->addr->nwid); } // // Peer events // if (msg->eventCode == ZTS_EVENT_PEER_P2P) { printf("ZTS_EVENT_PEER_P2P --- node=%llx\n", msg->peer->address); // A direct path is known for nodeId } if (msg->eventCode == ZTS_EVENT_PEER_RELAY) { printf("ZTS_EVENT_PEER_RELAY --- node=%llx\n", msg->peer->address); // No direct path is known for nodeId } } void printPeerDetails(struct zts_peer_details *pd) { printf("\npeer=%llx, latency=%d, version=%d.%d.%d, pathCount=%d\n", pd->address, pd->latency, pd->versionMajor, pd->versionMinor, pd->versionRev, pd->pathCount); // Print all known paths for each peer for (int j=0; jpathCount; j++) { char ipstr[INET6_ADDRSTRLEN]; int port; struct sockaddr *sa = (struct sockaddr *)&(pd->paths[j].address); if (sa->sa_family == AF_INET) { struct sockaddr_in *in4 = (struct sockaddr_in*)sa; inet_ntop(AF_INET, &(in4->sin_addr), ipstr, INET_ADDRSTRLEN); port = ntohs(in4->sin_port); } if (sa->sa_family == AF_INET6) { struct sockaddr_in6 *in6 = (struct sockaddr_in6*)sa; inet_ntop(AF_INET6, &(in6->sin6_addr), ipstr, INET6_ADDRSTRLEN); } printf("\tpath[%d]=%s, port=%d\n", j, ipstr, port); } } void getSinglePeerDetails(uint64_t peerId) { struct zts_peer_details pd; int err = zts_get_peer(&pd, peerId); if (err == ZTS_ERR_OK) { printf("(%d) call succeeded\n", err); } if (err == ZTS_ERR_INVALID_ARG) { printf("(%d) invalid argument\n", err); return; } if (err == ZTS_ERR_SERVICE) { printf("(%d) error: service is unavailable\n", err); return; } if (err == ZTS_ERR_INVALID_OP) { printf("(%d) error: invalid API operation\n", err); return; } if (err == ZTS_ERR_NO_RESULT) { printf("(%d) error: object or result not found\n", err); return; } if (err == 0) { // ZTS_ERR_OK printPeerDetails(&pd); } } // Similar to "zerotier-cli listpeers" void getAllPeerDetails() { struct zts_peer_details pd[128]; /* This number should be large enough to handle the expected number of peers. This call can also get expensive for large numbers of peers. Consider using get_peer(struct zts_peer_details *pds, uint64_t peerId) instead */ int num = 128; int err; if ((err = zts_get_peers(pd, &num)) < 0) { printf("error (%d)\n", err); return; } if (num) { printf("num=%d\n", num); for (int i=0; i