2019-02-06 22:00:39 -08:00
|
|
|
/*
|
2020-04-13 23:38:06 -07:00
|
|
|
* Copyright (c)2013-2020 ZeroTier, Inc.
|
2019-02-06 22:00:39 -08:00
|
|
|
*
|
2020-04-13 23:38:06 -07:00
|
|
|
* Use of this software is governed by the Business Source License included
|
|
|
|
|
* in the LICENSE.TXT file in the project's root directory.
|
2019-02-06 22:00:39 -08:00
|
|
|
*
|
2020-04-13 23:38:06 -07:00
|
|
|
* Change Date: 2024-01-01
|
2019-02-06 22:00:39 -08:00
|
|
|
*
|
2020-04-13 23:38:06 -07:00
|
|
|
* On the date above, in accordance with the Business Source License, use
|
|
|
|
|
* of this software will be governed by version 2.0 of the Apache License.
|
2019-02-06 22:00:39 -08:00
|
|
|
*/
|
2020-04-13 23:38:06 -07:00
|
|
|
/****/
|
2019-02-06 22:00:39 -08:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @file
|
|
|
|
|
*
|
2020-05-01 19:15:38 -07:00
|
|
|
* Network control interface
|
2019-02-06 22:00:39 -08:00
|
|
|
*/
|
|
|
|
|
|
2020-05-01 19:15:38 -07:00
|
|
|
#include <inttypes.h>
|
|
|
|
|
#include <sys/types.h>
|
2019-02-06 22:00:39 -08:00
|
|
|
|
|
|
|
|
#include "Node.hpp"
|
2020-05-01 19:15:38 -07:00
|
|
|
#include "Mutex.hpp"
|
2019-02-06 22:00:39 -08:00
|
|
|
#include "OSUtils.hpp"
|
2019-03-04 18:04:37 -08:00
|
|
|
|
2019-02-06 22:00:39 -08:00
|
|
|
#include "Debug.hpp"
|
2020-05-01 19:15:38 -07:00
|
|
|
#include "NodeService.hpp"
|
|
|
|
|
#include "VirtualTap.hpp"
|
|
|
|
|
#include "Events.hpp"
|
|
|
|
|
#include "ZeroTierSockets.h"
|
2020-04-13 23:38:06 -07:00
|
|
|
|
2020-05-01 19:15:38 -07:00
|
|
|
using namespace ZeroTier;
|
2019-02-14 17:27:16 -08:00
|
|
|
|
2019-02-06 22:00:39 -08:00
|
|
|
#ifdef SDK_JNI
|
2020-05-01 19:15:38 -07:00
|
|
|
#include <jni.h>
|
2019-02-06 22:00:39 -08:00
|
|
|
#endif
|
|
|
|
|
|
2020-05-01 19:15:38 -07:00
|
|
|
namespace ZeroTier
|
2019-02-06 22:00:39 -08:00
|
|
|
{
|
2020-05-01 19:15:38 -07:00
|
|
|
extern NodeService *service;
|
|
|
|
|
extern Mutex serviceLock;
|
|
|
|
|
extern void (*_userEventCallbackFunc)(void *);
|
|
|
|
|
extern uint8_t allowNetworkCaching;
|
|
|
|
|
extern uint8_t allowPeerCaching;
|
|
|
|
|
extern uint8_t allowLocalConf;
|
2019-02-06 22:00:39 -08:00
|
|
|
|
|
|
|
|
#ifdef SDK_JNI
|
2020-05-01 19:15:38 -07:00
|
|
|
// References to JNI objects and VM kept for future callbacks
|
|
|
|
|
JavaVM *jvm = NULL;
|
|
|
|
|
jobject objRef = NULL;
|
|
|
|
|
jmethodID _userCallbackMethodRef = NULL;
|
2019-02-06 22:00:39 -08:00
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-01 19:15:38 -07:00
|
|
|
int zts_allow_network_caching(uint8_t allowed = 1)
|
2019-02-27 18:37:00 -08:00
|
|
|
{
|
2020-05-01 19:15:38 -07:00
|
|
|
Mutex::Lock _l(serviceLock);
|
|
|
|
|
if(!service) {
|
|
|
|
|
allowNetworkCaching = allowed;
|
|
|
|
|
return ZTS_ERR_OK;
|
2019-02-06 22:00:39 -08:00
|
|
|
}
|
2020-05-01 19:15:38 -07:00
|
|
|
return ZTS_ERR_SERVICE;
|
2019-02-06 22:00:39 -08:00
|
|
|
}
|
|
|
|
|
|
2020-05-01 19:15:38 -07:00
|
|
|
int zts_allow_peer_caching(uint8_t allowed = 1)
|
2019-02-06 22:00:39 -08:00
|
|
|
{
|
2020-05-01 19:15:38 -07:00
|
|
|
Mutex::Lock _l(serviceLock);
|
|
|
|
|
if(!service) {
|
|
|
|
|
allowPeerCaching = allowed;
|
|
|
|
|
return ZTS_ERR_OK;
|
2019-02-06 22:00:39 -08:00
|
|
|
}
|
2020-05-01 19:15:38 -07:00
|
|
|
return ZTS_ERR_SERVICE;
|
2019-02-06 22:00:39 -08:00
|
|
|
}
|
|
|
|
|
|
2020-05-01 19:15:38 -07:00
|
|
|
int zts_allow_local_conf(uint8_t allowed = 1)
|
2019-02-06 22:00:39 -08:00
|
|
|
{
|
2020-05-01 19:15:38 -07:00
|
|
|
Mutex::Lock _l(serviceLock);
|
|
|
|
|
if(!service) {
|
|
|
|
|
allowLocalConf = allowed;
|
|
|
|
|
return ZTS_ERR_OK;
|
2019-02-06 22:00:39 -08:00
|
|
|
}
|
2020-05-01 19:15:38 -07:00
|
|
|
return ZTS_ERR_SERVICE;
|
2020-04-15 16:08:40 -07:00
|
|
|
}
|
|
|
|
|
|
2020-05-01 19:15:38 -07:00
|
|
|
int zts_start(const char *path, void (*callback)(void *), uint16_t port)
|
2019-02-06 22:00:39 -08:00
|
|
|
{
|
2020-05-01 19:15:38 -07:00
|
|
|
Mutex::Lock _l(serviceLock);
|
|
|
|
|
_lwip_driver_init();
|
|
|
|
|
if (service || _getState(ZTS_STATE_NODE_RUNNING)) {
|
2019-02-06 22:00:39 -08:00
|
|
|
// Service is already initialized
|
2020-05-01 19:15:38 -07:00
|
|
|
return ZTS_ERR_SERVICE;
|
2019-02-06 22:00:39 -08:00
|
|
|
}
|
2020-05-01 19:15:38 -07:00
|
|
|
if (_getState(ZTS_STATE_FREE_CALLED)) {
|
2019-03-18 14:23:34 -07:00
|
|
|
// Stack (presumably lwIP) has been dismantled,
|
|
|
|
|
// an application restart is required now
|
2020-05-01 19:15:38 -07:00
|
|
|
return ZTS_ERR_SERVICE;
|
2019-02-06 22:00:39 -08:00
|
|
|
}
|
|
|
|
|
#ifdef SDK_JNI
|
|
|
|
|
_userEventCallbackFunc = callback;
|
2020-05-01 19:15:38 -07:00
|
|
|
#else
|
2019-02-06 22:00:39 -08:00
|
|
|
_userEventCallbackFunc = callback;
|
2020-05-01 19:15:38 -07:00
|
|
|
#endif
|
|
|
|
|
if (!_isCallbackRegistered()) {
|
2019-02-06 22:00:39 -08:00
|
|
|
// Must have a callback
|
2020-05-01 19:15:38 -07:00
|
|
|
return ZTS_ERR_ARG;
|
2019-02-06 22:00:39 -08:00
|
|
|
}
|
|
|
|
|
if (!path) {
|
2020-05-01 19:15:38 -07:00
|
|
|
return ZTS_ERR_ARG;
|
2019-02-06 22:00:39 -08:00
|
|
|
}
|
|
|
|
|
if (port < 0 || port > 0xFFFF) {
|
2020-05-01 19:15:38 -07:00
|
|
|
return ZTS_ERR_ARG;
|
2019-02-06 22:00:39 -08:00
|
|
|
}
|
|
|
|
|
serviceParameters *params = new serviceParameters();
|
|
|
|
|
|
|
|
|
|
params->port = port;
|
|
|
|
|
params->path = std::string(path);
|
|
|
|
|
|
|
|
|
|
if (params->path.length() == 0) {
|
2020-05-01 19:15:38 -07:00
|
|
|
return ZTS_ERR_ARG;
|
2019-02-06 22:00:39 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int err;
|
|
|
|
|
int retval = ZTS_ERR_OK;
|
2020-05-01 19:15:38 -07:00
|
|
|
|
|
|
|
|
_setState(ZTS_STATE_CALLBACKS_RUNNING);
|
|
|
|
|
_setState(ZTS_STATE_NODE_RUNNING);
|
2019-02-06 22:00:39 -08:00
|
|
|
|
|
|
|
|
// Start the ZT service thread
|
2020-05-01 19:15:38 -07:00
|
|
|
#if defined(__WINDOWS__)
|
|
|
|
|
HANDLE serviceThread = CreateThread(NULL, 0, _runNodeService, (void*)params, 0, NULL);
|
|
|
|
|
HANDLE callbackThread = CreateThread(NULL, 0, _runCallbacks, NULL, 0, NULL);
|
2019-06-18 11:06:05 -07:00
|
|
|
#else
|
|
|
|
|
pthread_t service_thread;
|
|
|
|
|
pthread_t callback_thread;
|
2020-05-01 19:15:38 -07:00
|
|
|
if ((err = pthread_create(&service_thread, NULL, _runNodeService, (void*)params)) != 0) {
|
2019-02-06 22:00:39 -08:00
|
|
|
retval = err;
|
|
|
|
|
}
|
2020-05-01 19:15:38 -07:00
|
|
|
if ((err = pthread_create(&callback_thread, NULL, _runCallbacks, NULL)) != 0) {
|
2019-02-06 22:00:39 -08:00
|
|
|
retval = err;
|
|
|
|
|
}
|
2019-06-18 11:06:05 -07:00
|
|
|
#endif
|
2019-02-06 22:00:39 -08:00
|
|
|
#if defined(__linux__)
|
|
|
|
|
pthread_setname_np(service_thread, ZTS_SERVICE_THREAD_NAME);
|
|
|
|
|
pthread_setname_np(callback_thread, ZTS_EVENT_CALLBACK_THREAD_NAME);
|
|
|
|
|
#endif
|
|
|
|
|
if (retval != ZTS_ERR_OK) {
|
2020-05-01 19:15:38 -07:00
|
|
|
_clrState(ZTS_STATE_CALLBACKS_RUNNING);
|
|
|
|
|
_clrState(ZTS_STATE_NODE_RUNNING);
|
|
|
|
|
_clearRegisteredCallback();
|
|
|
|
|
//delete params;
|
2019-02-06 22:00:39 -08:00
|
|
|
}
|
|
|
|
|
return retval;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef SDK_JNI
|
2020-05-01 19:15:38 -07:00
|
|
|
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_start(
|
2019-02-06 22:00:39 -08:00
|
|
|
JNIEnv *env, jobject thisObj, jstring path, jobject callback, jint port)
|
|
|
|
|
{
|
|
|
|
|
if (!path) {
|
2020-05-01 19:15:38 -07:00
|
|
|
return ZTS_ERR_ARG;
|
2019-02-06 22:00:39 -08:00
|
|
|
}
|
|
|
|
|
jclass eventListenerClass = env->GetObjectClass(callback);
|
|
|
|
|
if(eventListenerClass == NULL) {
|
|
|
|
|
DEBUG_ERROR("Couldn't find class for ZeroTierEventListener instance");
|
2020-05-01 19:15:38 -07:00
|
|
|
return ZTS_ERR_ARG;
|
2019-02-06 22:00:39 -08:00
|
|
|
}
|
|
|
|
|
jmethodID eventListenerCallbackMethod = env->GetMethodID(eventListenerClass, "onZeroTierEvent", "(JI)V");
|
|
|
|
|
if(eventListenerCallbackMethod == NULL) {
|
|
|
|
|
DEBUG_ERROR("Couldn't find onZeroTierEvent method");
|
2020-05-01 19:15:38 -07:00
|
|
|
return ZTS_ERR_ARG;
|
2019-02-06 22:00:39 -08:00
|
|
|
}
|
2019-03-18 14:23:34 -07:00
|
|
|
// Reference used for later calls
|
|
|
|
|
objRef = env->NewGlobalRef(callback);
|
2019-02-06 22:00:39 -08:00
|
|
|
_userCallbackMethodRef = eventListenerCallbackMethod;
|
|
|
|
|
const char* utf_string = env->GetStringUTFChars(path, NULL);
|
2019-03-18 14:23:34 -07:00
|
|
|
if (!utf_string) {
|
|
|
|
|
return ZTS_ERR_GENERAL;
|
|
|
|
|
}
|
|
|
|
|
// using _userCallbackMethodRef
|
|
|
|
|
int retval = zts_start(utf_string, NULL, port);
|
2019-02-06 22:00:39 -08:00
|
|
|
env->ReleaseStringUTFChars(path, utf_string);
|
2019-02-28 15:47:49 -08:00
|
|
|
return retval;
|
2019-02-06 22:00:39 -08:00
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2019-03-04 18:04:37 -08:00
|
|
|
int zts_stop()
|
2019-02-06 22:00:39 -08:00
|
|
|
{
|
2020-05-01 19:15:38 -07:00
|
|
|
Mutex::Lock _l(serviceLock);
|
|
|
|
|
if (_canPerformServiceOperation()) {
|
|
|
|
|
_clrState(ZTS_STATE_NODE_RUNNING);
|
2019-02-06 22:00:39 -08:00
|
|
|
service->terminate();
|
2020-05-01 19:15:38 -07:00
|
|
|
#if defined(__WINDOWS__)
|
2019-02-06 22:00:39 -08:00
|
|
|
WSACleanup();
|
|
|
|
|
#endif
|
|
|
|
|
return ZTS_ERR_OK;
|
|
|
|
|
}
|
|
|
|
|
return ZTS_ERR_SERVICE;
|
|
|
|
|
}
|
|
|
|
|
#ifdef SDK_JNI
|
|
|
|
|
JNIEXPORT void JNICALL Java_com_zerotier_libzt_ZeroTier_stop(
|
|
|
|
|
JNIEnv *env, jobject thisObj)
|
|
|
|
|
{
|
|
|
|
|
zts_stop();
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2019-03-27 15:08:27 -07:00
|
|
|
int zts_restart()
|
|
|
|
|
{
|
2020-05-01 19:15:38 -07:00
|
|
|
serviceLock.lock();
|
2019-03-27 15:08:27 -07:00
|
|
|
// Store callback references
|
2019-03-27 17:09:30 -07:00
|
|
|
#ifdef SDK_JNI
|
|
|
|
|
static jmethodID _tmpUserCallbackMethodRef = _userCallbackMethodRef;
|
|
|
|
|
#else
|
2020-05-01 19:15:38 -07:00
|
|
|
void (*_tmpUserEventCallbackFunc)(void *);
|
2019-03-27 15:08:27 -07:00
|
|
|
_tmpUserEventCallbackFunc = _userEventCallbackFunc;
|
2019-03-27 17:09:30 -07:00
|
|
|
#endif
|
2020-05-01 19:15:38 -07:00
|
|
|
int userProvidedPort = 0;
|
|
|
|
|
std::string userProvidedPath;
|
|
|
|
|
if (service) {
|
|
|
|
|
userProvidedPort = service->_userProvidedPort;
|
|
|
|
|
userProvidedPath = service->_userProvidedPath;
|
|
|
|
|
}
|
2019-03-27 15:08:27 -07:00
|
|
|
// Stop the service
|
2020-05-01 19:15:38 -07:00
|
|
|
if (_canPerformServiceOperation()) {
|
|
|
|
|
_clrState(ZTS_STATE_NODE_RUNNING);
|
2019-03-27 15:08:27 -07:00
|
|
|
service->terminate();
|
2020-05-01 19:15:38 -07:00
|
|
|
#if defined(__WINDOWS__)
|
2019-03-27 15:08:27 -07:00
|
|
|
WSACleanup();
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
else {
|
2020-05-01 19:15:38 -07:00
|
|
|
serviceLock.unlock();
|
2019-03-27 15:08:27 -07:00
|
|
|
return ZTS_ERR_SERVICE;
|
|
|
|
|
}
|
|
|
|
|
// Start again with same parameters as initial call
|
2020-05-01 19:15:38 -07:00
|
|
|
serviceLock.unlock();
|
2019-03-27 15:08:27 -07:00
|
|
|
while (service) {
|
2020-05-01 19:15:38 -07:00
|
|
|
zts_delay_ms(ZTS_CALLBACK_PROCESSING_INTERVAL);
|
2019-03-27 15:08:27 -07:00
|
|
|
}
|
2019-03-27 17:09:30 -07:00
|
|
|
/* Some of the logic in Java_com_zerotier_libzt_ZeroTier_start
|
|
|
|
|
is replicated here */
|
|
|
|
|
#ifdef SDK_JNI
|
|
|
|
|
_userCallbackMethodRef = _tmpUserCallbackMethodRef;
|
2020-05-01 19:15:38 -07:00
|
|
|
return zts_start(userProvidedPath.c_str(), NULL, userProvidedPort);
|
2019-03-27 17:09:30 -07:00
|
|
|
#else
|
2020-05-01 19:15:38 -07:00
|
|
|
//return zts_start(userProvidedPath.c_str(), _tmpUserEventCallbackFunc, userProvidedPort);
|
2019-03-27 17:09:30 -07:00
|
|
|
#endif
|
2019-03-27 15:08:27 -07:00
|
|
|
}
|
|
|
|
|
#ifdef SDK_JNI
|
|
|
|
|
JNIEXPORT void JNICALL Java_com_zerotier_libzt_ZeroTier_restart(
|
|
|
|
|
JNIEnv *env, jobject thisObj)
|
|
|
|
|
{
|
|
|
|
|
zts_restart();
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2019-03-04 18:04:37 -08:00
|
|
|
int zts_free()
|
2019-02-06 22:00:39 -08:00
|
|
|
{
|
2020-05-01 19:15:38 -07:00
|
|
|
Mutex::Lock _l(serviceLock);
|
|
|
|
|
if (_getState(ZTS_STATE_FREE_CALLED)) {
|
|
|
|
|
return ZTS_ERR_SERVICE;
|
2019-02-06 22:00:39 -08:00
|
|
|
}
|
2020-05-01 19:15:38 -07:00
|
|
|
_setState(ZTS_STATE_FREE_CALLED);
|
2019-02-06 22:00:39 -08:00
|
|
|
return zts_stop();
|
|
|
|
|
// TODO: add stack shutdown logic
|
|
|
|
|
}
|
|
|
|
|
#ifdef SDK_JNI
|
|
|
|
|
JNIEXPORT void JNICALL Java_com_zerotier_libzt_ZeroTier_free(
|
|
|
|
|
JNIEnv *env, jobject thisObj)
|
|
|
|
|
{
|
|
|
|
|
zts_free();
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
uint64_t zts_get_node_id()
|
|
|
|
|
{
|
2020-05-01 19:15:38 -07:00
|
|
|
Mutex::Lock _l(serviceLock);
|
|
|
|
|
if (!_canPerformServiceOperation()) {
|
|
|
|
|
return ZTS_ERR_OK; // Not really
|
2019-02-06 22:00:39 -08:00
|
|
|
}
|
|
|
|
|
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
|
|
|
|
|
|
2020-05-01 19:15:38 -07:00
|
|
|
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(
|
|
|
|
|
JNIEnv *env, jobject thisObj)
|
|
|
|
|
{
|
|
|
|
|
jint rs = env->GetJavaVM(&jvm);
|
|
|
|
|
return rs != JNI_OK ? ZTS_ERR_GENERAL : ZTS_ERR_OK;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
int zts_join(const uint64_t nwid)
|
|
|
|
|
{
|
|
|
|
|
Mutex::Lock _l(serviceLock);
|
|
|
|
|
if (!_canPerformServiceOperation()) {
|
|
|
|
|
return ZTS_ERR_SERVICE;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
service->join(nwid);
|
|
|
|
|
}
|
|
|
|
|
return ZTS_ERR_OK;
|
|
|
|
|
}
|
|
|
|
|
#ifdef SDK_JNI
|
|
|
|
|
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_join(
|
|
|
|
|
JNIEnv *env, jobject thisObj, jlong nwid)
|
|
|
|
|
{
|
|
|
|
|
return zts_join((uint64_t)nwid);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
int zts_leave(const uint64_t nwid)
|
|
|
|
|
{
|
|
|
|
|
Mutex::Lock _l(serviceLock);
|
|
|
|
|
if (!_canPerformServiceOperation()) {
|
|
|
|
|
return ZTS_ERR_SERVICE;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
service->leave(nwid);
|
|
|
|
|
}
|
|
|
|
|
return ZTS_ERR_OK;
|
|
|
|
|
}
|
|
|
|
|
#ifdef SDK_JNI
|
|
|
|
|
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_leave(
|
|
|
|
|
JNIEnv *env, jobject thisObj, jlong nwid)
|
|
|
|
|
{
|
|
|
|
|
return zts_leave((uint64_t)nwid);
|
|
|
|
|
}
|
|
|
|
|
#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);
|
|
|
|
|
void *tptr = NULL;
|
|
|
|
|
if (!_canPerformServiceOperation()) {
|
|
|
|
|
return ZTS_ERR_SERVICE;
|
|
|
|
|
} else {
|
|
|
|
|
service->getNode()->orbit(tptr, moonWorldId, moonSeed);
|
|
|
|
|
}
|
|
|
|
|
return ZTS_ERR_OK;
|
|
|
|
|
}
|
|
|
|
|
#ifdef SDK_JNI
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
int zts_deorbit(uint64_t moonWorldId)
|
|
|
|
|
{
|
|
|
|
|
Mutex::Lock _l(serviceLock);
|
|
|
|
|
void *tptr = NULL;
|
|
|
|
|
if (!_canPerformServiceOperation()) {
|
|
|
|
|
return ZTS_ERR_SERVICE;
|
|
|
|
|
} else {
|
|
|
|
|
service->getNode()->deorbit(tptr, moonWorldId);
|
|
|
|
|
}
|
|
|
|
|
return ZTS_ERR_OK;
|
|
|
|
|
}
|
|
|
|
|
#ifdef SDK_JNI
|
|
|
|
|
#endif
|
|
|
|
|
|
2020-05-07 22:56:54 -04:00
|
|
|
int zts_get_6plane_addr(struct zts_sockaddr_storage *addr, const uint64_t nwid, const uint64_t nodeId)
|
2020-04-13 23:38:06 -07:00
|
|
|
{
|
|
|
|
|
if (!addr || !nwid || !nodeId) {
|
2020-05-01 19:15:38 -07:00
|
|
|
return ZTS_ERR_ARG;
|
2020-04-13 23:38:06 -07:00
|
|
|
}
|
|
|
|
|
InetAddress _6planeAddr = InetAddress::makeIpv66plane(nwid,nodeId);
|
2020-04-15 16:08:40 -07:00
|
|
|
struct sockaddr_in6 *in6 = (struct sockaddr_in6*)addr;
|
|
|
|
|
memcpy(in6->sin6_addr.s6_addr, _6planeAddr.rawIpData(), sizeof(struct in6_addr));
|
2020-04-20 23:50:21 -07:00
|
|
|
return ZTS_ERR_OK;
|
2020-04-13 23:38:06 -07:00
|
|
|
}
|
|
|
|
|
|
2020-05-07 22:56:54 -04:00
|
|
|
int zts_get_rfc4193_addr(struct zts_sockaddr_storage *addr, const uint64_t nwid, const uint64_t nodeId)
|
2020-04-13 23:38:06 -07:00
|
|
|
{
|
|
|
|
|
if (!addr || !nwid || !nodeId) {
|
2020-05-01 19:15:38 -07:00
|
|
|
return ZTS_ERR_ARG;
|
2020-04-13 23:38:06 -07:00
|
|
|
}
|
|
|
|
|
InetAddress _rfc4193Addr = InetAddress::makeIpv6rfc4193(nwid,nodeId);
|
2020-04-15 16:08:40 -07:00
|
|
|
struct sockaddr_in6 *in6 = (struct sockaddr_in6*)addr;
|
|
|
|
|
memcpy(in6->sin6_addr.s6_addr, _rfc4193Addr.rawIpData(), sizeof(struct in6_addr));
|
2020-04-20 23:50:21 -07:00
|
|
|
return ZTS_ERR_OK;
|
2020-04-13 23:38:06 -07:00
|
|
|
}
|
|
|
|
|
|
2020-05-01 19:15:38 -07:00
|
|
|
|
2020-04-17 11:37:46 -07:00
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-01 19:15:38 -07:00
|
|
|
int zts_get_peers(struct zts_peer_details *pds, uint32_t *num)
|
2019-02-06 22:00:39 -08:00
|
|
|
{
|
2020-05-01 19:15:38 -07:00
|
|
|
Mutex::Lock _l(serviceLock);
|
2019-02-06 22:00:39 -08:00
|
|
|
if (!pds || !num) {
|
2020-05-01 19:15:38 -07:00
|
|
|
return ZTS_ERR_ARG;
|
2019-02-06 22:00:39 -08:00
|
|
|
}
|
2020-05-01 19:15:38 -07:00
|
|
|
if (!_canPerformServiceOperation()) {
|
2019-02-06 22:00:39 -08:00
|
|
|
return ZTS_ERR_SERVICE;
|
|
|
|
|
}
|
|
|
|
|
ZT_PeerList *pl = service->getNode()->peers();
|
|
|
|
|
if (pl) {
|
2019-02-26 13:40:04 -08:00
|
|
|
if (*num < pl->peerCount) {
|
|
|
|
|
service->getNode()->freeQueryResult((void *)pl);
|
2020-05-01 19:15:38 -07:00
|
|
|
return ZTS_ERR_ARG;
|
2019-02-26 13:40:04 -08:00
|
|
|
}
|
2019-02-06 22:00:39 -08:00
|
|
|
*num = pl->peerCount;
|
|
|
|
|
for(unsigned long i=0;i<pl->peerCount;++i) {
|
|
|
|
|
memcpy(&(pds[i]), &(pl->peers[i]), sizeof(struct zts_peer_details));
|
2020-04-20 23:50:21 -07:00
|
|
|
for (unsigned int j=0; j<pl->peers[i].pathCount; j++) {
|
2019-02-26 13:40:04 -08:00
|
|
|
memcpy(&(pds[i].paths[j].address),
|
|
|
|
|
&(pl->peers[i].paths[j].address), sizeof(struct sockaddr_storage));
|
|
|
|
|
}
|
2019-02-06 22:00:39 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
service->getNode()->freeQueryResult((void *)pl);
|
|
|
|
|
return ZTS_ERR_OK;
|
|
|
|
|
}
|
|
|
|
|
#ifdef SDK_JNI
|
|
|
|
|
#endif
|
|
|
|
|
|
2019-02-26 13:40:04 -08:00
|
|
|
int zts_get_peer(struct zts_peer_details *pd, uint64_t peerId)
|
2019-02-06 22:00:39 -08:00
|
|
|
{
|
2020-05-01 19:15:38 -07:00
|
|
|
Mutex::Lock _l(serviceLock);
|
2019-02-26 13:40:04 -08:00
|
|
|
if (!pd || !peerId) {
|
2020-05-01 19:15:38 -07:00
|
|
|
return ZTS_ERR_ARG;
|
2019-02-26 13:40:04 -08:00
|
|
|
}
|
2020-05-01 19:15:38 -07:00
|
|
|
if (!_canPerformServiceOperation()) {
|
2019-02-06 22:00:39 -08:00
|
|
|
return ZTS_ERR_SERVICE;
|
|
|
|
|
}
|
2019-02-26 13:40:04 -08:00
|
|
|
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));
|
2020-04-20 23:50:21 -07:00
|
|
|
for (unsigned int j=0; j<pl->peers[i].pathCount; j++) {
|
2019-02-26 13:40:04 -08:00
|
|
|
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;
|
2019-02-06 22:00:39 -08:00
|
|
|
}
|
|
|
|
|
#ifdef SDK_JNI
|
|
|
|
|
#endif
|
|
|
|
|
|
2019-07-02 10:14:39 -07:00
|
|
|
void _get_network_details_helper(uint64_t nwid, struct zts_network_details *nd)
|
2019-02-06 22:00:39 -08:00
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
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();
|
2019-07-02 10:14:39 -07:00
|
|
|
_get_network_details_helper(nwid, nd);
|
2019-02-06 22:00:39 -08:00
|
|
|
_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();
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-04 18:04:37 -08:00
|
|
|
int zts_get_network_details(uint64_t nwid, struct zts_network_details *nd)
|
2019-02-06 22:00:39 -08:00
|
|
|
{
|
|
|
|
|
/*
|
2020-05-01 19:15:38 -07:00
|
|
|
serviceLock.lock();
|
2019-03-04 18:04:37 -08:00
|
|
|
int retval = ZTS_ERR_OK;
|
2019-02-06 22:00:39 -08:00
|
|
|
if (!nd || nwid == 0) {
|
2020-05-01 19:15:38 -07:00
|
|
|
retval = ZTS_ERR_ARG;
|
2019-02-06 22:00:39 -08:00
|
|
|
}
|
|
|
|
|
if (!service || _freeHasBeenCalled || _serviceIsShuttingDown) {
|
|
|
|
|
retval = ZTS_ERR_SERVICE;
|
|
|
|
|
}
|
|
|
|
|
if (retval == ZTS_ERR_OK) {
|
|
|
|
|
_get_network_details(nwid, nd);
|
|
|
|
|
}
|
2020-05-01 19:15:38 -07:00
|
|
|
serviceLock.unlock();
|
2019-02-06 22:00:39 -08:00
|
|
|
return retval;
|
|
|
|
|
*/
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
#ifdef SDK_JNI
|
|
|
|
|
#endif
|
|
|
|
|
|
2019-03-04 18:04:37 -08:00
|
|
|
int zts_get_all_network_details(struct zts_network_details *nds, int *num)
|
2019-02-06 22:00:39 -08:00
|
|
|
{
|
|
|
|
|
/*
|
2020-05-01 19:15:38 -07:00
|
|
|
serviceLock.lock();
|
2019-03-04 18:04:37 -08:00
|
|
|
int retval = ZTS_ERR_OK;
|
2019-02-06 22:00:39 -08:00
|
|
|
if (!nds || !num) {
|
2020-05-01 19:15:38 -07:00
|
|
|
retval = ZTS_ERR_ARG;
|
2019-02-06 22:00:39 -08:00
|
|
|
}
|
|
|
|
|
if (!service || _freeHasBeenCalled || _serviceIsShuttingDown) {
|
|
|
|
|
retval = ZTS_ERR_SERVICE;
|
|
|
|
|
}
|
|
|
|
|
if (retval == ZTS_ERR_OK) {
|
|
|
|
|
_get_all_network_details(nds, num);
|
|
|
|
|
}
|
2020-05-01 19:15:38 -07:00
|
|
|
serviceLock.unlock();
|
2019-02-06 22:00:39 -08:00
|
|
|
return retval;
|
|
|
|
|
*/
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
#ifdef SDK_JNI
|
|
|
|
|
#endif
|
|
|
|
|
|
2020-05-01 19:15:38 -07:00
|
|
|
void zts_delay_ms(long interval_ms)
|
2019-03-27 15:08:27 -07:00
|
|
|
{
|
2020-05-01 19:15:38 -07:00
|
|
|
#if defined(__WINDOWS__)
|
|
|
|
|
Sleep(interval_ms);
|
2019-03-27 15:08:27 -07:00
|
|
|
#else
|
2020-05-01 19:15:38 -07:00
|
|
|
struct timespec sleepValue = {0};
|
|
|
|
|
sleepValue.tv_nsec = interval_ms * 500000;
|
|
|
|
|
nanosleep(&sleepValue, NULL);
|
2019-02-26 13:40:04 -08:00
|
|
|
#endif
|
2019-02-06 22:00:39 -08:00
|
|
|
}
|