diff options
author | Adam Ierymenko <adam.ierymenko@gmail.com> | 2017-03-30 09:54:10 -0700 |
---|---|---|
committer | Adam Ierymenko <adam.ierymenko@gmail.com> | 2017-03-30 09:54:10 -0700 |
commit | b3298a8f5717a12e4520f63a06db165972053798 (patch) | |
tree | 7d2934bb7a692406e4d9d3de239c0c132a8450a6 | |
parent | e5284771e472544ff6363ce773ee7f055fe575f1 (diff) | |
parent | 5f611dad51f8244b59a63ecdf48a2126c5995d74 (diff) | |
download | infinitytier-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.cpp | 226 | ||||
-rw-r--r-- | java/src/com/zerotier/sdk/Node.java | 43 | ||||
-rw-r--r-- | java/src/com/zerotier/sdk/PathChecker.java | 45 |
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); +} |