Change event code numbering scheme, fix Windows startup bug, fix zts_free(), remove vestigial API functions, update documentation

This commit is contained in:
Joseph Henry
2020-05-30 18:29:04 -07:00
parent 2ae7ebb0fe
commit 37c01e18cf
12 changed files with 725 additions and 946 deletions

View File

@@ -20,6 +20,7 @@
#include <inttypes.h>
#include <sys/types.h>
#include "Constants.hpp"
#include "Node.hpp"
#include "Mutex.hpp"
#include "OSUtils.hpp"
@@ -36,7 +37,10 @@ using namespace ZeroTier;
#include <jni.h>
#endif
#ifdef __WINDOWS__
#include <Windows.h>
WSADATA wsaData;
#endif
namespace ZeroTier
{
@@ -55,6 +59,10 @@ namespace ZeroTier
#endif
}
#ifdef __cplusplus
extern "C" {
#endif
int zts_allow_network_caching(uint8_t allowed = 1)
{
Mutex::Lock _l(serviceLock);
@@ -121,15 +129,14 @@ int zts_start(const char *path, void (*callback)(void *), uint16_t port)
if (params->path.length() == 0) {
return ZTS_ERR_ARG;
}
int err;
int retval = ZTS_ERR_OK;
_setState(ZTS_STATE_CALLBACKS_RUNNING);
_setState(ZTS_STATE_NODE_RUNNING);
// Start the ZT service thread
#if defined(__WINDOWS__)
WSAStartup(MAKEWORD(2, 2), &wsaData);
HANDLE serviceThread = CreateThread(NULL, 0, _runNodeService, (void*)params, 0, NULL);
HANDLE callbackThread = CreateThread(NULL, 0, _runCallbacks, NULL, 0, NULL);
#else
@@ -155,11 +162,6 @@ int zts_start(const char *path, void (*callback)(void *), uint16_t port)
return retval;
}
#ifdef __cplusplus
extern "C" {
#endif
#ifdef SDK_JNI
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_start(
JNIEnv *env, jobject thisObj, jstring path, jobject callback, jint port)
@@ -205,7 +207,7 @@ int zts_stop()
return ZTS_ERR_SERVICE;
}
#ifdef SDK_JNI
JNIEXPORT void JNICALL Java_com_zerotier_libzt_ZeroTier_stop(
JNIEXPORT void JNICALL Java_com_zerotier_libzt_ZeroTier_stop(
JNIEnv *env, jobject thisObj)
{
zts_stop();
@@ -255,7 +257,7 @@ int zts_restart()
#endif
}
#ifdef SDK_JNI
JNIEXPORT void JNICALL Java_com_zerotier_libzt_ZeroTier_restart(
JNIEXPORT void JNICALL Java_com_zerotier_libzt_ZeroTier_restart(
JNIEnv *env, jobject thisObj)
{
zts_restart();
@@ -264,102 +266,29 @@ int zts_restart()
int zts_free()
{
Mutex::Lock _l(serviceLock);
if (_getState(ZTS_STATE_FREE_CALLED)) {
return ZTS_ERR_SERVICE;
}
_setState(ZTS_STATE_FREE_CALLED);
return zts_stop();
// TODO: add stack shutdown logic
int err = zts_stop();
Mutex::Lock _l(serviceLock);
_lwip_driver_shutdown();
return err;
}
#ifdef SDK_JNI
JNIEXPORT void JNICALL Java_com_zerotier_libzt_ZeroTier_free(
JNIEXPORT void JNICALL Java_com_zerotier_libzt_ZeroTier_free(
JNIEnv *env, jobject thisObj)
{
zts_free();
}
#endif
uint64_t zts_get_node_id()
{
Mutex::Lock _l(serviceLock);
if (!_canPerformServiceOperation()) {
return ZTS_ERR_OK; // Not really
}
return service->getNode()->address();
}
#ifdef SDK_JNI
JNIEXPORT jlong JNICALL Java_com_zerotier_libzt_ZeroTier_get_1node_1id(
JNIEnv *env, jobject thisObj)
{
return zts_get_node_id();
}
#endif
int zts_get_node_status()
{
Mutex::Lock _l(serviceLock);
// Don't check _canPerformServiceOperation() here.
return service
&& service->getNode()
&& service->getNode()->online() ? ZTS_EVENT_NODE_ONLINE : ZTS_EVENT_NODE_OFFLINE;
}
#ifdef SDK_JNI
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_get_1node_1status(
JNIEnv *env, jobject thisObj)
{
return zts_get_node_status();
}
#endif
int zts_get_network_status(uint64_t networkId)
{
Mutex::Lock _l(serviceLock);
if (!networkId) {
return ZTS_ERR_ARG;
}
if (!_canPerformServiceOperation()) {
return ZTS_ERR_SERVICE;
}
/*
TODO:
ZTS_EVENT_NETWORK_READY_IP4
ZTS_EVENT_NETWORK_READY_IP6
ZTS_EVENT_NETWORK_READY_IP4_IP6
*/
return ZTS_ERR_NO_RESULT;
}
#ifdef SDK_JNI
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_get_1network_1status(
JNIEnv *env, jobject thisObj, jlong networkId)
{
return zts_get_network_status(networkId);
}
#endif
int zts_get_peer_status(uint64_t peerId)
{
Mutex::Lock _l(serviceLock);
int retval = ZTS_ERR_OK;
if (!_canPerformServiceOperation()) {
return ZTS_ERR_SERVICE;
}
return service->getPeerStatus(peerId);
}
#ifdef SDK_JNI
JNIEXPORT jlong JNICALL Java_com_zerotier_libzt_ZeroTier_get_1peer_1status(
JNIEnv *env, jobject thisObj, jlong peerId)
{
return zts_get_peer_status(peerId);
}
#endif
#ifdef SDK_JNI
/*
* Called from Java, saves a static reference to the VM so it can be used
* later to call a user-specified callback method from C.
*/
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_init(
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_init(
JNIEnv *env, jobject thisObj)
{
jint rs = env->GetJavaVM(&jvm);
@@ -367,63 +296,44 @@ int zts_get_peer_status(uint64_t peerId)
}
#endif
int zts_join(const uint64_t nwid)
int zts_join(const uint64_t networkId)
{
Mutex::Lock _l(serviceLock);
if (!_canPerformServiceOperation()) {
return ZTS_ERR_SERVICE;
}
else {
service->join(nwid);
service->join(networkId);
}
return ZTS_ERR_OK;
}
#ifdef SDK_JNI
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_join(
JNIEnv *env, jobject thisObj, jlong nwid)
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_join(
JNIEnv *env, jobject thisObj, jlong networkId)
{
return zts_join((uint64_t)nwid);
return zts_join((uint64_t)networkId);
}
#endif
#ifdef __cplusplus
}
#endif
int zts_leave(const uint64_t nwid)
int zts_leave(const uint64_t networkId)
{
Mutex::Lock _l(serviceLock);
if (!_canPerformServiceOperation()) {
return ZTS_ERR_SERVICE;
}
else {
service->leave(nwid);
service->leave(networkId);
}
return ZTS_ERR_OK;
}
#ifdef SDK_JNI
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_leave(
JNIEnv *env, jobject thisObj, jlong nwid)
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_leave(
JNIEnv *env, jobject thisObj, jlong networkId)
{
return zts_leave((uint64_t)nwid);
return zts_leave((uint64_t)networkId);
}
#endif
int zts_leave_all()
{
Mutex::Lock _l(serviceLock);
if (!_canPerformServiceOperation()) {
return ZTS_ERR_SERVICE;
}
else {
service->leaveAll();
}
return ZTS_ERR_OK;
}
#ifdef SDK_JNI
#endif
int zts_orbit(uint64_t moonWorldId, uint64_t moonSeed)
{
Mutex::Lock _l(serviceLock);
@@ -452,197 +362,57 @@ int zts_deorbit(uint64_t moonWorldId)
#ifdef SDK_JNI
#endif
int zts_get_6plane_addr(struct zts_sockaddr_storage *addr, const uint64_t nwid, const uint64_t nodeId)
int zts_get_6plane_addr(struct zts_sockaddr_storage *addr, const uint64_t networkId, const uint64_t nodeId)
{
if (!addr || !nwid || !nodeId) {
if (!addr || !networkId || !nodeId) {
return ZTS_ERR_ARG;
}
InetAddress _6planeAddr = InetAddress::makeIpv66plane(nwid,nodeId);
InetAddress _6planeAddr = InetAddress::makeIpv66plane(networkId,nodeId);
struct sockaddr_in6 *in6 = (struct sockaddr_in6*)addr;
memcpy(in6->sin6_addr.s6_addr, _6planeAddr.rawIpData(), sizeof(struct in6_addr));
return ZTS_ERR_OK;
}
int zts_get_rfc4193_addr(struct zts_sockaddr_storage *addr, const uint64_t nwid, const uint64_t nodeId)
int zts_get_rfc4193_addr(struct zts_sockaddr_storage *addr, const uint64_t networkId, const uint64_t nodeId)
{
if (!addr || !nwid || !nodeId) {
if (!addr || !networkId || !nodeId) {
return ZTS_ERR_ARG;
}
InetAddress _rfc4193Addr = InetAddress::makeIpv6rfc4193(nwid,nodeId);
InetAddress _rfc4193Addr = InetAddress::makeIpv6rfc4193(networkId,nodeId);
struct sockaddr_in6 *in6 = (struct sockaddr_in6*)addr;
memcpy(in6->sin6_addr.s6_addr, _rfc4193Addr.rawIpData(), sizeof(struct in6_addr));
return ZTS_ERR_OK;
}
uint64_t zts_generate_adhoc_nwid_from_range(uint16_t startPortOfRange, uint16_t endPortOfRange)
{
char nwidStr[INET6_ADDRSTRLEN];
sprintf(nwidStr, "ff%04x%04x000000", startPortOfRange, endPortOfRange);
return strtoull(nwidStr, NULL, 16);
char networkIdStr[INET6_ADDRSTRLEN];
sprintf(networkIdStr, "ff%04x%04x000000", startPortOfRange, endPortOfRange);
return strtoull(networkIdStr, NULL, 16);
}
int zts_get_peers(struct zts_peer_details *pds, uint32_t *num)
{
Mutex::Lock _l(serviceLock);
if (!pds || !num) {
return ZTS_ERR_ARG;
}
if (!_canPerformServiceOperation()) {
return ZTS_ERR_SERVICE;
}
ZT_PeerList *pl = service->getNode()->peers();
if (pl) {
if (*num < pl->peerCount) {
service->getNode()->freeQueryResult((void *)pl);
return ZTS_ERR_ARG;
}
*num = pl->peerCount;
for(unsigned long i=0;i<pl->peerCount;++i) {
memcpy(&(pds[i]), &(pl->peers[i]), sizeof(struct zts_peer_details));
for (unsigned int j=0; j<pl->peers[i].pathCount; j++) {
memcpy(&(pds[i].paths[j].address),
&(pl->peers[i].paths[j].address), sizeof(struct sockaddr_storage));
}
}
}
service->getNode()->freeQueryResult((void *)pl);
return ZTS_ERR_OK;
}
#ifdef SDK_JNI
#endif
int zts_get_peer(struct zts_peer_details *pd, uint64_t peerId)
{
Mutex::Lock _l(serviceLock);
if (!pd || !peerId) {
return ZTS_ERR_ARG;
}
if (!_canPerformServiceOperation()) {
return ZTS_ERR_SERVICE;
}
ZT_PeerList *pl = service->getNode()->peers();
int retval = ZTS_ERR_NO_RESULT;
if (pl) {
for(unsigned long i=0;i<pl->peerCount;++i) {
if (pl->peers[i].address == peerId) {
memcpy(pd, &(pl->peers[i]), sizeof(struct zts_peer_details));
for (unsigned int j=0; j<pl->peers[i].pathCount; j++) {
memcpy(&(pd->paths[j].address),
&(pl->peers[i].paths[j].address), sizeof(struct sockaddr_storage));
}
retval = ZTS_ERR_OK;
break;
}
}
}
service->getNode()->freeQueryResult((void *)pl);
return retval;
}
#ifdef SDK_JNI
#endif
void _get_network_details_helper(uint64_t nwid, struct zts_network_details *nd)
{
/*
socklen_t addrlen;
VirtualTap *tap = vtapMap[nwid];
nd->nwid = tap->_nwid;
nd->mtu = tap->_mtu;
// assigned addresses
nd->num_addresses = tap->_ips.size() < ZTS_MAX_ASSIGNED_ADDRESSES ? tap->_ips.size() : ZTS_MAX_ASSIGNED_ADDRESSES;
for (int j=0; j<nd->num_addresses; j++) {
addrlen = tap->_ips[j].isV4() ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6);
memcpy(&(nd->addr[j]), &(tap->_ips[j]), addrlen);
}
// routes
nd->num_routes = ZTS_MAX_NETWORK_ROUTES;;
service->getRoutes(nwid, (ZT_VirtualNetworkRoute*)&(nd->routes)[0], &(nd->num_routes));
*/
}
void _get_network_details(uint64_t nwid, struct zts_network_details *nd)
{
/*
_vtaps_lock.lock();
_get_network_details_helper(nwid, nd);
_vtaps_lock.unlock();
*/
}
void _get_all_network_details(struct zts_network_details *nds, int *num)
{
/*
_vtaps_lock.lock();
*num = vtapMap.size();
int idx = 0;
std::map<uint64_t, VirtualTap*>::iterator it;
for (it = vtapMap.begin(); it != vtapMap.end(); it++) {
_get_network_details(it->first, &nds[idx]);
idx++;
}
_vtaps_lock.unlock();
*/
}
int zts_get_network_details(uint64_t nwid, struct zts_network_details *nd)
{
/*
serviceLock.lock();
int retval = ZTS_ERR_OK;
if (!nd || nwid == 0) {
retval = ZTS_ERR_ARG;
}
if (!service || _freeHasBeenCalled || _serviceIsShuttingDown) {
retval = ZTS_ERR_SERVICE;
}
if (retval == ZTS_ERR_OK) {
_get_network_details(nwid, nd);
}
serviceLock.unlock();
return retval;
*/
return 0;
}
#ifdef SDK_JNI
#endif
int zts_get_all_network_details(struct zts_network_details *nds, int *num)
{
/*
serviceLock.lock();
int retval = ZTS_ERR_OK;
if (!nds || !num) {
retval = ZTS_ERR_ARG;
}
if (!service || _freeHasBeenCalled || _serviceIsShuttingDown) {
retval = ZTS_ERR_SERVICE;
}
if (retval == ZTS_ERR_OK) {
_get_all_network_details(nds, num);
}
serviceLock.unlock();
return retval;
*/
return 0;
}
#ifdef SDK_JNI
#endif
void zts_delay_ms(long interval_ms)
{
#if defined(__WINDOWS__)
Sleep(interval_ms);
#ifdef __WINDOWS__
#include <windows.h>
#elif _POSIX_C_SOURCE >= 199309L
#include <time.h> // for nanosleep
#else
struct timespec sleepValue = {0};
sleepValue.tv_nsec = interval_ms * 500000;
nanosleep(&sleepValue, NULL);
#include <unistd.h> // for usleep
#endif
void zts_delay_ms(long milliseconds)
{
#ifdef __WINDOWS__
Sleep(milliseconds);
#elif _POSIX_C_SOURCE >= 199309L
struct timespec ts;
ts.tv_sec = milliseconds / 1000;
ts.tv_nsec = (milliseconds % 1000) * 1000000;
nanosleep(&ts, NULL);
#else
usleep(milliseconds * 1000);
#endif
}
#ifdef __cplusplus
}
#endif

View File

@@ -136,7 +136,6 @@
#else
#define DEBUG_TRANS(fmt, args...)
#endif
#else // !LIBZT_DEBUG || !__NATIVE_TEST__
#if defined(_WIN32)
#define DEBUG_ERROR(...)

View File

@@ -23,6 +23,7 @@
#include <jni.h>
#endif
#include "Constants.hpp"
#include "Node.hpp"
#include "OSUtils.hpp"
@@ -32,11 +33,10 @@
#include "NodeService.hpp"
#define NODE_EVENT_TYPE(code) code >= ZTS_EVENT_NODE_UP && code <= ZTS_EVENT_NODE_NORMAL_TERMINATION
#define NETWORK_EVENT_TYPE(code) code >= ZTS_EVENT_NETWORK_NOT_FOUND && code <= ZTS_EVENT_NETWORK_DOWN
#define NETWORK_EVENT_TYPE(code) code >= ZTS_EVENT_NETWORK_NOT_FOUND && code <= ZTS_EVENT_NETWORK_UPDATE
#define STACK_EVENT_TYPE(code) code >= ZTS_EVENT_STACK_UP && code <= ZTS_EVENT_STACK_DOWN
#define NETIF_EVENT_TYPE(code) code >= ZTS_EVENT_NETIF_UP && code <= ZTS_EVENT_NETIF_LINK_DOWN
#define PEER_EVENT_TYPE(code) code >= ZTS_EVENT_PEER_DIRECT && code <= ZTS_EVENT_PEER_UNREACHABLE
#define PATH_EVENT_TYPE(code) code >= ZTS_EVENT_PATH_DISCOVERED && code <= ZTS_EVENT_PATH_DEAD
#define PEER_EVENT_TYPE(code) code >= ZTS_EVENT_PEER_DIRECT && code <= ZTS_EVENT_PEER_PATH_DEAD
#define ROUTE_EVENT_TYPE(code) code >= ZTS_EVENT_ROUTE_ADDED && code <= ZTS_EVENT_ROUTE_REMOVED
#define ADDR_EVENT_TYPE(code) code >= ZTS_EVENT_ADDR_ADDED_IP4 && code <= ZTS_EVENT_ADDR_REMOVED_IP6
@@ -52,41 +52,39 @@ Mutex _callbackLock;
void (*_userEventCallbackFunc)(void *);
moodycamel::ConcurrentQueue<struct ::zts_callback_msg*> _callbackMsgQueue;
moodycamel::ConcurrentQueue<struct zts_callback_msg*> _callbackMsgQueue;
void _enqueueEvent(int16_t eventCode, void *arg)
{
struct ::zts_callback_msg *msg = new ::zts_callback_msg();
msg->node = NULL;
msg->network = NULL;
msg->netif = NULL;
msg->route = NULL;
msg->path = NULL;
msg->peer = NULL;
msg->addr = NULL;
struct zts_callback_msg *msg = new zts_callback_msg();
msg->eventCode = eventCode;
if (NODE_EVENT_TYPE(eventCode)) {
msg->node = (struct zts_node_details*)arg;
} if (NETWORK_EVENT_TYPE(eventCode)) {
msg->network = (struct zts_network_details*)arg;
} if (STACK_EVENT_TYPE(eventCode)) {
/* nothing to convey to user */
} if (NETIF_EVENT_TYPE(eventCode)) {
msg->netif = (struct zts_netif_details*)arg;
} if (ROUTE_EVENT_TYPE(eventCode)) {
msg->route = (struct zts_virtual_network_route*)arg;
} if (PATH_EVENT_TYPE(eventCode)) {
msg->path = (struct zts_physical_path*)arg;
} if (PEER_EVENT_TYPE(eventCode)) {
msg->peer = (struct zts_peer_details*)arg;
} if (ADDR_EVENT_TYPE(eventCode)) {
msg->addr = (struct zts_addr_details*)arg;
}
_callbackMsgQueue.enqueue(msg);
if (msg && _callbackMsgQueue.size_approx() > 1024) {
// Rate-limit number of events
_freeEvent(msg);
}
else {
_callbackMsgQueue.enqueue(msg);
}
}
void _freeEvent(struct ::zts_callback_msg *msg)
void _freeEvent(struct zts_callback_msg *msg)
{
if (!msg) {
return;
@@ -95,21 +93,21 @@ void _freeEvent(struct ::zts_callback_msg *msg)
if (msg->network) { delete msg->network; }
if (msg->netif) { delete msg->netif; }
if (msg->route) { delete msg->route; }
if (msg->path) { delete msg->path; }
if (msg->peer) { delete msg->peer; }
if (msg->addr) { delete msg->addr; }
}
void _passDequeuedEventToUser(struct ::zts_callback_msg *msg)
void _passDequeuedEventToUser(struct zts_callback_msg *msg)
{
bool bShouldStopCallbackThread = (msg->eventCode == ZTS_EVENT_STACK_DOWN);
#ifdef SDK_JNI
if(_userCallbackMethodRef) {
JNIEnv *env;
#if defined(__ANDROID__)
#if defined(__ANDROID__)
jint rs = jvm->AttachCurrentThread(&env, NULL);
#else
#else
jint rs = jvm->AttachCurrentThread((void **)&env, NULL);
#endif
#endif
assert (rs == JNI_OK);
uint64_t arg = 0;
uint64_t id = 0;
@@ -131,6 +129,11 @@ void _passDequeuedEventToUser(struct ::zts_callback_msg *msg)
_freeEvent(msg);
}
#endif
if (bShouldStopCallbackThread) {
/* Ensure last possible callback ZTS_EVENT_STACK_DOWN is
delivered before callback thread is finally stopped. */
_clrState(ZTS_STATE_CALLBACKS_RUNNING);
}
}
bool _isCallbackRegistered()
@@ -168,8 +171,8 @@ int _canPerformServiceOperation()
}
#define RESET_FLAGS( ) _serviceStateFlags = 0;
#define SET_FLAGS(f) _serviceStateFlags |= f;
#define CLR_FLAGS(f) _serviceStateFlags &= ~f;
#define SET_FLAGS(f) _serviceStateFlags |= f;
#define CLR_FLAGS(f) _serviceStateFlags &= ~f;
#define GET_FLAGS(f) ((_serviceStateFlags & f) > 0)
void _setState(uint8_t newFlags)
@@ -222,7 +225,7 @@ void *_runCallbacks(void *thread_id)
#endif
while (_getState(ZTS_STATE_CALLBACKS_RUNNING) || _callbackMsgQueue.size_approx() > 0)
{
struct ::zts_callback_msg *msg;
struct zts_callback_msg *msg;
size_t sz = _callbackMsgQueue.size_approx();
for (size_t j = 0; j < sz; j++) {
if (_callbackMsgQueue.try_dequeue(msg)) {

View File

@@ -22,8 +22,13 @@
#include <string>
#include "Constants.hpp"
#include "ZeroTierSockets.h"
#ifdef __WINDOWS__
#include <BaseTsd.h>
#endif
#ifdef SDK_JNI
#include <jni.h>
#endif

View File

@@ -18,6 +18,9 @@
*/
#include <thread>
#include <iostream>
#include "../version.h"
#include "Debug.hpp"
#include "Events.hpp"
@@ -39,7 +42,7 @@
#include "BlockingQueue.hpp"
#if defined(__WINDOWS__)
WSADATA wsaData;
//WSADATA wsaData;
#include <WinSock2.h>
#include <Windows.h>
#include <ShlObj.h>
@@ -123,7 +126,7 @@ public:
volatile unsigned int _udpPortPickerCounter;
//
std::map<uint64_t, bool> peerCache;
std::map<uint64_t, int> peerCache;
//
unsigned long _incomingPacketConcurrency;
@@ -230,10 +233,6 @@ public:
allowNetworkCaching = true;
allowPeerCaching = true;
allowLocalConf = false;
#ifdef __WINDOWS__
// Initialize WinSock. Used in Phy for loopback pipe
WSAStartup(MAKEWORD(2, 2), &wsaData);
#endif
}
virtual ~NodeServiceImpl()
@@ -609,14 +608,42 @@ public:
newManagedIps.erase(std::unique(newManagedIps.begin(),newManagedIps.end()),newManagedIps.end());
for(std::vector<InetAddress>::iterator ip(n.managedIps.begin());ip!=n.managedIps.end();++ip) {
if (std::find(newManagedIps.begin(),newManagedIps.end(),*ip) == newManagedIps.end()) {
if (!n.tap->removeIp(*ip))
if (!n.tap->removeIp(*ip)) {
fprintf(stderr,"ERROR: unable to remove ip address %s" ZT_EOL_S, ip->toString(ipbuf));
} else {
struct zts_addr_details *ad = new zts_addr_details();
ad->nwid = n.tap->_nwid;
if ((*ip).isV4()) {
struct sockaddr_in *in4 = (struct sockaddr_in*)&(ad->addr);
memcpy(&(in4->sin_addr.s_addr), (*ip).rawIpData(), 4);
_enqueueEvent(ZTS_EVENT_ADDR_REMOVED_IP4, (void*)ad);
}
if ((*ip).isV6()) {
struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&(ad->addr);
memcpy(&(in6->sin6_addr.s6_addr), (*ip).rawIpData(), 16);
_enqueueEvent(ZTS_EVENT_ADDR_REMOVED_IP6, (void*)ad);
}
}
}
}
for(std::vector<InetAddress>::iterator ip(newManagedIps.begin());ip!=newManagedIps.end();++ip) {
if (std::find(n.managedIps.begin(),n.managedIps.end(),*ip) == n.managedIps.end()) {
if (!n.tap->addIp(*ip))
if (!n.tap->addIp(*ip)) {
fprintf(stderr,"ERROR: unable to add ip address %s" ZT_EOL_S, ip->toString(ipbuf));
} else {
struct zts_addr_details *ad = new zts_addr_details();
ad->nwid = n.tap->_nwid;
if ((*ip).isV4()) {
struct sockaddr_in *in4 = (struct sockaddr_in*)&(ad->addr);
memcpy(&(in4->sin_addr.s_addr), (*ip).rawIpData(), 4);
_enqueueEvent(ZTS_EVENT_ADDR_ADDED_IP4, (void*)ad);
}
if ((*ip).isV6()) {
struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&(ad->addr);
memcpy(&(in6->sin6_addr.s6_addr), (*ip).rawIpData(), 16);
_enqueueEvent(ZTS_EVENT_ADDR_ADDED_IP6, (void*)ad);
}
}
}
}
n.managedIps.swap(newManagedIps);
@@ -694,6 +721,9 @@ public:
_nets.erase(nwid);
return -999; // tap init failed
}
if (op == ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE) { // Prevent junk from ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP
_enqueueEvent(ZTS_EVENT_NETWORK_UPDATE, (void*)prepare_network_details_msg(n));
}
break;
case ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DOWN:
@@ -727,6 +757,12 @@ public:
case ZT_EVENT_ONLINE: {
struct zts_node_details *nd = new zts_node_details;
nd->address = _node->address();
nd->versionMajor = ZEROTIER_ONE_VERSION_MAJOR;
nd->versionMinor = ZEROTIER_ONE_VERSION_MINOR;
nd->versionRev = ZEROTIER_ONE_VERSION_REVISION;
nd->primaryPort = _primaryPort;
nd->secondaryPort = _secondaryPort;
nd->tertiaryPort = _tertiaryPort;
_enqueueEvent(ZTS_EVENT_NODE_ONLINE, (void*)nd);
} break;
case ZT_EVENT_OFFLINE: {
@@ -758,10 +794,65 @@ public:
}
}
inline struct zts_network_details *prepare_network_details_msg(uint64_t nwid)
void native_ss_to_zts_ss(struct zts_sockaddr_storage *ss_out, const struct sockaddr_storage *ss_in)
{
struct zts_network_details *nd = new zts_network_details;
nd->nwid = nwid;
if (ss_in->ss_family == AF_INET) {
struct sockaddr_in *s_in4 = (struct sockaddr_in *)ss_in;
struct zts_sockaddr_in *d_in4 = (struct zts_sockaddr_in *)ss_out;
#ifndef __WINDOWS__
d_in4->sin_len = 0; // s_in4->sin_len;
#endif
d_in4->sin_family = ZTS_AF_INET;
d_in4->sin_port = s_in4->sin_port;
memcpy(&(d_in4->sin_addr), &(s_in4->sin_addr), sizeof(s_in4->sin_addr));
}
if (ss_in->ss_family == AF_INET6) {
struct sockaddr_in6 *s_in6 = (struct sockaddr_in6 *)ss_in;
struct zts_sockaddr_in6 *d_in6 = (struct zts_sockaddr_in6 *)ss_out;
#ifndef __WINDOWS__
d_in6->sin6_len = 0; // s_in6->sin6_len;
#endif
d_in6->sin6_family = ZTS_AF_INET6;
d_in6->sin6_port = s_in6->sin6_port;
d_in6->sin6_flowinfo = s_in6->sin6_flowinfo;
memcpy(&(d_in6->sin6_addr), &(s_in6->sin6_addr), sizeof(s_in6->sin6_addr));
d_in6->sin6_scope_id = s_in6->sin6_scope_id;
}
}
struct zts_network_details *prepare_network_details_msg(const NetworkState &n)
{
struct zts_network_details *nd = new zts_network_details();
nd->nwid = n.config.nwid;
nd->mac = n.config.mac;
memcpy(nd->name, n.config.name, sizeof(n.config.name));
nd->status = (ZTS_VirtualNetworkStatus)n.config.status;
nd->type = (ZTS_VirtualNetworkType)n.config.type;
nd->mtu = n.config.mtu;
nd->dhcp = n.config.dhcp;
nd->bridge = n.config.bridge;
nd->broadcastEnabled = n.config.broadcastEnabled;
nd->portError = n.config.portError;
nd->netconfRevision = n.config.netconfRevision;
// Copy and convert address structures
nd->assignedAddressCount = n.config.assignedAddressCount;
for (int i=0; i<n.config.assignedAddressCount; i++) {
native_ss_to_zts_ss(&(nd->assignedAddresses[i]), &(n.config.assignedAddresses[i]));
}
nd->routeCount = n.config.routeCount;
for (int i=0; i<n.config.routeCount; i++) {
native_ss_to_zts_ss(&(nd->routes[i].target), &(n.config.routes[i].target));
native_ss_to_zts_ss(&(nd->routes[i].via), &(n.config.routes[i].via));
nd->routes[i].flags = n.config.routes[i].flags;
nd->routes[i].metric = n.config.routes[i].metric;
}
nd->multicastSubscriptionCount = n.config.multicastSubscriptionCount;
memcpy(nd->multicastSubscriptions, &(n.config.multicastSubscriptions), sizeof(n.config.multicastSubscriptions));
return nd;
}
@@ -783,34 +874,34 @@ public:
}
switch (mostRecentStatus) {
case ZT_NETWORK_STATUS_NOT_FOUND:
_enqueueEvent(ZTS_EVENT_NETWORK_NOT_FOUND, (void*)prepare_network_details_msg(nwid));
_enqueueEvent(ZTS_EVENT_NETWORK_NOT_FOUND, (void*)prepare_network_details_msg(n->second));
break;
case ZT_NETWORK_STATUS_CLIENT_TOO_OLD:
_enqueueEvent(ZTS_EVENT_NETWORK_CLIENT_TOO_OLD, (void*)prepare_network_details_msg(nwid));
_enqueueEvent(ZTS_EVENT_NETWORK_CLIENT_TOO_OLD, (void*)prepare_network_details_msg(n->second));
break;
case ZT_NETWORK_STATUS_REQUESTING_CONFIGURATION:
_enqueueEvent(ZTS_EVENT_NETWORK_REQ_CONFIG, (void*)prepare_network_details_msg(nwid));
_enqueueEvent(ZTS_EVENT_NETWORK_REQ_CONFIG, (void*)prepare_network_details_msg(n->second));
break;
case ZT_NETWORK_STATUS_OK:
if (tap->hasIpv4Addr() && _lwip_is_netif_up(tap->netif4)) {
_enqueueEvent(ZTS_EVENT_NETWORK_READY_IP4, (void*)prepare_network_details_msg(nwid));
_enqueueEvent(ZTS_EVENT_NETWORK_READY_IP4, (void*)prepare_network_details_msg(n->second));
}
if (tap->hasIpv6Addr() && _lwip_is_netif_up(tap->netif6)) {
_enqueueEvent(ZTS_EVENT_NETWORK_READY_IP6, (void*)prepare_network_details_msg(nwid));
_enqueueEvent(ZTS_EVENT_NETWORK_READY_IP6, (void*)prepare_network_details_msg(n->second));
}
// In addition to the READY messages, send one OK message
_enqueueEvent(ZTS_EVENT_NETWORK_OK, (void*)prepare_network_details_msg(nwid));
_enqueueEvent(ZTS_EVENT_NETWORK_OK, (void*)prepare_network_details_msg(n->second));
break;
case ZT_NETWORK_STATUS_ACCESS_DENIED:
_enqueueEvent(ZTS_EVENT_NETWORK_ACCESS_DENIED, (void*)prepare_network_details_msg(nwid));
_enqueueEvent(ZTS_EVENT_NETWORK_ACCESS_DENIED, (void*)prepare_network_details_msg(n->second));
break;
default:
break;
}
n->second.tap->_networkStatus = mostRecentStatus;
}
// TODO: Add ZTS_EVENT_PEER_NEW
bool bShouldCopyPeerInfo = false;
int eventCode = 0;
ZT_PeerList *pl = _node->peers();
struct zts_peer_details *pd;
if (pl) {
@@ -818,28 +909,41 @@ public:
if (!peerCache.count(pl->peers[i].address)) {
// New peer, add status
if (pl->peers[i].pathCount > 0) {
pd = new zts_peer_details;
memcpy(pd, &(pl->peers[i]), sizeof(struct zts_peer_details));
_enqueueEvent(ZTS_EVENT_PEER_DIRECT, (void*)pd);
bShouldCopyPeerInfo=true;
eventCode = ZTS_EVENT_PEER_DIRECT;
}
if (pl->peers[i].pathCount == 0) {
pd = new zts_peer_details;
memcpy(pd, &(pl->peers[i]), sizeof(struct zts_peer_details));
_enqueueEvent(ZTS_EVENT_PEER_RELAY, (void*)pd);
bShouldCopyPeerInfo=true;
eventCode = ZTS_EVENT_PEER_RELAY, (void*)pd;
}
}
// Previously known peer, update status
else {
if ((peerCache[pl->peers[i].address] == false) && pl->peers[i].pathCount > 0) {
pd = new zts_peer_details;
memcpy(pd, &(pl->peers[i]), sizeof(struct zts_peer_details));
_enqueueEvent(ZTS_EVENT_PEER_DIRECT, (void*)pd);
if (peerCache[pl->peers[i].address] < pl->peers[i].pathCount) {
bShouldCopyPeerInfo=true;
eventCode = ZTS_EVENT_PEER_PATH_DISCOVERED, (void*)pd;
}
if ((peerCache[pl->peers[i].address] == true) && pl->peers[i].pathCount == 0) {
pd = new zts_peer_details;
memcpy(pd, &(pl->peers[i]), sizeof(struct zts_peer_details));
_enqueueEvent(ZTS_EVENT_PEER_RELAY, (void*)pd);
if (peerCache[pl->peers[i].address] > pl->peers[i].pathCount) {
bShouldCopyPeerInfo=true;
eventCode = ZTS_EVENT_PEER_PATH_DEAD, (void*)pd;
}
if (peerCache[pl->peers[i].address] == 0 && pl->peers[i].pathCount > 0) {
bShouldCopyPeerInfo=true;
eventCode = ZTS_EVENT_PEER_DIRECT, (void*)pd;
}
if (peerCache[pl->peers[i].address] > 0 && pl->peers[i].pathCount == 0) {
bShouldCopyPeerInfo=true;
eventCode = ZTS_EVENT_PEER_RELAY, (void*)pd;
}
}
if (bShouldCopyPeerInfo) {
pd = new zts_peer_details();
memcpy(pd, &(pl->peers[i]), sizeof(struct zts_peer_details));
for (unsigned int j=0; j<pl->peers[i].pathCount; j++) {
native_ss_to_zts_ss(&(pd->paths[j].address), &(pl->peers[i].paths[j].address));
}
_enqueueEvent(eventCode, (void*)pd);
bShouldCopyPeerInfo = false;
}
// Update our cache with most recently observed path count
peerCache[pl->peers[i].address] = pl->peers[i].pathCount;
@@ -848,12 +952,6 @@ public:
_node->freeQueryResult((void *)pl);
}
inline size_t networkCount()
{
Mutex::Lock _l(_nets_m);
return _nets.size();
}
inline void join(uint64_t nwid)
{
_node->join(nwid, NULL, NULL);
@@ -864,30 +962,6 @@ public:
_node->leave(nwid, NULL, NULL);
}
inline void leaveAll()
{
Mutex::Lock _l(_nets_m);
for(std::map<uint64_t,NetworkState>::iterator n(_nets.begin());n!=_nets.end();++n) {
_node->leave(n->first, NULL, NULL);
}
}
inline int getPeerStatus(uint64_t id)
{
ZT_PeerList *pl = _node->peers();
int status = ZTS_EVENT_PEER_UNREACHABLE;
if (pl) {
for(unsigned long i=0;i<pl->peerCount;++i) {
if (pl->peers[i].address == id) {
status = pl->peers[i].pathCount > 0 ? ZTS_EVENT_PEER_DIRECT : ZTS_EVENT_PEER_RELAY;
break;
}
}
}
_node->freeQueryResult((void *)pl);
return status;
}
inline void nodeStatePutFunction(enum ZT_StateObjectType type,const uint64_t id[2],const void *data,int len)
{
char p[1024];
@@ -1232,7 +1306,7 @@ DWORD WINAPI _runNodeService(LPVOID arg)
#else
void *_runNodeService(void *arg)
#endif
{
{
#if defined(__APPLE__)
pthread_setname_np(ZTS_SERVICE_THREAD_NAME);
#endif
@@ -1295,12 +1369,12 @@ void *_runNodeService(void *arg)
service = (NodeService *)0;
serviceLock.unlock();
_enqueueEvent(ZTS_EVENT_NODE_DOWN,NULL);
} catch ( ... ) {
}
catch ( ... ) {
DEBUG_ERROR("unexpected exception starting ZeroTier instance");
}
delete params;
zts_delay_ms(ZTS_CALLBACK_PROCESSING_INTERVAL*2);
_clrState(ZTS_STATE_CALLBACKS_RUNNING);
#ifndef __WINDOWS__
pthread_exit(0);
#endif

View File

@@ -23,6 +23,7 @@
#include <string>
#include <vector>
#include "Constants.hpp"
#include "Node.hpp"
#include "InetAddress.hpp"
#include "Mutex.hpp"
@@ -168,12 +169,9 @@ public:
*/
virtual void getRoutes(uint64_t nwid, void *routeArray, unsigned int *numRoutes) = 0;
virtual size_t networkCount() = 0;
virtual void leaveAll() = 0;
virtual void join(uint64_t nwid) = 0;
virtual void leave(uint64_t nwid) = 0;
virtual int getPeerStatus(uint64_t id) = 0;
/**
* Terminate background service (can be called from other threads)
*/

View File

@@ -23,7 +23,13 @@
#include "lwip/stats.h"
#include "ZeroTierSockets.h"
#include "Events.hpp"
//#include "Events.hpp"
#define ZTS_STATE_NODE_RUNNING 0x01
#define ZTS_STATE_STACK_RUNNING 0x02
#define ZTS_STATE_NET_SERVICE_RUNNING 0x04
#define ZTS_STATE_CALLBACKS_RUNNING 0x08
#define ZTS_STATE_FREE_CALLED 0x10
#ifdef SDK_JNI
#include <jni.h>

View File

@@ -17,6 +17,7 @@
* Virtual ethernet tap device and combined network stack driver
*/
#include "Constants.hpp"
#include "MAC.hpp"
#include "Mutex.hpp"
#include "InetAddress.hpp"
@@ -90,7 +91,6 @@ VirtualTap::~VirtualTap()
{
struct zts_network_details *nd = new zts_network_details;
nd->nwid = _nwid;
_enqueueEvent(ZTS_EVENT_NETWORK_DOWN, (void*)nd);
_run = false;
#ifndef __WINDOWS__
::write(_shutdownSignalPipe[1],"\0",1);
@@ -100,6 +100,7 @@ VirtualTap::~VirtualTap()
netif4 = NULL;
_lwip_remove_netif(netif6);
netif6 = NULL;
_enqueueEvent(ZTS_EVENT_NETWORK_DOWN, (void*)nd);
Thread::join(_thread);
#ifndef __WINDOWS__
::close(_shutdownSignalPipe[0]);
@@ -170,21 +171,7 @@ bool VirtualTap::addIp(const InetAddress &ip)
}
if (std::find(_ips.begin(),_ips.end(),ip) == _ips.end()) {
_lwip_init_interface((void*)this, ip);
// TODO: Add ZTS_EVENT_ADDR_NEW ?
_ips.push_back(ip);
// Send callback message
struct zts_addr_details *ad = new zts_addr_details;
ad->nwid = _nwid;
if (ip.isV4()) {
struct sockaddr_in *in4 = (struct sockaddr_in*)&(ad->addr);
memcpy(&(in4->sin_addr.s_addr), ip.rawIpData(), 4);
_enqueueEvent(ZTS_EVENT_ADDR_ADDED_IP4, (void*)ad);
}
if (ip.isV6()) {
struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&(ad->addr);
memcpy(&(in6->sin6_addr.s6_addr), ip.rawIpData(), 16);
_enqueueEvent(ZTS_EVENT_ADDR_ADDED_IP6, (void*)ad);
}
std::sort(_ips.begin(),_ips.end());
}
return true;
@@ -195,20 +182,7 @@ bool VirtualTap::removeIp(const InetAddress &ip)
Mutex::Lock _l(_ips_m);
std::vector<InetAddress>::iterator i(std::find(_ips.begin(),_ips.end(),ip));
if (std::find(_ips.begin(),_ips.end(),ip) != _ips.end()) {
struct zts_addr_details *ad = new zts_addr_details;
ad->nwid = _nwid;
if (ip.isV4()) {
struct sockaddr_in *in4 = (struct sockaddr_in*)&(ad->addr);
memcpy(&(in4->sin_addr.s_addr), ip.rawIpData(), 4);
_enqueueEvent(ZTS_EVENT_ADDR_REMOVED_IP4, (void*)ad);
// FIXME: De-register from network stack
}
if (ip.isV6()) {
// FIXME: De-register from network stack
struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&(ad->addr);
memcpy(&(in6->sin6_addr.s6_addr), ip.rawIpData(), 16);
_enqueueEvent(ZTS_EVENT_ADDR_REMOVED_IP6, (void*)ad);
}
_lwip_remove_address_from_netif((void*)this, ip);
_ips.erase(i);
}
return true;
@@ -361,18 +335,12 @@ bool _lwip_is_up()
return _getState(ZTS_STATE_STACK_RUNNING);
}
bool _lwip_has_previously_shutdown()
{
Mutex::Lock _l(stackLock);
return _has_exited;
}
void _lwip_driver_init()
{
if (_lwip_is_up()) {
return;
}
if (_lwip_has_previously_shutdown()) {
if (_has_exited) {
return;
}
Mutex::Lock _l(stackLock);
@@ -385,7 +353,7 @@ void _lwip_driver_init()
void _lwip_driver_shutdown()
{
if (_lwip_has_previously_shutdown()) {
if (_has_exited) {
return;
}
Mutex::Lock _l(stackLock);
@@ -393,11 +361,6 @@ void _lwip_driver_shutdown()
_clrState(ZTS_STATE_STACK_RUNNING);
// Wait until the main lwIP thread has exited
while (!_has_exited) { zts_delay_ms(LWIP_DRIVER_LOOP_INTERVAL); }
/*
if (tcpip_shutdown() == ERR_OK) {
sys_timeouts_free();
}
*/
}
void _lwip_remove_netif(void *netif)
@@ -532,28 +495,6 @@ void _lwip_eth_rx(VirtualTap *tap, const MAC &from, const MAC &to, unsigned int
}
}
/*
static void print_netif_info(struct netif *n) {
DEBUG_INFO("n=%p, %c%c, %d, o=%p, o6=%p, mc=%x:%x:%x:%x:%x:%x, hwln=%d, st=%p, flgs=%d\n",
n,
n->name[0],
n->name[1],
n->mtu,
n->output,
n->output_ip6,
n->hwaddr[0],
n->hwaddr[1],
n->hwaddr[2],
n->hwaddr[3],
n->hwaddr[4],
n->hwaddr[5],
n->hwaddr_len,
n->state,
n->flags
);
}
*/
bool _lwip_is_netif_up(void *n)
{
if (!n) {
@@ -565,10 +506,19 @@ bool _lwip_is_netif_up(void *n)
return result;
}
/**
* Called when a netif is removed (ZTS_EVENT_NETIF_INTERFACE_REMOVED)
*/
#if LWIP_NETIF_REMOVE_CALLBACK
static struct zts_netif_details *_lwip_prepare_netif_status_msg(struct netif *n)
{
if (!n || !n->state) {
return NULL;
}
VirtualTap *tap = (VirtualTap *)n->state;
struct zts_netif_details *details = new zts_netif_details();
details->nwid = tap->_nwid;
memcpy(&(details->mac), n->hwaddr, n->hwaddr_len);
details->mtu = n->mtu;
return details;
}
static void _netif_remove_callback(struct netif *n)
{
// Called from core, no need to lock
@@ -576,75 +526,35 @@ static void _netif_remove_callback(struct netif *n)
return;
}
VirtualTap *tap = (VirtualTap *)n->state;
uint64_t mac = 0;
memcpy(&mac, n->hwaddr, n->hwaddr_len);
struct zts_netif_details *ifd = new zts_netif_details;
ifd->nwid = tap->_nwid;
memcpy(&(ifd->mac), n->hwaddr, n->hwaddr_len);
ifd->mac = lwip_htonl(ifd->mac) >> 16;
_enqueueEvent(ZTS_EVENT_NETIF_REMOVED, (void*)ifd);
struct zts_netif_details *details = new zts_netif_details();
details->nwid = tap->_nwid;
details->mac = 0;
details->mtu = 0;
_enqueueEvent(ZTS_EVENT_NETIF_REMOVED, (void*)details);
}
static void _netif_status_callback(struct netif *n)
{
// Called from core, no need to lock
if (!n) {
return;
} if (netif_is_up(n)) {
_enqueueEvent(ZTS_EVENT_NETIF_UP, (void*)_lwip_prepare_netif_status_msg(n));
} else {
_enqueueEvent(ZTS_EVENT_NETIF_DOWN, (void*)_lwip_prepare_netif_status_msg(n));
}
}
#endif
/**
* Called when a link is brought up or down (ZTS_EVENT_NETIF_LINK_UP, ZTS_EVENT_NETIF_LINK_DOWN)
*/
#if LWIP_NETIF_LINK_CALLBACK
static void _netif_link_callback(struct netif *n)
{
// Called from core, no need to lock
if (!n || !n->state) {
return;
}
VirtualTap *tap = (VirtualTap *)n->state;
uint64_t mac = 0;
memcpy(&mac, n->hwaddr, n->hwaddr_len);
if (n->flags & NETIF_FLAG_LINK_UP) {
struct zts_netif_details *ifd = new zts_netif_details;
ifd->nwid = tap->_nwid;
memcpy(&(ifd->mac), n->hwaddr, n->hwaddr_len);
ifd->mac = lwip_htonl(ifd->mac) >> 16;
_enqueueEvent(ZTS_EVENT_NETIF_LINK_UP, (void*)ifd);
}
if (n->flags & NETIF_FLAG_LINK_UP) {
struct zts_netif_details *ifd = new zts_netif_details;
ifd->nwid = tap->_nwid;
memcpy(&(ifd->mac), n->hwaddr, n->hwaddr_len);
ifd->mac = lwip_htonl(ifd->mac) >> 16;
_enqueueEvent(ZTS_EVENT_NETIF_LINK_DOWN, (void*)ifd);
}
}
#endif
void _lwip_set_callbacks(struct netif *n)
{
if (!n) {
return;
} if (netif_is_link_up(n)) {
_enqueueEvent(ZTS_EVENT_NETIF_LINK_UP, (void*)_lwip_prepare_netif_status_msg(n));
} else {
_enqueueEvent(ZTS_EVENT_NETIF_LINK_DOWN, (void*)_lwip_prepare_netif_status_msg(n));
}
#if LWIP_NETIF_STATUS_CALLBACK
// Not currently used
netif_set_status_callback(n, netif_status_callback);
#endif
#if LWIP_NETIF_REMOVE_CALLBACK
netif_set_remove_callback(n, netif_remove_callback);
#endif
#if LWIP_NETIF_LINK_CALLBACK
netif_set_link_callback(n, netif_link_callback);
#endif
}
static struct zts_netif_details *_lwip_prepare_netif_status_msg(struct netif *n)
{
if (!n || !n->state) {
return NULL;
}
VirtualTap *tap = (VirtualTap*)(n->state);
struct zts_netif_details *ifd = new zts_netif_details;
ifd->nwid = tap->_nwid;
ifd->mtu = n->mtu;
memcpy(&(ifd->mac), n->hwaddr, n->hwaddr_len);
ifd->mac = htonll(ifd->mac) >> 16;
return ifd;
}
static err_t _netif_init4(struct netif *n)
@@ -652,7 +562,7 @@ static err_t _netif_init4(struct netif *n)
if (!n || !n->state) {
return ERR_IF;
}
// Called from netif code, no need to lock
// Called from core, no need to lock
VirtualTap *tap = (VirtualTap*)(n->state);
n->hwaddr_len = 6;
n->name[0] = '4';
@@ -680,7 +590,7 @@ static err_t _netif_init6(struct netif *n)
n->hwaddr_len = sizeof(n->hwaddr);
VirtualTap *tap = (VirtualTap*)(n->state);
tap->_mac.copyTo(n->hwaddr, n->hwaddr_len);
// Called from netif code, no need to lock
// Called from core, no need to lock
n->hwaddr_len = 6;
n->name[0] = '6';
n->name[1] = 'a'+netifCount;
@@ -715,6 +625,11 @@ void _lwip_init_interface(void *tapref, const InetAddress &ip)
isNewNetif = true;
netifCount++;
}
/*
netif_set_status_callback(n, _netif_status_callback);
netif_set_remove_callback(n, _netif_remove_callback);
netif_set_link_callback(n, _netif_link_callback);
*/
char nmbuf[INET6_ADDRSTRLEN];
static ip4_addr_t ip4, netmask, gw;
IP4_ADDR(&gw,127,0,0,1);
@@ -723,13 +638,12 @@ void _lwip_init_interface(void *tapref, const InetAddress &ip)
LOCK_TCPIP_CORE();
netif_add(n, &ip4, &netmask, &gw, (void*)vtap, _netif_init4, tcpip_input);
vtap->netif4 = (void*)n;
_enqueueEvent(ZTS_EVENT_NETIF_UP, (void*)_lwip_prepare_netif_status_msg(n));
UNLOCK_TCPIP_CORE();
snprintf(macbuf, ZTS_MAC_ADDRSTRLEN, "%02x:%02x:%02x:%02x:%02x:%02x",
n->hwaddr[0], n->hwaddr[1], n->hwaddr[2],
n->hwaddr[3], n->hwaddr[4], n->hwaddr[5]);
DEBUG_INFO("initialized netif=%p as [mac=%s, addr=%s, nm=%s, tap=%p]",n,
macbuf, ip.toString(ipbuf), ip.netmask().toString(nmbuf), vtap);
//DEBUG_INFO("initialized netif=%p as [mac=%s, addr=%s, nm=%s, tap=%p]",n,
// macbuf, ip.toString(ipbuf), ip.netmask().toString(nmbuf), vtap);
}
if (ip.isV6()) {
if (vtap->netif6) {
@@ -739,7 +653,11 @@ void _lwip_init_interface(void *tapref, const InetAddress &ip)
n = new struct netif;
isNewNetif = true;
netifCount++;
}
}/*
netif_set_status_callback(n, _netif_status_callback);
netif_set_remove_callback(n, _netif_remove_callback);
netif_set_link_callback(n, _netif_link_callback);
*/
static ip6_addr_t ip6;
memcpy(&(ip6.addr), ip.rawIpData(), sizeof(ip6.addr));
LOCK_TCPIP_CORE();
@@ -756,13 +674,37 @@ void _lwip_init_interface(void *tapref, const InetAddress &ip)
netif_add_ip6_address(n,&ip6,NULL);
n->output_ip6 = ethip6_output;
UNLOCK_TCPIP_CORE();
_enqueueEvent(ZTS_EVENT_NETIF_UP, (void*)_lwip_prepare_netif_status_msg(n));
snprintf(macbuf, ZTS_MAC_ADDRSTRLEN, "%02x:%02x:%02x:%02x:%02x:%02x",
n->hwaddr[0], n->hwaddr[1], n->hwaddr[2],
n->hwaddr[3], n->hwaddr[4], n->hwaddr[5]);
DEBUG_INFO("initialized netif=%p as [mac=%s, addr=%s, tap=%p]", n,
macbuf, ip.toString(ipbuf), vtap);
//DEBUG_INFO("initialized netif=%p as [mac=%s, addr=%s, tap=%p]", n,
// macbuf, ip.toString(ipbuf), vtap);
}
}
void _lwip_remove_address_from_netif(void *tapref, const InetAddress &ip)
{
if (!tapref) {
return;
}
VirtualTap *vtap = (VirtualTap*)tapref;
struct netif *n = NULL;
/* When true multi-homing is implemented this will need to
be a bit more sophisticated */
if (ip.isV4()) {
if (vtap->netif4) {
n = (struct netif*)vtap->netif4;
}
}
if (ip.isV6()) {
if (vtap->netif6) {
n = (struct netif*)vtap->netif6;
}
}
if (!n) {
return;
}
_lwip_remove_netif(n);
}
} // namespace ZeroTier

View File

@@ -22,7 +22,7 @@
#include "lwip/err.h"
#define ZTS_LWIP_DRIVER_THREAD_NAME "NetworkStackThread"
#define ZTS_LWIP_DRIVER_THREAD_NAME "ZTNetworkStackThread"
#include "MAC.hpp"
#include "Phy.hpp"
@@ -119,20 +119,6 @@ public:
void threadMain()
throw();
#if defined(__MINGW32__)
/* The following is merely to make ZeroTier's OneService happy while building on Windows.
we won't use these in libzt */
NET_LUID _deviceLuid;
std::string _deviceInstanceId;
/**
* Returns whether the VirtualTap interface has been initialized
*/
bool isInitialized() const { return _initialized; };
inline const NET_LUID &luid() const { return _deviceLuid; }
inline const std::string &instanceId() const { return _deviceInstanceId; }
#endif
/**
* For moving data onto the ZeroTier virtual wire
*/
@@ -151,8 +137,6 @@ public:
int _networkStatus = 0;
std::vector<std::pair<InetAddress, InetAddress> > routes;
char vtap_full_name[64];
std::vector<InetAddress> ips() const;
@@ -223,7 +207,6 @@ bool _lwip_is_up();
* @brief Initialize network stack semaphores, threads, and timers.
*
* @usage This is called during the initial setup of each VirtualTap but is only allowed to execute once
* @return
*/
void _lwip_driver_init();
@@ -233,30 +216,21 @@ void _lwip_driver_init();
* @usage This is to be called after it is determined that no further network activity will take place.
* The tcpip thread will be stopped, all interfaces will be brought down and all resources will
* be deallocated. A full application restart will be required to bring the stack back online.
* @return
*/
void _lwip_driver_shutdown();
/**
* @brief Requests that a netif be brought down and removed.
*
* @return
*/
void _lwip_remove_netif(void *netif);
/**
* @brief Initialize and start the DNS client
*
* @usage Called after lwip_driver_init()
* @return
*/
void _lwip_dns_init();
/**
* @brief Starts DHCP timers
*
* @usage lwip_driver_init()
* @return
*/
void _lwip_start_dhcp(void *netif);
@@ -286,13 +260,19 @@ static void _netif_link_callback(struct netif *netif);
/**
* @brief Set up an interface in the network stack for the VirtualTap.
*
* @param
* @param tapref Reference to VirtualTap that will be responsible for sending and receiving data
* @param ip Virtual IP address for this ZeroTier VirtualTap interface
* @return
*/
void _lwip_init_interface(void *tapref, const InetAddress &ip);
/**
* @brief Remove an assigned address from an lwIP netif
*
* @param tapref Reference to VirtualTap
* @param ip Virtual IP address to remove from this interface
*/
void _lwip_remove_address_from_netif(void *tapref, const InetAddress &ip);
/**
* @brief Called from the stack, outbound ethernet frames from the network stack enter the ZeroTier virtual wire here.
*
@@ -313,7 +293,6 @@ err_t _lwip_eth_tx(struct netif *netif, struct pbuf *p);
* @param etherType Protocol type
* @param data Pointer to Ethernet frame
* @param len Length of Ethernet frame
* @return
*/
void _lwip_eth_rx(VirtualTap *tap, const MAC &from, const MAC &to, unsigned int etherType,
const void *data, unsigned int len);