summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Ierymenko <adam.ierymenko@gmail.com>2017-03-30 09:54:10 -0700
committerAdam Ierymenko <adam.ierymenko@gmail.com>2017-03-30 09:54:10 -0700
commitb3298a8f5717a12e4520f63a06db165972053798 (patch)
tree7d2934bb7a692406e4d9d3de239c0c132a8450a6
parente5284771e472544ff6363ce773ee7f055fe575f1 (diff)
parent5f611dad51f8244b59a63ecdf48a2126c5995d74 (diff)
downloadinfinitytier-b3298a8f5717a12e4520f63a06db165972053798.tar.gz
infinitytier-b3298a8f5717a12e4520f63a06db165972053798.zip
Merge branch 'dev' of http://10.6.6.2/zerotier/ZeroTierOne into dev
-rw-r--r--java/jni/com_zerotierone_sdk_Node.cpp226
-rw-r--r--java/src/com/zerotier/sdk/Node.java43
-rw-r--r--java/src/com/zerotier/sdk/PathChecker.java45
3 files changed, 313 insertions, 1 deletions
diff --git a/java/jni/com_zerotierone_sdk_Node.cpp b/java/jni/com_zerotierone_sdk_Node.cpp
index 47bbc40e..defbe7f2 100644
--- a/java/jni/com_zerotierone_sdk_Node.cpp
+++ b/java/jni/com_zerotierone_sdk_Node.cpp
@@ -56,6 +56,7 @@ namespace {
, eventListener(NULL)
, frameListener(NULL)
, configListener(NULL)
+ , pathChecker(NULL)
, callbacks(NULL)
{
callbacks = (ZT_Node_Callbacks*)malloc(sizeof(ZT_Node_Callbacks));
@@ -73,6 +74,7 @@ namespace {
env->DeleteGlobalRef(eventListener);
env->DeleteGlobalRef(frameListener);
env->DeleteGlobalRef(configListener);
+ env->DeleteGlobalRef(pathChecker);
free(callbacks);
callbacks = NULL;
@@ -90,6 +92,7 @@ namespace {
jobject eventListener;
jobject frameListener;
jobject configListener;
+ jobject pathChecker;
ZT_Node_Callbacks *callbacks;
};
@@ -487,6 +490,165 @@ namespace {
return retval;
}
+ int PathCheckFunction(ZT_Node *node,
+ void *userPtr,
+ void *threadPtr,
+ uint64_t address,
+ const struct sockaddr_storage *localAddress,
+ const struct sockaddr_storage *remoteAddress)
+ {
+ JniRef *ref = (JniRef*)userPtr;
+ assert(ref->node == node);
+
+ if(ref->pathChecker == NULL) {
+ return true;
+ }
+
+ JNIEnv *env = NULL;
+ ref->jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
+
+ jclass pathCheckerClass = env->GetObjectClass(ref->pathChecker);
+ if(pathCheckerClass == NULL)
+ {
+ LOGE("Couldn't find class for PathChecker instance");
+ return true;
+ }
+
+ jmethodID pathCheckCallbackMethod = lookup.findMethod(pathCheckerClass,
+ "onPathCheck", "(JLjava/net/InetSocketAddress;Ljava/net/InetSocketAddress;)Z");
+ if(pathCheckCallbackMethod == NULL)
+ {
+ LOGE("Couldn't find onPathCheck method implementation");
+ return true;
+ }
+
+ jobject localAddressObj = NULL;
+ jobject remoteAddressObj = NULL;
+
+ if(memcmp(localAddress, &ZT_SOCKADDR_NULL, sizeof(sockaddr_storage)) != 0)
+ {
+ localAddressObj = newInetSocketAddress(env, *localAddress);
+ }
+ if(memcmp(remoteAddress, &ZT_SOCKADDR_NULL, sizeof(sockaddr_storage)) != 0)
+ {
+ remoteAddressObj = newInetSocketAddress(env, *remoteAddress);
+ }
+
+ return env->CallBooleanMethod(ref->pathChecker, pathCheckCallbackMethod, address, localAddressObj, remoteAddressObj);
+ }
+
+ int PathLookupFunction(ZT_Node *node,
+ void *userPtr,
+ void *threadPtr,
+ uint64_t address,
+ int ss_family,
+ struct sockaddr_storage *result)
+ {
+ JniRef *ref = (JniRef*)userPtr;
+ assert(ref->node == node);
+
+ if(ref->pathChecker == NULL) {
+ return false;
+ }
+
+ JNIEnv *env = NULL;
+ ref->jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
+
+ jclass pathCheckerClass = env->GetObjectClass(ref->pathChecker);
+ if(pathCheckerClass == NULL)
+ {
+ LOGE("Couldn't find class for PathChecker instance");
+ return false;
+ }
+
+ jmethodID pathLookupMethod = lookup.findMethod(pathCheckerClass,
+ "onPathLookup", "(JI)Ljava/net/InetSocketAddress;");
+ if(pathLookupMethod == NULL) {
+ return false;
+ }
+
+ jobject sockAddressObject = env->CallObjectMethod(ref->pathChecker, pathLookupMethod, address, ss_family);
+ if(sockAddressObject == NULL)
+ {
+ LOGE("Unable to call onPathLookup implementation");
+ return false;
+ }
+
+ jclass inetSockAddressClass = env->GetObjectClass(sockAddressObject);
+ if(inetSockAddressClass == NULL)
+ {
+ LOGE("Unable to find InetSocketAddress class");
+ return false;
+ }
+
+ jmethodID getAddressMethod = lookup.findMethod(inetSockAddressClass, "getAddress", "()Ljava/net/InetAddress;");
+ if(getAddressMethod == NULL)
+ {
+ LOGE("Unable to find InetSocketAddress.getAddress() method");
+ return false;
+ }
+
+ jmethodID getPortMethod = lookup.findMethod(inetSockAddressClass, "getPort", "()I");
+ if(getPortMethod == NULL)
+ {
+ LOGE("Unable to find InetSocketAddress.getPort() method");
+ return false;
+ }
+
+ jint port = env->CallIntMethod(sockAddressObject, getPortMethod);
+ jobject addressObject = env->CallObjectMethod(sockAddressObject, getAddressMethod);
+
+ jclass inetAddressClass = lookup.findClass("java/net/InetAddress");
+ if(inetAddressClass == NULL)
+ {
+ LOGE("Unable to find InetAddress class");
+ return false;
+ }
+
+ getAddressMethod = lookup.findMethod(inetAddressClass, "getAddress", "()[B");
+ if(getAddressMethod == NULL)
+ {
+ LOGE("Unable to find InetAddress.getAddress() method");
+ return false;
+ }
+
+ jbyteArray addressBytes = (jbyteArray)env->CallObjectMethod(addressObject, getAddressMethod);
+ if(addressBytes == NULL)
+ {
+ LOGE("Unable to call InetAddress.getBytes()");
+ return false;
+ }
+
+ int addressSize = env->GetArrayLength(addressBytes);
+ if(addressSize == 4)
+ {
+ // IPV4
+ sockaddr_in *addr = (sockaddr_in*)result;
+ addr->sin_family = AF_INET;
+ addr->sin_port = htons(port);
+
+ void *data = env->GetPrimitiveArrayCritical(addressBytes, NULL);
+ memcpy(&addr->sin_addr, data, 4);
+ env->ReleasePrimitiveArrayCritical(addressBytes, data, 0);
+ }
+ else if (addressSize == 16)
+ {
+ // IPV6
+ sockaddr_in6 *addr = (sockaddr_in6*)result;
+ addr->sin6_family = AF_INET6;
+ addr->sin6_port = htons(port);
+ void *data = env->GetPrimitiveArrayCritical(addressBytes, NULL);
+ memcpy(&addr->sin6_addr, data, 16);
+ env->ReleasePrimitiveArrayCritical(addressBytes, data, 0);
+ }
+ else
+ {
+ return false;
+ }
+
+ return true;
+ }
+
typedef std::map<uint64_t, JniRef*> NodeMap;
static NodeMap nodeMap;
ZeroTier::Mutex nodeMapMutex;
@@ -619,12 +781,28 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_node_1init(
}
ref->eventListener = env->NewGlobalRef(tmp);
+ fid = lookup.findField(
+ cls, "pathChecker", "Lcom/zerotier/sdk/PathChecker;");
+ if(fid == NULL)
+ {
+ LOGE("no path checker?");
+ return NULL;
+ }
+
+ tmp = env->GetObjectField(obj, fid);
+ if(tmp != NULL)
+ {
+ ref->pathChecker = env->NewGlobalRef(tmp);
+ }
+
ref->callbacks->dataStoreGetFunction = &DataStoreGetFunction;
ref->callbacks->dataStorePutFunction = &DataStorePutFunction;
ref->callbacks->wirePacketSendFunction = &WirePacketSendFunction;
ref->callbacks->virtualNetworkFrameFunction = &VirtualNetworkFrameFunctionCallback;
ref->callbacks->virtualNetworkConfigFunction = &VirtualNetworkConfigFunctionCallback;
ref->callbacks->eventCallback = &EventCallback;
+ ref->callbacks->pathCheckFunction = &PathCheckFunction;
+ ref->callbacks->pathLookupFunction = &PathLookupFunction;
ZT_ResultCode rc = ZT_Node_new(
&node,
@@ -1108,6 +1286,54 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_multicastUnsubscribe(
}
/*
+ * Class: com_zerotier_sdk_Node
+ * Method: orbit
+ * Signature: (JJJ)Lcom/zerotier/sdk/ResultCode;
+ */
+JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_orbit(
+ JNIEnv *env, jobject obj,
+ jlong id,
+ jlong in_moonWorldId,
+ jlong in_moonSeed)
+{
+ uint64_t nodeId = (uint64_t)id;
+ ZT_Node *node = findNode(nodeId);
+ if(node == NULL)
+ {
+ return createResultObject(env, ZT_RESULT_FATAL_ERROR_INTERNAL);
+ }
+
+ uint64_t moonWorldId = (uint64_t)in_moonWorldId;
+ uint64_t moonSeed = (uint64_t)in_moonSeed;
+
+ ZT_ResultCode rc = ZT_Node_orbit(node, NULL, moonWorldId, moonSeed);
+ return createResultObject(env, rc);
+}
+
+/*
+ * Class: com_zerotier_sdk_Node
+ * Method: deorbit
+ * Signature: (JJ)L/com/zerotier/sdk/ResultCode;
+ */
+JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_deorbit(
+ JNIEnv *env, jobject obj,
+ jlong id,
+ jlong in_moonWorldId)
+{
+ uint64_t nodeId = (uint64_t)id;
+ ZT_Node *node = findNode(nodeId);
+ if(node == NULL)
+ {
+ return createResultObject(env, ZT_RESULT_FATAL_ERROR_INTERNAL);
+ }
+
+ uint64_t moonWorldId = (uint64_t)in_moonWorldId;
+
+ ZT_ResultCode rc = ZT_Node_deorbit(node, NULL, moonWorldId);
+ return createResultObject(env, rc);
+}
+
+/*
* Class: com_zerotier_sdk_Node
* Method: address
* Signature: (J)J
diff --git a/java/src/com/zerotier/sdk/Node.java b/java/src/com/zerotier/sdk/Node.java
index 4bc6e184..8e7d44e7 100644
--- a/java/src/com/zerotier/sdk/Node.java
+++ b/java/src/com/zerotier/sdk/Node.java
@@ -74,6 +74,7 @@ public class Node {
private final EventListener eventListener;
private final VirtualNetworkFrameListener frameListener;
private final VirtualNetworkConfigListener configListener;
+ private final PathChecker pathChecker;
/**
* Create a new ZeroTier One node
@@ -88,6 +89,7 @@ public class Node {
* @param eventListener User written instance of the {@link EventListener} interface to receive status updates and non-fatal error notices. This instance must be unique per Node object.
* @param frameListener
* @param configListener User written instance of the {@link VirtualNetworkConfigListener} interface to be called when virtual LANs are created, deleted, or their config parameters change. This instance must be unique per Node object.
+ * @param pathChecker User written instance of the {@link PathChecker} interface. Not required and can be null.
*/
public Node(long now,
DataStoreGetListener getListener,
@@ -95,7 +97,8 @@ public class Node {
PacketSender sender,
EventListener eventListener,
VirtualNetworkFrameListener frameListener,
- VirtualNetworkConfigListener configListener) throws NodeException
+ VirtualNetworkConfigListener configListener,
+ PathChecker pathChecker) throws NodeException
{
this.nodeId = now;
@@ -105,6 +108,7 @@ public class Node {
this.eventListener = eventListener;
this.frameListener = frameListener;
this.configListener = configListener;
+ this.pathChecker = pathChecker;
ResultCode rc = node_init(now);
if(rc != ResultCode.RESULT_OK)
@@ -319,6 +323,34 @@ public class Node {
}
/**
+ * Add or update a moon
+ *
+ * Moons are persisted in the data store in moons.d/, so this can persist
+ * across invocations if the contents of moon.d are scanned and orbit is
+ * called for each on startup.
+ *
+ * @param moonWorldId Moon's world ID
+ * @param moonSeed If non-zero, the ZeroTier address of any member of the moon to query for moon definition
+ * @return Error if moon was invalid or failed to be added
+ */
+ public ResultCode orbit(
+ long moonWorldId,
+ long moonSeed) {
+ return orbit(nodeId, moonWorldId, moonSeed);
+ }
+
+ /**
+ * Remove a moon (does nothing if not present)
+ *
+ * @param moonWorldId World ID of moon to remove
+ * @return Error if anything bad happened
+ */
+ public ResultCode deorbit(
+ long moonWorldId) {
+ return deorbit(nodeId, moonWorldId);
+ }
+
+ /**
* Get this node's 40-bit ZeroTier address
*
* @return ZeroTier address (least significant 40 bits of 64-bit int)
@@ -420,6 +452,15 @@ public class Node {
long multicastGroup,
long multicastAdi);
+ private native ResultCode orbit(
+ long nodeId,
+ long moonWorldId,
+ long moonSeed);
+
+ private native ResultCode deorbit(
+ long nodeId,
+ long moonWorldId);
+
private native long address(long nodeId);
private native NodeStatus status(long nodeId);
diff --git a/java/src/com/zerotier/sdk/PathChecker.java b/java/src/com/zerotier/sdk/PathChecker.java
new file mode 100644
index 00000000..3e02f112
--- /dev/null
+++ b/java/src/com/zerotier/sdk/PathChecker.java
@@ -0,0 +1,45 @@
+/*
+ * ZeroTier One - Network Virtualization Everywhere
+ * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/
+ */
+
+package com.zerotier.sdk;
+
+import java.net.InetSocketAddress;
+
+public interface PathChecker {
+ /**
+ * Callback to check whether a path should be used for ZeroTier traffic
+ *
+ * This function must return true if the path should be used.
+ *
+ * If no path check function is specified, ZeroTier will still exclude paths
+ * that overlap with ZeroTier-assigned and managed IP address blocks. But the
+ * use of a path check function is recommended to ensure that recursion does
+ * not occur in cases where addresses are assigned by the OS or managed by
+ * an out of band mechanism like DHCP. The path check function should examine
+ * all configured ZeroTier interfaces and check to ensure that the supplied
+ * addresses will not result in ZeroTier traffic being sent over a ZeroTier
+ * interface (recursion).
+ *
+ * Obviously this is not required in configurations where this can't happen,
+ * such as network containers or embedded.
+ *
+ * @param ztAddress ZeroTier address or 0 for none/any
+ * @param localAddress Local interface address
+ * @param remoteAddress remote address
+ */
+ boolean onPathCheck(long ztAddress, InetSocketAddress localAddress, InetSocketAddress remoteAddress);
+
+ /**
+ * Function to get physical addresses for ZeroTier peers
+ *
+ * If provided this function will be occasionally called to get physical
+ * addresses that might be tried to reach a ZeroTier address.
+ *
+ * @param ztAddress ZeroTier address (least significant 40 bits)
+ * @param ss_family desired address family or -1 for any
+ * @return address and port of ztAddress or null
+ */
+ InetSocketAddress onPathLookup(long ztAddress, int ss_family);
+}