From 8d1d77a8a480640ff162291f298652a94ee772f0 Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Tue, 21 Nov 2017 15:53:31 -0800 Subject: [PATCH] zts_* API updates, unfinished lwIP tweaks --- Makefile | 43 +- include/RingBuffer.h | 4 + include/VirtualTap.h | 5 + include/libzt.h | 87 +++- include/libztDefs.h | 7 +- src/VirtualTap.cpp | 4 +- src/ZT1Service.cpp | 146 +++++-- src/libzt.cpp | 63 +-- src/libztJNI.cpp | 775 ++++++++++++++++----------------- src/lwIP.cpp | 157 +++---- test/create_test_identities.sh | 1 + 11 files changed, 733 insertions(+), 559 deletions(-) diff --git a/Makefile b/Makefile index a871314..e49462d 100644 --- a/Makefile +++ b/Makefile @@ -43,6 +43,7 @@ ARTOOL=ar ARFLAGS=rcs CC=gcc CXX=g++ +CFLAGS= CXXFLAGS+=-fpermissive -Wno-unknown-pragmas -Wno-pointer-arith -Wno-deprecated-declarations -Wno-conversion-null WINDEFS=-lws2_32 -lshlwapi -liphlpapi -static -static-libgcc -static-libstdc++ LWIPARCHINCLUDE=$(LWIPCONTRIBDIR)/ports/win32/include @@ -137,7 +138,8 @@ STRIP=strip # ZeroTier debug and tracing ifeq ($(ZT_DEBUG),1) - CFLAGS?=-Wall -g -pthread + CFLAGS?=-Wall -g -pthread + ZT_DEFS+=-DZT_TRACE=1 STRIP=echo else CFLAGS?=-Ofast -fstack-protector @@ -178,10 +180,14 @@ ifeq ($(LIBZT_SANITIZE),1) endif # JNI (Java Native Interface) -# jni.h +ifeq ($(OSTYPE),darwin) JNI_INCLUDES+=-I$(shell /usr/libexec/java_home)/include -# jni_md.h -JNI_INCLUDES+=-I$(shell /usr/libexec/java_home)/include/$(OSTYPE) +JNI_INCLUDES+=-I$(shell /usr/libexec/java_home)/include/$(OSTYPE) +endif +ifeq ($(OSTYPE),linux) +JNI_INCLUDES+=-I$(shell dirname $(shell dirname $(shell readlink -f $(shell which javac))))/include +JNI_INCLUDES+=-I$(shell dirname $(shell dirname $(shell readlink -f $(shell which javac))))/include/$(OSTYPE) +endif CXXFLAGS+=$(CFLAGS) -Wno-format -fno-rtti -std=c++11 ZT_DEFS+=-DZT_SDK -DZT_SOFTWARE_UPDATE_DEFAULT="\"disable\"" @@ -291,7 +297,14 @@ shared_lib: lwip lwip_driver libzt_socket_layer utilities $(ZTO_OBJS) shared_jni_lib: lwip lwip_driver libzt_socket_layer jni_socket_wrapper utilities $(ZTO_OBJS) @mkdir -p $(BUILD) obj mv *.o obj - $(CXX) $(CXXFLAGS) -dynamiclib -o $(BUILD)/libzt.dylib obj/*.o + #$(CXX) $(CXXFLAGS) -shared -o $(BUILD)/libzt.so obj/*.o + $(CXX) $(CXXFLAGS) -dynamiclib obj/*.o -o $(BUILD)/libzt.dylib -lpthread + +# static library for use with Java JNI, scala, etc +static_jni_lib: lwip lwip_driver libzt_socket_layer jni_socket_wrapper utilities $(ZTO_OBJS) + @mkdir -p $(BUILD) obj + mv *.o obj + $(ARTOOL) $(ARFLAGS) -o $(STATIC_LIB) obj/*.o # static library static_lib: picotcp picotcp_driver lwip lwip_driver libzt_socket_layer utilities $(ZTO_OBJS) @@ -329,7 +342,7 @@ python_module: ## Unit Tests ## ############################################################################## -tests: selftest nativetest ztproxy simple +tests: selftest nativetest ztproxy ipv4simple ipv6simple ipv6adhoc # intercept ZT_UTILS:=zto/node/Utils.cpp -Izto/node @@ -352,9 +365,21 @@ intercept: $(CXX) $(CXXFLAGS) $(SANFLAGS) $(STACK_DRIVER_DEFS) $(LIBZT_INCLUDES) \ $(ZT_INCLUDES) examples/intercept/intercept.cpp -D_GNU_SOURCE \ -shared -o $(BUILD)/intercept.so $< -ldl -simple: - $(CXX) $(CXXFLAGS) $(SANFLAGS) $(LIBZT_INCLUDES) $(LIBZT_DEFS) examples/bindings/cpp/simple_client_server/client.cpp -o $(BUILD)/client -L$(BUILD) -lpthread -lzt $(WINDEFS) - $(CXX) $(CXXFLAGS) $(SANFLAGS) $(LIBZT_INCLUDES) $(LIBZT_DEFS) examples/bindings/cpp/simple_client_server/server.cpp -o $(BUILD)/server -L$(BUILD) -lpthread -lzt $(WINDEFS) +ipv4simple: + $(CXX) $(CXXFLAGS) $(SANFLAGS) $(LIBZT_INCLUDES) $(LIBZT_DEFS) \ + examples/bindings/cpp/ipv4simple/client.cpp -o $(BUILD)/ipv4client -L$(BUILD) -lpthread -lzt $(WINDEFS) + $(CXX) $(CXXFLAGS) $(SANFLAGS) $(LIBZT_INCLUDES) $(LIBZT_DEFS) \ + examples/bindings/cpp/ipv4simple/server.cpp -o $(BUILD)/ipv4server -L$(BUILD) -lpthread -lzt $(WINDEFS) +ipv6simple: + $(CXX) $(CXXFLAGS) $(SANFLAGS) $(LIBZT_INCLUDES) $(LIBZT_DEFS) \ + examples/bindings/cpp/ipv6simple/client.cpp -o $(BUILD)/ipv6client -L$(BUILD) -lpthread -lzt $(WINDEFS) + $(CXX) $(CXXFLAGS) $(SANFLAGS) $(LIBZT_INCLUDES) $(LIBZT_DEFS) \ + examples/bindings/cpp/ipv6simple/server.cpp -o $(BUILD)/ipv6server -L$(BUILD) -lpthread -lzt $(WINDEFS) +ipv6adhoc: + $(CXX) $(CXXFLAGS) $(SANFLAGS) $(LIBZT_INCLUDES) $(LIBZT_DEFS) \ + examples/bindings/cpp/ipv6adhoc/client.cpp -o $(BUILD)/ipv6adhocclient -L$(BUILD) -lpthread -lzt $(WINDEFS) + $(CXX) $(CXXFLAGS) $(SANFLAGS) $(LIBZT_INCLUDES) $(LIBZT_DEFS) \ + examples/bindings/cpp/ipv6adhoc/server.cpp -o $(BUILD)/ipv6adhocserver -L$(BUILD) -lpthread -lzt $(WINDEFS) dlltest: $(CXX) $(CXXFLAGS) diff --git a/include/RingBuffer.h b/include/RingBuffer.h index 7e5b74e..d935a20 100644 --- a/include/RingBuffer.h +++ b/include/RingBuffer.h @@ -33,6 +33,10 @@ #ifndef ZT_RINGBUFFER_H #define ZT_RINGBUFFER_H +#include +#include + + typedef char bufElementType; class RingBuffer diff --git a/include/VirtualTap.h b/include/VirtualTap.h index 22fb0d9..ab877d4 100644 --- a/include/VirtualTap.h +++ b/include/VirtualTap.h @@ -33,6 +33,9 @@ #ifndef ZT_VIRTUALTAP_HPP #define ZT_VIRTUALTAP_HPP +extern int errno; + + #include "Mutex.hpp" #include "MulticastGroup.hpp" #include "InetAddress.hpp" @@ -52,6 +55,8 @@ extern ZeroTier::Mutex _vtaps_lock; #include #endif + + using namespace ZeroTier; class VirtualSocket; diff --git a/include/libzt.h b/include/libzt.h index bd22fab..421216d 100644 --- a/include/libzt.h +++ b/include/libzt.h @@ -37,6 +37,7 @@ #include #include +#include #if defined(__linux__) || defined(__APPLE__) #include @@ -116,30 +117,47 @@ ZT_SOCKET_API int ZTCALL zts_startjoin(const char *path, const uint64_t nwid); ZT_SOCKET_API void ZTCALL zts_stop(); /** - * @brief Return whether ZeroTier is currently running + * @brief Return whether ZeroTier core service is currently running * - * @usage Call this before, during, or after zts_start() - * @return + * @usage Call this after zts_start() + * @return 1 if running, 0 if not running */ -ZT_SOCKET_API int ZTCALL zts_running(); +ZT_SOCKET_API int ZTCALL zts_core_running(); + +/** + * @brief Return whether the userspace network stack is currently running + * + * @usage Call this after zts_start() + * @return 1 if running, 0 if not running + */ +ZT_SOCKET_API int ZTCALL zts_stack_running(); + +/** + * @brief Return whether libzt is ready to handle socket API calls. Alternatively you could + * have just called zts_startjoin(path, nwid) + * + * @usage Call this after zts_start() + * @return 1 if running, 0 if not running + */ +ZT_SOCKET_API int ZTCALL zts_ready(); /** * @brief Join a network * * @usage Call this from application thread. Only after zts_start() has succeeded * @param nwid A 16-digit hexidecimal virtual network ID - * @return + * @return 0 if successful, -1 for any failure */ -ZT_SOCKET_API void ZTCALL zts_join(const uint64_t nwid); +ZT_SOCKET_API int ZTCALL zts_join(const uint64_t nwid); /** * @brief Leave a network * * @usage Call this from application thread. Only after zts_start() has succeeded * @param nwid A 16-digit hexidecimal virtual network ID - * @return + * @return 0 if successful, -1 for any failure */ -ZT_SOCKET_API void ZTCALL zts_leave(const uint64_t nwid); +ZT_SOCKET_API int ZTCALL zts_leave(const uint64_t nwid); /** * @brief Copies the configuration path used by ZeroTier into the provided buffer @@ -147,9 +165,9 @@ ZT_SOCKET_API void ZTCALL zts_leave(const uint64_t nwid); * @usage * @param homePath Path to ZeroTier configuration files * @param len Length of destination buffer - * @return + * @return */ -ZT_SOCKET_API void ZTCALL zts_get_homepath(char *homePath, const size_t len); +ZT_SOCKET_API void ZTCALL zts_get_path(char *homePath, const size_t len); /** * @brief Returns the node ID of this instance @@ -177,16 +195,38 @@ ZT_SOCKET_API uint64_t ZTCALL zts_get_node_id_from_file(const char *filepath); */ ZT_SOCKET_API int ZTCALL zts_has_address(const uint64_t nwid); + +/** + * @brief Returns the number of addresses assigned to this node for the given nwid + * + * @param nwid Network ID + * @return The number of addresses assigned + */ +ZT_SOCKET_API int ZTCALL zts_get_num_assigned_addresses(const uint64_t nwid); + +/** + * @brief Returns the assigned address located at the given index + * + * @usage The indices of each assigned address are not guaranteed and should only + * be used for iterative purposes. + * @param nwid Network ID + * @param index location of assigned address + * @return The number of addresses assigned + */ +ZT_SOCKET_API int ZTCALL zts_get_address_at_index( + const uint64_t nwid, const int index, struct sockaddr_storage *addr); + /** * @brief Get IP address for this device on a given network * * @usage FIXME: Only returns first address found, good enough for most cases * @param nwid Network ID * @param addr Destination structure for address - * @param addrlen Length of destination structure - * @return + * @param address_family To designate what family of addresses we want to return. AF_INET or AF_INET6 + * @return 0 if an address was successfully found, -1 if failure */ -ZT_SOCKET_API void ZTCALL zts_get_address(const uint64_t nwid, struct sockaddr_storage *addr, const size_t addrlen); +ZT_SOCKET_API int ZTCALL zts_get_address( + const uint64_t nwid, struct sockaddr_storage *addr, const int address_family); /** * @brief Computes a 6PLANE IPv6 address for the given Network ID and Node ID @@ -197,7 +237,8 @@ ZT_SOCKET_API void ZTCALL zts_get_address(const uint64_t nwid, struct sockaddr_s * @param nodeId Node ID * @return */ -ZT_SOCKET_API void ZTCALL zts_get_6plane_addr(struct sockaddr_storage *addr, const uint64_t nwid, const uint64_t nodeId); +ZT_SOCKET_API void ZTCALL zts_get_6plane_addr( + struct sockaddr_storage *addr, const uint64_t nwid, const uint64_t nodeId); /** * @brief Computes a RFC4193 IPv6 address for the given Network ID and Node ID @@ -208,7 +249,8 @@ ZT_SOCKET_API void ZTCALL zts_get_6plane_addr(struct sockaddr_storage *addr, con * @param nodeId Node ID * @return */ -ZT_SOCKET_API void ZTCALL zts_get_rfc4193_addr(struct sockaddr_storage *addr, const uint64_t nwid, const uint64_t nodeId); +ZT_SOCKET_API void ZTCALL zts_get_rfc4193_addr( + struct sockaddr_storage *addr, const uint64_t nwid, const uint64_t nodeId); /** * @brief Return the number of peers @@ -325,7 +367,8 @@ ZT_SOCKET_API int ZTCALL zts_accept(int fd, struct sockaddr *addr, socklen_t *ad * @param optlen Length of option value * @return */ -ZT_SOCKET_API int ZTCALL zts_setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen); +ZT_SOCKET_API int ZTCALL zts_setsockopt( + int fd, int level, int optname, const void *optval, socklen_t optlen); /** * @brief Get socket options @@ -338,7 +381,8 @@ ZT_SOCKET_API int ZTCALL zts_setsockopt(int fd, int level, int optname, const vo * @param optlen Length of value * @return */ -ZT_SOCKET_API int ZTCALL zts_getsockopt(int fd, int level, int optname, void *optval, socklen_t *optlen); +ZT_SOCKET_API int ZTCALL zts_getsockopt( + int fd, int level, int optname, void *optval, socklen_t *optlen); /** * @brief Get socket name @@ -427,7 +471,8 @@ int zts_poll(struct pollfd *fds, nfds_t nfds, int timeout); * @param timeout * @return */ -ZT_SOCKET_API int ZTCALL zts_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); +ZT_SOCKET_API int ZTCALL zts_select( + int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); /** * @brief Issue file control commands on a socket @@ -475,7 +520,8 @@ ZT_SOCKET_API ssize_t ZTCALL zts_send(int fd, const void *buf, size_t len, int f * @param addrlen Length of destination address * @return */ -ZT_SOCKET_API ssize_t ZTCALL zts_sendto(int fd, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t addrlen); +ZT_SOCKET_API ssize_t ZTCALL zts_sendto( + int fd, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t addrlen); /** * @brief Send message to remote host @@ -512,7 +558,8 @@ ZT_SOCKET_API ssize_t ZTCALL zts_recv(int fd, void *buf, size_t len, int flags); * @param addrlen * @return */ -ZT_SOCKET_API ssize_t ZTCALL zts_recvfrom(int fd, void *buf, size_t len, int flags, struct sockaddr *addr, socklen_t *addrlen); +ZT_SOCKET_API ssize_t ZTCALL zts_recvfrom( + int fd, void *buf, size_t len, int flags, struct sockaddr *addr, socklen_t *addrlen); /** * @brief Receive a message from remote host diff --git a/include/libztDefs.h b/include/libztDefs.h index d5aa611..27aeee0 100644 --- a/include/libztDefs.h +++ b/include/libztDefs.h @@ -120,7 +120,7 @@ /** * How fast service states are re-checked (in milliseconds) */ -#define ZTO_WRAPPER_CHECK_INTERVAL 50 +#define ZTO_WRAPPER_CHECK_INTERVAL 100 /** * Length of buffer required to hold a ztAddress/nodeID @@ -351,13 +351,10 @@ typedef signed char err_t; */ #define ZT_STACK_SOCKET_RD_MAX 4096*4 -#define ZT_CORE_VERSION "1.2.5" -#define ZT_LIB_VERSION "1.1.5" - /** * Maximum length of libzt/ZeroTier home path (where keys, and config files are stored) */ -#define ZT_HOME_PATH_MAX_LEN 128 +#define ZT_HOME_PATH_MAX_LEN 256 /** * Length of human-readable MAC address string diff --git a/src/VirtualTap.cpp b/src/VirtualTap.cpp index c74d2f9..50c87e9 100644 --- a/src/VirtualTap.cpp +++ b/src/VirtualTap.cpp @@ -128,14 +128,14 @@ bool VirtualTap::addIp(const InetAddress &ip) { #if defined(NO_STACK) char ipbuf[INET6_ADDRSTRLEN]; - DEBUG_INFO("addIp (%s)", ip.toString(ipbuf)); + DEBUG_INFO("addIp=%s, nwid=%llx", ip.toString(ipbuf), _nwid); _ips.push_back(ip); std::sort(_ips.begin(),_ips.end()); return true; #endif #if defined(STACK_PICO) || defined(STACK_LWIP) char ipbuf[INET6_ADDRSTRLEN]; - DEBUG_EXTRA("addr=%s", ip.toString(ipbuf)); + DEBUG_EXTRA("addr=%s, nwid=%llx", ip.toString(ipbuf), _nwid); Mutex::Lock _l(_ips_m); if (registerIpWithStack(ip)) { if (std::find(_ips.begin(),_ips.end(),ip) == _ips.end()) { diff --git a/src/ZT1Service.cpp b/src/ZT1Service.cpp index 7f8178e..558241f 100644 --- a/src/ZT1Service.cpp +++ b/src/ZT1Service.cpp @@ -57,6 +57,9 @@ ZeroTier::Mutex _multiplexer_lock; WSADATA wsaData; #endif +// prototype +void api_sleep(int interval_ms); + /****************************************************************************/ /* ZeroTier Core helper functions for libzt - DON'T CALL THESE DIRECTLY */ /****************************************************************************/ @@ -246,28 +249,96 @@ void *zts_start_service(void *thread_id) return NULL; } -void zts_get_address(const uint64_t nwid, struct sockaddr_storage *addr, const size_t addrlen) +int zts_get_num_assigned_addresses(const uint64_t nwid) { if (!zt1Service) { - return; + return -1; } VirtualTap *tap = getTapByNWID(nwid); - if (tap && tap->_ips.size()) { + if (!tap) { + return -1; + } + int sz = -1; + _vtaps_lock.lock(); + sz = tap->_ips.size(); + _vtaps_lock.unlock(); + return sz; +} + +int zts_get_address_at_index( + const uint64_t nwid, const int index, struct sockaddr_storage *addr) +{ + if (!zt1Service) { + return -1; + } + VirtualTap *tap = getTapByNWID(nwid); + int err = -1; + if (!tap) { + return err; + } + _vtaps_lock.lock(); + if (index <= tap->_ips.size()) { + memcpy(addr, &(tap->_ips[index]), sizeof(struct sockaddr_storage)); + err = 0; + } + _vtaps_lock.unlock(); + return err; +} + +int zts_get_address(const uint64_t nwid, struct sockaddr_storage *addr, + const int address_family) +{ + int err = -1; + if (!zt1Service) { + return -1; + } + VirtualTap *tap = getTapByNWID(nwid); + if (!tap) { + //DEBUG_ERROR("!tap"); + return -1; + } + _vtaps_lock.lock(); + if (!tap->_ips.size()) { + // DEBUG_ERROR("!sz"); + } + else { + socklen_t addrlen = sizeof(struct sockaddr_storage); for (size_t i=0; i_ips.size(); i++) { - if (tap->_ips[i].isV4()) { - memcpy(addr, &(tap->_ips[i]), addrlen); - return; + if (address_family == AF_INET) { + if (tap->_ips[i].isV4()) { + memcpy(addr, &(tap->_ips[i]), addrlen); + addr->ss_family = AF_INET; + err = 0; + break; + } + } + if (address_family == AF_INET6) { + if (tap->_ips[i].isV6()) { + memcpy(addr, &(tap->_ips[i]), addrlen); + addr->ss_family = AF_INET6; + err = 0; + break; + } } } } + _vtaps_lock.unlock(); + return err; // nothing found } int zts_has_address(const uint64_t nwid) { struct sockaddr_storage ss; memset(&ss, 0, sizeof(ss)); - zts_get_address(nwid, &ss, sizeof(ss)); - return ss.ss_family == AF_INET || ss.ss_family == AF_INET6; + zts_get_address(nwid, &ss, AF_INET); + if (ss.ss_family == AF_INET) { + return true; + } + zts_get_address(nwid, &ss, AF_INET6); + if (ss.ss_family == AF_INET6) { + return true; + } + return false; } void zts_get_6plane_addr(struct sockaddr_storage *addr, const uint64_t nwid, const uint64_t nodeId) @@ -282,40 +353,57 @@ void zts_get_rfc4193_addr(struct sockaddr_storage *addr, const uint64_t nwid, co memcpy(addr, _rfc4193Addr.rawIpData(), sizeof(struct sockaddr_storage)); } -void zts_join(const uint64_t nwid) +int zts_join(const uint64_t nwid) { DEBUG_EXTRA(); + if (nwid == 0) { + return -1; + } if (zt1Service) { - std::string confFile = zt1Service->givenHomePath() + "/networks.d/" + std::to_string(nwid) + ".conf"; - if (ZeroTier::OSUtils::mkdir(netDir) == false) { - DEBUG_ERROR("unable to create: %s", netDir.c_str()); - } - if (ZeroTier::OSUtils::writeFile(confFile.c_str(), "") == false) { - DEBUG_ERROR("unable to write network conf file: %s", confFile.c_str()); - } zt1Service->join(nwid); } // provide ZTO service reference to virtual taps // TODO: This might prove to be unreliable, but it works for now + _vtaps_lock.lock(); for (size_t i=0;izt1ServiceRef=(void*)zt1Service; } + _vtaps_lock.unlock(); + return 0; } -void zts_leave(const uint64_t nwid) +int zts_leave(const uint64_t nwid) { DEBUG_EXTRA(); + if (nwid == 0) { + return -1; + } if (zt1Service) { zt1Service->leave(nwid); } + return 0; } -int zts_running() +bool zts_core_running() { return zt1Service == NULL ? false : zt1Service->isRunning(); } +bool zts_stack_running() +{ + _vtaps_lock.lock(); + // TODO: Perhaps a more robust way to check for this + int running = vtaps.size() > 0 ? true : false; + _vtaps_lock.unlock(); + return running; +} + +bool zts_ready() +{ + return zts_core_running() && zts_stack_running(); +} + int zts_start(const char *path, bool blocking = false) { DEBUG_EXTRA(); @@ -332,14 +420,14 @@ int zts_start(const char *path, bool blocking = false) int err = pthread_create(&service_thread, NULL, zts_start_service, NULL); if (blocking) { // block to prevent service calls before we're ready ZT_NodeStatus status; - while (zts_running() == false || zt1Service->getNode() == NULL) { - nanosleep((const struct timespec[]) {{0, (ZTO_WRAPPER_CHECK_INTERVAL * 500000)}}, NULL); + while (zts_core_running() == false || zt1Service->getNode() == NULL) { + api_sleep(ZTO_WRAPPER_CHECK_INTERVAL); } while (zt1Service->getNode()->address() <= 0) { - nanosleep((const struct timespec[]) {{0, (ZTO_WRAPPER_CHECK_INTERVAL * 500000)}}, NULL); + api_sleep(ZTO_WRAPPER_CHECK_INTERVAL); } while (status.online <= 0) { - nanosleep((const struct timespec[]) {{0, (ZTO_WRAPPER_CHECK_INTERVAL * 500000)}}, NULL); + api_sleep(ZTO_WRAPPER_CHECK_INTERVAL); zt1Service->getNode()->status(&status); } } @@ -350,7 +438,6 @@ int zts_startjoin(const char *path, const uint64_t nwid) { DEBUG_EXTRA(); int err = zts_start(path, true); - // only now can we attempt a join while (true) { try { zts_join(nwid); @@ -358,10 +445,11 @@ int zts_startjoin(const char *path, const uint64_t nwid) } catch( ... ) { DEBUG_ERROR("there was a problem joining the virtual network %s", nwid); + api_sleep(ZTO_WRAPPER_CHECK_INTERVAL); } } while (zts_has_address(nwid) == false) { - nanosleep((const struct timespec[]) {{0, (ZTO_WRAPPER_CHECK_INTERVAL * 500000)}}, NULL); + api_sleep(ZTO_WRAPPER_CHECK_INTERVAL); } return err; } @@ -374,11 +462,11 @@ void zts_stop() // disableTaps(); } #if defined(__MINGW32__) || defined(__MINGW64__) - WSACleanup(); // clean up WinSock + WSACleanup(); #endif } -void zts_get_homepath(char *homePath, size_t len) +void zts_get_path(char *homePath, size_t len) { DEBUG_EXTRA(); if (homeDir.length()) { @@ -462,6 +550,12 @@ bool _ipv6_in_subnet(ZeroTier::InetAddress *subnet, ZeroTier::InetAddress *addr) memset(b1, 0, 64); return !strcmp(r.toIpString(b0), b.toIpString(b1)); } + +void api_sleep(int interval_ms) +{ + nanosleep((const struct timespec[]) {{0, (interval_ms * 500000)}}, NULL); +} + #ifdef __cplusplus } #endif diff --git a/src/libzt.cpp b/src/libzt.cpp index f41df17..8d89ffc 100644 --- a/src/libzt.cpp +++ b/src/libzt.cpp @@ -56,12 +56,12 @@ extern "C" { int platform_adjusted_socket_family(int family); void fix_addr_socket_family(struct sockaddr *addr); -bool zts_running(); +bool zts_ready(); int zts_socket(int socket_family, int socket_type, int protocol) { DEBUG_EXTRA("family=%d, type=%d, proto=%d", socket_family, socket_type, protocol); - if (zts_running() == false) { + if (zts_ready() == false) { DEBUG_ERROR("service not started yet, call zts_startjoin()"); return -1; } @@ -75,7 +75,8 @@ int zts_socket(int socket_family, int socket_type, int protocol) /* use the lwIP community's own socket API, this provides thread safety and core locking */ int socket_family_adj = platform_adjusted_socket_family(socket_family); - return lwip_socket(socket_family_adj, socket_type, protocol); + int err = lwip_socket(socket_family_adj, socket_type, protocol); + return err; #endif #if defined(ZT_PICO_BSD_SOCKET) // return pico_bsd_socket(socket_family, socket_type, protocol); @@ -86,7 +87,7 @@ int zts_socket(int socket_family, int socket_type, int protocol) int zts_connect(int fd, const struct sockaddr *addr, socklen_t addrlen) { DEBUG_EXTRA("fd=%d",fd); - if (zts_running() == false) { + if (zts_ready() == false) { DEBUG_ERROR("service not started yet, call zts_startjoin()"); return -1; } @@ -107,7 +108,7 @@ int zts_connect(int fd, const struct sockaddr *addr, socklen_t addrlen) int zts_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) { DEBUG_EXTRA("fd=%d", fd); - if (zts_running() == false) { + if (zts_ready() == false) { DEBUG_ERROR("service not started yet, call zts_startjoin()"); return -1; } @@ -128,7 +129,7 @@ int zts_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) int zts_listen(int fd, int backlog) { DEBUG_EXTRA("fd=%d", fd); - if (zts_running() == false) { + if (zts_ready() == false) { DEBUG_ERROR("service not started yet, call zts_startjoin()"); return -1; } @@ -146,7 +147,7 @@ int zts_listen(int fd, int backlog) int zts_accept(int fd, struct sockaddr *addr, socklen_t *addrlen) { DEBUG_EXTRA("fd=%d", fd); - if (zts_running() == false) { + if (zts_ready() == false) { DEBUG_ERROR("service not started yet, call zts_startjoin()"); return -1; } @@ -165,7 +166,7 @@ int zts_accept(int fd, struct sockaddr *addr, socklen_t *addrlen) int zts_accept4(int fd, struct sockaddr *addr, socklen_t *addrlen, int flags) { DEBUG_EXTRA("fd=%d", fd); - if (zts_running() == false) { + if (zts_ready() == false) { DEBUG_ERROR("service not started yet, call zts_startjoin()"); return -1; } @@ -185,7 +186,7 @@ int zts_accept4(int fd, struct sockaddr *addr, socklen_t *addrlen, int flags) int zts_setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen) { DEBUG_EXTRA("fd=%d, level=%d, optname=%d", fd, level, optname); - if (zts_running() == false) { + if (zts_ready() == false) { DEBUG_ERROR("service not started yet, call zts_startjoin()"); return -1; } @@ -203,7 +204,7 @@ int zts_setsockopt(int fd, int level, int optname, const void *optval, socklen_t int zts_getsockopt(int fd, int level, int optname, void *optval, socklen_t *optlen) { DEBUG_EXTRA("fd=%d, level=%d, optname=%d", fd, level, optname); - if (zts_running() == false) { + if (zts_ready() == false) { DEBUG_ERROR("service not started yet, call zts_startjoin()"); return -1; } @@ -221,7 +222,7 @@ int zts_getsockopt(int fd, int level, int optname, void *optval, socklen_t *optl int zts_getsockname(int fd, struct sockaddr *addr, socklen_t *addrlen) { DEBUG_EXTRA("fd=%p", fd); - if (zts_running() == false) { + if (zts_ready() == false) { DEBUG_ERROR("service not started yet, call zts_startjoin()"); return -1; } @@ -239,7 +240,7 @@ int zts_getsockname(int fd, struct sockaddr *addr, socklen_t *addrlen) int zts_getpeername(int fd, struct sockaddr *addr, socklen_t *addrlen) { DEBUG_EXTRA("fd=%d", fd); - if (zts_running() == false) { + if (zts_ready() == false) { DEBUG_ERROR("service not started yet, call zts_startjoin()"); return -1; } @@ -257,7 +258,7 @@ int zts_getpeername(int fd, struct sockaddr *addr, socklen_t *addrlen) int zts_gethostname(char *name, size_t len) { DEBUG_EXTRA(); - if (zts_running() == false) { + if (zts_ready() == false) { DEBUG_ERROR("service not started yet, call zts_startjoin()"); return -1; } @@ -275,7 +276,7 @@ int zts_gethostname(char *name, size_t len) int zts_sethostname(const char *name, size_t len) { DEBUG_EXTRA(); - if (zts_running() == false) { + if (zts_ready() == false) { DEBUG_ERROR("service not started yet, call zts_startjoin()"); return -1; } @@ -292,7 +293,7 @@ int zts_sethostname(const char *name, size_t len) struct hostent *zts_gethostbyname(const char *name) { - if (zts_running() == false) { + if (zts_ready() == false) { DEBUG_ERROR("service not started yet, call zts_startjoin()"); return NULL; } @@ -328,7 +329,7 @@ struct hostent *zts_gethostbyname(const char *name) int zts_close(int fd) { DEBUG_EXTRA("fd=%d", fd); - if (zts_running() == false) { + if (zts_ready() == false) { DEBUG_ERROR("service not started yet, call zts_startjoin()"); return -1; } @@ -348,7 +349,7 @@ int zts_close(int fd) int zts_poll(struct pollfd *fds, nfds_t nfds, int timeout) { DEBUG_ERROR("warning, this is not implemented"); - if (zts_running() == false) { + if (zts_ready() == false) { DEBUG_ERROR("service not started yet, call zts_startjoin()"); return -1; } @@ -372,7 +373,7 @@ int zts_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, { //DEBUG_EXTRA(); /* - if (zts_running() == false) { + if (zts_ready() == false) { DEBUG_ERROR("service not started yet, call zts_startjoin()"); return -1; } @@ -391,7 +392,7 @@ int zts_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, int zts_fcntl(int fd, int cmd, int flags) { DEBUG_EXTRA("fd=%d, cmd=%d, flags=%d", fd, cmd, flags); - if (zts_running() == false) { + if (zts_ready() == false) { DEBUG_ERROR("service not started yet, call zts_startjoin()"); return -1; } @@ -421,7 +422,7 @@ int zts_fcntl(int fd, int cmd, int flags) int zts_ioctl(int fd, unsigned long request, void *argp) { DEBUG_EXTRA("fd=%d, req=%d", fd, request); - if (zts_running() == false) { + if (zts_ready() == false) { DEBUG_ERROR("service not started yet, call zts_startjoin()"); return -1; } @@ -440,7 +441,7 @@ ssize_t zts_sendto(int fd, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t addrlen) { DEBUG_TRANS("fd=%d, len=%d", fd, len); - if (zts_running() == false) { + if (zts_ready() == false) { DEBUG_ERROR("service not started yet, call zts_startjoin()"); return -1; } @@ -462,7 +463,7 @@ ssize_t zts_sendto(int fd, const void *buf, size_t len, int flags, ssize_t zts_send(int fd, const void *buf, size_t len, int flags) { DEBUG_TRANS("fd=%d, len=%d", fd, len); - if (zts_running() == false) { + if (zts_ready() == false) { DEBUG_ERROR("service not started yet, call zts_startjoin()"); return -1; } @@ -480,7 +481,7 @@ ssize_t zts_send(int fd, const void *buf, size_t len, int flags) ssize_t zts_sendmsg(int fd, const struct msghdr *msg, int flags) { DEBUG_TRANS("fd=%d", fd); - if (zts_running() == false) { + if (zts_ready() == false) { DEBUG_ERROR("service not started yet, call zts_startjoin()"); return -1; } @@ -498,7 +499,7 @@ ssize_t zts_sendmsg(int fd, const struct msghdr *msg, int flags) ssize_t zts_recv(int fd, void *buf, size_t len, int flags) { DEBUG_TRANS("fd=%d", fd); - if (zts_running() == false) { + if (zts_ready() == false) { DEBUG_ERROR("service not started yet, call zts_startjoin()"); return -1; } @@ -517,7 +518,7 @@ ssize_t zts_recvfrom(int fd, void *buf, size_t len, int flags, struct sockaddr *addr, socklen_t *addrlen) { DEBUG_TRANS("fd=%d", fd); - if (zts_running() == false) { + if (zts_ready() == false) { DEBUG_ERROR("service not started yet, call zts_startjoin()"); return -1; } @@ -535,7 +536,7 @@ ssize_t zts_recvfrom(int fd, void *buf, size_t len, int flags, ssize_t zts_recvmsg(int fd, struct msghdr *msg,int flags) { DEBUG_TRANS("fd=%d", fd); - if (zts_running() == false) { + if (zts_ready() == false) { DEBUG_ERROR("service not started yet, call zts_startjoin()"); return -1; } @@ -554,7 +555,7 @@ ssize_t zts_recvmsg(int fd, struct msghdr *msg,int flags) int zts_read(int fd, void *buf, size_t len) { DEBUG_TRANS("fd=%d, len=%d", fd, len); - if (zts_running() == false) { + if (zts_ready() == false) { DEBUG_ERROR("service not started yet, call zts_startjoin()"); return -1; } @@ -572,7 +573,7 @@ int zts_read(int fd, void *buf, size_t len) int zts_write(int fd, const void *buf, size_t len) { DEBUG_EXTRA("fd=%d, len=%d", fd, len); - if (zts_running() == false) { + if (zts_ready() == false) { DEBUG_ERROR("service not started yet, call zts_startjoin()"); return -1; } @@ -590,7 +591,7 @@ int zts_write(int fd, const void *buf, size_t len) int zts_shutdown(int fd, int how) { DEBUG_EXTRA("fd=%d, how=%d", fd, how); - if (zts_running() == false) { + if (zts_ready() == false) { DEBUG_ERROR("service not started yet, call zts_startjoin()"); return -1; } @@ -608,7 +609,7 @@ int zts_shutdown(int fd, int how) int zts_add_dns_nameserver(struct sockaddr *addr) { DEBUG_EXTRA(); - if (zts_running() == false) { + if (zts_ready() == false) { DEBUG_ERROR("service not started yet, call zts_startjoin()"); return -1; } @@ -631,7 +632,7 @@ int zts_add_dns_nameserver(struct sockaddr *addr) int zts_del_dns_nameserver(struct sockaddr *addr) { DEBUG_EXTRA(); - if (zts_running() == false) { + if (zts_ready() == false) { DEBUG_ERROR("service not started yet, call zts_startjoin()"); return -1; } diff --git a/src/libztJNI.cpp b/src/libztJNI.cpp index 6f32c5e..c824ed1 100644 --- a/src/libztJNI.cpp +++ b/src/libztJNI.cpp @@ -31,10 +31,16 @@ * JNI naming convention: Java_PACKAGENAME_CLASSNAME_METHODNAME */ +#ifdef SDK_JNI + #include +#include +#include #include "libzt.h" -#include "ZT1Service.h" +#include "libztDefs.h" + +#include #ifdef __cplusplus extern "C" { @@ -42,368 +48,221 @@ extern "C" { namespace ZeroTier { - #include + // prototype + jobject ss2inet(JNIEnv *env, struct sockaddr_storage *src_ss); + int sockinet2ss(JNIEnv *env, jobject src_inet, struct sockaddr_storage *dest_ss); /****************************************************************************/ - /* ZeroTier Socket API (for JNI wrapper) */ + /* ZeroTier service controls */ /****************************************************************************/ - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_socket(JNIEnv *env, jobject thisObj, - jint family, jint type, jint protocol) + JNIEXPORT void JNICALL Java_zerotier_ZeroTier_start( + JNIEnv *env, jobject thisObj, jstring path, jboolean blocking) + { + if (path) { + zts_start(env->GetStringUTFChars(path, NULL), blocking); + } + } + + JNIEXPORT void JNICALL Java_zerotier_ZeroTier_startjoin( + JNIEnv *env, jobject thisObj, jstring path, jlong nwid) + { + if (path && nwid) { + zts_startjoin(env->GetStringUTFChars(path, NULL), (uint64_t)nwid); + } + } + + JNIEXPORT void JNICALL Java_zerotier_ZeroTier_stop( + JNIEnv *env, jobject thisObj) + { + zts_stop(); + } + + JNIEXPORT jboolean JNICALL Java_zerotier_ZeroTier_core_1running( + JNIEnv *env, jobject thisObj) + { + return zts_core_running(); + } + + JNIEXPORT jboolean JNICALL Java_zerotier_ZeroTier_stack_1running( + JNIEnv *env, jobject thisObj) + { + return zts_stack_running(); + } + + JNIEXPORT jboolean JNICALL Java_zerotier_ZeroTier_ready( + JNIEnv *env, jobject thisObj) + { + return zts_ready(); + } + + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_join( + JNIEnv *env, jobject thisObj, jlong nwid) + { + return zts_join((uint64_t)nwid); + } + + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_leave( + JNIEnv *env, jobject thisObj, jlong nwid) + { + return zts_leave((uint64_t)nwid); + } + + JNIEXPORT jstring JNICALL Java_zerotier_ZeroTier_get_1path( + JNIEnv *env, jobject thisObj) + { + char pathBuf[ZT_HOME_PATH_MAX_LEN]; + zts_get_path(pathBuf, ZT_HOME_PATH_MAX_LEN); + return (*env).NewStringUTF(pathBuf); + } + + JNIEXPORT jlong JNICALL Java_zerotier_ZeroTier_get_1node_1id( + JNIEnv *env, jobject thisObj) + { + return zts_get_node_id(); + } + + // TODO: ZT_SOCKET_API uint64_t ZTCALL zts_get_node_id_from_file(const char *filepath); + + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_get_1num_1assigned_1addresses( + JNIEnv *env, jobject thisObj, jlong nwid) + { + return zts_get_num_assigned_addresses(nwid); + } + + JNIEXPORT jobject JNICALL Java_zerotier_ZeroTier_get_1address_1at_1index( + JNIEnv *env, jobject thisObj, jlong nwid, jint index) + { + struct sockaddr_storage ss; + int err; + if((err = zts_get_address_at_index(nwid, index, &ss)) < 0) { + return NULL; + } + return ss2inet(env, &ss); + } + + JNIEXPORT jboolean JNICALL Java_zerotier_ZeroTier_has_1address( + JNIEnv *env, jobject thisObj, jlong nwid) + { + return zts_has_address(nwid); + } + + JNIEXPORT jobject JNICALL Java_zerotier_ZeroTier_get_1address( + JNIEnv *env, jobject thisObj, jlong nwid, jint address_family) + { + struct sockaddr_storage ss; + int err; + if ((err = zts_get_address((uint64_t)nwid, &ss, address_family)) < 0) { + return NULL; + } + return ss2inet(env, &ss); + } + + JNIEXPORT jobject JNICALL Java_zerotier_ZeroTier_get_6plane_addr( + JNIEnv *env, jobject thisObj, jlong nwid, jlong nodeId) + { + struct sockaddr_storage ss; + zts_get_6plane_addr(&ss, nwid, nodeId); + return ss2inet(env, &ss); + } + + JNIEXPORT jobject JNICALL Java_zerotier_ZeroTier_get_rfc4193_addr( + JNIEnv *env, jobject thisObj, jlong nwid, jlong nodeId) + { + struct sockaddr_storage ss; + zts_get_rfc4193_addr(&ss, nwid, nodeId); + return ss2inet(env, &ss); + } + + JNIEXPORT jlong JNICALL Java_zerotier_ZeroTier_get_peer_count( + JNIEnv *env, jobject thisObj) + { + return zts_get_peer_count(); + } + + // TODO: ZT_SOCKET_API int ZTCALL zts_get_peer_address(char *peer, const uint64_t nodeId); + // TODO: ZT_SOCKET_API void ZTCALL zts_allow_http_control(bool allowed); + + /****************************************************************************/ + /* ZeroTier Socket API */ + /****************************************************************************/ + + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_socket( + JNIEnv *env, jobject thisObj, jint family, jint type, jint protocol) { return zts_socket(family, type, protocol); } - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_connect(JNIEnv *env, jobject thisObj, - jint fd, jstring addrstr, jint port) + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_connect( + JNIEnv *env, jobject thisObj, jint fd, jobject addr) { struct sockaddr_storage ss; - socklen_t namelen = sizeof(ss); - int err = 0; - if ((err = zts_getsockname(fd, (struct sockaddr*)&ss, &namelen)) < 0) { - DEBUG_ERROR("error while determining socket family"); - return -1; + if(sockinet2ss(env, addr, &ss) < 0) { + return -1; // possibly invalid address format + // TODO: set errno } - const char *str; -#if defined(LIBZT_IPV4) - if (ss.ss_family == AF_INET) { - struct sockaddr_in in_addr; - str = (*env).GetStringUTFChars(addrstr, 0); - in_addr.sin_addr.s_addr = inet_addr(str); - in_addr.sin_family = AF_INET; - in_addr.sin_port = htons(port); - (*env).ReleaseStringUTFChars(addrstr, str); - } -#endif // LIBZT_IPV4 -#if defined(LIBZT_IPV6) - if (ss.ss_family == AF_INET6) { - struct sockaddr_in6 in_addr; - str = (*env).GetStringUTFChars(addrstr, 0); - //in_addr.sin_addr.s_addr = inet_addr(str); - in_addr.sin6_family = AF_INET6; - in_addr.sin6_port = htons(port); - (*env).ReleaseStringUTFChars(addrstr, str); - } -#endif // LIBZT_IPV6 - DEBUG_INFO("fd=%d, addr=%s, port=%d", fd, str, port); - return zts_connect(fd, (struct sockaddr *)&ss, sizeof(in_addr)); + return zts_connect(fd, (struct sockaddr *)&ss, sizeof(struct sockaddr_storage)); } -/* - - JNIEXPORT jobject JNICALL Java_zerotier_ZeroTier_get_address( - JNIEnv *env, jobject thisObj, jstring nwid) - { - // get address - const char *nwid_str = env->GetStringUTFChars(nwid, NULL); - struct sockaddr_storage ss; - zts_get_address(nwid_str, &ss, INET_ADDRSTRLEN); - // map sockaddr_storage contents to java InetAddress - jclass c = (*env).FindClass("java/net/InetSocketAddress"); - if (c) { - - jobject addresses = (*env).NewObject(c, (*env).GetMethodID(c, "", "()V")); - env->CallBooleanMethod(addresses, env->GetMethodID(c, "getPort", "(Ljava/lang/Object;)Z"), _str); - - DEBUG_INFO("port from JNI layer = %d", port); - - fid = (*env).GetFieldID(c, "port", "I"); - (*env).SetIntField(ztaddr, fid, addr.sin_port); - fid = (*env).GetFieldID(c,"_rawAddr", "J"); - (*env).SetLongField(ztaddr, fid,addr.sin_addr.s_addr); - //jobject addresses = (*env).NewObject(c, (*env).GetMethodID(c, "", "()V")); - //env->CallBooleanMethod(addresses, env->GetMethodID(c, "add", "(Ljava/lang/Object;)Z"), _str); - //return addresses; - } - return NULL; - } - -*/ - - -/* - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_bind(JNIEnv *env, jobject thisObj, - jint fd, jstring addrstr, jint port) + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_bind( + JNIEnv *env, jobject thisObj, jint fd, jobject addr) { struct sockaddr_storage ss; - socklen_t namelen = sizeof(ss); - int err = 0; - if ((err = zts_getsockname(fd, (struct sockaddr*)&ss, &namelen)) < 0) { - DEBUG_ERROR("error while determining socket family"); - return -1; - } - const char *str; -#if defined(LIBZT_IPV4) - if (ss.ss_family == AF_INET) { - struct sockaddr_in in_addr; - str = (*env).GetStringUTFChars(addrstr, 0); - in_addr.sin_addr.s_addr = inet_addr(str); - in_addr.sin_family = AF_INET; - in_addr.sin_port = htons(port); - (*env).ReleaseStringUTFChars(addrstr, str); - } -#endif // LIBZT_IPV4 -#if defined(LIBZT_IPV6) - if (ss.ss_family == AF_INET6) { - struct sockaddr_in6 in_addr; - str = (*env).GetStringUTFChars(addrstr, 0); - //in_addr.sin_addr.s_addr = inet_addr(str); - in_addr.sin6_family = AF_INET6; - in_addr.sin6_port = htons(port); - (*env).ReleaseStringUTFChars(addrstr, str); - } -#endif // LIBZT_IPV6 - DEBUG_INFO("fd=%d, addr=%s, port=%d", fd, str, port); - return zts_bind(fd, (struct sockaddr *)&ss, sizeof(in_addr)); - } -*/ - - - - -/* - jfieldID IPv4 = (*env).GetFieldID(inetClass, "IPv4", "I"); - if (IPv4) { - ipv4 = (*env).GetIntField(inetClass, IPv4); - } - else { - DEBUG_ERROR("No field IPv4"); - } - jfieldID IPv6 = (*env).GetFieldID(inetClass, "IPv6", "I"); - if (IPv6) { - ipv6 = (*env).GetIntField(inetClass, IPv6); - } - else { - DEBUG_ERROR("No field IPv6"); - } - ipv6 = (*env).GetIntField(inetClass, IPv6); -*/ - - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_bind(JNIEnv *env, jobject thisObj, jint fd, jobject addr) - { - struct sockaddr_storage ss; - memset(&ss, 0, sizeof(ss)); struct sockaddr_in *in4 = (struct sockaddr_in*)&ss; struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&ss; - int err = -1; - int port = 0; - int socket_family = 0; - socklen_t addrlen; - - jclass c = (*env).GetObjectClass(addr); - if (!c) { - return -1; + int err; + if(sockinet2ss(env, addr, &ss) < 0) { + return -1; // possibly invalid address format + // TODO: set errno } - // get port - jmethodID getPort = (*env).GetMethodID(c, "getPort", "()I"); - if (!getPort) { - return -1; - } - port = (*env).CallIntMethod(addr, getPort); - // get internal InetAddress - jobject inetaddr; - int family = 0; - jmethodID getAddress = (*env).GetMethodID(c, "getAddress", "()Ljava/net/InetAddress;"); - if (!getAddress) { - return -1; - } - inetaddr = (*env).CallObjectMethod(addr, getAddress); - if (!inetaddr) { - return -1; - } - jclass inetClass = (*env).GetObjectClass(inetaddr); - if (!inetClass) { - return -1; - } - // string representation of IP address - jmethodID getHostAddress = (*env).GetMethodID(inetClass, "getHostAddress", "()Ljava/lang/String;"); - jstring addrstr = (jstring)(*env).CallObjectMethod(inetaddr, getHostAddress); - const char *addr_str = (*env).GetStringUTFChars(addrstr, NULL); - DEBUG_INFO("addr_str=%s", addr_str); - for (int i=0; isin_family = AF_INET; - in4->sin_port = htons(port); - in4->sin_addr.s_addr = inet_addr(addr_str); - /* - if (!inet_pton(AF_INET, addr_str, &(in4->sin_addr))) { - DEBUG_ERROR("error converting address %s", addr_str); - } - */ - addrlen = sizeof(struct sockaddr_in); - break; - } - if (addr_str[i]==':') { - DEBUG_INFO("ipv6"); - socket_family = AF_INET6; - if (!inet_pton(AF_INET6, addr_str, &(in6->sin6_addr))) { - DEBUG_ERROR("error converting address %s", addr_str); - } - addrlen = sizeof(struct sockaddr_in6); - break; - } - } - (*env).ReleaseStringUTFChars(addrstr, addr_str); - - DEBUG_TEST("RESULT => %s : %d", inet_ntoa(in4->sin_addr), ntohs(in4->sin_port)); - - // - /* - jmethodID getRawAddress = (*env).GetMethodID(inetClass, "getAddress", "()[B"); // get raw IP bytes - if (getRawAddress) - { - jbyte rawIPbuf = (*env).CallByteMethod(inetaddr, getRawAddress); - if (socket_family == AF_INET) - { - DEBUG_INFO("copying buffer as AF_INET"); - in4->sin_family = socket_family; - in4->sin_port = port; - memcpy(in4->sin_addr, &rawIPbuf, sizeof(in4->sin_addr)); - } - if (socket_family == AF_INET6) - { - DEBUG_INFO("copying buffer as AF_INET"); - in6->sin6_family = socket_family; - } - } - else { - DEBUG_ERROR("!getRawAddress"); - } - */ - - //DEBUG_INFO("port = %d", port); - //DEBUG_INFO("inetaddr = %p", inetaddr); + //DEBUG_TEST("RESULT => %s : %d", inet_ntoa(in4->sin_addr), ntohs(in4->sin_port)); + socklen_t addrlen = ss.ss_family == AF_INET ? 4 : 16; err = zts_bind(fd, (struct sockaddr*)&ss, addrlen); return err; } -#if defined(__linux__) - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_accept4(JNIEnv *env, jobject thisObj, - jint fd, jstring addrstr, jint port, jint flags) - { - struct sockaddr_in addr; - char *str; - // = env->GetStringUTFChars(addrstr, NULL); - (*env).ReleaseStringUTFChars(addrstr, str); - addr.sin_addr.s_addr = inet_addr(str); - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - return zts_accept4(fd, (struct sockaddr *)&addr, sizeof(addr), flags); - } -#endif - - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_accept(JNIEnv *env, jobject thisObj, - jint fd, jstring addrstr, jint port) - { - struct sockaddr_in addr; - // TODO: Send addr info back to Javaland - addr.sin_addr.s_addr = inet_addr(""); - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - return zts_accept(fd, (struct sockaddr *)&addr, (socklen_t *)sizeof(addr)); - } - - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_listen(JNIEnv *env, jobject thisObj, - jint fd, int backlog) + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_listen( + JNIEnv *env, jobject thisObj, jint fd, int backlog) { return zts_listen(fd, backlog); } - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_close(JNIEnv *env, jobject thisObj, - jint fd) + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_accept( + JNIEnv *env, jobject thisObj, jint fd, jobject addr, jint port) { - return zts_close(fd); - } - - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_sendto( - JNIEnv *env, jobject thisObj, jint fd, jarray buf, jint len, jint flags, jobject ztaddr) - { - struct sockaddr_in addr; - int sent_bytes = 0; - jclass c = (*env).GetObjectClass( ztaddr); - if (c) { - jfieldID f = (*env).GetFieldID(c, "port", "I"); - addr.sin_port = htons((*env).GetIntField( ztaddr, f)); - f = (*env).GetFieldID(c, "_rawAddr", "J"); - addr.sin_addr.s_addr = (*env).GetLongField( ztaddr, f); - addr.sin_family = AF_INET; - //LOGV("zt_sendto(): fd = %d\naddr = %s\nport=%d", fd, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); - // TODO: Optimize this - jbyte *body = (*env).GetByteArrayElements((_jbyteArray *)buf, 0); - char * bufp = (char *)malloc(sizeof(char)*len); - memcpy(bufp, body, len); - (*env).ReleaseByteArrayElements((_jbyteArray *)buf, body, 0); - // "connect" and send buffer contents - sent_bytes = zts_sendto(fd, body, len, flags, (struct sockaddr *)&addr, sizeof(addr)); + struct sockaddr_storage ss; + int err; + socklen_t addrlen = sizeof(struct sockaddr_storage); + if ((err = zts_accept(fd, (struct sockaddr *)&ss, &addrlen)) < 0) { + return err; } - return sent_bytes; + addr = ss2inet(env, &ss); + return err; } - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_recvfrom( - JNIEnv *env, jobject thisObj, jint fd, jbyteArray buf, jint len, jint flags, jobject ztaddr) - { - struct sockaddr_in addr; - jbyte *body = (*env).GetByteArrayElements( buf, 0); - unsigned char buffer[ZT_SDK_MTU]; - int payload_offset = sizeof(int32_t) + sizeof(struct sockaddr_storage); - int rxbytes = zts_recvfrom(fd, &buffer, len, flags, (struct sockaddr *)&addr, (socklen_t *)sizeof(struct sockaddr_storage)); - if (rxbytes > 0) { - memcpy(body, (jbyte*)buffer + payload_offset, rxbytes); +#if defined(__linux__) + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_accept4( + JNIEnv *env, jobject thisObj, jint fd, jobject addr, jint port, jint flags) + { + struct sockaddr_storage ss; + int err; + socklen_t addrlen = sizeof(struct sockaddr_storage); + if ((err = zts_accept(fd, (struct sockaddr *)&ss, &addrlen, flags)) < 0) { + return err; } - (*env).ReleaseByteArrayElements( buf, body, 0); - // Update fields of Java ZTAddress object - jfieldID fid; - jclass c = (*env).GetObjectClass( ztaddr); - if (c) { - fid = (*env).GetFieldID(c, "port", "I"); - (*env).SetIntField(ztaddr, fid, addr.sin_port); - fid = (*env).GetFieldID(c,"_rawAddr", "J"); - (*env).SetLongField(ztaddr, fid,addr.sin_addr.s_addr); - } - return rxbytes; - } - - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_send(JNIEnv *env, jobject thisObj, jint fd, jarray buf, jint len, int flags) - { - jbyte *body = (*env).GetByteArrayElements((_jbyteArray *)buf, 0); - char * bufp = (char *)malloc(sizeof(char)*len); - memcpy(bufp, body, len); - (*env).ReleaseByteArrayElements((_jbyteArray *)buf, body, 0); - int written_bytes = zts_write(fd, body, len); - return written_bytes; - } - - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_write(JNIEnv *env, jobject thisObj, - jint fd, jarray buf, jint len) - { - jbyte *body = (*env).GetByteArrayElements((_jbyteArray *)buf, 0); - char * bufp = (char *)malloc(sizeof(char)*len); - memcpy(bufp, body, len); - (*env).ReleaseByteArrayElements((_jbyteArray *)buf, body, 0); - int written_bytes = zts_write(fd, body, len); - return written_bytes; - } - - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_read(JNIEnv *env, jobject thisObj, - jint fd, jarray buf, jint len) - { - jbyte *body = (*env).GetByteArrayElements((_jbyteArray *)buf, 0); - int read_bytes = read(fd, body, len); - (*env).ReleaseByteArrayElements((_jbyteArray *)buf, body, 0); - return read_bytes; + addr = ss2inet(env, &ss); + return err; } +#endif JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_setsockopt( - JNIEnv *env, jobject thisObj, - jint fd, jint level, jint optname, jint optval, jint optlen) + JNIEnv *env, jobject thisObj, jint fd, jint level, jint optname, jint optval, jint optlen) { return zts_setsockopt(fd, level, optname, (const void*)optval, optlen); } - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_getsockopt(JNIEnv *env, jobject thisObj, - jint fd, jint level, jint optname, jint optval, jint optlen) + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_getsockopt( + JNIEnv *env, jobject thisObj, jint fd, jint level, jint optname, jint optval, jint optlen) { return zts_getsockopt(fd, level, optname, (void*)optval, (socklen_t *)optlen); } @@ -440,87 +299,227 @@ namespace ZeroTier { return err; } - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_fcntl(JNIEnv *env, jobject thisObj, - jint fd, jint cmd, jint flags) + // TODO: ZT_SOCKET_API struct hostent *zts_gethostbyname(const char *name); + + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_close( + JNIEnv *env, jobject thisObj, jint fd) { - return zts_fcntl(fd,cmd,flags); + return zts_close(fd); } - /****************************************************************************/ - /* ZeroTier service controls (for JNI wrapper) */ - /****************************************************************************/ + // TODO: ZT_SOCKET_API int ZTCALL zts_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); - JNIEXPORT void JNICALL Java_zerotier_ZeroTier_start(JNIEnv *env, jobject thisObj, jstring path, jboolean blocking) + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_fcntl( + JNIEnv *env, jobject thisObj, jint fd, jint cmd, jint flags) { - if (path) { - zts_start(env->GetStringUTFChars(path, NULL), blocking); - } + return zts_fcntl(fd, cmd, flags); } - JNIEXPORT void JNICALL Java_zerotier_ZeroTier_startjoin(JNIEnv *env, jobject thisObj, jstring path, jstring nwid) + // TODO: ZT_SOCKET_API int ZTCALL zts_ioctl(int fd, unsigned long request, void *argp); + + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_send(JNIEnv *env, jobject thisObj, jint fd, jarray buf, jint len, int flags) { - if (path && nwid) { - zts_startjoin(env->GetStringUTFChars(path, NULL), env->GetStringUTFChars(nwid, NULL)); - } + jbyte *body = (*env).GetByteArrayElements((_jbyteArray *)buf, 0); + char * bufp = (char *)malloc(sizeof(char)*len); + memcpy(bufp, body, len); + (*env).ReleaseByteArrayElements((_jbyteArray *)buf, body, 0); + int written_bytes = zts_write(fd, body, len); + return written_bytes; } - JNIEXPORT void JNICALL Java_zerotier_ZeroTier_stop(JNIEnv *env, jobject thisObj) + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_sendto( + JNIEnv *env, jobject thisObj, jint fd, jarray buf, jint len, jint flags, jobject ztaddr) { - zts_stop(); - } - - JNIEXPORT jboolean JNICALL Java_zerotier_ZeroTier_running( - JNIEnv *env, jobject thisObj) - { - return zts_running(); - } - - JNIEXPORT void JNICALL Java_zerotier_ZeroTier_join(JNIEnv *env, jobject thisObj, jstring nwid) - { - if (nwid) { - zts_join(env->GetStringUTFChars(nwid, NULL)); - } - } - - JNIEXPORT void JNICALL Java_zerotier_ZeroTier_leave(JNIEnv *env, jobject thisObj, jstring nwid) - { - if (nwid) { - zts_leave(env->GetStringUTFChars(nwid, NULL)); - } - } - - JNIEXPORT jstring JNICALL Java_zerotier_ZeroTier_homepath( - JNIEnv *env, jobject thisObj) - { - // TODO: fix, should copy into given arg - // return (*env).NewStringUTF(zts_get_homepath()); - return (*env).NewStringUTF(""); - } - - JNIEXPORT jobject JNICALL Java_zerotier_ZeroTier_get_address( - JNIEnv *env, jobject thisObj, jstring nwid) - { - // get address - const char *nwid_str = env->GetStringUTFChars(nwid, NULL); - struct sockaddr_storage ss; - zts_get_address(nwid_str, &ss, INET_ADDRSTRLEN); - // map sockaddr_storage contents to java InetAddress - /* - jclass c = (*env).FindClass("java/net/InetAddress"); + struct sockaddr_in addr; + int sent_bytes = 0; + jclass c = (*env).GetObjectClass( ztaddr); if (c) { - jobject addresses = (*env).NewObject(c, (*env).GetMethodID(c, "", "()V")); - env->CallBooleanMethod(addresses, env->GetMethodID(c, "add", "(Ljava/lang/Object;)Z"), _str); - return addresses; - }*/ - return NULL; + jfieldID f = (*env).GetFieldID(c, "port", "I"); + addr.sin_port = htons((*env).GetIntField( ztaddr, f)); + f = (*env).GetFieldID(c, "_rawAddr", "J"); + addr.sin_addr.s_addr = (*env).GetLongField( ztaddr, f); + addr.sin_family = AF_INET; + //LOGV("zt_sendto(): fd = %d\naddr = %s\nport=%d", fd, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); + // TODO: Optimize this + jbyte *body = (*env).GetByteArrayElements((_jbyteArray *)buf, 0); + char * bufp = (char *)malloc(sizeof(char)*len); + memcpy(bufp, body, len); + (*env).ReleaseByteArrayElements((_jbyteArray *)buf, body, 0); + // "connect" and send buffer contents + sent_bytes = zts_sendto(fd, body, len, flags, (struct sockaddr *)&addr, sizeof(addr)); + } + return sent_bytes; } - JNIEXPORT jint Java_zerotier_ZeroTier_get_id() + // TODO: ZT_SOCKET_API ssize_t ZTCALL zts_sendmsg(int fd, const struct msghdr *msg, int flags); + // TODO: ZT_SOCKET_API ssize_t ZTCALL zts_recv(int fd, void *buf, size_t len, int flags); + + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_recvfrom( + JNIEnv *env, jobject thisObj, jint fd, jbyteArray buf, jint len, jint flags, jobject ztaddr) { - return zts_get_id(NULL); // TODO + /* + struct sockaddr_in addr; + jbyte *body = (*env).GetByteArrayElements( buf, 0); + unsigned char buffer[ZT_SDK_MTU]; + int payload_offset = sizeof(int32_t) + sizeof(struct sockaddr_storage); + int rxbytes = zts_recvfrom(fd, &buffer, len, flags, (struct sockaddr *)&addr, (socklen_t *)sizeof(struct sockaddr_storage)); + if (rxbytes > 0) { + memcpy(body, (jbyte*)buffer + payload_offset, rxbytes); + } + (*env).ReleaseByteArrayElements( buf, body, 0); + // Update fields of Java ZTAddress object + jfieldID fid; + jclass c = (*env).GetObjectClass( ztaddr); + if (c) { + fid = (*env).GetFieldID(c, "port", "I"); + (*env).SetIntField(ztaddr, fid, addr.sin_port); + fid = (*env).GetFieldID(c,"_rawAddr", "J"); + (*env).SetLongField(ztaddr, fid,addr.sin_addr.s_addr); + } + */ + return 1; } + + // TODO: ZT_SOCKET_API ssize_t ZTCALL zts_recvmsg(int fd, struct msghdr *msg,int flags); + + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_read(JNIEnv *env, jobject thisObj, + jint fd, jarray buf, jint len) + { + jbyte *body = (*env).GetByteArrayElements((_jbyteArray *)buf, 0); + int read_bytes = read(fd, body, len); + (*env).ReleaseByteArrayElements((_jbyteArray *)buf, body, 0); + return read_bytes; + } + + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_write(JNIEnv *env, jobject thisObj, + jint fd, jarray buf, jint len) + { + jbyte *body = (*env).GetByteArrayElements((_jbyteArray *)buf, 0); + char * bufp = (char *)malloc(sizeof(char)*len); + memcpy(bufp, body, len); + (*env).ReleaseByteArrayElements((_jbyteArray *)buf, body, 0); + int written_bytes = zts_write(fd, body, len); + return written_bytes; + } + + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_shutdown( + JNIEnv *env, jobject thisObj, int fd, int how) + { + return zts_shutdown(fd, how); + } + + // TODO: ZT_SOCKET_API int ZTCALL zts_add_dns_nameserver(struct sockaddr *addr); + // TODO: ZT_SOCKET_API int ZTCALL zts_del_dns_nameserver(struct sockaddr *addr); } + +// convenience function +jobject ss2inet(JNIEnv *env, struct sockaddr_storage *src_ss) +{ + jobject dest_inet; + if(src_ss->ss_family == AF_INET) + { + DEBUG_ERROR("converting from INET"); + struct sockaddr_in *in4 = (struct sockaddr_in*)src_ss; + int arrlen = 4; + jbyteArray bytes = (*env).NewByteArray(arrlen); + jbyte *java_address_bytes; + java_address_bytes = (*env).GetByteArrayElements(bytes, NULL); + memcpy(java_address_bytes, &(in4->sin_addr.s_addr), arrlen); + (*env).ReleaseByteArrayElements(bytes, java_address_bytes, 0); + jclass cls = (*env).FindClass("java/net/InetAddress"); + jmethodID mid = (*env).GetStaticMethodID(cls, "getByAddress", "([B)Ljava/net/InetAddress;"); + dest_inet = (*env).CallStaticObjectMethod(cls, mid, bytes); + (*env).DeleteLocalRef(bytes); + } + if(src_ss->ss_family == AF_INET6) + { + DEBUG_ERROR("converting from INET6"); + struct sockaddr_in6 *in6 = (struct sockaddr_in6*)src_ss; + int arrlen = 16; + jbyteArray bytes = (*env).NewByteArray(arrlen); + (*env).SetByteArrayRegion(bytes, 0, 16, (const jbyte *)&(in6->sin6_addr)); + jclass cls = (*env).FindClass("java/net/InetAddress"); + jmethodID mid = (*env).GetStaticMethodID(cls, "getByAddress", "([B)Ljava/net/InetAddress;"); + dest_inet = (*env).CallStaticObjectMethod(cls, mid, bytes); + (*env).DeleteLocalRef(bytes); + } + return dest_inet; +} + + +int sockinet2ss(JNIEnv *env, jobject src_inet, struct sockaddr_storage *dest_ss) +{ + struct sockaddr_in *in4 = (struct sockaddr_in*)dest_ss; + struct sockaddr_in6 *in6 = (struct sockaddr_in6*)dest_ss; + int err = -1; + int port = 0; + int socket_family = 0; + socklen_t addrlen; + + // --- + + jclass c = (*env).GetObjectClass(src_inet); + if (!c) { + return -1; + } + // get port + jmethodID getPort = (*env).GetMethodID(c, "getPort", "()I"); + if (!getPort) { + return -1; + } + port = (*env).CallIntMethod(src_inet, getPort); + // get internal InetAddress + jobject inetaddr; + int family = 0; + jmethodID getAddress = (*env).GetMethodID(c, "getAddress", "()Ljava/net/InetAddress;"); + if (!getAddress) { + return -1; + } + inetaddr = (*env).CallObjectMethod(src_inet, getAddress); + if (!inetaddr) { + return -1; + } + jclass inetClass = (*env).GetObjectClass(inetaddr); + if (!inetClass) { + return -1; + } + // string representation of IP address + jmethodID getHostAddress = (*env).GetMethodID(inetClass, "getHostAddress", "()Ljava/lang/String;"); + jstring addrstr = (jstring)(*env).CallObjectMethod(inetaddr, getHostAddress); + const char *addr_str = (*env).GetStringUTFChars(addrstr, NULL); + for (int i=0; isin_family = AF_INET; + in4->sin_port = htons(port); + in4->sin_addr.s_addr = inet_addr(addr_str); + /* + if (!inet_pton(AF_INET, addr_str, &(in4->sin_addr))) { + DEBUG_ERROR("error converting address %s", addr_str); + } + */ + addrlen = sizeof(struct sockaddr_in); + break; + } + if (addr_str[i]==':') { + DEBUG_INFO("ipv6"); + socket_family = AF_INET6; + if (!inet_pton(AF_INET6, addr_str, &(in6->sin6_addr))) { + DEBUG_ERROR("error converting address %s", addr_str); + } + addrlen = sizeof(struct sockaddr_in6); + break; + } + } + (*env).ReleaseStringUTFChars(addrstr, addr_str); + DEBUG_TEST("RESULT => %s : %d", inet_ntoa(in4->sin_addr), ntohs(in4->sin_port)); +} + + #ifdef __cplusplus } #endif + +#endif // SDK_JNI \ No newline at end of file diff --git a/src/lwIP.cpp b/src/lwIP.cpp index 6f01335..12ad221 100644 --- a/src/lwIP.cpp +++ b/src/lwIP.cpp @@ -39,12 +39,9 @@ #ifdef STACK_LWIP -int errno; - -// forward declarations -#include "VirtualTap.h" #include "VirtualSocket.h" +// forward declarations class VirtualTap; class VirtualSocket; bool virt_can_provision_new_socket(int socket_type); @@ -77,9 +74,9 @@ bool virt_can_provision_new_socket(int socket_type); #include "lwIP.h" -// lwIP netif interfaces used by virtual taps struct netif lwipInterfaces[10]; -static int lwipInterfacesCount = 0; +int lwipInterfacesCount = 0; + bool lwip_driver_initialized = false; ZeroTier::Mutex driver_m; @@ -144,6 +141,8 @@ void lwip_driver_init() NULL, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO); } + + err_t lwip_eth_tx(struct netif *netif, struct pbuf *p) { struct pbuf *q; @@ -185,78 +184,6 @@ err_t lwip_eth_tx(struct netif *netif, struct pbuf *p) return ERR_OK; } -void lwip_dns_init() -{ - dns_init(); -} - -void lwip_start_dhcp(void *netif) -{ -#if defined(LIBZT_IPV4) - netifapi_dhcp_start((struct netif *)netif); -#endif -} - -void lwip_init_interface(void *tapref, const ZeroTier::MAC &mac, const ZeroTier::InetAddress &ip) -{ - char ipbuf[INET6_ADDRSTRLEN], nmbuf[INET6_ADDRSTRLEN]; - char macbuf[ZT_MAC_ADDRSTRLEN]; - DEBUG_EXTRA("lwipInterfacesCount=%d", lwipInterfacesCount); - struct netif *lwipdev = &lwipInterfaces[lwipInterfacesCount]; - DEBUG_EXTRA("netif=%p", lwipdev); - - if (ip.isV4()) { - static ip4_addr_t ipaddr, netmask, gw; - IP4_ADDR(&gw,127,0,0,1); - ipaddr.addr = *((u32_t *)ip.rawIpData()); - netmask.addr = *((u32_t *)ip.netmask().rawIpData()); - netif_add(lwipdev, &ipaddr, &netmask, &gw, NULL, tapif_init, tcpip_input); - lwipdev->state = tapref; - lwipdev->output = etharp_output; - lwipdev->mtu = ZT_MAX_MTU; - lwipdev->name[0] = 'l'; - lwipdev->name[1] = '0'+lwipInterfacesCount; - lwipdev->linkoutput = lwip_eth_tx; - lwipdev->hwaddr_len = 6; - mac.copyTo(lwipdev->hwaddr, lwipdev->hwaddr_len); - lwipdev->flags = 0; - lwipdev->flags = NETIF_FLAG_BROADCAST - | NETIF_FLAG_ETHARP - | NETIF_FLAG_IGMP - | NETIF_FLAG_LINK_UP - | NETIF_FLAG_UP; - netif_set_default(lwipdev); - netif_set_link_up(lwipdev); - netif_set_up(lwipdev); - mac2str(macbuf, ZT_MAC_ADDRSTRLEN, lwipdev->hwaddr); - DEBUG_INFO("initialized netif as [mac=%s, addr=%s, nm=%s]", macbuf, ip.toString(ipbuf), ip.netmask().toString(nmbuf)); - } - if (ip.isV6()) { - static ip6_addr_t ipaddr; - memcpy(&(ipaddr.addr), ip.rawIpData(), sizeof(ipaddr.addr)); - lwipdev->mtu = ZT_MAX_MTU; - lwipdev->name[0] = 'l'; - lwipdev->name[1] = '0'+lwipInterfacesCount; - lwipdev->hwaddr_len = 6; - lwipdev->linkoutput = lwip_eth_tx; - lwipdev->ip6_autoconfig_enabled = 1; - mac.copyTo(lwipdev->hwaddr, lwipdev->hwaddr_len); - netif_add(lwipdev, NULL, NULL, NULL, NULL, tapif_init, ethernet_input); - lwipdev->output_ip6 = ethip6_output; - lwipdev->state = tapref; - netif_create_ip6_linklocal_address(lwipdev, 1); - s8_t idx = 1; - netif_add_ip6_address(lwipdev, &ipaddr, &idx); - netif_set_default(lwipdev); - netif_set_up(lwipdev); - netif_set_link_up(lwipdev); - netif_ip6_addr_set_state(lwipdev, 1, IP6_ADDR_TENTATIVE); - mac2str(macbuf, ZT_MAC_ADDRSTRLEN, lwipdev->hwaddr); - DEBUG_INFO("initialized netif as [mac=%s, addr=%s]", macbuf, ip.toString(ipbuf)); - } - lwipInterfacesCount++; -} - void lwip_eth_rx(VirtualTap *tap, const ZeroTier::MAC &from, const ZeroTier::MAC &to, unsigned int etherType, const void *data, unsigned int len) { @@ -353,6 +280,80 @@ void lwip_eth_rx(VirtualTap *tap, const ZeroTier::MAC &from, const ZeroTier::MAC } } +void lwip_dns_init() +{ + dns_init(); +} + +void lwip_start_dhcp(void *netif) +{ +#if defined(LIBZT_IPV4) + netifapi_dhcp_start((struct netif *)netif); +#endif +} + +void lwip_init_interface(void *tapref, const ZeroTier::MAC &mac, const ZeroTier::InetAddress &ip) +{ + char ipbuf[INET6_ADDRSTRLEN], nmbuf[INET6_ADDRSTRLEN]; + char macbuf[ZT_MAC_ADDRSTRLEN]; + DEBUG_EXTRA("lwipInterfacesCount=%d", lwipInterfacesCount); + struct netif *lwipdev = &lwipInterfaces[lwipInterfacesCount]; + DEBUG_EXTRA("netif=%p", lwipdev); + + if (ip.isV4()) { + static ip4_addr_t ipaddr, netmask, gw; + IP4_ADDR(&gw,127,0,0,1); + ipaddr.addr = *((u32_t *)ip.rawIpData()); + netmask.addr = *((u32_t *)ip.netmask().rawIpData()); + netif_add(lwipdev, &ipaddr, &netmask, &gw, NULL, tapif_init, tcpip_input); + lwipdev->state = tapref; + lwipdev->output = etharp_output; + lwipdev->mtu = ZT_MAX_MTU; + lwipdev->name[0] = 'l'; + lwipdev->name[1] = '0'+lwipInterfacesCount; + lwipdev->linkoutput = lwip_eth_tx; + lwipdev->hwaddr_len = 6; + mac.copyTo(lwipdev->hwaddr, lwipdev->hwaddr_len); + lwipdev->flags = 0; + lwipdev->flags = NETIF_FLAG_BROADCAST + | NETIF_FLAG_ETHARP + | NETIF_FLAG_IGMP + | NETIF_FLAG_LINK_UP + | NETIF_FLAG_UP; + netif_set_default(lwipdev); + netif_set_link_up(lwipdev); + netif_set_up(lwipdev); + mac2str(macbuf, ZT_MAC_ADDRSTRLEN, lwipdev->hwaddr); + DEBUG_INFO("initialized netif as [mac=%s, addr=%s, nm=%s]", macbuf, ip.toString(ipbuf), ip.netmask().toString(nmbuf)); + } + if (ip.isV6()) { + static ip6_addr_t ipaddr; + memcpy(&(ipaddr.addr), ip.rawIpData(), sizeof(ipaddr.addr)); + lwipdev->mtu = ZT_MAX_MTU; + lwipdev->name[0] = 'l'; + lwipdev->name[1] = '0'+lwipInterfacesCount; + lwipdev->hwaddr_len = 6; + lwipdev->linkoutput = lwip_eth_tx; + lwipdev->ip6_autoconfig_enabled = 1; + mac.copyTo(lwipdev->hwaddr, lwipdev->hwaddr_len); + netif_add(lwipdev, NULL, NULL, NULL, NULL, tapif_init, ethernet_input); + lwipdev->output_ip6 = ethip6_output; + lwipdev->state = tapref; + netif_create_ip6_linklocal_address(lwipdev, 1); + s8_t idx = 1; + netif_add_ip6_address(lwipdev, &ipaddr, &idx); + netif_set_default(lwipdev); + netif_set_up(lwipdev); + netif_set_link_up(lwipdev); + netif_ip6_addr_set_state(lwipdev, 1, IP6_ADDR_TENTATIVE); + mac2str(macbuf, ZT_MAC_ADDRSTRLEN, lwipdev->hwaddr); + DEBUG_INFO("initialized netif as [mac=%s, addr=%s]", macbuf, ip.toString(ipbuf)); + } + lwipInterfacesCount++; +} + + + /****************************************************************************/ diff --git a/test/create_test_identities.sh b/test/create_test_identities.sh index a87af3c..8ddcf6b 100755 --- a/test/create_test_identities.sh +++ b/test/create_test_identities.sh @@ -1,4 +1,5 @@ # !/bin/bash +# Generates test identities and joins them to a test network NWID=""