Preparation for C--, removed classes, namespaces, advanced build options are now controlled via include/libztDefs.h
This commit is contained in:
124
Makefile
124
Makefile
@@ -159,6 +159,10 @@ endif
|
||||
ifeq ($(LIBZT_TRACE),1)
|
||||
LIBZT_DEFS+=-DLIBZT_DEBUG
|
||||
endif
|
||||
# For using experimental stack drivers which interface via raw API's
|
||||
ifeq ($(LIBZT_RAW),1)
|
||||
LIBZT_DEFS+=-DLIBZT_RAW=1
|
||||
endif
|
||||
|
||||
ifeq ($(NS_DEBUG),1)
|
||||
CFLAGS+=-Wall -g
|
||||
@@ -173,13 +177,10 @@ ifeq ($(LIBZT_SANITIZE),1)
|
||||
endif
|
||||
|
||||
# JNI (Java Native Interface)
|
||||
ifeq ($(SDK_JNI), 1)
|
||||
# jni.h
|
||||
LIBZT_INCLUDES+=-I$(shell /usr/libexec/java_home)/include
|
||||
# jni_md.h
|
||||
LIBZT_INCLUDES+=-I$(shell /usr/libexec/java_home)/include/$(OSTYPE)
|
||||
LIBZT_DEFS+=-DSDK_JNI
|
||||
endif
|
||||
# jni.h
|
||||
JNI_INCLUDES+=-I$(shell /usr/libexec/java_home)/include
|
||||
# jni_md.h
|
||||
JNI_INCLUDES+=-I$(shell /usr/libexec/java_home)/include/$(OSTYPE)
|
||||
|
||||
CXXFLAGS+=$(CFLAGS) -Wno-format -fno-rtti -std=c++11
|
||||
ZT_DEFS+=-DZT_SDK -DZT_SOFTWARE_UPDATE_DEFAULT="\"disable\""
|
||||
@@ -190,48 +191,19 @@ STATIC_LIB=$(BUILD)/libzt.a
|
||||
## Stack Configuration ##
|
||||
##############################################################################
|
||||
|
||||
# default stack (picoTCP)
|
||||
STACK_LWIP=1
|
||||
ifeq ($(NO_STACK)$(STACK_PICO),1)
|
||||
STACK_LWIP=0
|
||||
endif
|
||||
#ifeq ($(NO_STACK),1)
|
||||
#STACK_DRIVER_DEFS+=-DNO_STACK
|
||||
#endif
|
||||
|
||||
# picoTCP
|
||||
ifeq ($(STACK_PICO),1)
|
||||
# picoTCP default protocol versions
|
||||
ifeq ($(NS_DEBUG),1)
|
||||
STACK_DEFS+=
|
||||
endif
|
||||
ifeq ($(LIBZT_IPV4)$(LIBZT_IPV6),1)
|
||||
ifeq ($(LIBZT_IPV4),1)
|
||||
STACK_DRIVER_DEFS+=-DLIBZT_IPV4
|
||||
STACK_DEFS+=IPV4=1
|
||||
endif
|
||||
ifeq ($(LIBZT_IPV6),1)
|
||||
STACK_DRIVER_DEFS+=-DLIBZT_IPV6
|
||||
STACK_DEFS+=IPV6=1
|
||||
endif
|
||||
else
|
||||
STACK_DRIVER_DEFS+=-DLIBZT_IPV4 -DLIBZT_IPV6
|
||||
STACK_DEFS+=IPV6=1 IPV4=1
|
||||
endif
|
||||
STACK_DRIVER_DEFS+=-DSTACK_PICO
|
||||
STACK_LIB:=libpicotcp.a
|
||||
STACK_DIR:=ext/picotcp
|
||||
STACK_LIB:=$(STACK_DIR)/build/lib/$(STACK_LIB)
|
||||
STACK_DRIVER_FILES:=src/picoTCP.cpp
|
||||
STACK_INCLUDES+=-Iext/picotcp/include -Iext/picotcp/build/include
|
||||
endif
|
||||
|
||||
# lwIP
|
||||
ifeq ($(STACK_LWIP),1)
|
||||
# lwIP default protocol versions
|
||||
ifeq ($(NS_DEBUG),1)
|
||||
STACK_DEFS+=LWIP_DEBUG=1
|
||||
endif
|
||||
STACK_DRIVER_DEFS+=-DLWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS
|
||||
STACK_DRIVER_DEFS+=-DSTACK_LWIP
|
||||
STACK_DRIVER_FILES:=src/lwIP.cpp
|
||||
|
||||
# picoTCP
|
||||
STACK_INCLUDES+=-Iext/picotcp/include -Iext/picotcp/build/include
|
||||
STACK_DRIVER_FILES:=src/picoTCP.cpp
|
||||
|
||||
# lwIP
|
||||
LWIPDIR=ext/lwip/src
|
||||
STACK_INCLUDES+=-I$(LWIPARCHINCLUDE) -Iext/lwip/src/include/lwip \
|
||||
-I$(LWIPDIR)/include \
|
||||
@@ -239,14 +211,7 @@ STACK_INCLUDES+=-I$(LWIPARCHINCLUDE) -Iext/lwip/src/include/lwip \
|
||||
-I$(LWIPDIR)/include/ipv4 \
|
||||
-I$(LWIPDIR) \
|
||||
-Iext
|
||||
endif
|
||||
|
||||
ifeq ($(NO_STACK),1)
|
||||
STACK_DRIVER_DEFS+=-DNO_STACK
|
||||
endif
|
||||
|
||||
STACK_DRIVER_DEFS+=-DLIBZT_IPV4 -DLWIP_IPV4=1 -DLIBZT_IPV6 -DLWIP_IPV6=1
|
||||
STACK_DEFS+=LIBZT_IPV6=1 IPV6=1 LIBZT_IPV4=1 IPV4=1
|
||||
STACK_DRIVER_FILES:=src/lwIP.cpp
|
||||
|
||||
##############################################################################
|
||||
## Targets ##
|
||||
@@ -254,7 +219,7 @@ STACK_DEFS+=LIBZT_IPV6=1 IPV6=1 LIBZT_IPV4=1 IPV4=1
|
||||
|
||||
%.o : %.cpp
|
||||
@mkdir -p $(BUILD) obj
|
||||
$(CXX) $(CXXFLAGS) $(SANFLAGS) $(STACK_DRIVER_DEFS) $(ZT_DEFS) \
|
||||
$(CXX) $(CXXFLAGS) $(STACK_DRIVER_DEFS) $(ZT_DEFS) \
|
||||
$(ZT_INCLUDES) $(LIBZT_INCLUDES) -c $^ -o obj/$(@F)
|
||||
|
||||
%.o : %.c
|
||||
@@ -270,37 +235,38 @@ picotcp:
|
||||
|
||||
lwip:
|
||||
echo $(STACK_DEFS)
|
||||
make -f make-liblwip.mk liblwip.a $(STACK_DEFS)
|
||||
make -f make-liblwip.mk liblwip.a LIBZT_IPV4=1 IPV4=1
|
||||
|
||||
lwip_driver:
|
||||
$(CXX) $(CXXFLAGS) -c src/lwIP.cpp \
|
||||
$(ZT_DEFS) $(ZT_INCLUDES) $(STACK_INCLUDES) $(LIBZT_DEFS) $(LIBZT_INCLUDES) $(STACK_DRIVER_DEFS)
|
||||
$(ZT_DEFS) $(ZT_INCLUDES) $(STACK_INCLUDES) $(LIBZT_DEFS) $(LIBZT_INCLUDES) -DZT_DRIVER_MODULE
|
||||
|
||||
picotcp_driver:
|
||||
$(CXX) $(CXXFLAGS) -c src/picoTCP.cpp \
|
||||
$(ZT_DEFS) $(ZT_INCLUDES) $(STACK_INCLUDES) $(LIBZT_DEFS) $(LIBZT_INCLUDES) $(STACK_DRIVER_DEFS)
|
||||
$(ZT_DEFS) $(ZT_INCLUDES) $(STACK_INCLUDES) $(LIBZT_DEFS) $(LIBZT_INCLUDES) -DZT_DRIVER_MODULE
|
||||
|
||||
libzt_socket_layer:
|
||||
$(CXX) $(CXXFLAGS) -c src/VirtualSocket.cpp \
|
||||
$(LIBZT_INCLUDES)
|
||||
$(CXX) $(CXXFLAGS) -c src/VirtualBindingPair.cpp \
|
||||
$(ZT_INCLUDES) $(LIBZT_INCLUDES)
|
||||
$(ZT_DEFS) $(ZT_INCLUDES) $(LIBZT_INCLUDES) $(LIBZT_DEFS)
|
||||
$(CXX) $(CXXFLAGS) -c src/VirtualSocketLayer.cpp \
|
||||
$(ZT_DEFS) $(ZT_INCLUDES) $(STACK_INCLUDES) $(LIBZT_INCLUDES) $(LIBZT_DEFS)
|
||||
$(CXX) $(CXXFLAGS) -c src/VirtualTap.cpp \
|
||||
$(ZT_DEFS) $(ZT_INCLUDES) $(LIBZT_DEFS) $(LIBZT_INCLUDES) $(STACK_DRIVER_DEFS)
|
||||
$(ZT_DEFS) $(ZT_INCLUDES) $(LIBZT_DEFS) $(LIBZT_INCLUDES)
|
||||
$(CXX) $(CXXFLAGS) -c src/ZT1Service.cpp \
|
||||
$(ZT_DEFS) $(ZT_INCLUDES) $(LIBZT_INCLUDES) $(LIBZT_DEFS) $(STACK_DRIVER_DEFS)
|
||||
$(ZT_DEFS) $(ZT_INCLUDES) $(LIBZT_INCLUDES) $(LIBZT_DEFS)
|
||||
$(CXX) $(CXXFLAGS) -c src/libzt.cpp \
|
||||
$(ZT_DEFS) $(ZT_INCLUDES) $(STACK_INCLUDES) $(LIBZT_DEFS) $(LIBZT_INCLUDES) $(STACK_DRIVER_DEFS)
|
||||
$(ZT_DEFS) $(ZT_INCLUDES) $(STACK_INCLUDES) $(LIBZT_DEFS) $(LIBZT_INCLUDES)
|
||||
$(CXX) $(CXXFLAGS) -c src/RingBuffer.cpp $(LIBZT_INCLUDES)
|
||||
|
||||
jni_socket_wrapper:
|
||||
$(CXX) $(CXXFLAGS) -DSDK_JNI -c src/libztJNI.cpp \
|
||||
$(ZT_DEFS) $(ZT_INCLUDES) $(STACK_INCLUDES) $(LIBZT_DEFS) $(LIBZT_INCLUDES) $(STACK_DRIVER_DEFS)
|
||||
$(ZT_DEFS) $(ZT_INCLUDES) $(STACK_INCLUDES) $(JNI_INCLUDES) $(LIBZT_DEFS) $(LIBZT_INCLUDES)
|
||||
|
||||
utilities:
|
||||
$(CXX) $(CXXFLAGS) -c src/Platform.cpp \
|
||||
$(CXX) $(CXXFLAGS) -c src/SysUtils.cpp \
|
||||
$(LIBZT_INCLUDES)
|
||||
$(CXX) $(CXXFLAGS) -c src/Utilities.cpp \
|
||||
$(ZT_DEFS) $(ZT_INCLUDES) $(LIBZT_INCLUDES) $(STACK_DRIVER_DEFS)
|
||||
$(ZT_DEFS) $(ZT_INCLUDES) $(LIBZT_INCLUDES) $(STACK_INCLUDES)
|
||||
|
||||
# windows DLL
|
||||
win_dll: lwip lwip_driver libzt_socket_layer utilities $(ZTO_OBJS)
|
||||
@@ -327,27 +293,12 @@ shared_jni_lib: lwip lwip_driver libzt_socket_layer jni_socket_wrapper utilities
|
||||
$(CXX) $(CXXFLAGS) -dynamiclib -o $(BUILD)/libzt.dylib obj/*.o
|
||||
|
||||
# static library
|
||||
ifeq ($(STACK_PICO),1)
|
||||
static_lib: picotcp picotcp_driver libzt_socket_layer utilities $(ZTO_OBJS)
|
||||
static_lib: picotcp picotcp_driver lwip lwip_driver libzt_socket_layer utilities $(ZTO_OBJS)
|
||||
@mkdir -p $(BUILD) obj
|
||||
mv *.o obj
|
||||
mv ext/picotcp/build/lib/*.o obj
|
||||
mv ext/picotcp/build/modules/*.o obj
|
||||
$(ARTOOL) $(ARFLAGS) -o $(STATIC_LIB) obj/*.o
|
||||
endif
|
||||
ifeq ($(STACK_LWIP),1)
|
||||
static_lib: lwip lwip_driver libzt_socket_layer utilities $(ZTO_OBJS)
|
||||
@mkdir -p $(BUILD) obj
|
||||
mv *.o obj
|
||||
$(ARTOOL) $(ARFLAGS) -o $(STATIC_LIB) obj/*.o
|
||||
endif
|
||||
# for layer-2 only (this will omit all userspace network stack code)
|
||||
ifeq ($(NO_STACK),1)
|
||||
static_lib: libzt_socket_layer utilities $(ZTO_OBJS)
|
||||
@mkdir -p $(BUILD) obj
|
||||
mv *.o obj
|
||||
$(ARTOOL) $(ARFLAGS) -o $(STATIC_LIB) obj/*.o
|
||||
endif
|
||||
|
||||
##############################################################################
|
||||
## iOS/macOS App Frameworks ##
|
||||
@@ -377,7 +328,7 @@ python_module:
|
||||
## Unit Tests ##
|
||||
##############################################################################
|
||||
|
||||
tests: selftest nativetest ztproxy
|
||||
tests: selftest nativetest ztproxy simple
|
||||
# intercept
|
||||
|
||||
ZT_UTILS:=zto/node/Utils.cpp -Izto/node
|
||||
@@ -400,8 +351,11 @@ 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) -lzt
|
||||
$(CXX) $(CXXFLAGS) $(SANFLAGS) $(LIBZT_INCLUDES) $(LIBZT_DEFS) examples/bindings/cpp/simple_client_server/server.cpp -o $(BUILD)/server -L$(BUILD) -lzt
|
||||
dlltest:
|
||||
$(CXX) $(CXXFLAGS)
|
||||
$(CXX) $(CXXFLAGS)
|
||||
|
||||
|
||||
##############################################################################
|
||||
@@ -410,9 +364,7 @@ dlltest:
|
||||
|
||||
standardize:
|
||||
vera++ --transform trim_right src/*.cpp
|
||||
vera++ --transform trim_right src/*.hpp
|
||||
vera++ --transform trim_right include/*.h
|
||||
vera++ --transform trim_right include/*.hpp
|
||||
|
||||
clean:
|
||||
-rm -rf .depend
|
||||
|
||||
@@ -28,8 +28,6 @@ A library version of [ZeroTier](https://github.com/zerotier/ZeroTierOne), **libz
|
||||
int main()
|
||||
{
|
||||
char *str = "welcome to the machine";
|
||||
char *nwid = "c7cd7c981b0f52a2"; // network
|
||||
char *path = "config_path"; // where this instance's keys and configs are stored
|
||||
char *ip = "10.8.8.42"; // remote address
|
||||
int port = 8080; // remote port
|
||||
|
||||
@@ -38,7 +36,7 @@ int main()
|
||||
addr.sin_addr.s_addr = inet_addr(ip);
|
||||
addr.sin_port = htons(port);
|
||||
|
||||
zts_startjoin(path, nwid);
|
||||
zts_startjoin("path", 0xc7cd7c981b0f52a2); // config path, nwid
|
||||
|
||||
int fd, err = 0;
|
||||
if ((fd = zts_socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||
@@ -85,4 +83,7 @@ Please make pull requests against the `dev` branch. The `master` branch is relea
|
||||
|
||||
### Commercial License
|
||||
- To be released from GPLv3, contact us directly via `contact@zerotier.com` to discuss commercial licensing.
|
||||
|
||||
### Adding a custom network stack
|
||||
- If you wish to use something other than lwIP or picoTCP, you can easily add your own API function calls in `src/libzt.cpp` or `src/VirtualSocket.cpp` depending on whether your stack's API exposes a POSIX-socket API or a raw API, respectively.
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
### 2017-XX-XX -- Version 1.1.6
|
||||
- In progress
|
||||
Current version: 1.1.5
|
||||
***
|
||||
|
||||
### 2017-11-10 -- Version 1.1.6
|
||||
- [In progress]
|
||||
- API simplification
|
||||
- Removed protocol specific address getters, )
|
||||
- Changed how network IDs and node IDs are passed to the library (everything is now uint64_t)
|
||||
- Initial steps for C-- efforts
|
||||
- Removed classes for stack drivers
|
||||
- Removed namespaces
|
||||
- Names of key classes changed slightly to prevent collisions
|
||||
- Re-classification of Virtual Socket Layer (and associated stack drivers) as experimental
|
||||
- lwIP sequential socket API is now default
|
||||
|
||||
### 2017-10-19 -- Version 1.1.5 (Current)
|
||||
|
||||
|
||||
@@ -24,27 +24,25 @@
|
||||
* of your own application.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
|
||||
#include "RingBuffer.hpp"
|
||||
#include "ztproxy.hpp"
|
||||
#include "Utilities.h"
|
||||
#include "libzt.h"
|
||||
|
||||
#include "RingBuffer.h"
|
||||
#include "ztproxy.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
typedef void PhySocket;
|
||||
@@ -292,7 +290,7 @@ namespace ZeroTier {
|
||||
}
|
||||
// Write data coming from client TCP connection to its TX buffer, later emptied into libzt by threadMain I/O loop
|
||||
conn->tx_m.lock();
|
||||
if ((wr = conn->TXbuf->write((const unsigned char *)data, len)) < 0) {
|
||||
if ((wr = conn->TXbuf->write((const char *)data, len)) < 0) {
|
||||
DEBUG_ERROR("there was an error while writing data from client to tx buffer, err=%d", wr);
|
||||
}
|
||||
else {
|
||||
@@ -368,7 +366,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
std::string path = argv[1];
|
||||
int proxy_listen_port = atoi(argv[2]);
|
||||
std::string nwid = argv[3];
|
||||
std::string nwidstr = argv[3];
|
||||
std::string internal_addr = argv[4];
|
||||
int internal_port = atoi(argv[5]);
|
||||
std::string dns_nameserver= "";//argv[6];
|
||||
@@ -376,13 +374,14 @@ int main(int argc, char **argv)
|
||||
// Start ZeroTier Node
|
||||
// Join Network which contains resources we need to proxy
|
||||
DEBUG_INFO("waiting for libzt to come online");
|
||||
zts_startjoin(path.c_str(), nwid.c_str());
|
||||
uint64_t nwid = strtoll(nwidstr.c_str(),NULL,16);
|
||||
zts_startjoin(path.c_str(), nwid);
|
||||
|
||||
ZeroTier::ZTProxy *proxy = new ZeroTier::ZTProxy(proxy_listen_port, nwid, path, internal_addr, internal_port, dns_nameserver);
|
||||
ZeroTier::ZTProxy *proxy = new ZeroTier::ZTProxy(proxy_listen_port, nwidstr, path, internal_addr, internal_port, dns_nameserver);
|
||||
|
||||
if (proxy) {
|
||||
printf("\nZTProxy started. Listening on %d\n", proxy_listen_port);
|
||||
printf("Traffic will be proxied to and from %s:%d on network %s\n", internal_addr.c_str(), internal_port, nwid.c_str());
|
||||
printf("Traffic will be proxied to and from %s:%d on network %s\n", internal_addr.c_str(), internal_port, nwidstr.c_str());
|
||||
printf("Proxy Node config files and key stored in: %s/\n\n", path.c_str());
|
||||
while(1) {
|
||||
sleep(1);
|
||||
|
||||
@@ -54,14 +54,13 @@ namespace ZeroTier {
|
||||
public:
|
||||
int zfd;
|
||||
PhySocket *client_sock;
|
||||
RingBuffer<unsigned char> *TXbuf;
|
||||
RingBuffer<unsigned char> *RXbuf;
|
||||
RingBuffer *TXbuf, *RXbuf;
|
||||
Mutex tx_m, rx_m;
|
||||
|
||||
TcpConnection() {
|
||||
zfd = -1;
|
||||
TXbuf = new RingBuffer<unsigned char>(BUF_SZ);
|
||||
RXbuf = new RingBuffer<unsigned char>(BUF_SZ);
|
||||
TXbuf = new RingBuffer(BUF_SZ);
|
||||
RXbuf = new RingBuffer(BUF_SZ);
|
||||
}
|
||||
|
||||
~TcpConnection() {
|
||||
|
||||
@@ -20,7 +20,7 @@ int main(int argc, char **argv)
|
||||
exit(0);
|
||||
}
|
||||
std::string path = argv[1];
|
||||
std::string nwid = argv[2];
|
||||
std::string nwidstr = argv[2];
|
||||
std::string remote_addr = argv[3];
|
||||
int remote_port = atoi(argv[4]);
|
||||
int r=0, w=0, err=0, sockfd;
|
||||
@@ -36,10 +36,10 @@ int main(int argc, char **argv)
|
||||
// --- BEGIN
|
||||
|
||||
DEBUG_TEST("Waiting for libzt to come online...\n");
|
||||
zts_startjoin(path.c_str(), nwid.c_str());
|
||||
char device_id[11];
|
||||
zts_get_id(device_id);
|
||||
DEBUG_TEST("I am %s", device_id);
|
||||
uint64_t nwid = strtoll(nwidstr.c_str(),NULL,16);
|
||||
zts_startjoin(path.c_str(), nwid);
|
||||
uint64_t nodeId = zts_get_node_id();
|
||||
DEBUG_TEST("I am %x", nodeId);
|
||||
sleep(2);
|
||||
|
||||
// socket()
|
||||
|
||||
@@ -18,7 +18,7 @@ int main(int argc, char **argv)
|
||||
exit(0);
|
||||
}
|
||||
std::string path = argv[1];
|
||||
std::string nwid = argv[2];
|
||||
std::string nwidstr = argv[2];
|
||||
int bind_port = atoi(argv[3]);
|
||||
int w=0, r=0, err=0, sockfd, accfd;
|
||||
char rbuf[32];
|
||||
@@ -33,10 +33,10 @@ int main(int argc, char **argv)
|
||||
|
||||
|
||||
DEBUG_TEST("Waiting for libzt to come online...\n");
|
||||
zts_startjoin(path.c_str(), nwid.c_str());
|
||||
char device_id[11];
|
||||
zts_get_id(device_id);
|
||||
DEBUG_TEST("I am %s", device_id);
|
||||
uint64_t nwid = strtoll(nwidstr.c_str(),NULL,16);
|
||||
zts_startjoin(path.c_str(), nwid);
|
||||
uint64_t nodeId = zts_get_node_id();
|
||||
DEBUG_TEST("I am %x", nodeId);
|
||||
sleep(2);
|
||||
|
||||
// socket()
|
||||
|
||||
@@ -18,58 +18,46 @@ namespace ZeroTier
|
||||
public static extern int zts_start(string path);
|
||||
|
||||
[DllImport("libzt.dll", CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern int zts_startjoin(string path, string nwid);
|
||||
public static extern int zts_startjoin(string path, ulong nwid);
|
||||
|
||||
[DllImport("libzt.dll", CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern void zts_stop();
|
||||
|
||||
[DllImport("libzt.dll", CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern void zts_join(string nwid);
|
||||
public static extern void zts_join(ulong nwid);
|
||||
|
||||
[DllImport("libzt.dll", CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern void zts_join_soft(string filepath, string nwid);
|
||||
|
||||
[DllImport("libzt.dll", CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern void zts_leave(string nwid);
|
||||
|
||||
[DllImport("libzt.dll", CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern void zts_leave_soft(string filepath, string nwid);
|
||||
public static extern void zts_leave(ulong nwid);
|
||||
|
||||
[DllImport("libzt.dll", CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern void zts_get_homepath(string homePath, int len);
|
||||
|
||||
[DllImport("libzt.dll", CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern int zts_get_id(string devID);
|
||||
public static extern int zts_get_id(string nodeId);
|
||||
|
||||
[DllImport("libzt.dll", CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern int zts_running();
|
||||
|
||||
[DllImport("libzt.dll", CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern int zts_has_ipv4_address(string nwid);
|
||||
public static extern int zts_has_address(ulong nwid);
|
||||
|
||||
[DllImport("libzt.dll", CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern int zts_has_ipv6_address(string nwid);
|
||||
public static extern int zts_has_address(ulong nwid);
|
||||
|
||||
[DllImport("libzt.dll", CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern int zts_has_address(string nwid);
|
||||
public static extern void zts_get_address(ulong nwid, System.IntPtr addr, int addrlen);
|
||||
|
||||
[DllImport("libzt.dll", CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern void zts_get_ipv4_address(string nwid, string addrstr, int addrlen);
|
||||
public static extern void zts_get_6plane_addr(System.IntPtr addr addr, string nwid, string nodeId);
|
||||
|
||||
[DllImport("libzt.dll", CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern void zts_get_ipv6_address(string nwid, string addrstr, int addrlen);
|
||||
|
||||
[DllImport("libzt.dll", CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern void zts_get_6plane_addr(string addr, string nwid, string devID);
|
||||
|
||||
[DllImport("libzt.dll", CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern void zts_get_rfc4193_addr(string addr, string nwid, string devID);
|
||||
public static extern void zts_get_rfc4193_addr(System.IntPtr addr addr, string nwid, string nodeId);
|
||||
|
||||
[DllImport("libzt.dll", CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern long zts_get_peer_count();
|
||||
|
||||
[DllImport("libzt.dll", CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern int zts_get_peer_address(string peer, string devID);
|
||||
public static extern int zts_get_peer_address(string peer, ulong nodeId);
|
||||
|
||||
[DllImport("libzt.dll", CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern void zts_enable_http_control_plane();
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
// Simple Java example for libzt using JNI
|
||||
|
||||
import zerotier.ZeroTier;
|
||||
import java.net.*;
|
||||
|
||||
public class ExampleApp {
|
||||
|
||||
@@ -39,25 +40,28 @@ public class ExampleApp {
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
|
||||
final ZeroTier libzt = new ZeroTier();
|
||||
|
||||
new Thread(new Runnable() {
|
||||
public void run() {
|
||||
System.out.println("starting libzt");
|
||||
libzt.startjoin("/Users/joseph/op/zt/libzt/ztjni", "1212121212121212");
|
||||
//libzt.startjoin("config_path", "123456789abcdeff");
|
||||
libzt.startjoin("/Users/joseph/op/zt/libzt/ztjni", "17d709436c2c5367");
|
||||
System.out.println("started.");
|
||||
// start(path) will not block
|
||||
// startjoin(path, nwid) will block
|
||||
|
||||
int fd = 0, err = 0;
|
||||
if ((fd = libzt.socket(libzt.AF_INET, libzt.SOCK_STREAM, 0)) < 0) {
|
||||
System.out.println("error creating socket");
|
||||
return;
|
||||
}
|
||||
if ((err = libzt.bind(fd, "0.0.0.0", 3000)) < 0) {
|
||||
|
||||
InetSocketAddress addr = new InetSocketAddress("0.0.0.0", 3434);
|
||||
|
||||
if ((err = libzt.bind(fd, addr)) < 0) {
|
||||
System.out.println("error binding socket to virtual interface");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
|
||||
|
||||
@@ -11,4 +11,11 @@ To get this example project to work, do the following:
|
||||
|
||||
Notes:
|
||||
|
||||
Upon execution, it will load the libzt dynamic library via the `loadLibrary` method and begin generating an identity.
|
||||
Upon execution, it will load the libzt dynamic library via the `loadLibrary` method and begin generating an identity.
|
||||
|
||||
|
||||
***
|
||||
|
||||
More resources on JNI usage:
|
||||
|
||||
http://journals.ecs.soton.ac.uk/java/tutorial/native1.1/implementing/index.html
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
/*
|
||||
* ZeroTier SDK - Network Virtualization Everywhere
|
||||
* Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* --
|
||||
*
|
||||
* You can be released from the requirements of the license by purchasing
|
||||
* a commercial license. Buying such a license is mandatory as soon as you
|
||||
* develop commercial closed-source software that incorporates or links
|
||||
* directly against ZeroTier software without disclosing the source code
|
||||
* of your own application.
|
||||
*/
|
||||
|
||||
package zerotier;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/*
|
||||
|
||||
The ZTAddress object is merely a convenience object for moving address information
|
||||
across the JNI memory border.
|
||||
|
||||
*/
|
||||
|
||||
public class Address
|
||||
{
|
||||
// int -> byte array
|
||||
static public byte[] toIPByteArray(long addr){
|
||||
return new byte[]{(byte)addr,(byte)(addr>>>8),(byte)(addr>>>16),(byte)(addr>>>24)};
|
||||
}
|
||||
|
||||
// byte array -> int
|
||||
long toIPInt(String _addr) {
|
||||
long result = 0;
|
||||
for(String part: _addr.split(Pattern.quote("."))) {
|
||||
result = result << 8;
|
||||
result |= Integer.parseInt(part);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public int port;
|
||||
public int Port() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public long _rawAddr;
|
||||
public String Address()
|
||||
{
|
||||
try {
|
||||
return InetAddress.getByAddress(toIPByteArray(_rawAddr)).getHostAddress();
|
||||
} catch (UnknownHostException e) {
|
||||
// should never happen
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return Address() + ":" + Port();
|
||||
}
|
||||
|
||||
public Address()
|
||||
{
|
||||
port = -1;
|
||||
_rawAddr = -1;
|
||||
}
|
||||
|
||||
public Address(String _addr, int _port)
|
||||
{
|
||||
_rawAddr = toIPInt(_addr);
|
||||
port = _port;
|
||||
}
|
||||
|
||||
public void ZTAddress(InetSocketAddress ins)
|
||||
{
|
||||
port = ins.getPort();
|
||||
_rawAddr = toIPInt(ins.getAddress().getHostAddress());
|
||||
}
|
||||
|
||||
public InetSocketAddress ToInetSocketAddress() throws IllegalArgumentException {
|
||||
InetSocketAddress sock_addr = null;
|
||||
try {
|
||||
sock_addr = new InetSocketAddress(Address(), port);
|
||||
} catch (IllegalArgumentException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return sock_addr;
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,8 @@
|
||||
|
||||
package zerotier;
|
||||
|
||||
import java.net.*;
|
||||
|
||||
public class ZeroTier {
|
||||
|
||||
// socket families
|
||||
@@ -58,7 +60,7 @@ public class ZeroTier {
|
||||
// socket API
|
||||
public native int socket(int family, int type, int protocol);
|
||||
public native int connect(int fd, String addr, int port);
|
||||
public native int bind(int fd, String addr, int port);
|
||||
public native int bind(int fd, InetSocketAddress addr);
|
||||
public native int listen(int fd, int backlog);
|
||||
public native int accept(int fd, Address addr);
|
||||
public native int accept4(int fd, String addr, int port);
|
||||
|
||||
@@ -340,8 +340,8 @@ etharp_find_entry(const ip4_addr_t *ipaddr, u8_t flags, struct netif* netif)
|
||||
if (((flags & ETHARP_FLAG_FIND_ONLY) != 0) ||
|
||||
/* or no empty entry found and not allowed to recycle? */
|
||||
((empty == ARP_TABLE_SIZE) && ((flags & ETHARP_FLAG_TRY_HARD) == 0))) {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: no empty entry found and not allowed to recycle\n"));
|
||||
return (s8_t)ERR_MEM;
|
||||
//LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: no empty entry found and not allowed to recycle\n"));
|
||||
//return (s8_t)ERR_MEM;
|
||||
}
|
||||
|
||||
/* b) choose the least destructive entry to recycle:
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
* in turn pull in a lot of standard libary code. In resource-constrained
|
||||
* systems, this should be defined to something less resource-consuming.
|
||||
*/
|
||||
#include "Debug.hpp"
|
||||
#include "libztDebug.h"
|
||||
#ifndef LWIP_PLATFORM_DIAG
|
||||
#define LWIP_PLATFORM_DIAG(x) DEBUG_STACK x
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -174,7 +174,8 @@ extern "C" {
|
||||
#define EMEDIUMTYPE 124 /* Wrong medium type */
|
||||
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
//extern int errno;
|
||||
//#include <errno.h>
|
||||
#endif
|
||||
|
||||
#else /* LWIP_PROVIDE_ERRNO */
|
||||
|
||||
339
ext/pico_bsd/LICENSE
Normal file
339
ext/pico_bsd/LICENSE
Normal file
@@ -0,0 +1,339 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
{description}
|
||||
Copyright (C) {year} {fullname}
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
{signature of Ty Coon}, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
4
ext/pico_bsd/README.md
Normal file
4
ext/pico_bsd/README.md
Normal file
@@ -0,0 +1,4 @@
|
||||
picotcp-bsd
|
||||
===========
|
||||
|
||||
BSD POSIX-compliant socket support for PicoTCP running on any OS.
|
||||
1585
ext/pico_bsd/pico_bsd_sockets.c
Normal file
1585
ext/pico_bsd/pico_bsd_sockets.c
Normal file
File diff suppressed because it is too large
Load Diff
331
ext/pico_bsd/pico_bsd_sockets.h
Normal file
331
ext/pico_bsd/pico_bsd_sockets.h
Normal file
@@ -0,0 +1,331 @@
|
||||
/*********************************************************************
|
||||
PicoTCP. Copyright (c) 2013 TASS Belgium NV. Some rights reserved.
|
||||
See LICENSE and COPYING for usage.
|
||||
Do not redistribute without a written permission by the Copyright
|
||||
holders.
|
||||
|
||||
Author: Maxime Vincent, Daniele Lacamera
|
||||
*********************************************************************/
|
||||
#ifndef PICO_BSD_SOCKETS_H_
|
||||
#define PICO_BSD_SOCKETS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <signal.h>
|
||||
#include "pico_defines.h"
|
||||
#include "pico_constants.h"
|
||||
#include "pico_config.h"
|
||||
#include "pico_stack.h"
|
||||
#include "pico_icmp4.h"
|
||||
#include "pico_stack.h"
|
||||
#include "pico_ipv4.h"
|
||||
#include "pico_ipv6.h"
|
||||
#include "pico_dns_client.h"
|
||||
#include "pico_socket.h"
|
||||
|
||||
#define SOCKSIZE 16
|
||||
#define SOCKSIZE6 28
|
||||
|
||||
struct pico_bsd_endpoint;
|
||||
extern void *picoLock;
|
||||
extern void *pico_signal_tick;
|
||||
|
||||
#if defined STDSOCKET || defined __socklen_t_defined
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/time.h>
|
||||
#ifdef __linux__
|
||||
#include <linux/tcp.h>
|
||||
#endif
|
||||
|
||||
static inline int sockopt_get_name(int posix_name)
|
||||
{
|
||||
switch (posix_name) {
|
||||
case IP_MULTICAST_LOOP: return PICO_IP_MULTICAST_LOOP;
|
||||
case IP_MULTICAST_TTL: return PICO_IP_MULTICAST_TTL;
|
||||
case IP_MULTICAST_IF: return PICO_IP_MULTICAST_IF;
|
||||
case IP_ADD_MEMBERSHIP: return PICO_IP_ADD_MEMBERSHIP;
|
||||
case IP_DROP_MEMBERSHIP: return PICO_IP_DROP_MEMBERSHIP;
|
||||
case SO_RCVBUF : return PICO_SOCKET_OPT_RCVBUF;
|
||||
case SO_SNDBUF : return PICO_SOCKET_OPT_SNDBUF;
|
||||
case TCP_NODELAY : return PICO_TCP_NODELAY;
|
||||
case TCP_KEEPCNT : return PICO_SOCKET_OPT_KEEPCNT;
|
||||
case TCP_KEEPIDLE : return PICO_SOCKET_OPT_KEEPIDLE;
|
||||
case TCP_KEEPINTVL : return PICO_SOCKET_OPT_KEEPINTVL;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define pico_fd_set fd_set
|
||||
#define PICO_FD_SET FD_SET
|
||||
#define PICO_FD_CLR FD_CLR
|
||||
#define PICO_FD_ISSET FD_ISSET
|
||||
#define PICO_FD_ZERO FD_ZERO
|
||||
|
||||
#undef fcntl
|
||||
#define fcntl pico_fcntl
|
||||
|
||||
#else
|
||||
typedef int socklen_t;
|
||||
#define AF_INET (PICO_PROTO_IPV4)
|
||||
#define AF_INET6 (PICO_PROTO_IPV6)
|
||||
#define SOCK_STREAM (PICO_PROTO_TCP)
|
||||
#define SOCK_DGRAM (PICO_PROTO_UDP)
|
||||
|
||||
#define SOL_SOCKET (0x80)
|
||||
|
||||
#define IP_MULTICAST_LOOP (PICO_IP_MULTICAST_LOOP)
|
||||
#define IP_MULTICAST_TTL (PICO_IP_MULTICAST_TTL)
|
||||
#define IP_MULTICAST_IF (PICO_IP_MULTICAST_IF)
|
||||
#define IP_ADD_MEMBERSHIP (PICO_IP_ADD_MEMBERSHIP)
|
||||
#define IP_DROP_MEMBERSHIP (PICO_IP_DROP_MEMBERSHIP)
|
||||
#define SO_RCVBUF (PICO_SOCKET_OPT_RCVBUF)
|
||||
#define SO_SNDBUF (PICO_SOCKET_OPT_SNDBUF)
|
||||
#define TCP_NODELAY (PICO_TCP_NODELAY)
|
||||
#define TCP_KEEPCNT (PICO_SOCKET_OPT_KEEPCNT)
|
||||
#define TCP_KEEPIDLE (PICO_SOCKET_OPT_KEEPIDLE)
|
||||
#define TCP_KEEPINTVL (PICO_SOCKET_OPT_KEEPINTVL)
|
||||
#define SO_ERROR (4103)
|
||||
#define SO_REUSEADDR (2)
|
||||
#define sockopt_get_name(x) ((x))
|
||||
|
||||
#define INET_ADDRSTRLEN (16)
|
||||
#define INET6_ADDRSTRLEN (46)
|
||||
|
||||
struct sockaddr {
|
||||
uint16_t sa_family;
|
||||
};
|
||||
|
||||
struct in_addr {
|
||||
uint32_t s_addr;
|
||||
};
|
||||
|
||||
#define INADDR_ANY ((uint32_t)0U)
|
||||
|
||||
struct in6_addr {
|
||||
uint8_t s6_addr[16];
|
||||
};
|
||||
|
||||
struct __attribute__((packed)) sockaddr_in {
|
||||
uint16_t sin_family;
|
||||
uint16_t sin_port;
|
||||
struct in_addr sin_addr;
|
||||
uint8_t _pad[SOCKSIZE - 8];
|
||||
};
|
||||
|
||||
|
||||
struct __attribute__((packed)) sockaddr_in6 {
|
||||
uint16_t sin6_family;
|
||||
uint16_t sin6_port;
|
||||
uint32_t sin6_flowinfo;
|
||||
struct in6_addr sin6_addr;
|
||||
uint32_t sin6_scope_id;
|
||||
};
|
||||
|
||||
struct __attribute__((packed)) sockaddr_storage {
|
||||
uint16_t ss_family;
|
||||
uint8_t _pad[(SOCKSIZE6 - sizeof(uint16_t))];
|
||||
};
|
||||
|
||||
/* getaddrinfo */
|
||||
struct addrinfo {
|
||||
int ai_flags;
|
||||
int ai_family;
|
||||
int ai_socktype;
|
||||
int ai_protocol;
|
||||
socklen_t ai_addrlen;
|
||||
struct sockaddr *ai_addr;
|
||||
char *ai_canonname;
|
||||
struct addrinfo *ai_next;
|
||||
};
|
||||
|
||||
|
||||
/* hostent */
|
||||
struct hostent {
|
||||
char *h_name; /* official name of host */
|
||||
char **h_aliases; /* alias list */
|
||||
int h_addrtype; /* host address type */
|
||||
int h_length; /* length of address */
|
||||
char **h_addr_list; /* list of addresses */
|
||||
};
|
||||
#define h_addr h_addr_list[0] /* for backward compatibility */
|
||||
|
||||
/* fd_set */
|
||||
#ifndef FD_SETSIZE
|
||||
#define FD_SETSIZE 64 /* 64 files max, 1 bit per file -> 64bits = 8 bytes */
|
||||
#endif
|
||||
|
||||
struct pico_fd_set_s {
|
||||
uint8_t fds_bits[FD_SETSIZE/8];
|
||||
};
|
||||
|
||||
typedef struct pico_fd_set_s pico_fd_set;
|
||||
#ifndef fd_set
|
||||
#define fd_set pico_fd_set
|
||||
#endif
|
||||
|
||||
//typedef void sigset_t;
|
||||
|
||||
#define PICO_FD_SET(n, p) ((p)->fds_bits[(n)/8] |= (1u << ((n) % 8)))
|
||||
#define PICO_FD_CLR(n, p) ((p)->fds_bits[(n)/8] &= ~(1u << ((n) % 8)))
|
||||
#define PICO_FD_ISSET(n, p) ((p)->fds_bits[(n)/8] & (1u << ((n) % 8)))
|
||||
#define PICO_FD_ZERO(p) do{memset((p)->fds_bits, 0, sizeof(struct pico_fd_set_s));}while(0)
|
||||
|
||||
/* Not socket related */
|
||||
#ifndef __time_t_defined
|
||||
typedef pico_time time_t;
|
||||
#define __time_t_defined
|
||||
#endif
|
||||
|
||||
#if !defined _TIME_H && !defined _TIMEVAL_DEFINED && !defined _STRUCT_TIMEVAL
|
||||
struct timeval {
|
||||
time_t tv_sec;
|
||||
time_t tv_usec;
|
||||
};
|
||||
|
||||
#if !defined __timespec_defined && !defined _SYS__TIMESPEC_H_
|
||||
struct timespec {
|
||||
long tv_sec;
|
||||
long tv_nsec;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct timezone {
|
||||
int tz_minuteswest; /* minutes west of Greenwich */
|
||||
int tz_dsttime; /* type of DST correction */
|
||||
};
|
||||
#define _TIMEVAL_DEFINED
|
||||
#endif
|
||||
#endif /* STDSOCKET */
|
||||
|
||||
#ifndef SO_REUSEPORT
|
||||
#define SO_REUSEPORT (15)
|
||||
#endif
|
||||
|
||||
#ifndef FD_CLOEXEC
|
||||
#define FD_CLOEXEC 1
|
||||
#endif
|
||||
|
||||
#ifndef F_DUPFD
|
||||
#define F_DUPFD 0
|
||||
#endif
|
||||
|
||||
#ifndef F_GETFD
|
||||
#define F_GETFD 1
|
||||
#endif
|
||||
|
||||
#ifndef F_SETFD
|
||||
#define F_SETFD 2
|
||||
#endif
|
||||
|
||||
#ifndef F_GETFL
|
||||
#define F_GETFL 3
|
||||
#endif
|
||||
|
||||
#ifndef F_SETFL
|
||||
#define F_SETFL 4
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef O_NONBLOCK
|
||||
#define O_NONBLOCK 0x4000
|
||||
#endif
|
||||
|
||||
#ifndef _SYS_POLL_H
|
||||
#define POLLIN 0x001 /* There is data to read. */
|
||||
#define POLLPRI 0x002 /* There is urgent data to read. */
|
||||
#define POLLOUT 0x004 /* Writing now will not block. */
|
||||
#define POLLRDNORM 0x040 /* Normal data may be read. */
|
||||
#define POLLRDBAND 0x080 /* Priority data may be read. */
|
||||
#define POLLWRNORM 0x100 /* Writing now will not block. */
|
||||
#define POLLWRBAND 0x200 /* Priority data may be written. */
|
||||
|
||||
#define POLLMSG 0x400
|
||||
#define POLLREMOVE 0x1000
|
||||
#define POLLRDHUP 0x2000
|
||||
|
||||
#define POLLERR 0x008 /* Error condition. */
|
||||
#define POLLHUP 0x010 /* Hung up. */
|
||||
#define POLLNVAL 0x020 /* Invalid polling request. */
|
||||
|
||||
typedef unsigned long int nfds_t;
|
||||
|
||||
struct pollfd {
|
||||
int fd;
|
||||
uint16_t events;
|
||||
uint16_t revents;
|
||||
};
|
||||
#endif
|
||||
|
||||
int pico_newsocket(int domain, int type, int proto);
|
||||
int pico_bind(int sd, struct sockaddr * local_addr, socklen_t socklen);
|
||||
int pico_listen(int sd, int backlog);
|
||||
int pico_connect(int sd, struct sockaddr *_saddr, socklen_t socklen);
|
||||
int pico_isconnected(int sd);
|
||||
int pico_accept(int sd, struct sockaddr *_orig, socklen_t *socklen);
|
||||
int pico_sendto(int sd, void * buf, int len, int flags, struct sockaddr *_dst, socklen_t socklen);
|
||||
int pico_recvfrom(int sd, void * buf, int len, int flags, struct sockaddr *_addr, socklen_t *socklen);
|
||||
int pico_write(int sd, void * buf, int len);
|
||||
int pico_send(int sd, void * buf, int len, int flags);
|
||||
int pico_read(int sd, void * buf, int len);
|
||||
int pico_recv(int sd, void * buf, int len, int flags);
|
||||
int pico_close(int sd);
|
||||
int pico_shutdown(int sd, int how);
|
||||
int pico_getsockname(int sd, struct sockaddr * local_addr, socklen_t *socklen);
|
||||
int pico_getpeername(int sd, struct sockaddr * remote_addr, socklen_t *socklen);
|
||||
int pico_fcntl(int sd, int cmd, int arg);
|
||||
int pico_join_multicast_group(int sd, const char *address, const char *local);
|
||||
|
||||
#ifdef PICO_SUPPORT_DNS_CLIENT
|
||||
struct hostent *pico_gethostbyname(const char *name);
|
||||
|
||||
/* getaddrinfo */
|
||||
int pico_getaddrinfo(const char *node, const char *service,
|
||||
const struct addrinfo *hints,
|
||||
struct addrinfo **res);
|
||||
|
||||
void pico_freeaddrinfo(struct addrinfo *res);
|
||||
#endif
|
||||
|
||||
int pico_setsockopt (int sockfd, int level, int optname, const void *optval, socklen_t optlen);
|
||||
int pico_getsockopt (int sockfd, int level, int optname, void *optval, socklen_t *optlen);
|
||||
|
||||
int pico_select (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
|
||||
int pico_pselect (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec *timeout,
|
||||
const sigset_t *sigmask);
|
||||
|
||||
int pico_poll (struct pollfd *pfd, nfds_t npfd, int timeout);
|
||||
int pico_ppoll (struct pollfd *pfd, nfds_t npfd, const struct timespec *timeout_ts, const sigset_t *sigmask);
|
||||
|
||||
#ifndef PICO_SUPPORT_SNTP_CLIENT
|
||||
struct pico_timeval
|
||||
{
|
||||
pico_time tv_sec;
|
||||
pico_time tv_msec;
|
||||
};
|
||||
int pico_settimeofday(struct timeval *tv, struct timezone *tz);
|
||||
#endif
|
||||
|
||||
int pico_gettimeofday(struct timeval *tv, struct timezone *tz);
|
||||
long XTIME(void);
|
||||
#define XGMTIME gmtime
|
||||
|
||||
/* arpa/inet.h */
|
||||
const char *pico_inet_ntop (int af, const void *src, char *dst, socklen_t size);
|
||||
char *pico_inet_ntoa (struct in_addr in);
|
||||
|
||||
/* Non-POSIX */
|
||||
void pico_bsd_init(void);
|
||||
void pico_bsd_deinit(void);
|
||||
void pico_bsd_stack_tick(void);
|
||||
void pico_bsd_stack_tick_timeout(int timeout_ms);
|
||||
uint16_t pico_bsd_select(struct pico_bsd_endpoint *ep);
|
||||
|
||||
#ifdef REPLACE_STDCALLS
|
||||
#include "pico_bsd_syscalls.h"
|
||||
#endif
|
||||
|
||||
#endif /* PICO_BSD_SOCKETS_H_ */
|
||||
336
ext/pico_bsd/pico_bsd_syscalls.h
Normal file
336
ext/pico_bsd/pico_bsd_syscalls.h
Normal file
@@ -0,0 +1,336 @@
|
||||
#ifndef PICO_BSD_SYSCALLS_H_
|
||||
#define PICO_BSD_SYSCALLS_H_
|
||||
|
||||
#include "pico_bsd_sockets.h"
|
||||
|
||||
/* Cannot be included directly, expect from pico_bsd_sockets.h */
|
||||
|
||||
#if defined (__socklen_t_defined) && defined (REPLACE_STDCALLS)
|
||||
|
||||
/* For systems that have the syscalls already defined */
|
||||
#ifdef socket
|
||||
#undef socket
|
||||
#endif
|
||||
#define socket pico_newsocket
|
||||
|
||||
#ifdef bind
|
||||
#undef bind
|
||||
#endif
|
||||
#define bind pico_bind
|
||||
|
||||
#ifdef listen
|
||||
#undef listen
|
||||
#endif
|
||||
#define listen pico_listen
|
||||
|
||||
#ifdef connect
|
||||
#undef connect
|
||||
#endif
|
||||
#define connect pico_connect
|
||||
|
||||
#ifdef accept
|
||||
#undef accept
|
||||
#endif
|
||||
#define accept pico_accept
|
||||
|
||||
#ifdef sendto
|
||||
#undef sendto
|
||||
#endif
|
||||
#define sendto pico_sendto
|
||||
|
||||
#ifdef recvfrom
|
||||
#undef recvfrom
|
||||
#endif
|
||||
#define recvfrom pico_recvfrom
|
||||
|
||||
#ifdef write
|
||||
#undef write
|
||||
#endif
|
||||
#define write pico_write
|
||||
|
||||
#ifdef read
|
||||
#undef read
|
||||
#endif
|
||||
#define read pico_read
|
||||
|
||||
#ifdef send
|
||||
#undef send
|
||||
#endif
|
||||
#define send pico_send
|
||||
|
||||
#ifdef recv
|
||||
#undef recv
|
||||
#endif
|
||||
#define recv pico_recv
|
||||
|
||||
#ifdef close
|
||||
#undef close
|
||||
#endif
|
||||
#define close pico_close
|
||||
|
||||
#ifdef shutdown
|
||||
#undef shutdown
|
||||
#endif
|
||||
#define shutdown pico_shutdown
|
||||
|
||||
#ifdef getsockname
|
||||
#undef getsockname
|
||||
#endif
|
||||
#define getsockname pico_getsockname
|
||||
|
||||
#ifdef getpeername
|
||||
#undef getpeername
|
||||
#endif
|
||||
#define getpeername pico_getpeername
|
||||
|
||||
#ifdef setsockopt
|
||||
#undef setsockopt
|
||||
#endif
|
||||
#define setsockopt pico_setsockopt
|
||||
|
||||
#ifdef getsockopt
|
||||
#undef getsockopt
|
||||
#endif
|
||||
#define getsockopt pico_getsockopt
|
||||
|
||||
#ifdef gettimeofday
|
||||
#undef gettimeofday
|
||||
#endif
|
||||
#define gettimeofday pico_gettimeofday
|
||||
|
||||
#ifdef gethostbyname
|
||||
#undef gethostbyname
|
||||
#endif
|
||||
#define gethostbyname pico_gethostbyname
|
||||
|
||||
#ifdef getaddrinfo
|
||||
#undef getaddrinfo
|
||||
#endif
|
||||
#define getaddrinfo pico_getaddrinfo
|
||||
|
||||
#ifdef freeaddrinfo
|
||||
#undef freeaddrinfo
|
||||
#endif
|
||||
#define freeaddrinfo pico_freeaddrinfo
|
||||
|
||||
#ifdef htons
|
||||
#undef htons
|
||||
#endif
|
||||
#define htons short_be
|
||||
|
||||
#ifdef htonl
|
||||
#undef htonl
|
||||
#endif
|
||||
#define htonl long_be
|
||||
|
||||
#ifdef ntohs
|
||||
#undef ntohs
|
||||
#endif
|
||||
#define ntohs short_be
|
||||
|
||||
#ifdef ntohl
|
||||
#undef ntohl
|
||||
#endif
|
||||
#define ntohl long_be
|
||||
|
||||
#ifdef inet_ntoa
|
||||
#undef inet_ntoa
|
||||
#endif
|
||||
#define inet_ntoa pico_inet_ntoa
|
||||
|
||||
#ifdef inet_ntop
|
||||
#undef inet_ntop
|
||||
#endif
|
||||
#define inet_ntop pico_inet_ntop
|
||||
|
||||
#ifdef select
|
||||
#undef select
|
||||
#endif
|
||||
#define select pico_select
|
||||
|
||||
#ifdef pselect
|
||||
#undef pselect
|
||||
#endif
|
||||
#define pselect pico_pselect
|
||||
|
||||
#ifdef poll
|
||||
#undef poll
|
||||
#endif
|
||||
#define poll pico_poll
|
||||
|
||||
#ifdef ppoll
|
||||
#undef ppoll
|
||||
#endif
|
||||
#define ppoll pico_ppoll
|
||||
#else
|
||||
|
||||
static inline int socket(int domain, int type, int proto)
|
||||
{
|
||||
return pico_newsocket(domain, type, proto);
|
||||
}
|
||||
|
||||
static inline int bind(int sd, struct sockaddr * local_addr, socklen_t socklen)
|
||||
{
|
||||
return pico_bind(sd, local_addr, socklen);
|
||||
}
|
||||
|
||||
static inline int listen(int sd, int backlog)
|
||||
{
|
||||
return pico_listen(sd, backlog);
|
||||
}
|
||||
|
||||
static inline int connect(int sd, struct sockaddr *_saddr, socklen_t socklen)
|
||||
{
|
||||
return pico_connect(sd, _saddr, socklen);
|
||||
}
|
||||
|
||||
static inline int accept(int sd, struct sockaddr *_orig, socklen_t *socklen)
|
||||
{
|
||||
return pico_accept(sd, _orig, socklen);
|
||||
}
|
||||
|
||||
static inline int sendto(int sd, void * buf, int len, int flags, struct sockaddr *_dst, socklen_t socklen)
|
||||
{
|
||||
return pico_sendto(sd, buf, len, flags, _dst, socklen);
|
||||
}
|
||||
|
||||
static inline int recvfrom(int sd, void * buf, int len, int flags, struct sockaddr *_addr, socklen_t *socklen)
|
||||
{
|
||||
return pico_recvfrom(sd, buf, len, flags, _addr, socklen);
|
||||
}
|
||||
|
||||
static inline int write(int sd, void * buf, int len)
|
||||
{
|
||||
return pico_write(sd, buf, len);
|
||||
}
|
||||
|
||||
static inline int send(int sd, void * buf, int len, int flags)
|
||||
{
|
||||
return pico_send(sd, buf, len, flags);
|
||||
}
|
||||
|
||||
static inline int read(int sd, void * buf, int len)
|
||||
{
|
||||
return pico_read(sd, buf, len);
|
||||
}
|
||||
|
||||
static inline int recv(int sd, void * buf, int len, int flags)
|
||||
{
|
||||
return pico_recv(sd, buf, len, flags);
|
||||
}
|
||||
|
||||
static inline int close(int sd)
|
||||
{
|
||||
return pico_close(sd);
|
||||
}
|
||||
|
||||
static inline int shutdown(int sd, int how)
|
||||
{
|
||||
return pico_shutdown(sd, how);
|
||||
}
|
||||
|
||||
static inline int getsockname(int sd, struct sockaddr * local_addr, socklen_t *socklen)
|
||||
{
|
||||
return pico_getsockname(sd, local_addr, socklen);
|
||||
}
|
||||
|
||||
static inline int getpeername(int sd, struct sockaddr * remote_addr, socklen_t *socklen)
|
||||
{
|
||||
return pico_getpeername(sd, remote_addr, socklen);
|
||||
}
|
||||
|
||||
static inline int fcntl(int sd, int cmd, int arg)
|
||||
{
|
||||
return pico_fcntl(sd, cmd, arg);
|
||||
}
|
||||
|
||||
#ifdef PICO_SUPPORT_DNS_CLIENT
|
||||
static inline struct hostent *gethostbyname(const char *name)
|
||||
{
|
||||
return pico_gethostbyname(name);
|
||||
}
|
||||
|
||||
static inline int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res)
|
||||
{
|
||||
return pico_getaddrinfo(node, service, hints, res);
|
||||
}
|
||||
|
||||
static inline void freeaddrinfo(struct addrinfo *res)
|
||||
{
|
||||
return pico_freeaddrinfo(res);
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen)
|
||||
{
|
||||
return pico_setsockopt(sockfd, level, optname, optval, optlen);
|
||||
}
|
||||
|
||||
static inline int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen)
|
||||
{
|
||||
return pico_getsockopt(sockfd, level, optname, optval, optlen);
|
||||
}
|
||||
|
||||
static inline int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
|
||||
{
|
||||
return pico_select(nfds, readfds, writefds, exceptfds, timeout);
|
||||
}
|
||||
|
||||
static inline int pselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec *timeout, const sigset_t *sigmask)
|
||||
{
|
||||
return pico_pselect(nfds, readfds, writefds, exceptfds, timeout, sigmask);
|
||||
}
|
||||
|
||||
static inline int poll(struct pollfd *pfd, nfds_t npfd, int timeout)
|
||||
{
|
||||
return pico_poll(pfd, npfd, timeout);
|
||||
}
|
||||
|
||||
static inline int ppoll(struct pollfd *pfd, nfds_t npfd, const struct timespec *timeout_ts, const sigset_t *sigmask)
|
||||
{
|
||||
return pico_ppoll(pfd, npfd, timeout_ts, sigmask);
|
||||
}
|
||||
|
||||
static int gettimeofday(struct timeval *tv, struct timezone *tz)
|
||||
{
|
||||
return pico_gettimeofday(tv, tz);
|
||||
}
|
||||
|
||||
static int settimeofday(struct timeval *tv, struct timezone *tz)
|
||||
{
|
||||
return pico_settimeofday(tv, tz);
|
||||
}
|
||||
|
||||
static inline const char *inet_ntop(int af, const void *src, char *dst, socklen_t size)
|
||||
{
|
||||
return pico_inet_ntop(af, src, dst, size);
|
||||
}
|
||||
|
||||
static inline char *inet_ntoa(struct in_addr in)
|
||||
{
|
||||
return pico_inet_ntoa(in);
|
||||
}
|
||||
|
||||
static inline uint32_t htonl(uint32_t le)
|
||||
{
|
||||
return long_be(le);
|
||||
}
|
||||
|
||||
static inline uint32_t ntohl(uint32_t le)
|
||||
{
|
||||
return long_be(le);
|
||||
}
|
||||
|
||||
static inline uint16_t htons(uint16_t le)
|
||||
{
|
||||
return short_be(le);
|
||||
}
|
||||
|
||||
static inline uint16_t ntohs(uint16_t le)
|
||||
{
|
||||
return short_be(le);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* PICO_BSD_SYSCALLS_H_ */
|
||||
45
ext/pico_bsd/pico_osal.h
Normal file
45
ext/pico_bsd/pico_osal.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* pico_osal.h
|
||||
*
|
||||
* Created on: December 2013
|
||||
* Author: Maxime Vincent
|
||||
* Description: OS Abstraction Layer between PicoTCP and FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _PICO_OSAL_H_
|
||||
#define _PICO_OSAL_H_
|
||||
|
||||
/*****************************************************************************
|
||||
* Public types/enumerations/variables
|
||||
****************************************************************************/
|
||||
|
||||
/* Queue implementation API is: */
|
||||
|
||||
|
||||
/* Posix version of thread */
|
||||
typedef void* pico_thread_t;
|
||||
typedef void *(*pico_thread_fn)(void *);
|
||||
|
||||
void * pico_mutex_init(void);
|
||||
void pico_mutex_deinit(void * mutex);
|
||||
void pico_mutex_lock(void * mutex);
|
||||
int pico_mutex_lock_timeout(void * mutex, int timeout);
|
||||
void pico_mutex_unlock(void * mutex);
|
||||
void pico_mutex_unlock_ISR(void * mutex);
|
||||
|
||||
void * pico_signal_init(void);
|
||||
void pico_signal_deinit(void * signal);
|
||||
void pico_signal_wait(void * signal);
|
||||
int pico_signal_wait_timeout(void * signal, int timeout);
|
||||
void pico_signal_send(void * signal);
|
||||
void pico_signal_send_ISR(void * signal);
|
||||
|
||||
pico_thread_t pico_thread_create(pico_thread_fn thread, void *arg, int stack_size, int prio);
|
||||
void pico_thread_destroy(pico_thread_t t);
|
||||
void pico_msleep(int ms);
|
||||
|
||||
void pico_threads_schedule(void);
|
||||
|
||||
#endif /* _PICO_OSAL_H_ */
|
||||
|
||||
176
ext/pico_bsd/pico_osal_freertos.c
Normal file
176
ext/pico_bsd/pico_osal_freertos.c
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* pico_osal.h
|
||||
*
|
||||
* Created on: December 2013
|
||||
* Author: Maxime Vincent
|
||||
* Description: OS Abstraction Layer between PicoTCP and FreeRTOS
|
||||
*
|
||||
*/
|
||||
/* FreeRTOS includes */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "semphr.h"
|
||||
#include "portmacro.h"
|
||||
|
||||
|
||||
/* PicoTCP includes */
|
||||
#include "pico_defines.h"
|
||||
#include "pico_config.h"
|
||||
#include "pico_osal.h"
|
||||
|
||||
#define osal_dbg(...)
|
||||
//#define osal_dbg(...) printf(__VA_ARGS__)
|
||||
|
||||
/*****************************************************************************
|
||||
* Public functions
|
||||
****************************************************************************/
|
||||
|
||||
struct osal_mutex {
|
||||
void * mutex;
|
||||
uint8_t idx; /* only to keep track of the amount/idx, no real function .. */
|
||||
};
|
||||
static uint8_t mtx_number = 0;
|
||||
|
||||
|
||||
/* ============= */
|
||||
/* == SIGNALS == */
|
||||
/* ============= */
|
||||
|
||||
void * pico_signal_init(void)
|
||||
{
|
||||
struct osal_mutex *signal;
|
||||
signal = pico_zalloc(sizeof(struct osal_mutex));
|
||||
osal_dbg("mi: %p for %p\n", signal, __builtin_return_address(0));
|
||||
if (!signal)
|
||||
return NULL;
|
||||
signal->mutex= xSemaphoreCreateBinary();
|
||||
signal->idx = mtx_number++;
|
||||
return signal;
|
||||
}
|
||||
|
||||
void pico_signal_deinit(void * signal)
|
||||
{
|
||||
struct osal_mutex * mtx = signal;
|
||||
vSemaphoreDelete(mtx->mutex);
|
||||
pico_free(signal);
|
||||
}
|
||||
|
||||
void pico_signal_wait(void * signal)
|
||||
{
|
||||
pico_signal_wait_timeout(signal, (int)portMAX_DELAY);
|
||||
}
|
||||
|
||||
int pico_signal_wait_timeout(void * signal, int timeout)
|
||||
{
|
||||
int retval = 0;
|
||||
if(signal != NULL)
|
||||
{
|
||||
struct osal_mutex * mtx = signal;
|
||||
if (timeout == portMAX_DELAY) {
|
||||
while (xSemaphoreTake(mtx->mutex, portMAX_DELAY) == pdFALSE);
|
||||
} else {
|
||||
retval = xSemaphoreTake(mtx->mutex, timeout);
|
||||
}
|
||||
}
|
||||
if (retval) {
|
||||
return 0; /* Success */
|
||||
} else {
|
||||
return -1; /* Timeout */
|
||||
}
|
||||
}
|
||||
|
||||
void pico_signal_send(void * signal)
|
||||
{
|
||||
if(signal != NULL)
|
||||
{
|
||||
struct osal_mutex * mtx = signal;
|
||||
xSemaphoreGive(mtx->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
void pico_signal_send_ISR(void * signal)
|
||||
{
|
||||
if(signal != NULL)
|
||||
{
|
||||
struct osal_mutex * mtx = signal;
|
||||
long task_switch_needed = 0;
|
||||
xSemaphoreGiveFromISR(mtx->mutex, &task_switch_needed);
|
||||
portYIELD_FROM_ISR(task_switch_needed);
|
||||
}
|
||||
}
|
||||
|
||||
/* ============= */
|
||||
/* == MUTEXES == */
|
||||
/* ============= */
|
||||
|
||||
|
||||
void *pico_mutex_init(void)
|
||||
{
|
||||
struct osal_mutex *mutex;
|
||||
mutex = pico_zalloc(sizeof(struct osal_mutex));
|
||||
osal_dbg("mi: %p for %p\n", mutex, __builtin_return_address(0));
|
||||
if (!mutex)
|
||||
return NULL;
|
||||
mutex->mutex = xSemaphoreCreateMutex();
|
||||
mutex->idx = mtx_number++;
|
||||
return mutex;
|
||||
}
|
||||
|
||||
void pico_mutex_deinit(void * mutex)
|
||||
{
|
||||
pico_signal_deinit(mutex);
|
||||
}
|
||||
|
||||
int pico_mutex_lock_timeout(void * mutex, int timeout)
|
||||
{
|
||||
return pico_signal_wait_timeout(mutex, timeout);
|
||||
}
|
||||
|
||||
void pico_mutex_lock(void * mutex)
|
||||
{
|
||||
pico_signal_wait_timeout(mutex, (int)portMAX_DELAY);
|
||||
}
|
||||
|
||||
void pico_mutex_unlock(void * mutex)
|
||||
{
|
||||
pico_signal_send(mutex);
|
||||
}
|
||||
|
||||
void pico_mutex_unlock_ISR(void * mutex)
|
||||
{
|
||||
pico_signal_send_ISR(mutex);
|
||||
}
|
||||
|
||||
|
||||
/* ============= */
|
||||
/* == THREADS == */
|
||||
/* ============= */
|
||||
static char thread_name[4] = "T";
|
||||
static int thread_n = 0;
|
||||
|
||||
pico_thread_t pico_thread_create(pico_thread_fn thread, void *arg, int stack_size, int prio)
|
||||
{
|
||||
pico_thread_t t = PICO_ZALLOC(sizeof(TaskHandle_t));
|
||||
if (!t)
|
||||
return NULL;
|
||||
thread_name[2] = (thread_n++) % 10;
|
||||
thread_name[3] = 0;
|
||||
xTaskCreate((TaskFunction_t)thread, thread_name, stack_size, arg, prio, t);
|
||||
return t;
|
||||
}
|
||||
|
||||
void pico_thread_destroy(pico_thread_t t)
|
||||
{
|
||||
vTaskDelete((TaskHandle_t)t);
|
||||
PICO_FREE(t);
|
||||
}
|
||||
|
||||
void pico_msleep(int ms)
|
||||
{
|
||||
vTaskDelay(ms);
|
||||
}
|
||||
|
||||
void pico_threads_schedule(void)
|
||||
{
|
||||
vTaskStartScheduler();
|
||||
}
|
||||
166
ext/pico_bsd/pico_osal_noos.c
Normal file
166
ext/pico_bsd/pico_osal_noos.c
Normal file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* pico_osal.h
|
||||
*
|
||||
* Created on: December 2014
|
||||
* Author: Maxime Vincent
|
||||
* Description: OS Abstraction Layer between PicoTCP and No Operating System
|
||||
*
|
||||
*/
|
||||
|
||||
/* PicoTCP includes */
|
||||
#include "pico_defines.h"
|
||||
#include "pico_config.h"
|
||||
#include "pico_stack.h"
|
||||
#include "pico_osal.h"
|
||||
|
||||
#define osal_dbg(...)
|
||||
//#define osal_dbg(...) printf(__VA_ARGS__)
|
||||
|
||||
/*****************************************************************************
|
||||
* Public functions
|
||||
****************************************************************************/
|
||||
|
||||
/* ============= */
|
||||
/* == MUTEXES == */
|
||||
/* ============= */
|
||||
|
||||
struct osal_mutex {
|
||||
volatile int want_to_take; /* for ISR safety, basically a mutex for the mutex */
|
||||
volatile int mutex;
|
||||
int idx; /* only to keep track of the amount/idx, no real function .. */
|
||||
};
|
||||
|
||||
static uint8_t mtx_number = 0;
|
||||
|
||||
void * pico_mutex_init(void)
|
||||
{
|
||||
struct osal_mutex * mutex;
|
||||
mutex = pico_zalloc(sizeof(struct osal_mutex));
|
||||
osal_dbg("mi: %p for %p\n", mutex, __builtin_return_address(0));
|
||||
if (!mutex)
|
||||
return NULL;
|
||||
mutex->mutex = 1;
|
||||
mutex->idx = mtx_number++;
|
||||
return mutex;
|
||||
}
|
||||
|
||||
void pico_mutex_deinit(void * mutex)
|
||||
{
|
||||
struct osal_mutex * mtx = mutex;
|
||||
pico_free(mutex);
|
||||
}
|
||||
|
||||
int pico_mutex_lock_timeout(void * mutex, int timeout)
|
||||
{
|
||||
int retval = 0;
|
||||
if(mutex != NULL)
|
||||
{
|
||||
struct osal_mutex * mtx = mutex;
|
||||
pico_time timestamp = PICO_TIME_MS();
|
||||
while (mtx->mutex == 0)
|
||||
{
|
||||
pico_stack_tick();
|
||||
#ifdef _POSIX_VERSION
|
||||
usleep(500);
|
||||
#endif
|
||||
|
||||
/* break on timeout unless infinite timeout */
|
||||
if ((timeout != -1) && (PICO_TIME_MS() > (timestamp + timeout)))
|
||||
break;
|
||||
}
|
||||
if (mtx->mutex == 1)
|
||||
{
|
||||
mtx->mutex = 0; /* take the mutex */
|
||||
}
|
||||
else
|
||||
{
|
||||
retval = -1; /* timeout */
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
void pico_mutex_lock(void * mutex)
|
||||
{
|
||||
pico_mutex_lock_timeout(mutex, -1);
|
||||
}
|
||||
|
||||
void pico_mutex_unlock(void * mutex)
|
||||
{
|
||||
if(mutex != NULL)
|
||||
{
|
||||
struct osal_mutex * mtx = mutex;
|
||||
mtx->mutex = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void pico_mutex_unlock_ISR(void * mutex)
|
||||
{
|
||||
if(mutex != NULL)
|
||||
{
|
||||
struct osal_mutex * mtx = mutex;
|
||||
// tricky stuff needed or not?
|
||||
mtx->mutex = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* ============= */
|
||||
/* == SIGNALS == */
|
||||
/* ============= */
|
||||
|
||||
void * pico_signal_init(void)
|
||||
{
|
||||
void * signal = pico_mutex_init();
|
||||
pico_mutex_lock(signal);
|
||||
return signal;
|
||||
}
|
||||
|
||||
void pico_signal_deinit(void * signal)
|
||||
{
|
||||
pico_mutex_deinit(signal);
|
||||
}
|
||||
|
||||
void pico_signal_wait(void * signal)
|
||||
{
|
||||
pico_signal_wait_timeout(signal, -1);
|
||||
}
|
||||
|
||||
int pico_signal_wait_timeout(void * signal, int timeout)
|
||||
{
|
||||
return pico_mutex_lock_timeout(signal, timeout);
|
||||
}
|
||||
|
||||
void pico_signal_send(void * signal)
|
||||
{
|
||||
pico_mutex_unlock(signal);
|
||||
}
|
||||
|
||||
void pico_signal_send_ISR(void * signal)
|
||||
{
|
||||
pico_mutex_unlock_ISR(signal);
|
||||
}
|
||||
|
||||
|
||||
/* ============= */
|
||||
/* == THREADS == */
|
||||
/* ============= */
|
||||
|
||||
pico_thread_t pico_thread_create(pico_thread_fn thread, void *arg, int stack_size, int prio)
|
||||
{
|
||||
(void)thread;
|
||||
(void)arg;
|
||||
(void)stack_size;
|
||||
(void)prio;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void pico_thread_destroy(pico_thread_t t)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void pico_msleep(int ms)
|
||||
{
|
||||
pico_time now = PICO_TIME_MS();
|
||||
while ((pico_time)(now + ms) < PICO_TIME_MS());
|
||||
}
|
||||
119
ext/pico_bsd/pico_osal_pthread.c
Normal file
119
ext/pico_bsd/pico_osal_pthread.c
Normal file
@@ -0,0 +1,119 @@
|
||||
/* Pthread osal implementation, for testing purposes */
|
||||
#include <pthread.h>
|
||||
#include "pico_defines.h"
|
||||
#include "pico_stack.h"
|
||||
#include "pico_osal.h"
|
||||
#include <semaphore.h>
|
||||
#include <time.h>
|
||||
|
||||
#define BILLION 1000000000
|
||||
|
||||
void * pico_mutex_init(void) {
|
||||
pthread_mutex_t *mutex = pico_zalloc(sizeof(pthread_mutex_t));
|
||||
if (!mutex)
|
||||
return NULL;
|
||||
if (pthread_mutex_init(mutex, NULL) == 0 )
|
||||
return mutex;
|
||||
pico_free(mutex);
|
||||
return NULL;
|
||||
}
|
||||
void pico_mutex_deinit(void * mutex)
|
||||
{
|
||||
pthread_mutex_destroy((pthread_mutex_t *)mutex);
|
||||
pico_free(mutex);
|
||||
}
|
||||
|
||||
void pico_mutex_lock(void * mutex)
|
||||
{
|
||||
pthread_mutex_lock((pthread_mutex_t *)mutex);
|
||||
}
|
||||
|
||||
int pico_mutex_lock_timeout(void *mutex, int timeout)
|
||||
{
|
||||
if (timeout < 0) {
|
||||
return pthread_mutex_lock((pthread_mutex_t *)mutex);
|
||||
|
||||
} else {
|
||||
struct timespec ts = { timeout / 1000, (timeout % 1000) * 1000000 };
|
||||
return pthread_mutex_timedlock((pthread_mutex_t *)mutex, &ts);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void pico_mutex_unlock(void * mutex)
|
||||
{
|
||||
pthread_mutex_unlock((pthread_mutex_t *)mutex);
|
||||
}
|
||||
|
||||
|
||||
void * pico_signal_init(void)
|
||||
{
|
||||
sem_t *sem = pico_zalloc(sizeof(pthread_mutex_t));
|
||||
if (!sem)
|
||||
return NULL;
|
||||
if (sem_init(sem, 0, 0) == 0)
|
||||
return sem;
|
||||
pico_free(sem);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void pico_signal_deinit(void * signal)
|
||||
{
|
||||
sem_destroy((sem_t *) signal);
|
||||
}
|
||||
|
||||
void pico_signal_wait(void * signal)
|
||||
{
|
||||
sem_wait((sem_t *) signal);
|
||||
}
|
||||
|
||||
int pico_signal_wait_timeout(void * signal, int timeout)
|
||||
{
|
||||
if (timeout < 0) {
|
||||
return sem_wait((sem_t *) signal);
|
||||
} else {
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
ts.tv_sec += (timeout / 1000);
|
||||
ts.tv_nsec += ((timeout % 1000) * 1000000);
|
||||
if (ts.tv_nsec >= BILLION) {
|
||||
ts.tv_nsec -= BILLION;
|
||||
ts.tv_sec++;
|
||||
}
|
||||
return sem_timedwait((sem_t *) signal, &ts);
|
||||
}
|
||||
}
|
||||
|
||||
void pico_signal_send(void * signal)
|
||||
{
|
||||
sem_post((sem_t *) signal);
|
||||
}
|
||||
|
||||
pico_thread_t pico_thread_create(pico_thread_fn thread, void *arg, int stack_size, int prio)
|
||||
{
|
||||
pico_thread_t t = PICO_ZALLOC(sizeof(pthread_t));
|
||||
if (!t)
|
||||
return NULL;
|
||||
(void)stack_size;
|
||||
(void)prio;
|
||||
pthread_create((pthread_t *)t, NULL, thread, arg);
|
||||
pthread_detach(*((pthread_t *)t));
|
||||
}
|
||||
|
||||
void pico_thread_destroy(pico_thread_t t)
|
||||
{
|
||||
pthread_cancel(*((pthread_t *)t));
|
||||
PICO_FREE(t);
|
||||
}
|
||||
|
||||
void pico_msleep(int ms)
|
||||
{
|
||||
struct timespec ts = { ms / 1000, (ms % 1000) * 1000000 };
|
||||
nanosleep(&ts, NULL);
|
||||
}
|
||||
|
||||
void pico_threads_schedule(void)
|
||||
{
|
||||
while (1 < 2)
|
||||
pico_msleep(1000);
|
||||
}
|
||||
429
ext/pico_bsd/pico_posix_wrapper.c
Normal file
429
ext/pico_bsd/pico_posix_wrapper.c
Normal file
@@ -0,0 +1,429 @@
|
||||
#include "pico_bsd_sockets.h"
|
||||
#define _GNU_SOURCE
|
||||
#define __GNU_SOURCE
|
||||
#define __USE_GNU
|
||||
#include <dlfcn.h>
|
||||
#include <stdio.h>
|
||||
#include "pico_ipv4.h"
|
||||
#include "pico_ipv6.h"
|
||||
#include "pico_stack.h"
|
||||
#include "pico_socket.h"
|
||||
#include "pico_dev_vde.h"
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <libvdeplug.h>
|
||||
#include <errno.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/poll.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/select.h>
|
||||
|
||||
|
||||
static __thread int in_the_stack = 0;
|
||||
static int initialized = 0;
|
||||
#define ptsock_dbg printf
|
||||
|
||||
|
||||
|
||||
|
||||
#define swap_socketcall(call, name) \
|
||||
{ \
|
||||
const char *msg; \
|
||||
if (host_##call == NULL) { \
|
||||
*(void **)(&host_##call) = dlsym(RTLD_NEXT, name); \
|
||||
if ((msg = dlerror()) != NULL) \
|
||||
fprintf (stderr, "%s: dlsym(%s): %s\n", "picotcp", name, msg); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
#define conditional_steal_call(call, i, ...) \
|
||||
if(in_the_stack) { \
|
||||
return host_##call(i, ## __VA_ARGS__); \
|
||||
} else { \
|
||||
if (get_pico_fd(i) > -1) { \
|
||||
int __pico_retval = pico_##call(get_pico_fd(i), ## __VA_ARGS__); \
|
||||
if (__pico_retval != 0) \
|
||||
errno = pico_err; \
|
||||
return __pico_retval; \
|
||||
}else { \
|
||||
return host_##call(i, ## __VA_ARGS__); \
|
||||
} \
|
||||
}
|
||||
|
||||
static int max_fd = 0;
|
||||
static int *pico_fds = NULL;
|
||||
|
||||
static int remap_fd(int pico_fd)
|
||||
{
|
||||
int new_fd = open("/dev/zero", O_RDONLY);
|
||||
int old_max = max_fd;
|
||||
int i;
|
||||
if (new_fd < 0) {
|
||||
abort();
|
||||
}
|
||||
if (max_fd < new_fd + 1)
|
||||
max_fd = new_fd + 1;
|
||||
if (pico_fds == NULL) {
|
||||
pico_fds = malloc(sizeof(int) * max_fd);
|
||||
for (i = 0; i < max_fd; i++)
|
||||
pico_fds[i] = -1;
|
||||
pico_fds[new_fd] = pico_fd;
|
||||
return new_fd;
|
||||
}
|
||||
pico_fds = realloc(pico_fds, sizeof(int) * max_fd);
|
||||
for (i = old_max; i < max_fd; i++)
|
||||
pico_fds[i] = -1;
|
||||
pico_fds[new_fd] = pico_fd;
|
||||
return new_fd;
|
||||
}
|
||||
|
||||
static int get_pico_fd(int j)
|
||||
{
|
||||
if (j >= max_fd)
|
||||
return -1;
|
||||
return pico_fds[j];
|
||||
}
|
||||
|
||||
|
||||
static int (*host_socket ) (int domain, int type, int protocol) = NULL;
|
||||
static int (*host_bind ) (int sockfd, const struct sockaddr *addr, socklen_t addrlen);
|
||||
static int (*host_connect ) (int sockfd, const struct sockaddr *addr, socklen_t addrlen);
|
||||
static int (*host_accept ) (int sockfd, struct sockaddr *addr, socklen_t *addrlen);
|
||||
static int (*host_listen ) (int sockfd, int backlog);
|
||||
static ssize_t (*host_recvfrom) (int sockfd, void *buf, size_t len, int flags, struct sockaddr *addr, int *addrlen);
|
||||
static ssize_t (*host_recv ) (int sockfd, void *buf, size_t len, int flags);
|
||||
static ssize_t (*host_read ) (int sockfd, void *buf, size_t len);
|
||||
static ssize_t (*host_sendto ) (int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t addrlen);
|
||||
static ssize_t (*host_send ) (int sockfd, void *buf, size_t len, int flags);
|
||||
static ssize_t (*host_write ) (int sockfd, const void *buf, size_t len);
|
||||
static int (*host_close ) (int sockfd);
|
||||
static int (*host_shutdown) (int sockfd, int how);
|
||||
static int (*host_setsockopt) (int sockfd, int level, int optname, const void *optval, socklen_t optlen);
|
||||
static int (*host_getsockopt) (int sockfd, int level, int optname, void *optval, socklen_t *optlen);
|
||||
|
||||
int getaddrinfo(const char *node, const char *service,
|
||||
const struct addrinfo *hints,
|
||||
struct addrinfo **res);
|
||||
|
||||
void freeaddrinfo(struct addrinfo *res);
|
||||
|
||||
|
||||
static int (*host_getaddrinfo) (const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res);
|
||||
static int (*host_freeaddrinfo) (struct addrinfo *res);
|
||||
static int (*host_poll) (struct pollfd *pfd, nfds_t npfd, int timeout);
|
||||
static int (*host_ppoll) (struct pollfd *pfd, nfds_t npfd, const struct timespec *timeout_ts, const sigset_t *sigmask);
|
||||
static int (*host_select) (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
|
||||
static int (*host_pselect) (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec *timeout,
|
||||
const sigset_t *sigmask);
|
||||
|
||||
int socket(int domain, int type, int protocol)
|
||||
{
|
||||
int new_sd, posix_fd = -1;
|
||||
ptsock_dbg ("Called Socket (pid=%d) in_the_stack=%d\n", getpid(), in_the_stack);
|
||||
if (in_the_stack)
|
||||
return host_socket(domain, type, protocol);
|
||||
if ((domain != AF_INET) && (domain != AF_INET6)) {
|
||||
return host_socket(domain, type, protocol);
|
||||
}
|
||||
new_sd = pico_newsocket(domain, type, protocol);
|
||||
if (new_sd < 0) {
|
||||
ptsock_dbg("socket() call failed.\n");
|
||||
abort();
|
||||
}
|
||||
posix_fd = remap_fd(new_sd);
|
||||
ptsock_dbg ("Socket stolen, sd=%d, fd = %d\n", new_sd, posix_fd);
|
||||
return posix_fd;
|
||||
}
|
||||
|
||||
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
|
||||
{
|
||||
conditional_steal_call(bind, sockfd, addr, addrlen);
|
||||
}
|
||||
|
||||
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
|
||||
{
|
||||
conditional_steal_call(connect, sockfd, addr, addrlen);
|
||||
}
|
||||
|
||||
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
|
||||
{
|
||||
if(in_the_stack) {
|
||||
return host_accept(sockfd, addr, addrlen);
|
||||
} else {
|
||||
int posix_fd, new_sd, listen_sd = get_pico_fd(sockfd);
|
||||
if (listen_sd < 0) {
|
||||
return host_accept(sockfd, addr, addrlen);
|
||||
}
|
||||
|
||||
new_sd = pico_accept(listen_sd, addr, addrlen);
|
||||
if (new_sd < 0)
|
||||
return -1;
|
||||
posix_fd = remap_fd(new_sd);
|
||||
ptsock_dbg ("Socket accepted, sd=%d, fd = %d\n", new_sd, posix_fd);
|
||||
return posix_fd;
|
||||
}
|
||||
}
|
||||
|
||||
int listen(int sockfd, int backlog)
|
||||
{
|
||||
conditional_steal_call(listen, sockfd, backlog);
|
||||
}
|
||||
|
||||
ssize_t recv(int sockfd, void *buf, size_t len, int flags)
|
||||
{
|
||||
conditional_steal_call(recvfrom, sockfd, buf, len, flags, 0, 0);
|
||||
}
|
||||
|
||||
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *addr, socklen_t *addrlen)
|
||||
{
|
||||
conditional_steal_call(recvfrom, sockfd, buf, len, flags, addr, addrlen);
|
||||
}
|
||||
|
||||
ssize_t read(int sockfd, void *buf, size_t len)
|
||||
{
|
||||
conditional_steal_call(read, sockfd, buf, len);
|
||||
}
|
||||
|
||||
ssize_t send(int sockfd, const void *buf, size_t len, int flags)
|
||||
{
|
||||
conditional_steal_call(sendto, sockfd, buf, len, flags, 0, 0);
|
||||
}
|
||||
|
||||
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t addrlen)
|
||||
{
|
||||
conditional_steal_call(sendto, sockfd, buf, len, flags, addr, addrlen);
|
||||
}
|
||||
|
||||
ssize_t write(int sockfd, const void *buf, size_t len)
|
||||
{
|
||||
conditional_steal_call(write, sockfd, buf, len);
|
||||
}
|
||||
|
||||
int close(int sockfd)
|
||||
{
|
||||
int pico_sd;
|
||||
if (in_the_stack)
|
||||
return host_close(sockfd);
|
||||
pico_sd = get_pico_fd(sockfd);
|
||||
if (pico_sd < 0)
|
||||
return host_close(sockfd);
|
||||
pico_close(pico_sd);
|
||||
pico_fds[sockfd] = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int shutdown(int sockfd, int how)
|
||||
{
|
||||
int pico_sd;
|
||||
if (in_the_stack)
|
||||
return host_shutdown(sockfd, how);
|
||||
pico_sd = get_pico_fd(sockfd);
|
||||
if (pico_sd < 0)
|
||||
return host_shutdown(sockfd, how);
|
||||
|
||||
if (how != SHUT_WR)
|
||||
pico_fds[sockfd] = -1;
|
||||
pico_shutdown(pico_sd, how);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int setsockopt (int sockfd, int level, int optname, const void *optval, socklen_t optlen)
|
||||
{
|
||||
conditional_steal_call(setsockopt, sockfd, level, optname, optval, optlen);
|
||||
}
|
||||
|
||||
int getsockopt (int sockfd, int level, int optname, void *optval, socklen_t *optlen)
|
||||
{
|
||||
conditional_steal_call(getsockopt, sockfd, level, optname, optval, optlen);
|
||||
}
|
||||
|
||||
int poll(struct pollfd *pfd, nfds_t npfd, int timeout)
|
||||
{
|
||||
if(in_the_stack) {
|
||||
return host_poll(pfd, npfd, timeout);
|
||||
} else {
|
||||
int i, j = 0;
|
||||
struct pollfd pico_pfd[npfd];
|
||||
for (i = 0; i < npfd; i++) {
|
||||
pico_pfd[j].fd = get_pico_fd(pfd[i].fd);
|
||||
if (pico_pfd[j].fd >= 0) {
|
||||
j++;
|
||||
pico_pfd[j].events = pfd[i].events;
|
||||
}
|
||||
}
|
||||
if (j > 0) {
|
||||
int pico_retval = pico_poll(pico_pfd, j, timeout);
|
||||
if (pico_retval < 0)
|
||||
errno = pico_err;
|
||||
return pico_retval;
|
||||
} else {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int ppoll(struct pollfd *pfd, nfds_t npfd, const struct timespec *timeout_ts, const sigset_t *sigmask)
|
||||
{
|
||||
if(in_the_stack) {
|
||||
return host_ppoll(pfd, npfd, timeout_ts, sigmask);
|
||||
} else {
|
||||
int i, j = 0;
|
||||
struct pollfd pico_pfd[npfd];
|
||||
for (i = 0; i < npfd; i++) {
|
||||
pico_pfd[j].fd = get_pico_fd(pfd[i].fd);
|
||||
if (pico_pfd[j].fd >= 0) {
|
||||
j++;
|
||||
pico_pfd[j].events = pfd[i].events;
|
||||
}
|
||||
}
|
||||
if (j > 0) {
|
||||
int pico_retval = pico_ppoll(pico_pfd, j, timeout_ts, NULL);
|
||||
if (pico_retval < 0)
|
||||
errno = pico_err;
|
||||
return pico_retval;
|
||||
} else {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int pselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec *timeout, const sigset_t *sigmask)
|
||||
{
|
||||
pico_fd_set rs, ws, es;
|
||||
int pico_retval = -1;
|
||||
|
||||
PICO_FD_ZERO(&rs);
|
||||
PICO_FD_ZERO(&ws);
|
||||
PICO_FD_ZERO(&es);
|
||||
|
||||
if(in_the_stack) {
|
||||
return host_pselect(nfds, readfds, writefds, exceptfds, timeout, sigmask);
|
||||
} else {
|
||||
int i, max = -1;
|
||||
for (i = 0; i < nfds; i++) {
|
||||
int picofd = get_pico_fd(i);
|
||||
if (picofd >= 0) {
|
||||
if (FD_ISSET(i, readfds))
|
||||
PICO_FD_SET(picofd, &rs);
|
||||
if (FD_ISSET(i, writefds))
|
||||
PICO_FD_SET(picofd, &ws);
|
||||
if (FD_ISSET(i, exceptfds))
|
||||
PICO_FD_SET(picofd, &es);
|
||||
}
|
||||
if (picofd > max)
|
||||
max = picofd;
|
||||
}
|
||||
if (max < 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
max++;
|
||||
pico_retval = pico_pselect(max, &rs, &ws, &es, timeout, NULL);
|
||||
if (pico_retval < 0)
|
||||
errno = pico_err;
|
||||
else {
|
||||
for(i = 0; i < nfds; i++) {
|
||||
int picofd = get_pico_fd(i);
|
||||
FD_CLR(i, readfds);
|
||||
FD_CLR(i, writefds);
|
||||
FD_CLR(i, exceptfds);
|
||||
if (picofd >= 0) {
|
||||
if (FD_ISSET(picofd, &rs))
|
||||
FD_SET(i, readfds);
|
||||
if (FD_ISSET(picofd, &ws))
|
||||
FD_SET(i, writefds);
|
||||
if (FD_ISSET(picofd, &es))
|
||||
FD_SET(i, exceptfds);
|
||||
}
|
||||
}
|
||||
}
|
||||
return pico_retval;
|
||||
}
|
||||
}
|
||||
|
||||
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
|
||||
{
|
||||
if(in_the_stack) {
|
||||
return host_select(nfds, readfds, writefds, exceptfds, timeout);
|
||||
} else {
|
||||
if (timeout) {
|
||||
const struct timespec ts = {timeout->tv_sec, timeout->tv_usec * 1000};
|
||||
return pselect(nfds, readfds, writefds, exceptfds, &ts, NULL);
|
||||
} else {
|
||||
return pselect(nfds, readfds, writefds, exceptfds, NULL, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void *pico_tick_thread(void *arg) {
|
||||
struct pico_ip4 addr, netmask, gateway, zero = {};
|
||||
struct pico_device *vde;
|
||||
struct pico_ip4 v4_ip_host, v4_ip_route;
|
||||
struct pico_ip4 v4_mask;
|
||||
struct pico_ip4 v4_zero={}, v4_gateway;
|
||||
struct pico_ip6 v6_public;
|
||||
struct pico_ip6 v6_netmask = {0xff,0xff,};
|
||||
struct pico_device *tun;
|
||||
in_the_stack = 1;
|
||||
|
||||
pico_bsd_init();
|
||||
pico_stack_init();
|
||||
|
||||
tun = (struct pico_device *) pico_tun_create("psx0");
|
||||
if (!tun)
|
||||
abort();
|
||||
|
||||
pico_string_to_ipv4("192.168.2.150",&v4_ip_host.addr);
|
||||
pico_string_to_ipv4("192.168.2.1",&v4_ip_route.addr);
|
||||
pico_string_to_ipv4("255.255.0.0",&v4_mask.addr);
|
||||
pico_string_to_ipv4("192.168.2.1",&v4_gateway.addr);
|
||||
pico_string_to_ipv6("7a55::150",v6_public.addr);
|
||||
|
||||
pico_ipv4_link_add(tun, v4_ip_host, v4_mask);
|
||||
pico_ipv4_route_add(v4_ip_route, v4_mask, v4_gateway, 1, NULL);
|
||||
pico_ipv6_link_add(tun, v6_public, v6_netmask);
|
||||
|
||||
for (;;) {
|
||||
pico_bsd_stack_tick();
|
||||
usleep(1000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int __attribute__((constructor)) pico_wrapper_start(void)
|
||||
{
|
||||
pthread_t ticker;
|
||||
if (initialized++)
|
||||
return 0;
|
||||
printf("Stealing all your system calls, please wait...\n");
|
||||
swap_socketcall(socket , "socket");
|
||||
swap_socketcall(bind , "bind");
|
||||
swap_socketcall(connect , "connect");
|
||||
swap_socketcall(accept , "accept");
|
||||
swap_socketcall(listen , "listen");
|
||||
swap_socketcall(recvfrom, "recvfrom");
|
||||
swap_socketcall(recv , "recv");
|
||||
swap_socketcall(read , "read");
|
||||
swap_socketcall(sendto , "sendto");
|
||||
swap_socketcall(send , "send");
|
||||
swap_socketcall(write , "write");
|
||||
swap_socketcall(close , "close");
|
||||
swap_socketcall(shutdown, "shutdown");
|
||||
swap_socketcall(setsockopt, "setsockopt");
|
||||
swap_socketcall(getaddrinfo, "getaddrinfo");
|
||||
swap_socketcall(freeaddrinfo, "freeaddrinfo");
|
||||
swap_socketcall(poll, "poll");
|
||||
swap_socketcall(ppoll, "ppoll");
|
||||
swap_socketcall(select, "select");
|
||||
swap_socketcall(pselect, "pselect");
|
||||
pthread_create(&ticker, NULL, pico_tick_thread, NULL);
|
||||
sleep(1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -779,18 +779,18 @@ static int pico_dns_getname_univ(const char *ip, void (*callback)(char *, void *
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pico_dns_client_getname(const char *ip, void (*callback)(char *, void *), void *arg)
|
||||
extern int pico_dns_client_getname(const char *ip, void (*callback)(char *, void *), void *arg)
|
||||
{
|
||||
return pico_dns_getname_univ(ip, callback, arg, PICO_DNS_ARPA4);
|
||||
}
|
||||
|
||||
|
||||
int pico_dns_client_getname6(const char *ip, void (*callback)(char *, void *), void *arg)
|
||||
extern int pico_dns_client_getname6(const char *ip, void (*callback)(char *, void *), void *arg)
|
||||
{
|
||||
return pico_dns_getname_univ(ip, callback, arg, PICO_DNS_ARPA6);
|
||||
}
|
||||
|
||||
int pico_dns_client_nameserver(struct pico_ip4 *ns, uint8_t flag)
|
||||
extern int pico_dns_client_nameserver(struct pico_ip4 *ns, uint8_t flag)
|
||||
{
|
||||
if (!ns) {
|
||||
pico_err = PICO_ERR_EINVAL;
|
||||
@@ -820,7 +820,7 @@ int pico_dns_client_nameserver(struct pico_ip4 *ns, uint8_t flag)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pico_dns_client_init(void)
|
||||
extern int pico_dns_client_init(void)
|
||||
{
|
||||
struct pico_ip4 default_ns = {
|
||||
0
|
||||
@@ -834,7 +834,7 @@ int pico_dns_client_init(void)
|
||||
|
||||
#else
|
||||
|
||||
int pico_dns_client_init(void)
|
||||
extern int pico_dns_client_init(void)
|
||||
{
|
||||
dbg("ERROR Trying to initialize DNS module: IPv4 not supported in this build.\n");
|
||||
return -1;
|
||||
|
||||
@@ -37,6 +37,10 @@
|
||||
#define PICO_DNS_RR_A_RDLENGTH 4
|
||||
#define PICO_DNS_RR_AAAA_RDLENGTH 16
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int pico_dns_client_init(void);
|
||||
/* flag is PICO_DNS_NS_DEL or PICO_DNS_NS_ADD */
|
||||
int pico_dns_client_nameserver(struct pico_ip4 *ns, uint8_t flag);
|
||||
@@ -47,4 +51,8 @@ int pico_dns_client_getaddr6(const char *url, void (*callback)(char *, void *),
|
||||
int pico_dns_client_getname6(const char *url, void (*callback)(char *, void *), void *arg);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _INCLUDE_PICO_DNS_CLIENT */
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#include "pico_ethernet.h"
|
||||
#include "pico_mcast.h"
|
||||
|
||||
#include "../../../include/Debug.hpp"
|
||||
#include "../../../include/libztDebug.h"
|
||||
|
||||
#ifdef PICO_SUPPORT_IPV4
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include "pico_mcast.h"
|
||||
#ifdef PICO_SUPPORT_IPV6
|
||||
|
||||
#include "../../../include/Debug.hpp"
|
||||
#include "../../../include/libztDebug.h"
|
||||
|
||||
#define PICO_IPV6_EXTHDR_OPT_PAD1 0
|
||||
#define PICO_IPV6_EXTHDR_OPT_PADN 1
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
#include "pico_protocol.h"
|
||||
#include "pico_tree.h"
|
||||
#include "../../../include/Debug.hpp"
|
||||
#include "../../../include/libztDebug.h"
|
||||
|
||||
struct pico_proto_rr
|
||||
{
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include "pico_socket_tcp.h"
|
||||
#include "pico_socket_udp.h"
|
||||
|
||||
#include "../../../include/Debug.hpp"
|
||||
#include "../../../include/libztDebug.h"
|
||||
|
||||
#if defined (PICO_SUPPORT_IPV4) || defined (PICO_SUPPORT_IPV6)
|
||||
#if defined (PICO_SUPPORT_TCP) || defined (PICO_SUPPORT_UDP)
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#include "pico_socket.h"
|
||||
#include "heap.h"
|
||||
|
||||
#include "../../../include/Debug.hpp"
|
||||
#include "../../../include/libztDebug.h"
|
||||
|
||||
/* Mockables */
|
||||
#if defined UNIT_TEST
|
||||
|
||||
@@ -1 +1 @@
|
||||
For applications, see [libzt.h](libzt.h) for POSIX-like socket API.
|
||||
See [libzt.h](libzt.h) for POSIX-like socket API exposed for applications.
|
||||
|
||||
@@ -27,7 +27,68 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
*
|
||||
* Ring buffer implementation for network stack drivers
|
||||
*/
|
||||
|
||||
// Only available in experimental branch
|
||||
#ifndef ZT_RINGBUFFER_H
|
||||
#define ZT_RINGBUFFER_H
|
||||
|
||||
typedef char bufElementType;
|
||||
|
||||
class RingBuffer
|
||||
{
|
||||
private:
|
||||
bufElementType * buf;
|
||||
size_t size;
|
||||
size_t begin;
|
||||
size_t end;
|
||||
bool wrap;
|
||||
|
||||
public:
|
||||
/**
|
||||
* create a RingBuffer with space for up to size elements.
|
||||
*/
|
||||
explicit RingBuffer(size_t size)
|
||||
: size(size),
|
||||
begin(0),
|
||||
end(0),
|
||||
wrap(false)
|
||||
{
|
||||
buf = new bufElementType[size];
|
||||
}
|
||||
/*
|
||||
RingBuffer(const RingBuffer<T> & ring)
|
||||
{
|
||||
this(ring.size);
|
||||
begin = ring.begin;
|
||||
end = ring.end;
|
||||
memcpy(buf, ring.buf, sizeof(T) * size);
|
||||
}
|
||||
*/
|
||||
~RingBuffer()
|
||||
{
|
||||
delete[] buf;
|
||||
}
|
||||
|
||||
// get a reference to the underlying buffer
|
||||
bufElementType* get_buf();
|
||||
|
||||
// adjust buffer index pointer as if we copied data in
|
||||
size_t produce(size_t n);
|
||||
|
||||
// merely reset the buffer pointer, doesn't erase contents
|
||||
void reset();
|
||||
|
||||
// adjust buffer index pointer as if we copied data out
|
||||
size_t consume(size_t n);
|
||||
|
||||
size_t write(const bufElementType * data, size_t n);
|
||||
|
||||
size_t read(bufElementType * dest, size_t n);
|
||||
|
||||
size_t count();
|
||||
|
||||
size_t getFree();
|
||||
};
|
||||
|
||||
#endif // _H
|
||||
@@ -30,20 +30,11 @@
|
||||
* Platform-specific implementations of common functions
|
||||
*/
|
||||
|
||||
#ifndef LIBZT_PLATFORM_H
|
||||
#define LIBZT_PLATFORM_H
|
||||
#ifndef LIBZT_SYSUTILS_H
|
||||
#define LIBZT_SYSUTILS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Used to perform a common action upon a failure in the VirtualSocket/VirtualTap layer.
|
||||
*
|
||||
* @usage For internal use only.
|
||||
* @return
|
||||
*/
|
||||
void handle_general_failure();
|
||||
#include <sys/time.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @brief Returns the thread-id. Used in debug traces.
|
||||
@@ -53,8 +44,32 @@ void handle_general_failure();
|
||||
*/
|
||||
inline unsigned int gettid();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
/**
|
||||
* @brief Current time in milliseconds since epoch, platform-aware convenience function.
|
||||
*
|
||||
* @usage For internal use only.
|
||||
* @return Current time in integer form
|
||||
*/
|
||||
inline uint64_t time_now()
|
||||
{
|
||||
#ifdef __WINDOWS__
|
||||
FILETIME ft;
|
||||
SYSTEMTIME st;
|
||||
ULARGE_INTEGER tmp;
|
||||
GetSystemTime(&st);
|
||||
SystemTimeToFileTime(&st,&ft);
|
||||
tmp.LowPart = ft.dwLowDateTime;
|
||||
tmp.HighPart = ft.dwHighDateTime;
|
||||
return (uint64_t)( ((tmp.QuadPart - 116444736000000000LL) / 10000L) + st.wMilliseconds );
|
||||
#else
|
||||
struct timeval tv;
|
||||
#ifdef __LINUX__
|
||||
syscall(SYS_gettimeofday,&tv,0); /* fix for musl libc broken gettimeofday bug */
|
||||
#else
|
||||
gettimeofday(&tv,(struct timezone *)0);
|
||||
#endif
|
||||
return ( (1000LL * (uint64_t)tv.tv_sec) + (uint64_t)(tv.tv_usec / 1000) );
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // _H
|
||||
@@ -33,10 +33,14 @@
|
||||
#ifndef LIBZT_UTILITIES_H
|
||||
#define LIBZT_UTILITIES_H
|
||||
|
||||
#include "InetAddress.hpp"
|
||||
#include <stdio.h>
|
||||
|
||||
namespace ZeroTier {
|
||||
struct InetAddress;
|
||||
}
|
||||
|
||||
#if defined(__MINGW32__)
|
||||
|
||||
|
||||
#define NS_INADDRSZ 4
|
||||
#define NS_IN6ADDRSZ 16
|
||||
#define NS_INT16SZ 2
|
||||
@@ -46,15 +50,6 @@ int inet_pton6(const char *src, void *dst);
|
||||
int inet_pton(int af, const char *src, void *dst);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Returns masked address for subnet comparisons
|
||||
*
|
||||
* @usage For internal use only.
|
||||
* @param socket_type
|
||||
* @return
|
||||
*/
|
||||
bool ipv6_in_subnet(ZeroTier::InetAddress *subnet, ZeroTier::InetAddress *addr);
|
||||
|
||||
/**
|
||||
* @brief Convert protocol numbers to human-readable strings
|
||||
*
|
||||
@@ -64,17 +59,6 @@ bool ipv6_in_subnet(ZeroTier::InetAddress *subnet, ZeroTier::InetAddress *addr);
|
||||
*/
|
||||
char *beautify_eth_proto_nums(int proto);
|
||||
|
||||
/**
|
||||
* @brief Convert a struct sockaddr to a ZeroTier::InetAddress
|
||||
*
|
||||
* @usage For internal use only.
|
||||
* @param socket_family
|
||||
* @param addr
|
||||
* @param inet
|
||||
* @return
|
||||
*/
|
||||
//void sockaddr2inet(int socket_family, const struct sockaddr *addr, ZeroTier::InetAddress *inet);
|
||||
|
||||
/**
|
||||
* @brief Convert a raw MAC address byte array into a human-readable string
|
||||
*
|
||||
@@ -86,12 +70,4 @@ char *beautify_eth_proto_nums(int proto);
|
||||
*/
|
||||
void mac2str(char *macbuf, int len, unsigned char* addr);
|
||||
|
||||
#if defined(STACK_LWIP) && defined(LIBZT_IPV6)
|
||||
#define IP6_ADDR2(ipaddr, a,b,c,d,e,f,g,h) do { (ipaddr)->addr[0] = ZeroTier::Utils::hton((u32_t)((a & 0xffff) << 16) | (b & 0xffff)); \
|
||||
(ipaddr)->addr[1] = ZeroTier::Utils::hton(((c & 0xffff) << 16) | (d & 0xffff)); \
|
||||
(ipaddr)->addr[2] = ZeroTier::Utils::hton(((e & 0xffff) << 16) | (f & 0xffff)); \
|
||||
(ipaddr)->addr[3] = ZeroTier::Utils::hton(((g & 0xffff) << 16) | (h & 0xffff)); } while(0)
|
||||
|
||||
#endif
|
||||
|
||||
#endif // _H
|
||||
|
||||
@@ -37,7 +37,15 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct VirtualBindingPair;
|
||||
/**
|
||||
* A helper object for passing VirtualTap(s) and VirtualSocket(s) through the stack
|
||||
*/
|
||||
struct VirtualBindingPair
|
||||
{
|
||||
VirtualTap *tap;
|
||||
VirtualSocket *vs;
|
||||
VirtualBindingPair(VirtualTap *_tap, VirtualSocket *_vs) : tap(_tap), vs(_vs) {}
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -27,12 +27,60 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Platform-agnostic implementation of a socket-like object
|
||||
* Platform- and stack-agnostic implementation of a socket-like object
|
||||
*/
|
||||
|
||||
#ifndef LIBZT_VIRTUALSOCKET_H
|
||||
#define LIBZT_VIRTUALSOCKET_H
|
||||
|
||||
#include <queue>
|
||||
|
||||
#include "RingBuffer.h"
|
||||
#include "libztDefs.h"
|
||||
#include "VirtualTap.h"
|
||||
#include "Mutex.hpp"
|
||||
|
||||
#define VS_STATE_INACTIVE 0x000000u // Default value for newly created VirtualSocket
|
||||
#define VS_STATE_ACTIVE 0x000001u // VirtualSocket is RX'ing or TX'ing without issue
|
||||
#define VS_STATE_SHOULD_SHUTDOWN 0x000002u // Application, stack driver, or stack marked this VirtualSocket for death
|
||||
#define VS_STATE_SHUTDOWN 0x000004u // VirtualSocket and underlying protocol control structures will not RX/TX
|
||||
#define VS_STATE_CLOSED 0x000008u // VirtualSocket and underlying protocol control structures are closed
|
||||
#define VS_STATE_UNHANDLED_CONNECTED 0x000010u // stack callback has received a connection but we haven't dealt with it
|
||||
#define VS_STATE_CONNECTED 0x000020u // stack driver has akwnowledged new connection
|
||||
#define VS_STATE_LISTENING 0x000040u // virtual socket is listening for incoming connections
|
||||
|
||||
#define VS_OPT_TCP_NODELAY 0x000000u // Nagle's algorithm
|
||||
#define VS_OPT_SO_LINGER 0x000001u // VirtualSocket waits for data transmission before closure
|
||||
/*
|
||||
#define VS_RESERVED 0x000002u //
|
||||
#define VS_RESERVED 0x000004u //
|
||||
#define VS_RESERVED 0x000008u //
|
||||
#define VS_RESERVED 0x000010u //
|
||||
#define VS_RESERVED 0x000020u //
|
||||
#define VS_RESERVED 0x000040u //
|
||||
*/
|
||||
#define VS_OPT_FD_NONBLOCKING 0x000080u // Whether the VirtualSocket exhibits non-blocking behaviour
|
||||
/*
|
||||
#define VS_RESERVED 0x000100u //
|
||||
#define VS_RESERVED 0x000200u //
|
||||
#define VS_RESERVED 0x000400u //
|
||||
#define VS_RESERVED 0x000800u //
|
||||
#define VS_RESERVED 0x001000u //
|
||||
#define VS_RESERVED 0x002000u //
|
||||
#define VS_RESERVED 0x004000u //
|
||||
#define VS_RESERVED 0x008000u //
|
||||
#define VS_RESERVED 0x010000u //
|
||||
#define VS_RESERVED 0x020000u //
|
||||
#define VS_RESERVED 0x040000u //
|
||||
#define VS_RESERVED 0x080000u //
|
||||
#define VS_RESERVED 0x100000u //
|
||||
#define VS_RESERVED 0x200000u //
|
||||
#define VS_RESERVED 0x400000u //
|
||||
#define VS_RESERVED 0x800000u //
|
||||
*/
|
||||
|
||||
#define vs_is_nonblocking(vs) (((vs)->optflags & VS_OPT_FD_NONBLOCKING) != 0)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -42,7 +90,67 @@ extern "C" {
|
||||
* and the network stack's representation of a protocol control structure. This object is used by
|
||||
* the POSIX socket emulation layer and stack drivers.
|
||||
*/
|
||||
class VirtualSocket;
|
||||
class VirtualSocket
|
||||
{
|
||||
private:
|
||||
int _state = VS_STATE_INACTIVE;
|
||||
public:
|
||||
RingBuffer *TXbuf, *RXbuf;
|
||||
ZeroTier::Mutex _tx_m, _rx_m, _op_m;
|
||||
ZeroTier::PhySocket *sock = NULL;
|
||||
|
||||
void *pcb = NULL; // Protocol Control Block
|
||||
|
||||
#if defined(STACK_LWIP)
|
||||
int32_t optflags = 0;
|
||||
int linger;
|
||||
/*
|
||||
- TCP_WRITE_FLAG_COPY: indicates whether the new memory should be allocated
|
||||
for the data to be copied into. If this flag is not given, no new memory
|
||||
should be allocated and the data should only be referenced by pointer. This
|
||||
also means that the memory behind dataptr must not change until the data is
|
||||
ACKed by the remote host
|
||||
- TCP_WRITE_FLAG_MORE: indicates that more data follows. If this is omitted,
|
||||
the PSH flag is set in the last segment created by this call to tcp_write.
|
||||
If this flag is given, the PSH flag is not set.
|
||||
*/
|
||||
// copy as default, processed via pointer reference if set to 0. See notes in lwip_cb_sent() and lwip_Write()
|
||||
int8_t copymode = 1; // TCP_WRITE_FLAG_COPY;
|
||||
#endif
|
||||
struct sockaddr_storage local_addr; // address we've bound to locally
|
||||
struct sockaddr_storage peer_addr; // address of connection call to remote host
|
||||
int socket_family = 0;
|
||||
int socket_type = 0;
|
||||
int protocol = 0;
|
||||
int app_fd = 0; // used by app for I/O
|
||||
int sdk_fd = 0; // used by lib for I/O
|
||||
std::queue<VirtualSocket*> _AcceptedConnections;
|
||||
VirtualTap *tap = NULL;
|
||||
|
||||
/**
|
||||
* Sets the VirtualSocket's state value
|
||||
*/
|
||||
void apply_state(int state);
|
||||
|
||||
/**
|
||||
* Sets the VirtualSocket's state value
|
||||
*/
|
||||
void set_state(int state);
|
||||
/**
|
||||
* Gets the VirtualSocket's state value
|
||||
*/
|
||||
int get_state();
|
||||
|
||||
/**
|
||||
* default ctor
|
||||
*/
|
||||
VirtualSocket();
|
||||
|
||||
/**
|
||||
* dtor
|
||||
*/
|
||||
~VirtualSocket();
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
443
include/VirtualSocketLayer.h
Normal file
443
include/VirtualSocketLayer.h
Normal file
@@ -0,0 +1,443 @@
|
||||
/*
|
||||
* ZeroTier SDK - Network Virtualization Everywhere
|
||||
* Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* --
|
||||
*
|
||||
* You can be released from the requirements of the license by purchasing
|
||||
* a commercial license. Buying such a license is mandatory as soon as you
|
||||
* develop commercial closed-source software that incorporates or links
|
||||
* directly against ZeroTier software without disclosing the source code
|
||||
* of your own application.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* VirtualSocket management layer
|
||||
*/
|
||||
|
||||
//#include "InetAddress.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
class Mutex;
|
||||
struct InetAddress;
|
||||
}
|
||||
|
||||
class VirtualSocket;
|
||||
class VirtualTap;
|
||||
|
||||
extern ZeroTier::Mutex _multiplexer_lock;
|
||||
|
||||
VirtualSocket *get_virt_socket(int fd);
|
||||
int del_virt_socket(int fd);
|
||||
int add_unassigned_virt_socket(int fd, VirtualSocket *vs);
|
||||
int del_unassigned_virt_socket(int fd);
|
||||
int add_assigned_virt_socket(void *tap, VirtualSocket *vs, int fd);
|
||||
int del_assigned_virt_socket(void *tap, VirtualSocket *vs, int fd);
|
||||
//void *get_assigned_virtual_pair(int fd);
|
||||
|
||||
/**
|
||||
* @brief Stops all VirtualTap interfaces and associated I/O loops
|
||||
*
|
||||
* @usage For internal use only.
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
void disableTaps();
|
||||
|
||||
|
||||
/**
|
||||
* @brief Create a socket
|
||||
*
|
||||
* This function will return an integer which can be used in much the same way as a
|
||||
* typical file descriptor, however it is only valid for use with libzt library calls
|
||||
* as this is merely a facade which is associated with the internal socket representation
|
||||
* of both the network stacks and drivers.
|
||||
*
|
||||
* @usage Call this after virt_start() has succeeded
|
||||
* @param socket_family Address family (AF_INET, AF_INET6)
|
||||
* @param socket_type Type of socket (SOCK_STREAM, SOCK_DGRAM, SOCK_RAW)
|
||||
* @param protocol Protocols supported on this socket
|
||||
* @return
|
||||
*/
|
||||
int virt_socket(int socket_family, int socket_type, int protocol);
|
||||
|
||||
/**
|
||||
* @brief Connect a socket to a remote host
|
||||
*
|
||||
* @usage Call this after virt_start() has succeeded
|
||||
* @param fd File descriptor (only valid for use with libzt calls)
|
||||
* @param addr Remote host address to connect to
|
||||
* @param addrlen Length of address
|
||||
* @return
|
||||
*/
|
||||
int virt_connect(int fd, const struct sockaddr *addr, socklen_t addrlen);
|
||||
|
||||
/**
|
||||
* @brief Bind a socket to a virtual interface
|
||||
*
|
||||
* @usage Call this after virt_start() has succeeded
|
||||
* @param fd File descriptor (only valid for use with libzt calls)
|
||||
* @param addr Local interface address to bind to
|
||||
* @param addrlen Length of address
|
||||
* @return
|
||||
*/
|
||||
int virt_bind(int fd, const struct sockaddr *addr, socklen_t addrlen);
|
||||
|
||||
/**
|
||||
* @brief Listen for incoming connections
|
||||
*
|
||||
* @usage Call this after virt_start() has succeeded
|
||||
* @param fd File descriptor (only valid for use with libzt calls)
|
||||
* @param backlog Number of backlogged connection allowed
|
||||
* @return
|
||||
*/
|
||||
int virt_listen(int fd, int backlog);
|
||||
|
||||
/**
|
||||
* @brief Accept an incoming connection
|
||||
*
|
||||
* @usage Call this after virt_start() has succeeded
|
||||
* @param fd File descriptor (only valid for use with libzt calls)
|
||||
* @param addr Address of remote host for accepted connection
|
||||
* @param addrlen Length of address
|
||||
* @return
|
||||
*/
|
||||
int virt_accept(int fd, struct sockaddr *addr, socklen_t *addrlen);
|
||||
|
||||
/**
|
||||
* @brief Accept an incoming connection
|
||||
*
|
||||
* @usage Call this after virt_start() has succeeded
|
||||
* @param fd File descriptor (only valid for use with libzt calls)
|
||||
* @param addr Address of remote host for accepted connection
|
||||
* @param addrlen Length of address
|
||||
* @param flags
|
||||
* @return
|
||||
*/
|
||||
#if defined(__linux__)
|
||||
int virt_accept4(int fd, struct sockaddr *addr, socklen_t *addrlen, int flags);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Set socket options
|
||||
*
|
||||
* @usage Call this after virt_start() has succeeded
|
||||
* @param fd File descriptor (only valid for use with libzt calls)
|
||||
* @param level Protocol level to which option name should apply
|
||||
* @param optname Option name to set
|
||||
* @param optval Source of option value to set
|
||||
* @param optlen Length of option value
|
||||
* @return
|
||||
*/
|
||||
int virt_setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen);
|
||||
|
||||
/**
|
||||
* @brief Get socket options
|
||||
*
|
||||
* @usage Call this after virt_start() has succeeded
|
||||
* @param fd File descriptor (only valid for use with libzt calls)
|
||||
* @param level Protocol level to which option name should apply
|
||||
* @param optname Option name to get
|
||||
* @param optval Where option value will be stored
|
||||
* @param optlen Length of value
|
||||
* @return
|
||||
*/
|
||||
int virt_getsockopt(int fd, int level, int optname, void *optval, socklen_t *optlen);
|
||||
|
||||
/**
|
||||
* @brief Get socket name
|
||||
*
|
||||
* @usage Call this after virt_start() has succeeded
|
||||
* @param fd File descriptor (only valid for use with libzt calls)
|
||||
* @param addr Name associated with this socket
|
||||
* @param addrlen Length of name
|
||||
* @return
|
||||
*/
|
||||
int virt_getsockname(int fd, struct sockaddr *addr, socklen_t *addrlen);
|
||||
|
||||
/**
|
||||
* @brief Get the peer name for the remote end of a connected socket
|
||||
*
|
||||
* @usage Call this after virt_start() has succeeded
|
||||
* @param fd File descriptor (only valid for use with libzt calls)
|
||||
* @param addr Name associated with remote end of this socket
|
||||
* @param addrlen Length of name
|
||||
* @return
|
||||
*/
|
||||
int virt_getpeername(int fd, struct sockaddr *addr, socklen_t *addrlen);
|
||||
|
||||
/**
|
||||
* @brief Gets current hostname
|
||||
*
|
||||
* @usage Call this after virt_start() has succeeded
|
||||
* @param name
|
||||
* @param len
|
||||
* @return
|
||||
*/
|
||||
int virt_gethostname(char *name, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Sets current hostname
|
||||
*
|
||||
* @usage Call this after virt_start() has succeeded
|
||||
* @param name
|
||||
* @param len
|
||||
* @return
|
||||
*/
|
||||
int virt_sethostname(const char *name, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Return a pointer to an object with the following structure describing an internet host referenced by name
|
||||
*
|
||||
* @usage Call this after virt_start() has succeeded
|
||||
* @param name
|
||||
* @return Returns pointer to hostent structure otherwise NULL if failure
|
||||
*/
|
||||
struct hostent *virt_gethostbyname(const char *name);
|
||||
|
||||
/**
|
||||
* @brief Close a socket
|
||||
*
|
||||
* @usage Call this after virt_start() has succeeded
|
||||
* @param fd File descriptor (only valid for use with libzt calls)
|
||||
* @return
|
||||
*/
|
||||
int virt_close(int fd);
|
||||
|
||||
/**
|
||||
* @brief Waits for one of a set of file descriptors to become ready to perform I/O.
|
||||
*
|
||||
* @usage Call this after virt_start() has succeeded
|
||||
* @param fds
|
||||
* @param nfds
|
||||
* @param timeout
|
||||
* @return
|
||||
*/
|
||||
/*
|
||||
#ifdef __linux__
|
||||
int virt_poll(struct pollfd *fds, nfds_t nfds, int timeout);
|
||||
#endif
|
||||
*/
|
||||
/**
|
||||
* @brief Monitor multiple file descriptors, waiting until one or more of the file descriptors become "ready"
|
||||
*
|
||||
* @usage Call this after virt_start() has succeeded
|
||||
* @param nfds
|
||||
* @param readfds
|
||||
* @param writefds
|
||||
* @param exceptfds
|
||||
* @param timeout
|
||||
* @return
|
||||
*/
|
||||
int virt_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
|
||||
|
||||
/**
|
||||
* @brief Issue file control commands on a socket
|
||||
*
|
||||
* @usage Call this after virt_start() has succeeded
|
||||
* @param fd File descriptor (only valid for use with libzt calls)
|
||||
* @param cmd
|
||||
* @param flags
|
||||
* @return
|
||||
*/
|
||||
int virt_fcntl(int fd, int cmd, int flags);
|
||||
|
||||
/**
|
||||
* @brief Control a device
|
||||
*
|
||||
* @usage Call this after virt_start() has succeeded
|
||||
* @param fd File descriptor (only valid for use with libzt calls)
|
||||
* @param request
|
||||
* @param argp
|
||||
* @return
|
||||
*/
|
||||
int virt_ioctl(int fd, unsigned long request, void *argp);
|
||||
|
||||
/**
|
||||
* @brief Send data to remote host
|
||||
*
|
||||
* @usage Call this after virt_start() has succeeded
|
||||
* @param fd File descriptor (only valid for use with libzt calls)
|
||||
* @param buf Pointer to data buffer
|
||||
* @param len Length of data to write
|
||||
* @param flags
|
||||
* @return
|
||||
*/
|
||||
ssize_t virt_send(int fd, const void *buf, size_t len, int flags);
|
||||
|
||||
/**
|
||||
* @brief Send data to remote host
|
||||
*
|
||||
* @usage Call this after virt_start() has succeeded
|
||||
* @param fd File descriptor (only valid for use with libzt calls)
|
||||
* @param buf Pointer to data buffer
|
||||
* @param len Length of data to write
|
||||
* @param flags
|
||||
* @param addr Destination address
|
||||
* @param addrlen Length of destination address
|
||||
* @return
|
||||
*/
|
||||
ssize_t virt_sendto(int fd, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t addrlen);
|
||||
|
||||
/**
|
||||
* @brief Send message to remote host
|
||||
*
|
||||
* @usage Call this after virt_start() has succeeded
|
||||
* @param fd File descriptor (only valid for use with libzt calls)
|
||||
* @param msg
|
||||
* @param flags
|
||||
* @return
|
||||
*/
|
||||
ssize_t virt_sendmsg(int fd, const struct msghdr *msg, int flags);
|
||||
|
||||
/**
|
||||
* @brief Receive data from remote host
|
||||
*
|
||||
* @usage Call this after virt_start() has succeeded
|
||||
* @param fd File descriptor (only valid for use with libzt calls)
|
||||
* @param buf Pointer to data buffer
|
||||
* @param len Length of data buffer
|
||||
* @param flags
|
||||
* @return
|
||||
*/
|
||||
ssize_t virt_recv(int fd, void *buf, size_t len, int flags);
|
||||
|
||||
/**
|
||||
* @brief Receive data from remote host
|
||||
*
|
||||
* @usage Call this after virt_start() has succeeded
|
||||
* @param fd File descriptor (only valid for use with libzt calls)
|
||||
* @param buf Pointer to data buffer
|
||||
* @param len Length of data buffer
|
||||
* @param flags
|
||||
* @param addr
|
||||
* @param addrlen
|
||||
* @return
|
||||
*/
|
||||
ssize_t virt_recvfrom(int fd, void *buf, size_t len, int flags, struct sockaddr *addr, socklen_t *addrlen);
|
||||
|
||||
/**
|
||||
* @brief Receive a message from remote host
|
||||
*
|
||||
* @usage Call this after virt_start() has succeeded
|
||||
* @param fd File descriptor (only valid for use with libzt calls)
|
||||
* @param msg
|
||||
* @param flags
|
||||
* @return
|
||||
*/
|
||||
ssize_t virt_recvmsg(int fd, struct msghdr *msg,int flags);
|
||||
|
||||
/**
|
||||
* @brief Read bytes from socket onto buffer
|
||||
*
|
||||
* @usage Call this after virt_start() has succeeded
|
||||
* @param fd File descriptor (only valid for use with libzt calls)
|
||||
* @param buf Pointer to data buffer
|
||||
* @param len Length of data buffer to receive data
|
||||
* @return
|
||||
*/
|
||||
int virt_read(int fd, void *buf, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Write bytes from buffer to socket
|
||||
*
|
||||
* @usage Call this after virt_start() has succeeded
|
||||
* @param fd File descriptor (only valid for use with libzt calls)
|
||||
* @param buf Pointer to data buffer
|
||||
* @param len Length of buffer to write
|
||||
* @return
|
||||
*/
|
||||
int virt_write(int fd, const void *buf, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Shut down some aspect of a socket (read, write, or both)
|
||||
*
|
||||
* @usage Call this after virt_start() has succeeded
|
||||
* @param fd File descriptor (only valid for use with libzt calls)
|
||||
* @param how Which aspects of the socket should be shut down
|
||||
* @return
|
||||
*/
|
||||
int virt_shutdown(int fd, int how);
|
||||
|
||||
/**
|
||||
* @brief Adds a DNS nameserver for the network stack to use
|
||||
*
|
||||
* @usage Call this after virt_start() has succeeded
|
||||
* @param addr Address for DNS nameserver
|
||||
* @return
|
||||
*/
|
||||
int virt_add_dns_nameserver(struct sockaddr *addr);
|
||||
|
||||
/**
|
||||
* @brief Removes a DNS nameserver
|
||||
*
|
||||
* @usage Call this after virt_start() has succeeded
|
||||
* @param addr Address for DNS nameserver
|
||||
* @return
|
||||
*/
|
||||
int virt_del_dns_nameserver(struct sockaddr *addr);
|
||||
|
||||
/**
|
||||
* @brief Returns whether one can add a new socket or not. This depends on network stack in use.
|
||||
*
|
||||
* @usage Call this after zts_start() has succeeded
|
||||
* @param socket_type
|
||||
* @return
|
||||
*/
|
||||
bool virt_can_provision_new_socket(int socket_type);
|
||||
|
||||
/**
|
||||
* @brief Returns the number of VirtualSockets either already provisioned or waiting to be
|
||||
* Some network stacks may have a limit on the number of sockets that they can
|
||||
* safely handle due to timer construction, this is a way to check that we
|
||||
* haven't passed that limit. Someday if multiple stacks are used simultaneously
|
||||
* the logic for this function should change accordingly.
|
||||
*
|
||||
* @usage Call this after zts_start() has succeeded
|
||||
* @return
|
||||
*/
|
||||
int virt_num_active_sockets();
|
||||
|
||||
/**
|
||||
* @brief Return the maximum number of sockets allowable by platform/stack configuration
|
||||
*
|
||||
* @usage Call this after zts_start() has succeeded
|
||||
* @param socket_type
|
||||
* @return
|
||||
*/
|
||||
int virt_maxsockets(int socket_type);
|
||||
|
||||
/**
|
||||
* @brief Return the number of currently active picoTCP timers
|
||||
*
|
||||
* @usage Call this after zts_start() has succeeded
|
||||
* @return
|
||||
*/
|
||||
//int pico_ntimers();
|
||||
|
||||
/**
|
||||
* @brief Convert a struct sockaddr to a ZeroTier::InetAddress
|
||||
*
|
||||
* @usage For internal use only.
|
||||
* @param socket_family
|
||||
* @param addr
|
||||
* @param inet
|
||||
* @return
|
||||
*/
|
||||
void sockaddr2inet(int socket_family, const struct sockaddr *addr, ZeroTier::InetAddress *inet);
|
||||
|
||||
331
include/VirtualTap.h
Normal file
331
include/VirtualTap.h
Normal file
@@ -0,0 +1,331 @@
|
||||
/*
|
||||
* ZeroTier SDK - Network Virtualization Everywhere
|
||||
* Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* --
|
||||
*
|
||||
* You can be released from the requirements of the license by purchasing
|
||||
* a commercial license. Buying such a license is mandatory as soon as you
|
||||
* develop commercial closed-source software that incorporates or links
|
||||
* directly against ZeroTier software without disclosing the source code
|
||||
* of your own application.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Virtual Ethernet tap device
|
||||
*/
|
||||
|
||||
#ifndef ZT_VIRTUALTAP_HPP
|
||||
#define ZT_VIRTUALTAP_HPP
|
||||
|
||||
#include "Mutex.hpp"
|
||||
#include "MulticastGroup.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "Thread.hpp"
|
||||
#include "Phy.hpp"
|
||||
|
||||
#include "libztDefs.h"
|
||||
|
||||
#include <vector>
|
||||
extern std::vector<void*> vtaps;
|
||||
extern ZeroTier::Mutex _vtaps_lock;
|
||||
|
||||
#if defined(__MINGW32__) || defined(__MINGW64__)
|
||||
#include <WinSock2.h>
|
||||
#include <Windows.h>
|
||||
#include <IPHlpApi.h>
|
||||
#include <Ifdef.h>
|
||||
#endif
|
||||
|
||||
using namespace ZeroTier;
|
||||
|
||||
class VirtualSocket;
|
||||
|
||||
/**
|
||||
* emulates an Ethernet tap device
|
||||
*/
|
||||
class VirtualTap
|
||||
{
|
||||
friend class Phy<VirtualTap *>;
|
||||
|
||||
public:
|
||||
VirtualTap(
|
||||
const char *homePath,
|
||||
const ZeroTier::MAC &mac,
|
||||
unsigned int mtu,
|
||||
unsigned int metric,
|
||||
uint64_t nwid,
|
||||
const char *friendlyName,
|
||||
void (*handler)(void *, void *, uint64_t, const ZeroTier::MAC &,
|
||||
const ZeroTier::MAC &, unsigned int, unsigned int, const void *, unsigned int),
|
||||
void *arg);
|
||||
|
||||
~VirtualTap();
|
||||
|
||||
void setEnabled(bool en);
|
||||
bool enabled() const;
|
||||
|
||||
/**
|
||||
* Registers a device with the given address
|
||||
*/
|
||||
bool registerIpWithStack(const ZeroTier::InetAddress &ip);
|
||||
|
||||
/**
|
||||
* Adds an address to the userspace stack interface associated with this VirtualTap
|
||||
* - Starts VirtualTap main thread ONLY if successful
|
||||
*/
|
||||
bool addIp(const ZeroTier::InetAddress &ip);
|
||||
|
||||
/**
|
||||
* Removes an address from the userspace stack interface associated with this VirtualTap
|
||||
*/
|
||||
bool removeIp(const ZeroTier::InetAddress &ip);
|
||||
|
||||
/**
|
||||
* Presents data to the userspace stack
|
||||
*/
|
||||
void put(const ZeroTier::MAC &from,const ZeroTier::MAC &to,unsigned int etherType,const void *data,
|
||||
unsigned int len);
|
||||
|
||||
/**
|
||||
* Get VirtualTap device name (e.g. 'libzt4-17d72843bc2c5760')
|
||||
*/
|
||||
std::string deviceName() const;
|
||||
|
||||
/**
|
||||
* Get Node ID (ZT address)
|
||||
*/
|
||||
std::string nodeId() const;
|
||||
|
||||
/**
|
||||
* Set friendly name
|
||||
*/
|
||||
void setFriendlyName(const char *friendlyName);
|
||||
|
||||
/**
|
||||
* Scan multicast groups
|
||||
*/
|
||||
void scanMulticastGroups(std::vector<ZeroTier::MulticastGroup> &added,
|
||||
std::vector<ZeroTier::MulticastGroup> &removed);
|
||||
|
||||
/**
|
||||
* Set MTU
|
||||
*/
|
||||
void setMtu(unsigned int mtu);
|
||||
|
||||
/**
|
||||
* Calls main network stack loops
|
||||
*/
|
||||
void threadMain()
|
||||
throw();
|
||||
|
||||
#if defined(__MINGW32__)
|
||||
/* The following is merely to make ZeroTier's OneService happy while building on Windows.
|
||||
we won't use these in libzt */
|
||||
NET_LUID _deviceLuid;
|
||||
std::string _deviceInstanceId;
|
||||
|
||||
/**
|
||||
* Returns whether the VirtualTap interface has been initialized
|
||||
*/
|
||||
bool isInitialized() const { return _initialized; };
|
||||
|
||||
inline const NET_LUID &luid() const { return _deviceLuid; }
|
||||
inline const std::string &instanceId() const { return _deviceInstanceId; }
|
||||
#endif
|
||||
/**
|
||||
* For moving data onto the ZeroTier virtual wire
|
||||
*/
|
||||
void (*_handler)(void *, void *, uint64_t, const ZeroTier::MAC &, const ZeroTier::MAC &, unsigned int, unsigned int,
|
||||
const void *, unsigned int);
|
||||
|
||||
/**
|
||||
* Signals us to close the TcpVirtualSocket associated with this PhySocket
|
||||
*/
|
||||
void phyOnUnixClose(ZeroTier::PhySocket *sock, void **uptr);
|
||||
|
||||
/**
|
||||
* Notifies us that there is data to be read from an application's socket
|
||||
*/
|
||||
void phyOnUnixData(ZeroTier::PhySocket *sock, void **uptr, void *data, ssize_t len);
|
||||
|
||||
/**
|
||||
* Notifies us that we can write to an application's socket
|
||||
*/
|
||||
void phyOnUnixWritable(ZeroTier::PhySocket *sock, void **uptr, bool stack_invoked);
|
||||
|
||||
/**
|
||||
* Adds a route to the virtual tap
|
||||
*/
|
||||
bool routeAdd(const ZeroTier::InetAddress &ip, const ZeroTier::InetAddress &nm, const ZeroTier::InetAddress &gw);
|
||||
|
||||
/**
|
||||
* Deletes a route from the virtual tap
|
||||
*/
|
||||
bool routeDelete(const ZeroTier::InetAddress &ip, const ZeroTier::InetAddress &nm);
|
||||
|
||||
/**
|
||||
* Assign a VirtualSocket to the VirtualTap
|
||||
*/
|
||||
void addVirtualSocket(VirtualSocket *vs);
|
||||
|
||||
/**
|
||||
* Remove a VirtualSocket from the VirtualTap
|
||||
*/
|
||||
void removeVirtualSocket();
|
||||
|
||||
/****************************************************************************/
|
||||
/* DNS */
|
||||
/****************************************************************************/
|
||||
|
||||
/**
|
||||
* Registers a DNS nameserver with the network stack
|
||||
*/
|
||||
int add_DNS_Nameserver(struct sockaddr *addr);
|
||||
|
||||
/**
|
||||
* Un-registers a DNS nameserver from the network stack
|
||||
*/
|
||||
int del_DNS_Nameserver(struct sockaddr *addr);
|
||||
|
||||
/****************************************************************************/
|
||||
/* Vars */
|
||||
/****************************************************************************/
|
||||
|
||||
#if defined(STACK_PICO)
|
||||
bool should_start_stack = false;
|
||||
struct pico_device *picodev = NULL;
|
||||
|
||||
/****************************************************************************/
|
||||
/* Guarded RX Frame Buffer for picoTCP */
|
||||
/****************************************************************************/
|
||||
|
||||
unsigned char pico_frame_rxbuf[MAX_PICO_FRAME_RX_BUF_SZ];
|
||||
int pico_frame_rxbuf_tot = 0;
|
||||
Mutex _pico_frame_rxbuf_m;
|
||||
#endif
|
||||
|
||||
std::vector<std::pair<ZeroTier::InetAddress, ZeroTier::InetAddress>> routes;
|
||||
void *zt1ServiceRef = NULL;
|
||||
|
||||
char vtap_full_name[64];
|
||||
char vtap_abbr_name[16];
|
||||
|
||||
static int devno;
|
||||
size_t ifindex = 0;
|
||||
|
||||
std::vector<ZeroTier::InetAddress> ips() const;
|
||||
std::vector<ZeroTier::InetAddress> _ips;
|
||||
|
||||
std::string _homePath;
|
||||
void *_arg;
|
||||
volatile bool _initialized;
|
||||
volatile bool _enabled;
|
||||
volatile bool _run;
|
||||
ZeroTier::MAC _mac;
|
||||
unsigned int _mtu;
|
||||
uint64_t _nwid;
|
||||
ZeroTier::PhySocket *_unixListenSocket;
|
||||
ZeroTier::Phy<VirtualTap *> _phy;
|
||||
|
||||
std::vector<VirtualSocket*> _VirtualSockets;
|
||||
|
||||
Thread _thread;
|
||||
std::string _dev; // path to Unix domain socket
|
||||
|
||||
std::vector<MulticastGroup> _multicastGroups;
|
||||
Mutex _multicastGroups_m;
|
||||
Mutex _ips_m, _tcpconns_m, _rx_buf_m, _close_m;
|
||||
|
||||
/*
|
||||
* Timestamp of last run of housekeeping
|
||||
* SEE: ZT_HOUSEKEEPING_INTERVAL in libzt.h
|
||||
*/
|
||||
uint64_t last_housekeeping_ts = 0;
|
||||
|
||||
/****************************************************************************/
|
||||
/* In these, we will call the stack's corresponding functions, this is */
|
||||
/* where one would put logic to select between different stacks */
|
||||
/****************************************************************************/
|
||||
|
||||
/**
|
||||
* Connect to a remote host via the userspace stack interface associated with this VirtualTap
|
||||
*/
|
||||
int Connect(VirtualSocket *vs, const struct sockaddr *addr, socklen_t addrlen);
|
||||
|
||||
/**
|
||||
* Bind to the userspace stack interface associated with this VirtualTap
|
||||
*/
|
||||
int Bind(VirtualSocket *vs, const struct sockaddr *addr, socklen_t addrlen);
|
||||
|
||||
/**
|
||||
* Listen for a VirtualSocket
|
||||
*/
|
||||
int Listen(VirtualSocket *vs, int backlog);
|
||||
|
||||
/**
|
||||
* Accepts an incoming VirtualSocket
|
||||
*/
|
||||
VirtualSocket* Accept(VirtualSocket *vs);
|
||||
|
||||
/**
|
||||
* Move data from RX buffer to application's "socket"
|
||||
*/
|
||||
int Read(VirtualSocket *vs, PhySocket *sock, void **uptr, bool stack_invoked);
|
||||
|
||||
/**
|
||||
* Move data from application's "socket" into network stack
|
||||
*/
|
||||
int Write(VirtualSocket *vs, void *data, ssize_t len);
|
||||
|
||||
/**
|
||||
* Send data to specified host
|
||||
*/
|
||||
int SendTo(VirtualSocket *vs, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t addrlen);
|
||||
|
||||
/**
|
||||
* Closes a VirtualSocket
|
||||
*/
|
||||
int Close(VirtualSocket *vs);
|
||||
|
||||
/**
|
||||
* Shuts down some aspect of a VirtualSocket
|
||||
*/
|
||||
int Shutdown(VirtualSocket *vs, int how);
|
||||
|
||||
/**
|
||||
* Disposes of previously-closed VirtualSockets
|
||||
*/
|
||||
void Housekeeping();
|
||||
|
||||
/****************************************************************************/
|
||||
/* Not used in this implementation */
|
||||
/****************************************************************************/
|
||||
|
||||
void phyOnDatagram(PhySocket *sock,void **uptr,const struct sockaddr *local_address,
|
||||
const struct sockaddr *from,void *data,unsigned long len);
|
||||
void phyOnTcpConnect(PhySocket *sock,void **uptr,bool success);
|
||||
void phyOnTcpAccept(PhySocket *sockL,PhySocket *sockN,void **uptrL,void **uptrN,
|
||||
const struct sockaddr *from);
|
||||
void phyOnTcpClose(PhySocket *sock,void **uptr);
|
||||
void phyOnTcpData(PhySocket *sock,void **uptr,void *data,unsigned long len);
|
||||
void phyOnTcpWritable(PhySocket *sock,void **uptr);
|
||||
};
|
||||
|
||||
|
||||
#endif // _H
|
||||
@@ -31,7 +31,8 @@
|
||||
*/
|
||||
|
||||
#include "ZeroTierOne.h"
|
||||
#include "Defs.h"
|
||||
#include "InetAddress.hpp"
|
||||
#include "libztDefs.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
@@ -42,20 +43,13 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
namespace ZeroTier
|
||||
{
|
||||
extern std::vector<void*> vtaps;
|
||||
class VirtualTap;
|
||||
class VirtualSocket;
|
||||
|
||||
class picoTCP;
|
||||
extern ZeroTier::picoTCP *picostack;
|
||||
|
||||
class lwIP;
|
||||
extern ZeroTier::lwIP *lwipstack;
|
||||
|
||||
class VirtualTap;
|
||||
class VirtualSocket;
|
||||
struct InetAddress;
|
||||
}
|
||||
VirtualTap *getTapByAddr(ZeroTier::InetAddress *addr);
|
||||
VirtualTap *getTapByName(char *ifname);
|
||||
VirtualTap *getTapByIndex(size_t index);
|
||||
VirtualTap *getAnyTap();
|
||||
|
||||
/**
|
||||
* @brief Returns a vector of network routes { target, via, metric, etc... }
|
||||
@@ -64,7 +58,7 @@ namespace ZeroTier
|
||||
* @param nwid 16-digit hexidecimal network identifier
|
||||
* @return
|
||||
*/
|
||||
std::vector<ZT_VirtualNetworkRoute> *zts_get_network_routes(char *nwid);
|
||||
std::vector<ZT_VirtualNetworkRoute> *zts_get_network_routes(const uint64_t nwid);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
@@ -74,7 +68,7 @@ std::vector<ZT_VirtualNetworkRoute> *zts_get_network_routes(char *nwid);
|
||||
* @param devID buffer to which the device ID (nodeID, ztAddress) should be copied
|
||||
* @return
|
||||
*/
|
||||
int zts_getid_from_file(const char *filepath, char *devID);
|
||||
int zts_getid_from_file(const char *filepath, uint64_t nodeId);
|
||||
|
||||
/**
|
||||
* @brief Starts a ZeroTier service in the background
|
||||
@@ -86,62 +80,24 @@ int zts_getid_from_file(const char *filepath, char *devID);
|
||||
void *zts_start_service(void *thread_id);
|
||||
|
||||
/**
|
||||
* @brief Stops all VirtualTap interfaces and associated I/O loops
|
||||
*
|
||||
* @usage For internal use only.
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
void disableTaps();
|
||||
|
||||
/**
|
||||
* @brief Gets the VirtualTap's (interface) IPv4 address
|
||||
* @brief Gets the VirtualTap's (interface) IP address
|
||||
*
|
||||
* @usage For internal use only.
|
||||
* @param nwid
|
||||
* @param addrstr
|
||||
* @param addr
|
||||
* @param addrlen
|
||||
* @return
|
||||
*/
|
||||
void zts_get_ipv4_address(const char *nwid, char *addrstr, const size_t addrlen);
|
||||
void zts_get_address(const uint64_t nwid, struct sockaddr_storage *addr, const size_t addrlen);
|
||||
|
||||
/**
|
||||
* @brief Gets the VirtualTap's (interface) IPv6 address
|
||||
*
|
||||
* @usage For internal use only.
|
||||
* @param nwid
|
||||
* @param addrstr
|
||||
* @param addrlen
|
||||
* @return
|
||||
*/
|
||||
void zts_get_ipv6_address(const char *nwid, char *addrstr, const size_t addrlen);
|
||||
|
||||
/**
|
||||
* @brief Returns whether the VirtualTap has an assigned IPv4 address
|
||||
* @brief Returns whether the VirtualTap has an assigned address (IPv4 or IPv6)
|
||||
*
|
||||
* @usage For internal use only.
|
||||
* @param nwid
|
||||
* @return
|
||||
*/
|
||||
int zts_has_ipv4_address(const char *nwid);
|
||||
|
||||
/**
|
||||
* @brief Returns whether the VirtualTap has an assigned IPv6 address
|
||||
*
|
||||
* @usage For internal use only.
|
||||
* @param nwid
|
||||
* @return
|
||||
*/
|
||||
int zts_has_ipv6_address(const char *nwid);
|
||||
|
||||
/**
|
||||
* @brief Returns whether the VirtualTap has an assigned address of any protocol version
|
||||
*
|
||||
* @usage For internal use only.
|
||||
* @param nwid
|
||||
* @return
|
||||
*/
|
||||
int zts_has_address(const char *nwid);
|
||||
int zts_has_address(const uint64_t nwid);
|
||||
|
||||
/**
|
||||
* @brief Copies the 6PLANE IPv6 address for the VirtualTap into the provided buffer
|
||||
@@ -152,7 +108,7 @@ int zts_has_address(const char *nwid);
|
||||
* @param devID
|
||||
* @return
|
||||
*/
|
||||
void zts_get_6plane_addr(char *addr, const char *nwid, const char *devID);
|
||||
void zts_get_6plane_addr(struct sockaddr_storage *addr, const uint64_t nwid, const uint64_t nodeId);
|
||||
|
||||
/**
|
||||
* @brief Copies the RFC4193 IPv6 address for the VirtualTap into the provided buffer
|
||||
@@ -160,10 +116,10 @@ void zts_get_6plane_addr(char *addr, const char *nwid, const char *devID);
|
||||
* @usage
|
||||
* @param addr
|
||||
* @param nwid
|
||||
* @param devID
|
||||
* @param devID
|
||||
* @return
|
||||
*/
|
||||
void zts_get_rfc4193_addr(char *addr, const char *nwid, const char *devID);
|
||||
void zts_get_rfc4193_addr(struct sockaddr_storage *addr, const uint64_t nwid, const uint64_t nodeId);
|
||||
|
||||
/**
|
||||
* @brief Join a network
|
||||
@@ -172,7 +128,7 @@ void zts_get_rfc4193_addr(char *addr, const char *nwid, const char *devID);
|
||||
* @param nwid A 16-digit hexidecimal virtual network ID
|
||||
* @return
|
||||
*/
|
||||
void zts_join(const char * nwid);
|
||||
void zts_join(const uint64_t nwid);
|
||||
|
||||
/**
|
||||
* @brief Leave a network
|
||||
@@ -181,7 +137,7 @@ void zts_join(const char * nwid);
|
||||
* @param nwid A 16-digit hexidecimal virtual network ID
|
||||
* @return
|
||||
*/
|
||||
void zts_leave(const char * nwid);
|
||||
void zts_leave(const uint64_t nwid);
|
||||
|
||||
/**
|
||||
* @brief Return whether libzt (specifically the ZeroTier core service) is currently running
|
||||
@@ -213,7 +169,7 @@ int zts_start(const char *path, bool blocking);
|
||||
* @param nwid A 16-digit hexidecimal virtual network ID
|
||||
* @return Returns 0 on success, -1 on failure
|
||||
*/
|
||||
int zts_startjoin(const char *path, const char *nwid);
|
||||
int zts_startjoin(const char *path, const uint64_t nwid);
|
||||
|
||||
/**
|
||||
* @brief Stops libzt (ZeroTier core services, stack drivers, stack threads, etc)
|
||||
@@ -226,7 +182,7 @@ void zts_stop();
|
||||
/**
|
||||
* @brief Copies the configuration path used by ZeroTier into the provided buffer
|
||||
*
|
||||
* @usage
|
||||
* @usage
|
||||
* @param homePath
|
||||
* @param len
|
||||
* @return
|
||||
@@ -234,13 +190,12 @@ void zts_stop();
|
||||
void zts_get_homepath(char *homePath, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Copies the hexidecimal representation of this nodeID into the provided buffer
|
||||
* @brief Returns the ztaddress/nodeId/device ID of this instance
|
||||
*
|
||||
* @usage Call this after zts_start() and/or when zts_running() returns true
|
||||
* @param devID Buffer to which id string is copied
|
||||
* @return
|
||||
*/
|
||||
int zts_get_id(char *devID);
|
||||
uint64_t zts_get_node_id();
|
||||
|
||||
/**
|
||||
* @brief Return the number of peers
|
||||
@@ -258,7 +213,7 @@ unsigned long zts_get_peer_count();
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
int zts_get_peer_address(char *peer, const char *devID);
|
||||
int zts_get_peer_address(char *peer, const uint64_t nodeId);
|
||||
|
||||
/**
|
||||
* @brief Allow or disallow this instance of libzt to be controlled via HTTP requests
|
||||
@@ -270,42 +225,13 @@ int zts_get_peer_address(char *peer, const char *devID);
|
||||
void zts_allow_http_control(bool allowed);
|
||||
|
||||
/**
|
||||
* @brief Returns whether one can add a new socket or not. This depends on network stack in use.
|
||||
* @brief Returns masked address for subnet comparisons
|
||||
*
|
||||
* @usage Call this after zts_start() has succeeded
|
||||
* @usage For internal use only.
|
||||
* @param socket_type
|
||||
* @return
|
||||
*/
|
||||
bool can_provision_new_socket(int socket_type);
|
||||
|
||||
/**
|
||||
* @brief Returns the number of VirtualSockets either already provisioned or waiting to be
|
||||
* Some network stacks may have a limit on the number of sockets that they can
|
||||
* safely handle due to timer construction, this is a way to check that we
|
||||
* haven't passed that limit. Someday if multiple stacks are used simultaneously
|
||||
* the logic for this function should change accordingly.
|
||||
*
|
||||
* @usage Call this after zts_start() has succeeded
|
||||
* @return
|
||||
*/
|
||||
int zts_num_active_virt_sockets();
|
||||
|
||||
/**
|
||||
* @brief Return the maximum number of sockets allowable by platform/stack configuration
|
||||
*
|
||||
* @usage Call this after zts_start() has succeeded
|
||||
* @param socket_type
|
||||
* @return
|
||||
*/
|
||||
int zts_maxsockets(int socket_type);
|
||||
|
||||
/**
|
||||
* @brief Return the number of currently active picoTCP timers
|
||||
*
|
||||
* @usage Call this after zts_start() has succeeded
|
||||
* @return
|
||||
*/
|
||||
int pico_ntimers();
|
||||
bool _ipv6_in_subnet(ZeroTier::InetAddress *subnet, ZeroTier::InetAddress *addr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -33,16 +33,8 @@
|
||||
#ifndef LIBZT_H
|
||||
#define LIBZT_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <poll.h>
|
||||
#endif
|
||||
|
||||
#include "Debug.hpp"
|
||||
#include "Defs.h"
|
||||
#include "libztDebug.h"
|
||||
#include "sys/socket.h"
|
||||
|
||||
/****************************************************************************/
|
||||
/* DLL export for Windows (and other cruft) */
|
||||
@@ -52,6 +44,9 @@
|
||||
typedef int ssize_t;
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if defined(__MING32__) || defined(__MING64__)
|
||||
#ifdef ADD_EXPORTS
|
||||
#define ZT_SOCKET_API __declspec(dllexport)
|
||||
@@ -73,7 +68,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
// forward declarations from ZT1Service.h
|
||||
ZT_SOCKET_API int ZTCALL zts_get_id(char *devID);
|
||||
ZT_SOCKET_API uint64_t ZTCALL zts_get_node_id();
|
||||
ZT_SOCKET_API void ZTCALL init_network_stack();
|
||||
|
||||
/**
|
||||
@@ -104,7 +99,7 @@ ZT_SOCKET_API int ZTCALL zts_start(const char *path, bool blocking);
|
||||
* @param nwid A 16-digit hexidecimal network identifier (e.g. Earth: `8056c2e21c000001`)
|
||||
* @return 0 if successful; or 1 if failed
|
||||
*/
|
||||
ZT_SOCKET_API int ZTCALL zts_startjoin(const char *path, const char *nwid);
|
||||
ZT_SOCKET_API int ZTCALL zts_startjoin(const char *path, const uint64_t nwid);
|
||||
|
||||
/**
|
||||
* @brief Stops the ZeroTier core service and disconnects from all virtual networks
|
||||
@@ -129,7 +124,7 @@ ZT_SOCKET_API int ZTCALL zts_running();
|
||||
* @param nwid the 16-digit hexidecimal network identifier
|
||||
* @return
|
||||
*/
|
||||
ZT_SOCKET_API void ZTCALL zts_join(const char * nwid);
|
||||
ZT_SOCKET_API void ZTCALL zts_join(const uint64_t nwid);
|
||||
|
||||
/**
|
||||
* @brief Joins a network (eventually), this will create the dir and conf file required, don't instruct the core
|
||||
@@ -140,7 +135,7 @@ ZT_SOCKET_API void ZTCALL zts_join(const char * nwid);
|
||||
* @param nwid
|
||||
* @return
|
||||
*/
|
||||
ZT_SOCKET_API void ZTCALL zts_join_soft(const char * filepath, const char * nwid);
|
||||
ZT_SOCKET_API void ZTCALL zts_join_soft(const char * filepath, const uint64_t nwid);
|
||||
|
||||
/**
|
||||
* @brief Leaves a virtual network.
|
||||
@@ -149,7 +144,7 @@ ZT_SOCKET_API void ZTCALL zts_join_soft(const char * filepath, const char * nwid
|
||||
* @param nwid
|
||||
* @return
|
||||
*/
|
||||
ZT_SOCKET_API void ZTCALL zts_leave(const char * nwid);
|
||||
ZT_SOCKET_API void ZTCALL zts_leave(const uint64_t nwid);
|
||||
|
||||
/**
|
||||
* @brief Leave a network - Only delete the .conf file, this will prevent the service from joining upon next startup
|
||||
@@ -159,7 +154,7 @@ ZT_SOCKET_API void ZTCALL zts_leave(const char * nwid);
|
||||
* @param nwid
|
||||
* @return
|
||||
*/
|
||||
ZT_SOCKET_API void ZTCALL zts_leave_soft(const char * filepath, const char * nwid);
|
||||
ZT_SOCKET_API void ZTCALL zts_leave_soft(const char * filepath, const uint64_t nwid);
|
||||
|
||||
/**
|
||||
* @brief Returns path used by ZeroTier/libzt for storing identity and config files
|
||||
@@ -172,31 +167,13 @@ ZT_SOCKET_API void ZTCALL zts_leave_soft(const char * filepath, const char * nwi
|
||||
ZT_SOCKET_API void ZTCALL zts_get_homepath(char *homePath, const size_t len);
|
||||
|
||||
/**
|
||||
* @brief Get device ID (10-digit hex + NULL byte)
|
||||
* @brief Get device ID (10-digit hex number)
|
||||
*
|
||||
* @usage
|
||||
* @param devID
|
||||
* @param nodeId
|
||||
* @return
|
||||
*/
|
||||
ZT_SOCKET_API int ZTCALL zts_get_id(char *devID);
|
||||
|
||||
/**
|
||||
* @brief Returns whether any IPv6 address has been assigned to the SockTap for this network
|
||||
*
|
||||
* @usage This is used as an indicator of readiness for service for the ZeroTier core and stack
|
||||
* @param nwid
|
||||
* @return
|
||||
*/
|
||||
ZT_SOCKET_API int ZTCALL zts_has_ipv4_address(const char *nwid);
|
||||
|
||||
/**
|
||||
* @brief Returns whether any IPv4 address has been assigned to the SockTap for this network
|
||||
*
|
||||
* @usage This is used as an indicator of readiness for service for the ZeroTier core and stack
|
||||
* @param nwid
|
||||
* @return
|
||||
*/
|
||||
ZT_SOCKET_API int ZTCALL zts_has_ipv6_address(const char *nwid);
|
||||
ZT_SOCKET_API int ZTCALL zts_get_id(uint64_t *nodeId);
|
||||
|
||||
/**
|
||||
* @brief Returns whether any address has been assigned to the SockTap for this network
|
||||
@@ -205,29 +182,18 @@ ZT_SOCKET_API int ZTCALL zts_has_ipv6_address(const char *nwid);
|
||||
* @param nwid
|
||||
* @return
|
||||
*/
|
||||
ZT_SOCKET_API int ZTCALL zts_has_address(const char *nwid);
|
||||
ZT_SOCKET_API int ZTCALL zts_has_address(const uint64_t nwid);
|
||||
|
||||
/**
|
||||
* @brief Get IPV4 Address for this device on a given network
|
||||
* @brief Get IP address for this device on a given network
|
||||
*
|
||||
* @usage FIXME: Only returns first address found for given protocol and network (should be enough for now)
|
||||
* @usage FIXME: Only returns first address found, good enough for most cases
|
||||
* @param nwid
|
||||
* @param addrstr
|
||||
* @param addrlen
|
||||
* @return
|
||||
*/
|
||||
ZT_SOCKET_API void ZTCALL zts_get_ipv4_address(const char *nwid, char *addrstr, const size_t addrlen);
|
||||
|
||||
/**
|
||||
* @brief Get IPV6 Address for this device on a given network
|
||||
*
|
||||
* @usage FIXME: Only returns first address found for given protocol and network (should be enough for now)
|
||||
* @param nwid
|
||||
* @param addrstr
|
||||
* @param addrlen
|
||||
* @return
|
||||
*/
|
||||
ZT_SOCKET_API void ZTCALL zts_get_ipv6_address(const char *nwid, char *addrstr, const size_t addrlen);
|
||||
ZT_SOCKET_API void ZTCALL zts_get_address(const uint64_t nwid, struct sockaddr_storage *addr, const size_t addrlen);
|
||||
|
||||
/**
|
||||
* @brief Returns a 6PLANE IPv6 address given a network ID and zerotier ID
|
||||
@@ -235,10 +201,10 @@ ZT_SOCKET_API void ZTCALL zts_get_ipv6_address(const char *nwid, char *addrstr,
|
||||
* @usage
|
||||
* @param addr
|
||||
* @param nwid
|
||||
* @param devID
|
||||
* @param nodeId
|
||||
* @return
|
||||
*/
|
||||
ZT_SOCKET_API void ZTCALL zts_get_6plane_addr(char *addr, const char *nwid, const char *devID);
|
||||
ZT_SOCKET_API void ZTCALL zts_get_6plane_addr(struct sockaddr_storage *addr, const uint64_t nwid, const uint64_t nodeId);
|
||||
|
||||
/**
|
||||
* @brief Returns an RFC 4193 IPv6 address given a network ID and zerotier ID
|
||||
@@ -246,10 +212,10 @@ ZT_SOCKET_API void ZTCALL zts_get_6plane_addr(char *addr, const char *nwid, cons
|
||||
* @usage
|
||||
* @param addr
|
||||
* @param nwid
|
||||
* @param devID
|
||||
* @param nodeId
|
||||
* @return
|
||||
*/
|
||||
ZT_SOCKET_API void ZTCALL zts_get_rfc4193_addr(char *addr, const char *nwid, const char *devID);
|
||||
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 on this network
|
||||
@@ -264,10 +230,10 @@ ZT_SOCKET_API unsigned long zts_get_peer_count();
|
||||
*
|
||||
* @usage
|
||||
* @param peer
|
||||
* @param devID
|
||||
* @param nodeId
|
||||
* @return
|
||||
*/
|
||||
ZT_SOCKET_API int ZTCALL zts_get_peer_address(char *peer, const char *devID);
|
||||
ZT_SOCKET_API int ZTCALL zts_get_peer_address(char *peer, const uint64_t nodeId);
|
||||
|
||||
/**
|
||||
* @brief Enable HTTP control plane (traditionally used by zerotier-cli)
|
||||
@@ -462,7 +428,10 @@ ZT_SOCKET_API int ZTCALL zts_close(int fd);
|
||||
* @return
|
||||
*/
|
||||
#if defined(__linux__)
|
||||
/*
|
||||
typedef unsigned int nfds_t;
|
||||
int zts_poll(struct pollfd *fds, nfds_t nfds, int timeout);
|
||||
*/
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
||||
@@ -38,14 +38,11 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <cstring>
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <sys/syscall.h>
|
||||
#endif
|
||||
|
||||
#include "Platform.h"
|
||||
#include <string.h>
|
||||
|
||||
#define ZT_MSG_ERROR true // Errors
|
||||
#define ZT_MSG_INFO true // Information which is generally useful to any developer
|
||||
@@ -81,18 +78,13 @@
|
||||
|
||||
#define ZT_FILENAME (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) // short
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
extern unsigned int gettid(); // defined in libzt.cpp
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
extern unsigned int gettid();
|
||||
|
||||
#ifdef __linux__
|
||||
#define ZT_THREAD_ID syscall(SYS_gettid)
|
||||
#elif __APPLE__
|
||||
#define ZT_THREAD_ID (long)0//(long)gettid()
|
||||
#endif
|
||||
#ifdef __APPLE__
|
||||
#define ZT_THREAD_ID (long)0 //(long)gettid()
|
||||
#endif
|
||||
#ifdef __MINGW32__
|
||||
#define ZT_THREAD_ID (long)0
|
||||
@@ -33,6 +33,85 @@
|
||||
#ifndef LIBZT_DEFINES_H
|
||||
#define LIBZT_DEFINES_H
|
||||
|
||||
/**
|
||||
* Use ZeroTier Virtual Socket layer to abstract network stack raw API
|
||||
*/
|
||||
#define ZT_VIRTUAL_SOCKET 0
|
||||
/**
|
||||
* Use lwIP sockets API
|
||||
*/
|
||||
#define ZT_LWIP_SEQ_SOCKET 1
|
||||
/**
|
||||
* Use pico BSD socket API
|
||||
*/
|
||||
#define ZT_PICO_BSD_SOCKET 0
|
||||
|
||||
#define STACK_LWIP 1
|
||||
#define STACK_PICO 0
|
||||
#define NO_STACK 0 // for layer-2 only (this will omit all userspace network stack code)
|
||||
|
||||
|
||||
/* sanity checks for userspace network stack and socket API layer choices
|
||||
|
||||
EX.
|
||||
zts_socket()
|
||||
1. ) ZT_VIRTUAL_SOCKET? -> virt_socket() --- Choose this if the default socket layer isn't doing what you need
|
||||
STACK_LWIP? -> raw lwip_ API
|
||||
STACK_PICO? -> raw pico_ API
|
||||
otherStack? -> raw API
|
||||
|
||||
2.) ZT_LWIP_SEQ_SOCKET? (default) -> lwip_socket() --- currently provides greatest safety and performance
|
||||
3.) ZT_PICO_BSD_SOCKET? -> pico_ socket API
|
||||
otherStack? -> other_stack_socket()
|
||||
|
||||
Default is: STACK_LWIP=1 ZT_LWIP_SEQ_SOCKET=1
|
||||
|
||||
*/
|
||||
|
||||
#if (STACK_LWIP+STACK_PICO) > 1
|
||||
#error "Multiple network stacks specified. Pick only one."
|
||||
#endif
|
||||
#if STACK_LWIP==0 && STACK_PICO==0 && NO_STACK==0
|
||||
#error "No network stacks specified and NO_STACK wasn't set. Pick one."
|
||||
#endif
|
||||
#if ZT_VIRTUAL_SOCKET==0 && ZT_LWIP_SEQ_SOCKET==0 && ZT_PICO_BSD_SOCKET==0
|
||||
#error "No socket handling layer specified. Pick one."
|
||||
#endif
|
||||
#if (ZT_VIRTUAL_SOCKET + ZT_LWIP_SEQ_SOCKET + ZT_PICO_BSD_SOCKET) > 1
|
||||
#error "Multiple socket handling layers specified. Pick only one."
|
||||
#endif
|
||||
#if ZT_LWIP_SEQ_SOCKET==1 && STACK_LWIP==0
|
||||
#error "ZT_LWIP_SEQ_SOCKET is selected as socket handling layer, but STACK_LWIP isn't set"
|
||||
#endif
|
||||
#if ZT_PICO_BSD_SOCKET==1 && STACK_PICO==0
|
||||
#error "ZT_PICO_BSD_SOCKET is selected as socket handling layer, but STACK_PICO isn't set"
|
||||
#endif
|
||||
|
||||
#if STACK_LWIP==1
|
||||
#undef STACK_PICO
|
||||
#undef NO_STACK
|
||||
#endif
|
||||
#if STACK_PICO==1
|
||||
#undef STACK_LWIP
|
||||
#undef NO_STACK
|
||||
#endif
|
||||
#if NO_STACK==1
|
||||
#undef STACK_LWIP
|
||||
#undef STACK_PICO
|
||||
#endif
|
||||
#if ZT_VIRTUAL_SOCKET==1
|
||||
#undef ZT_LWIP_SEQ_SOCKET
|
||||
#undef ZT_PICO_BSD_SOCKET
|
||||
#endif
|
||||
#if ZT_LWIP_SEQ_SOCKET==1
|
||||
#undef ZT_VIRTUAL_SOCKET
|
||||
#undef ZT_PICO_BSD_SOCKET
|
||||
#endif
|
||||
#if ZT_PICO_BSD_SOCKET==1
|
||||
#undef ZT_VIRTUAL_SOCKET
|
||||
#undef ZT_LWIP_SEQ_SOCKET
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Maximum MTU size for ZeroTier
|
||||
*/
|
||||
@@ -49,7 +128,7 @@
|
||||
#define ZTO_ID_LEN 16
|
||||
|
||||
#if !defined(__MINGW32__)
|
||||
typedef uint32_t socklen_t;
|
||||
typedef unsigned int socklen_t;
|
||||
#endif
|
||||
|
||||
/****************************************************************************/
|
||||
@@ -137,6 +216,9 @@ struct sockaddr_ll {
|
||||
|
||||
typedef signed char err_t;
|
||||
|
||||
#define ND6_DISCOVERY_INTERVAL 1000
|
||||
#define ARP_DISCOVERY_INTERVAL ARP_TMR_INTERVAL
|
||||
|
||||
/**
|
||||
Specifies the polling interval and the callback function that should
|
||||
be called to poll the application. The interval is specified in
|
||||
@@ -310,13 +392,7 @@ typedef signed char err_t;
|
||||
/**
|
||||
* Interval for performing background tasks (such as adding routes) on VirtualTap objects (in seconds)
|
||||
*/
|
||||
#define ZT_HOUSEKEEPING_INTERVAL 3
|
||||
|
||||
/**
|
||||
* Whether or not we want libzt to exit on internal failure
|
||||
*/
|
||||
#define ZT_EXIT_ON_GENERAL_FAIL false
|
||||
|
||||
#define ZT_HOUSEKEEPING_INTERVAL 1
|
||||
|
||||
/****************************************************************************/
|
||||
/* Socket API Signatures */
|
||||
250
include/lwIP.h
Normal file
250
include/lwIP.h
Normal file
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
* ZeroTier SDK - Network Virtualization Everywhere
|
||||
* Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* --
|
||||
*
|
||||
* You can be released from the requirements of the license by purchasing
|
||||
* a commercial license. Buying such a license is mandatory as soon as you
|
||||
* develop commercial closed-source software that incorporates or links
|
||||
* directly against ZeroTier software without disclosing the source code
|
||||
* of your own application.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* lwIP network stack driver
|
||||
*/
|
||||
|
||||
#ifndef ZT_LWIP_HPP
|
||||
#define ZT_LWIP_HPP
|
||||
|
||||
#include "libztDefs.h"
|
||||
|
||||
#ifdef STACK_LWIP
|
||||
|
||||
namespace ZeroTier {
|
||||
class MAC;
|
||||
class Mutex;
|
||||
struct InetAddress;
|
||||
}
|
||||
|
||||
//#include "lwip/err.h"
|
||||
|
||||
/**
|
||||
* @brief Initialize network stack semaphores, threads, and timers.
|
||||
*
|
||||
* @usage This is called during the initial setup of each VirtualTap but is only allowed to execute once
|
||||
* @return
|
||||
*/
|
||||
void lwip_driver_init();
|
||||
|
||||
/**
|
||||
* @brief Initialize and start the DNS client
|
||||
*
|
||||
* @usage Called after lwip_driver_init()
|
||||
* @return
|
||||
*/
|
||||
void lwip_dns_init();
|
||||
|
||||
/**
|
||||
* @brief Starts DHCP timers
|
||||
*
|
||||
* @usage lwip_driver_init()
|
||||
* @return
|
||||
*/
|
||||
void lwip_start_dhcp(void *netif);
|
||||
|
||||
/**
|
||||
* @brief Set up an interface in the network stack for the VirtualTap.
|
||||
*
|
||||
* @param
|
||||
* @param tapref Reference to VirtualTap that will be responsible for sending and receiving data
|
||||
* @param mac Virtual hardware address for this ZeroTier VirtualTap interface
|
||||
* @param ip Virtual IP address for this ZeroTier VirtualTap interface
|
||||
* @return
|
||||
*/
|
||||
void lwip_init_interface(void *tapref, const ZeroTier::MAC &mac, const ZeroTier::InetAddress &ip);
|
||||
|
||||
/**
|
||||
* @brief Called from the stack, outbound ethernet frames from the network stack enter the ZeroTier virtual wire here.
|
||||
*
|
||||
* @usage This shall only be called from the stack or the stack driver. Not the application thread.
|
||||
* @param netif Transmits an outgoing Ethernet fram from the network stack onto the ZeroTier virtual wire
|
||||
* @param p A pointer to the beginning of a chain pf struct pbufs
|
||||
* @return
|
||||
*/
|
||||
err_t lwip_eth_tx(struct netif *netif, struct pbuf *p);
|
||||
|
||||
/**
|
||||
* @brief Receives incoming Ethernet frames from the ZeroTier virtual wire
|
||||
*
|
||||
* @usage This shall be called from the VirtualTap's I/O thread (via VirtualTap::put())
|
||||
* @param tap Pointer to VirtualTap from which this data comes
|
||||
* @param from Origin address (virtual ZeroTier hardware address)
|
||||
* @param to Intended destination address (virtual ZeroTier hardware address)
|
||||
* @param etherType Protocol type
|
||||
* @param data Pointer to Ethernet frame
|
||||
* @param len Length of Ethernet frame
|
||||
* @return
|
||||
*/
|
||||
void lwip_eth_rx(VirtualTap *tap, const ZeroTier::MAC &from, const ZeroTier::MAC &to, unsigned int etherType,
|
||||
const void *data, unsigned int len);
|
||||
|
||||
/****************************************************************************/
|
||||
/* Raw API driver */
|
||||
/****************************************************************************/
|
||||
|
||||
#ifdef ZT_VIRTUAL_SOCKET
|
||||
|
||||
class VirtualSocket;
|
||||
|
||||
/**
|
||||
* Returns the number of TCP PCBs currently allocated
|
||||
*/
|
||||
int rd_lwip_num_current_tcp_pcbs();
|
||||
|
||||
/**
|
||||
* Returns the number of UDP PCBs currently allocated
|
||||
*/
|
||||
int rd_lwip_num_current_udp_pcbs();
|
||||
|
||||
/**
|
||||
* Returns the number of RAW PCBs currently allocated
|
||||
*/
|
||||
int rd_lwip_num_current_raw_pcbs();
|
||||
|
||||
/**
|
||||
* Returns the total number of PCBs of any time or state
|
||||
*/
|
||||
int rd_lwip_num_total_pcbs();
|
||||
|
||||
/**
|
||||
* Registers a DNS nameserver with the network stack
|
||||
*/
|
||||
int rd_lwip_add_dns_nameserver(struct sockaddr *addr);
|
||||
|
||||
/**
|
||||
* Un-registers a DNS nameserver from the network stack
|
||||
*/
|
||||
int rd_lwip_del_dns_nameserver(struct sockaddr *addr);
|
||||
|
||||
/**
|
||||
* Main stack loop
|
||||
*/
|
||||
void rd_lwip_loop(VirtualTap *tap);
|
||||
|
||||
/**
|
||||
* Creates a stack-specific "socket" or "VirtualSocket object"
|
||||
*/
|
||||
int rd_lwip_socket(void **pcb, int socket_family, int socket_type, int protocol);
|
||||
|
||||
/**
|
||||
* Connect to remote host via userspace network stack interface - Called from VirtualTap
|
||||
*/
|
||||
int rd_lwip_connect(VirtualSocket *vs, const struct sockaddr *addr, socklen_t addrlen);
|
||||
|
||||
/**
|
||||
* Bind to a userspace network stack interface - Called from VirtualTap
|
||||
*/
|
||||
int rd_lwip_bind(VirtualTap *tap, VirtualSocket *vs, const struct sockaddr *addr, socklen_t addrlen);
|
||||
|
||||
/**
|
||||
* Listen for incoming VirtualSockets - Called from VirtualTap
|
||||
*/
|
||||
int rd_lwip_listen(VirtualSocket *vs, int backlog);
|
||||
|
||||
/**
|
||||
* Accept an incoming VirtualSocket - Called from VirtualTap
|
||||
*/
|
||||
VirtualSocket* rd_lwip_accept(VirtualSocket *vs);
|
||||
|
||||
/**
|
||||
* Read from RX buffer to application - Called from VirtualTap
|
||||
*/
|
||||
int rd_lwip_read(VirtualSocket *vs, bool lwip_invoked);
|
||||
|
||||
/**
|
||||
* Write to userspace network stack - Called from VirtualTap
|
||||
*/
|
||||
int rd_lwip_write(VirtualSocket *vs, void *data, ssize_t len);
|
||||
|
||||
/**
|
||||
* Close a VirtualSocket - Called from VirtualTap
|
||||
*/
|
||||
int rd_lwip_close(VirtualSocket *vs);
|
||||
|
||||
/**
|
||||
* Shuts down some aspect of a VirtualSocket - Called from VirtualTap
|
||||
*/
|
||||
int rd_lwip_shutdown(VirtualSocket *vs, int how);
|
||||
|
||||
/**
|
||||
* Sets a property of a socket
|
||||
*/
|
||||
int rd_lwip_setsockopt(VirtualSocket *vs, int level, int optname, const void *optval, socklen_t optlen);
|
||||
|
||||
/**
|
||||
* Gets a property of a socket
|
||||
*/
|
||||
int rd_lwip_getsockopt(VirtualSocket *vs, int level, int optname, void *optval, socklen_t *optlen);
|
||||
|
||||
// --- Callbacks from network stack ---
|
||||
|
||||
#ifdef ZT_DRIVER_MODULE // only include these symbols if we're building the full driver
|
||||
|
||||
/**
|
||||
* Callback for handling received UDP packets (already processed by network stack)
|
||||
*/
|
||||
static err_t rd_lwip_cb_tcp_recved(void *arg, struct tcp_pcb *PCB, struct pbuf *p, err_t err);
|
||||
|
||||
/**
|
||||
* Callback for handling accepted connection
|
||||
*/
|
||||
static err_t rd_lwip_cb_accept(void *arg, struct tcp_pcb *newPCB, err_t err);
|
||||
|
||||
/**
|
||||
* Callback for handling received TCP packets (already processed by stack)
|
||||
*/
|
||||
static void rd_lwip_cb_udp_recved(void * arg, struct udp_pcb * upcb, struct pbuf * p, const ip_addr_t * addr, u16_t port);
|
||||
|
||||
/**
|
||||
* Callback for handling errors from within the network stack
|
||||
*/
|
||||
static void rd_lwip_cb_err(void *arg, err_t err);
|
||||
|
||||
/**
|
||||
* Callback for handling periodic background tasks
|
||||
*/
|
||||
static err_t rd_lwip_cb_poll(void* arg, struct tcp_pcb *PCB);
|
||||
|
||||
/**
|
||||
* Callback for handling confirmation of sent packets
|
||||
*/
|
||||
static err_t rd_lwip_cb_sent(void *arg, struct tcp_pcb *PCB, u16_t len);
|
||||
|
||||
/**
|
||||
* Callback for handling successful connections
|
||||
*/
|
||||
static err_t rd_lwip_cb_connected(void *arg, struct tcp_pcb *PCB, err_t err);
|
||||
|
||||
#endif // ZT_DRIVER_MODULE
|
||||
|
||||
#endif
|
||||
|
||||
#endif // ZT_VIRTUAL_SOCKET
|
||||
#endif // STACK_LWIP
|
||||
101
include/lwIP.hpp
101
include/lwIP.hpp
@@ -1,101 +0,0 @@
|
||||
/*
|
||||
* ZeroTier SDK - Network Virtualization Everywhere
|
||||
* Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* --
|
||||
*
|
||||
* You can be released from the requirements of the license by purchasing
|
||||
* a commercial license. Buying such a license is mandatory as soon as you
|
||||
* develop commercial closed-source software that incorporates or links
|
||||
* directly against ZeroTier software without disclosing the source code
|
||||
* of your own application.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* lwIP network stack driver
|
||||
*/
|
||||
|
||||
#ifndef ZT_LWIP_HPP
|
||||
#define ZT_LWIP_HPP
|
||||
|
||||
#include "MAC.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "Defs.h"
|
||||
#include "Mutex.hpp"
|
||||
|
||||
/**
|
||||
* @brief Initialize network stack semaphores, threads, and timers.
|
||||
*
|
||||
* @usage This is called during the initial setup of each VirtualTap but is only allowed to execute once
|
||||
* @return
|
||||
*/
|
||||
void lwip_driver_init();
|
||||
|
||||
/**
|
||||
* @brief Initialize and start the DNS client
|
||||
*
|
||||
* @usage Called after lwip_driver_init()
|
||||
* @return
|
||||
*/
|
||||
void lwip_dns_init();
|
||||
|
||||
/**
|
||||
* @brief Starts DHCP timers
|
||||
*
|
||||
* @usage lwip_driver_init()
|
||||
* @return
|
||||
*/
|
||||
void lwip_start_dhcp(void *netif);
|
||||
|
||||
/**
|
||||
* @brief Set up an interface in the network stack for the VirtualTap.
|
||||
*
|
||||
* @param
|
||||
* @param tapref Reference to VirtualTap that will be responsible for sending and receiving data
|
||||
* @param mac Virtual hardware address for this ZeroTier VirtualTap interface
|
||||
* @param ip Virtual IP address for this ZeroTier VirtualTap interface
|
||||
* @return
|
||||
*/
|
||||
void lwip_init_interface(void *tapref, const ZeroTier::MAC &mac, const ZeroTier::InetAddress &ip);
|
||||
|
||||
/**
|
||||
* @brief Called from the stack, outbound ethernet frames from the network stack enter the ZeroTier virtual wire here.
|
||||
*
|
||||
* @usage This shall only be called from the stack or the stack driver. Not the application thread.
|
||||
* @param netif Transmits an outgoing Ethernet fram from the network stack onto the ZeroTier virtual wire
|
||||
* @param p A pointer to the beginning of a chain pf struct pbufs
|
||||
* @return
|
||||
*/
|
||||
err_t lwip_eth_tx(struct netif *netif, struct pbuf *p);
|
||||
|
||||
/**
|
||||
* @brief Receives incoming Ethernet frames from the ZeroTier virtual wire
|
||||
*
|
||||
* @usage This shall be called from the VirtualTap's I/O thread (via VirtualTap::put())
|
||||
* @param tap Pointer to VirtualTap from which this data comes
|
||||
* @param from Origin address (virtual ZeroTier hardware address)
|
||||
* @param to Intended destination address (virtual ZeroTier hardware address)
|
||||
* @param etherType Protocol type
|
||||
* @param data Pointer to Ethernet frame
|
||||
* @param len Length of Ethernet frame
|
||||
* @return
|
||||
*/
|
||||
void lwip_eth_rx(ZeroTier::VirtualTap *tap, const ZeroTier::MAC &from, const ZeroTier::MAC &to, unsigned int etherType,
|
||||
const void *data, unsigned int len);
|
||||
|
||||
#endif
|
||||
@@ -33,7 +33,7 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* lwIP Options Configuration
|
||||
* lwIP options configuration
|
||||
*/
|
||||
|
||||
#ifndef __LWIPOPTS_H__
|
||||
@@ -108,47 +108,47 @@
|
||||
#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL
|
||||
#define LWIP_DBG_TYPES_ON LWIP_DBG_ON
|
||||
|
||||
#define ETHARP_DEBUG LWIP_DBG_OFF
|
||||
#define ETHARP_DEBUG LWIP_DBG_ON
|
||||
|
||||
// interfaces
|
||||
#define SLIP_DEBUG LWIP_DBG_OFF
|
||||
#define NETIF_DEBUG LWIP_DBG_OFF
|
||||
#define NETIF_DEBUG LWIP_DBG_ON
|
||||
// API (not used in libzt)
|
||||
#define API_LIB_DEBUG LWIP_DBG_OFF
|
||||
#define API_MSG_DEBUG LWIP_DBG_OFF
|
||||
#define SOCKETS_DEBUG LWIP_DBG_OFF
|
||||
#define API_LIB_DEBUG LWIP_DBG_ON
|
||||
#define API_MSG_DEBUG LWIP_DBG_ON
|
||||
#define SOCKETS_DEBUG LWIP_DBG_ON
|
||||
// other
|
||||
#define ICMP_DEBUG LWIP_DBG_OFF
|
||||
#define IGMP_DEBUG LWIP_DBG_OFF
|
||||
#define INET_DEBUG LWIP_DBG_OFF
|
||||
#define RAW_DEBUG LWIP_DBG_OFF
|
||||
#define ICMP_DEBUG LWIP_DBG_ON
|
||||
#define IGMP_DEBUG LWIP_DBG_ON
|
||||
#define INET_DEBUG LWIP_DBG_ON
|
||||
#define RAW_DEBUG LWIP_DBG_ON
|
||||
// memory
|
||||
#define PBUF_DEBUG LWIP_DBG_OFF
|
||||
#define MEM_DEBUG LWIP_DBG_OFF
|
||||
#define MEMP_DEBUG LWIP_DBG_OFF
|
||||
#define PBUF_DEBUG LWIP_DBG_ON
|
||||
#define MEM_DEBUG LWIP_DBG_ON
|
||||
#define MEMP_DEBUG LWIP_DBG_ON
|
||||
// system
|
||||
#define SYS_DEBUG LWIP_DBG_OFF
|
||||
#define TIMERS_DEBUG LWIP_DBG_OFF
|
||||
// TCP
|
||||
#define TCP_DEBUG_TMR LWIP_DBG_OFF // not standard in lwIP, added for debugging convenience
|
||||
#define TCP_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_INPUT_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_DEBUG LWIP_DBG_ON
|
||||
#define TCP_INPUT_DEBUG LWIP_DBG_ON
|
||||
#define TCP_FR_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_RTO_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_CWND_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_WND_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_OUTPUT_DEBUG LWIP_DBG_ON
|
||||
#define TCP_RST_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_QLEN_DEBUG LWIP_DBG_OFF
|
||||
// IP
|
||||
#define AUTOIP_DEBUG LWIP_DBG_OFF
|
||||
#define IP_DEBUG LWIP_DBG_OFF
|
||||
#define IP_DEBUG LWIP_DBG_ON
|
||||
#define IP_REASS_DEBUG LWIP_DBG_OFF
|
||||
#define IP6_DEBUG LWIP_DBG_OFF
|
||||
#define IP6_DEBUG LWIP_DBG_ON
|
||||
// TCP/IP
|
||||
#define TCPIP_DEBUG LWIP_DBG_OFF
|
||||
#define TCPIP_DEBUG LWIP_DBG_ON
|
||||
// UDP
|
||||
#define UDP_DEBUG LWIP_DBG_OFF
|
||||
#define UDP_DEBUG LWIP_DBG_ON
|
||||
// services
|
||||
#define DHCP_DEBUG LWIP_DBG_OFF
|
||||
#define DNS_DEBUG LWIP_DBG_OFF
|
||||
@@ -381,7 +381,8 @@ happening sooner than they should.
|
||||
* LWIP_ARP==1: Enable ARP functionality.
|
||||
*/
|
||||
#define LWIP_ARP 1
|
||||
|
||||
#define ARP_TABLE_SIZE 64
|
||||
//#define ETHARP_FLAG_TRY_HARD 0
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
------------------------------------ IP options---------------------------------
|
||||
|
||||
222
include/picoTCP.h
Normal file
222
include/picoTCP.h
Normal file
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
* ZeroTier SDK - Network Virtualization Everywhere
|
||||
* Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* --
|
||||
*
|
||||
* You can be released from the requirements of the license by purchasing
|
||||
* a commercial license. Buying such a license is mandatory as soon as you
|
||||
* develop commercial closed-source software that incorporates or links
|
||||
* directly against ZeroTier software without disclosing the source code
|
||||
* of your own application.
|
||||
*/
|
||||
|
||||
#ifndef ZT_PICOTCP_HPP
|
||||
#define ZT_PICOTCP_HPP
|
||||
/*
|
||||
#include "pico_eth.h"
|
||||
#include "pico_stack.h"
|
||||
#include "pico_ipv4.h"
|
||||
#include "pico_icmp4.h"
|
||||
#include "pico_dev_tap.h"
|
||||
#include "pico_protocol.h"
|
||||
#include "pico_socket.h"
|
||||
#include "pico_device.h"
|
||||
#include "pico_ipv6.h"
|
||||
*/
|
||||
|
||||
struct pico_socket;
|
||||
class VirtualSocket;
|
||||
class VirtualTap;
|
||||
|
||||
#include "VirtualTap.h"
|
||||
|
||||
/****************************************************************************/
|
||||
/* PicoTCP API Signatures (See libzt.h for the application-facing API) */
|
||||
/****************************************************************************/
|
||||
|
||||
#define PICO_IPV4_TO_STRING_SIG char *ipbuf, const uint32_t ip
|
||||
#define PICO_TAP_CREATE_SIG char *name
|
||||
#define PICO_IPV4_LINK_ADD_SIG struct pico_device *dev, struct pico_ip4 address, struct pico_ip4 netmask
|
||||
#define PICO_DEVICE_INIT_SIG struct pico_device *dev, const char *name, uint8_t *mac
|
||||
#define PICO_STACK_RECV_SIG struct pico_device *dev, uint8_t *buffer, uint32_t len
|
||||
#define PICO_ICMP4_PING_SIG char *dst, int count, int interval, int timeout, int size, void (*cb)(struct pico_icmp4_stats *)
|
||||
#define PICO_TIMER_ADD_SIG pico_time expire, void (*timer)(pico_time, void *), void *arg
|
||||
#define PICO_STRING_TO_IPV4_SIG const char *ipstr, uint32_t *ip
|
||||
#define PICO_STRING_TO_IPV6_SIG const char *ipstr, uint8_t *ip
|
||||
#define PICO_SOCKET_SETOPTION_SIG struct pico_socket *s, int option, void *value
|
||||
#define PICO_SOCKET_SEND_SIG struct pico_socket *s, const void *buf, int len
|
||||
#define PICO_SOCKET_SENDTO_SIG struct pico_socket *s, const void *buf, int len, void *dst, uint16_t remote_port
|
||||
#define PICO_SOCKET_RECV_SIG struct pico_socket *s, void *buf, int len
|
||||
#define PICO_SOCKET_RECVFROM_SIG struct pico_socket *s, void *buf, int len, void *orig, uint16_t *remote_port
|
||||
#define PICO_SOCKET_OPEN_SIG uint16_t net, uint16_t proto, void (*wakeup)(uint16_t ev, struct pico_socket *s)
|
||||
#define PICO_SOCKET_BIND_SIG struct pico_socket *s, void *local_addr, uint16_t *port
|
||||
#define PICO_SOCKET_CONNECT_SIG struct pico_socket *s, const void *srv_addr, uint16_t remote_port
|
||||
#define PICO_SOCKET_LISTEN_SIG struct pico_socket *s, const int backlog
|
||||
#define PICO_SOCKET_READ_SIG struct pico_socket *s, void *buf, int len
|
||||
#define PICO_SOCKET_WRITE_SIG struct pico_socket *s, const void *buf, int len
|
||||
#define PICO_SOCKET_CLOSE_SIG struct pico_socket *s
|
||||
#define PICO_SOCKET_SHUTDOWN_SIG struct pico_socket *s, int mode
|
||||
#define PICO_SOCKET_ACCEPT_SIG struct pico_socket *s, void *orig, uint16_t *port
|
||||
#define PICO_IPV6_LINK_ADD_SIG struct pico_device *dev, struct pico_ip6 address, struct pico_ip6 netmask
|
||||
#define PICO_IPV4_ROUTE_ADD_SIG struct pico_ip4 address, struct pico_ip4 netmask, struct pico_ip4 gateway, int metric, struct pico_ipv4_link *link
|
||||
#define PICO_IPV4_ROUTE_DEL_SIG struct pico_ip4 address, struct pico_ip4 netmask, int metric
|
||||
#define PICO_IPV6_ROUTE_ADD_SIG struct pico_ip6 address, struct pico_ip6 netmask, struct pico_ip6 gateway, int metric, struct pico_ipv6_link *link
|
||||
#define PICO_IPV6_ROUTE_DEL_SIG struct pico_ip6 address, struct pico_ip6 netmask, struct pico_ip6 gateway, int metric, struct pico_ipv6_link *link
|
||||
#define PICO_DNS_CLIENT_NAMESERVER_SIG pico_ip4*, unsigned char
|
||||
|
||||
/**
|
||||
* Send raw frames from the stack to the ZeroTier virtual wire
|
||||
*/
|
||||
int rd_pico_eth_tx(struct pico_device *dev, void *buf, int len);
|
||||
|
||||
/**
|
||||
* Read raw frames from RX frame buffer into the stack
|
||||
*/
|
||||
int rd_pico_eth_poll(struct pico_device *dev, int loop_score);
|
||||
|
||||
/**
|
||||
* Set up an interface in the network stack for the VirtualTap
|
||||
*/
|
||||
bool pico_init_interface(VirtualTap *tap);
|
||||
|
||||
/**
|
||||
* Register an address with the stack
|
||||
*/
|
||||
bool pico_register_address(VirtualTap *tap, const InetAddress &ip);
|
||||
|
||||
/**
|
||||
* Adds a route to the picoTCP device
|
||||
*/
|
||||
bool rd_pico_route_add(VirtualTap *tap, const InetAddress &addr, const InetAddress &nm, const InetAddress &gw, int metric);
|
||||
|
||||
/**
|
||||
* Deletes a route from the picoTCP device
|
||||
*/
|
||||
bool rd_pico_route_del(VirtualTap *tap, const InetAddress &addr, const InetAddress &nm, int metric);
|
||||
|
||||
/**
|
||||
* Registers a DNS nameserver with the network stack
|
||||
*/
|
||||
int rd_pico_add_dns_nameserver(struct sockaddr *addr);
|
||||
|
||||
/**
|
||||
* Un-registers a DNS nameserver from the network stack
|
||||
*/
|
||||
int rd_pico_del_dns_nameserver(struct sockaddr *addr);
|
||||
|
||||
/**
|
||||
* Main stack loop
|
||||
*/
|
||||
void rd_pico_loop(VirtualTap *tap);
|
||||
|
||||
/**
|
||||
* Read bytes from the stack to the RX buffer (prepare to be read by app)
|
||||
*/
|
||||
void rd_pico_cb_tcp_read(VirtualTap *tap, struct pico_socket *s);
|
||||
|
||||
/**
|
||||
* Read bytes from the stack to the RX buffer (prepare to be read by app)
|
||||
*/
|
||||
void rd_pico_cb_udp_read(VirtualTap *tap, struct pico_socket *s);
|
||||
|
||||
/**
|
||||
* Write bytes from TX buffer to stack (prepare to be sent to ZT virtual wire)
|
||||
*/
|
||||
void rd_pico_cb_tcp_write(VirtualTap *tap, struct pico_socket *s);
|
||||
|
||||
/**
|
||||
* Write bytes from TX buffer to stack (prepare to be sent to ZT virtual wire)
|
||||
*/
|
||||
void rd_pico_cb_socket_ev(uint16_t ev, struct pico_socket *s);
|
||||
|
||||
/**
|
||||
* Packets from the ZeroTier virtual wire enter the stack here
|
||||
*/
|
||||
void rd_pico_eth_rx(VirtualTap *tap, const ZeroTier::MAC &from, const ZeroTier::MAC &to,
|
||||
unsigned int etherType, const void *data, unsigned int len);
|
||||
|
||||
/**
|
||||
* Creates a stack-specific "socket" or "VirtualSocket object"
|
||||
*/
|
||||
int rd_pico_socket(struct pico_socket **p, int socket_family, int socket_type, int protocol);
|
||||
|
||||
/**
|
||||
* Connect to remote host via userspace network stack interface - Called from VirtualTap
|
||||
*/
|
||||
int rd_pico_connect(VirtualSocket *vs, const struct sockaddr *addr, socklen_t addrlen);
|
||||
|
||||
/**
|
||||
* Bind to a userspace network stack interface - Called from VirtualTap
|
||||
*/
|
||||
int rd_pico_bind(VirtualSocket *vs, const struct sockaddr *addr, socklen_t addrlen);
|
||||
|
||||
/**
|
||||
* Listen for incoming VirtualSockets - Called from VirtualTap
|
||||
*/
|
||||
int rd_pico_listen(VirtualSocket *vs, int backlog);
|
||||
|
||||
/**
|
||||
* Accept an incoming VirtualSocket - Called from VirtualTap
|
||||
*/
|
||||
VirtualSocket* rd_pico_accept(VirtualSocket *vs);
|
||||
|
||||
/**
|
||||
* Read from RX buffer to application - Called from VirtualTap
|
||||
*/
|
||||
int rd_pico_read(VirtualTap *tap, ZeroTier::PhySocket *sock, VirtualSocket *vs, bool stack_invoked);
|
||||
|
||||
/**
|
||||
* Write to userspace network stack - Called from VirtualTap
|
||||
*/
|
||||
int rd_pico_write(VirtualSocket *vs, void *data, ssize_t len);
|
||||
|
||||
/**
|
||||
* Close a VirtualSocket - Called from VirtualTap
|
||||
*/
|
||||
int rd_pico_close(VirtualSocket *vs);
|
||||
|
||||
/**
|
||||
* Shuts down some aspect of a VirtualSocket - Called from VirtualTap
|
||||
*/
|
||||
int rd_pico_shutdown(VirtualSocket *vs, int how);
|
||||
|
||||
/**
|
||||
* Sets a property of a socket
|
||||
*/
|
||||
int rd_pico_setsockopt(VirtualSocket *vs, int level, int optname, const void *optval, socklen_t optlen);
|
||||
|
||||
/**
|
||||
* Gets a property of a socket
|
||||
*/
|
||||
int rd_pico_getsockopt(VirtualSocket *vs, int level, int optname, void *optval, socklen_t *optlen);
|
||||
|
||||
/**
|
||||
* Converts a pico_err to its most closely-related errno, and sets errno
|
||||
*/
|
||||
int map_pico_err_to_errno(int err);
|
||||
|
||||
/**
|
||||
* Converts picoTCP error codes to pretty string
|
||||
*/
|
||||
char *beautify_pico_error(int err);
|
||||
|
||||
/**
|
||||
* Converts picoTCP socket states into pretty string
|
||||
*/
|
||||
char *beautify_pico_state(int state);
|
||||
|
||||
#endif // _H
|
||||
@@ -64,7 +64,7 @@ LWIPARCH=$(CONTRIBDIR)/ports/unix
|
||||
endif
|
||||
|
||||
LWIPINCLUDES:=-I$(LWIPDIR)/include -I$(LWIPARCH) -I$(LWIPARCH)/include -I$(LWIPDIR) -I. -Iext -Iinclude
|
||||
CFLAGS=$(WINDEFS) -Wno-format -Wno-deprecated -O3 -g -Wall -fPIC $(LWIPINCLUDES)
|
||||
CFLAGS=$(WINDEFS) -Wno-format -Wno-missing-prototypes -Wno-deprecated -O3 -g -Wall -fPIC $(LWIPINCLUDES)
|
||||
|
||||
ifeq ($(NS_DEBUG),1)
|
||||
CFLAGS+=-DLWIP_DEBUG=1
|
||||
|
||||
143
src/RingBuffer.cpp
Normal file
143
src/RingBuffer.cpp
Normal file
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* ZeroTier SDK - Network Virtualization Everywhere
|
||||
* Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* --
|
||||
*
|
||||
* You can be released from the requirements of the license by purchasing
|
||||
* a commercial license. Buying such a license is mandatory as soon as you
|
||||
* develop commercial closed-source software that incorporates or links
|
||||
* directly against ZeroTier software without disclosing the source code
|
||||
* of your own application.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Ring buffer implementation for network stack drivers
|
||||
*/
|
||||
|
||||
#include <memory.h>
|
||||
#include <algorithm>
|
||||
|
||||
#include "RingBuffer.h"
|
||||
|
||||
bufElementType* RingBuffer::get_buf()
|
||||
{
|
||||
return buf + begin;
|
||||
}
|
||||
|
||||
size_t RingBuffer::produce(size_t n)
|
||||
{
|
||||
n = std::min(n, getFree());
|
||||
if (n == 0) {
|
||||
return n;
|
||||
}
|
||||
const size_t first_chunk = std::min(n, size - end);
|
||||
end = (end + first_chunk) % size;
|
||||
if (first_chunk < n) {
|
||||
const size_t second_chunk = n - first_chunk;
|
||||
end = (end + second_chunk) % size;
|
||||
}
|
||||
if (begin == end) {
|
||||
wrap = true;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
void RingBuffer::reset()
|
||||
{
|
||||
consume(count());
|
||||
}
|
||||
|
||||
size_t RingBuffer::consume(size_t n)
|
||||
{
|
||||
n = std::min(n, count());
|
||||
if (n == 0) {
|
||||
return n;
|
||||
}
|
||||
if (wrap) {
|
||||
wrap = false;
|
||||
}
|
||||
const size_t first_chunk = std::min(n, size - begin);
|
||||
begin = (begin + first_chunk) % size;
|
||||
if (first_chunk < n) {
|
||||
const size_t second_chunk = n - first_chunk;
|
||||
begin = (begin + second_chunk) % size;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t RingBuffer::write(const bufElementType * data, size_t n)
|
||||
{
|
||||
n = std::min(n, getFree());
|
||||
|
||||
if (n == 0) {
|
||||
return n;
|
||||
}
|
||||
const size_t first_chunk = std::min(n, size - end);
|
||||
memcpy(buf + end, data, first_chunk * sizeof(bufElementType));
|
||||
end = (end + first_chunk) % size;
|
||||
if (first_chunk < n) {
|
||||
const size_t second_chunk = n - first_chunk;
|
||||
memcpy(buf + end, data + first_chunk, second_chunk * sizeof(bufElementType));
|
||||
end = (end + second_chunk) % size;
|
||||
}
|
||||
if (begin == end) {
|
||||
wrap = true;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t RingBuffer::read(bufElementType * dest, size_t n)
|
||||
{
|
||||
n = std::min(n, count());
|
||||
|
||||
if (n == 0) {
|
||||
return n;
|
||||
}
|
||||
if (wrap) {
|
||||
wrap = false;
|
||||
}
|
||||
const size_t first_chunk = std::min(n, size - begin);
|
||||
memcpy(dest, buf + begin, first_chunk * sizeof(bufElementType));
|
||||
begin = (begin + first_chunk) % size;
|
||||
if (first_chunk < n) {
|
||||
const size_t second_chunk = n - first_chunk;
|
||||
memcpy(dest + first_chunk, buf + begin, second_chunk * sizeof(bufElementType));
|
||||
begin = (begin + second_chunk) % size;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t RingBuffer::count()
|
||||
{
|
||||
if (end == begin) {
|
||||
return wrap ? size : 0;
|
||||
}
|
||||
else if (end > begin) {
|
||||
return end - begin;
|
||||
}
|
||||
else {
|
||||
return size + end - begin;
|
||||
}
|
||||
}
|
||||
|
||||
size_t RingBuffer::getFree()
|
||||
{
|
||||
return size - count();
|
||||
}
|
||||
|
||||
@@ -1,185 +0,0 @@
|
||||
/*
|
||||
* ZeroTier SDK - Network Virtualization Everywhere
|
||||
* Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* --
|
||||
*
|
||||
* You can be released from the requirements of the license by purchasing
|
||||
* a commercial license. Buying such a license is mandatory as soon as you
|
||||
* develop commercial closed-source software that incorporates or links
|
||||
* directly against ZeroTier software without disclosing the source code
|
||||
* of your own application.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Ring buffer implementation for network stack drivers
|
||||
*/
|
||||
|
||||
#ifndef ZT_RINGBUFFER_HPP
|
||||
#define ZT_RINGBUFFER_HPP
|
||||
|
||||
#include <memory.h>
|
||||
#include <algorithm>
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
template<typename T> class RingBuffer {
|
||||
|
||||
private:
|
||||
T * buf;
|
||||
size_t size;
|
||||
size_t begin;
|
||||
size_t end;
|
||||
bool wrap;
|
||||
|
||||
public:
|
||||
/**
|
||||
* create a RingBuffer with space for up to size elements.
|
||||
*/
|
||||
explicit RingBuffer(size_t size)
|
||||
: size(size),
|
||||
begin(0),
|
||||
end(0),
|
||||
wrap(false)
|
||||
{
|
||||
buf = new T[size];
|
||||
}
|
||||
|
||||
RingBuffer(const RingBuffer<T> & ring)
|
||||
{
|
||||
this(ring.size);
|
||||
begin = ring.begin;
|
||||
end = ring.end;
|
||||
memcpy(buf, ring.buf, sizeof(T) * size);
|
||||
}
|
||||
|
||||
~RingBuffer()
|
||||
{
|
||||
delete[] buf;
|
||||
}
|
||||
|
||||
// get a reference to the underlying buffer
|
||||
T* get_buf()
|
||||
{
|
||||
return buf + begin;
|
||||
}
|
||||
|
||||
// adjust buffer index pointer as if we copied data in
|
||||
size_t produce(size_t n)
|
||||
{
|
||||
n = std::min(n, getFree());
|
||||
if (n == 0) {
|
||||
return n;
|
||||
}
|
||||
const size_t first_chunk = std::min(n, size - end);
|
||||
end = (end + first_chunk) % size;
|
||||
if (first_chunk < n) {
|
||||
const size_t second_chunk = n - first_chunk;
|
||||
end = (end + second_chunk) % size;
|
||||
}
|
||||
if (begin == end) {
|
||||
wrap = true;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
// merely reset the buffer pointer, doesn't erase contents
|
||||
void reset()
|
||||
{
|
||||
consume(count());
|
||||
}
|
||||
|
||||
// adjust buffer index pointer as if we copied data out
|
||||
size_t consume(size_t n)
|
||||
{
|
||||
n = std::min(n, count());
|
||||
if (n == 0) {
|
||||
return n;
|
||||
}
|
||||
if (wrap) {
|
||||
wrap = false;
|
||||
}
|
||||
const size_t first_chunk = std::min(n, size - begin);
|
||||
begin = (begin + first_chunk) % size;
|
||||
if (first_chunk < n) {
|
||||
const size_t second_chunk = n - first_chunk;
|
||||
begin = (begin + second_chunk) % size;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t write(const T * data, size_t n)
|
||||
{
|
||||
n = std::min(n, getFree());
|
||||
|
||||
if (n == 0) {
|
||||
return n;
|
||||
}
|
||||
const size_t first_chunk = std::min(n, size - end);
|
||||
memcpy(buf + end, data, first_chunk * sizeof(T));
|
||||
end = (end + first_chunk) % size;
|
||||
if (first_chunk < n) {
|
||||
const size_t second_chunk = n - first_chunk;
|
||||
memcpy(buf + end, data + first_chunk, second_chunk * sizeof(T));
|
||||
end = (end + second_chunk) % size;
|
||||
}
|
||||
if (begin == end) {
|
||||
wrap = true;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t read(T * dest, size_t n)
|
||||
{
|
||||
n = std::min(n, count());
|
||||
|
||||
if (n == 0) {
|
||||
return n;
|
||||
}
|
||||
if (wrap) {
|
||||
wrap = false;
|
||||
}
|
||||
const size_t first_chunk = std::min(n, size - begin);
|
||||
memcpy(dest, buf + begin, first_chunk * sizeof(T));
|
||||
begin = (begin + first_chunk) % size;
|
||||
if (first_chunk < n) {
|
||||
const size_t second_chunk = n - first_chunk;
|
||||
memcpy(dest + first_chunk, buf + begin, second_chunk * sizeof(T));
|
||||
begin = (begin + second_chunk) % size;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t count() {
|
||||
if (end == begin) {
|
||||
return wrap ? size : 0;
|
||||
}
|
||||
else if (end > begin) {
|
||||
return end - begin;
|
||||
}
|
||||
else {
|
||||
return size + end - begin;
|
||||
}
|
||||
}
|
||||
|
||||
size_t getFree() {
|
||||
return size - count();
|
||||
}
|
||||
};
|
||||
}
|
||||
#endif // ZT_RINGBUFFER_HPP
|
||||
@@ -30,7 +30,20 @@
|
||||
* Platform-specific implementations of common functions
|
||||
*/
|
||||
|
||||
#include "Platform.h"
|
||||
#if defined(STACK_LWIP)
|
||||
#include "lwip/sockets.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/netdb.h"
|
||||
#include "dns.h"
|
||||
#endif
|
||||
#if defined(NO_STACK)
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "SysUtils.h"
|
||||
#include <stdint.h>
|
||||
#include <pthread.h>
|
||||
|
||||
@@ -39,17 +52,6 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void handle_general_failure() {
|
||||
#ifdef ZT_EXIT_ON_GENERAL_FAIL
|
||||
DEBUG_ERROR("exiting (ZT_EXIT_ON_GENERAL_FAIL==1)");
|
||||
exit(-1);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline unsigned int gettid()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
@@ -63,7 +65,3 @@ inline unsigned int gettid()
|
||||
return static_cast<unsigned int>(tid64);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -30,8 +30,7 @@
|
||||
* Misc utilities
|
||||
*/
|
||||
|
||||
#include "InetAddress.hpp"
|
||||
#include "Debug.hpp"
|
||||
//#include "libztDebug.h"
|
||||
#include "Utilities.h"
|
||||
|
||||
#if defined(__MINGW32__)
|
||||
@@ -194,10 +193,6 @@ int inet_pton(int af, const char *src, void *dst)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
char *beautify_eth_proto_nums(int proto)
|
||||
{
|
||||
if (proto == 0x0800) return (char*)"IPv4";
|
||||
@@ -253,81 +248,8 @@ char *beautify_eth_proto_nums(int proto)
|
||||
return (char*)"UNKNOWN";
|
||||
}
|
||||
|
||||
bool ipv6_in_subnet(ZeroTier::InetAddress *subnet, ZeroTier::InetAddress *addr)
|
||||
{
|
||||
ZeroTier::InetAddress r(addr);
|
||||
ZeroTier::InetAddress b(subnet);
|
||||
const unsigned int bits = subnet->netmaskBits();
|
||||
switch(r.ss_family) {
|
||||
case AF_INET:
|
||||
reinterpret_cast<struct sockaddr_in *>(&r)->sin_addr.s_addr &= ZeroTier::Utils::hton((uint32_t)(0xffffffff << (32 - bits)));
|
||||
break;
|
||||
case AF_INET6: {
|
||||
uint64_t nm[2];
|
||||
uint64_t nm2[2];
|
||||
memcpy(nm,reinterpret_cast<struct sockaddr_in6 *>(&r)->sin6_addr.s6_addr,16);
|
||||
memcpy(nm2,reinterpret_cast<struct sockaddr_in6 *>(&b)->sin6_addr.s6_addr,16);
|
||||
|
||||
nm[0] &= ZeroTier::Utils::hton((uint64_t)((bits >= 64) ? 0xffffffffffffffffULL : (0xffffffffffffffffULL << (64 - bits))));
|
||||
nm[1] &= ZeroTier::Utils::hton((uint64_t)((bits <= 64) ? 0ULL : (0xffffffffffffffffULL << (128 - bits))));
|
||||
|
||||
nm2[0] &= ZeroTier::Utils::hton((uint64_t)((bits >= 64) ? 0xffffffffffffffffULL : (0xffffffffffffffffULL << (64 - bits))));
|
||||
nm2[1] &= ZeroTier::Utils::hton((uint64_t)((bits <= 64) ? 0ULL : (0xffffffffffffffffULL << (128 - bits))));
|
||||
|
||||
memcpy(reinterpret_cast<struct sockaddr_in6 *>(&r)->sin6_addr.s6_addr,nm,16);
|
||||
memcpy(reinterpret_cast<struct sockaddr_in6 *>(&b)->sin6_addr.s6_addr,nm2,16);
|
||||
}
|
||||
break;
|
||||
}
|
||||
char b0[64], b1[64];
|
||||
memset(b0, 0, 64);
|
||||
memset(b1, 0, 64);
|
||||
return !strcmp(r.toIpString(b0), b.toIpString(b1));
|
||||
}
|
||||
|
||||
/*
|
||||
void sockaddr2inet(int socket_family, const struct sockaddr *addr, ZeroTier::InetAddress *inet)
|
||||
{
|
||||
char ipstr[INET6_ADDRSTRLEN];
|
||||
memset(ipstr, 0, INET6_ADDRSTRLEN);
|
||||
if (socket_family == AF_INET) {
|
||||
inet_ntop(AF_INET,
|
||||
(const void *)&((struct sockaddr_in *)addr)->sin_addr.s_addr, ipstr, INET_ADDRSTRLEN);
|
||||
inet->fromString(ipstr);
|
||||
}
|
||||
if (socket_family == AF_INET6) {
|
||||
inet_ntop(AF_INET6,
|
||||
(const void *)&((struct sockaddr_in6 *)addr)->sin6_addr.s6_addr, ipstr, INET6_ADDRSTRLEN);
|
||||
char addrstr[64];
|
||||
sprintf(addrstr, "%s", ipstr);
|
||||
inet->fromString(addrstr);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
void mac2str(char *macbuf, int len, unsigned char* addr)
|
||||
{
|
||||
snprintf(macbuf, len, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert from standard IPV6 address structure to an lwIP native structure
|
||||
*/
|
||||
/*
|
||||
inline void in6_to_ip6(ip6_addr_t *ba, struct sockaddr_in6 *in6)
|
||||
{
|
||||
uint8_t *ip = &(in6->sin6_addr).s6_addr[0];
|
||||
IP6_ADDR2(ba,
|
||||
(((ip[ 0] & 0xffff) << 8) | ((ip[ 1]) & 0xffff)),
|
||||
(((ip[ 2] & 0xffff) << 8) | ((ip[ 3]) & 0xffff)),
|
||||
(((ip[ 4] & 0xffff) << 8) | ((ip[ 5]) & 0xffff)),
|
||||
(((ip[ 6] & 0xffff) << 8) | ((ip[ 7]) & 0xffff)),
|
||||
(((ip[ 8] & 0xffff) << 8) | ((ip[ 9]) & 0xffff)),
|
||||
(((ip[10] & 0xffff) << 8) | ((ip[11]) & 0xffff)),
|
||||
(((ip[12] & 0xffff) << 8) | ((ip[13]) & 0xffff)),
|
||||
(((ip[14] & 0xffff) << 8) | ((ip[15]) & 0xffff))
|
||||
);
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -27,97 +27,79 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Platform-agnostic implementation of a socket-like object
|
||||
* Platform- and stack-agnostic implementation of a socket-like object
|
||||
*/
|
||||
|
||||
#ifndef ZT_VIRTUALSOCKET_HPP
|
||||
#define ZT_VIRTUALSOCKET_HPP
|
||||
#include "libztDefs.h"
|
||||
|
||||
#ifdef ZT_VIRTUAL_SOCKET
|
||||
|
||||
#include <ctime>
|
||||
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#include "Phy.hpp"
|
||||
|
||||
#include "libzt.h"
|
||||
#include "libztDebug.h"
|
||||
#include "VirtualSocket.h"
|
||||
#include "VirtualBindingPair.h"
|
||||
#include "RingBuffer.hpp"
|
||||
#include "VirtualTap.h"
|
||||
#include "RingBuffer.h"
|
||||
|
||||
#define VS_STATE_INACTIVE 0x000000u // Default value for newly created VirtualSocket
|
||||
#define VS_STATE_ACTIVE 0x000001u // VirtualSocket is RX'ing or TX'ing without issue
|
||||
#define VS_STATE_SHOULD_SHUTDOWN 0x000002u // Application, stack driver, or stack marked this VirtualSocket for death
|
||||
#define VS_STATE_SHUTDOWN 0x000004u // VirtualSocket and underlying protocol control structures will not RX/TX
|
||||
#define VS_STATE_CLOSED 0x000008u // VirtualSocket and underlying protocol control structures are closed
|
||||
#define VS_STATE_UNHANDLED_CONNECTED 0x000010u // stack callback has received a connection but we haven't dealt with it
|
||||
#define VS_STATE_CONNECTED 0x000020u // stack driver has akwnowledged new connection
|
||||
#define VS_STATE_LISTENING 0x000040u // virtual socket is listening for incoming connections
|
||||
class VirtualTap;
|
||||
|
||||
#define VS_OPT_TCP_NODELAY 0x000000u // Nagle's algorithm
|
||||
#define VS_OPT_SO_LINGER 0x000001u // VirtualSocket waits for data transmission before closure
|
||||
/*
|
||||
#define VS_RESERVED 0x000002u //
|
||||
#define VS_RESERVED 0x000004u //
|
||||
#define VS_RESERVED 0x000008u //
|
||||
#define VS_RESERVED 0x000010u //
|
||||
#define VS_RESERVED 0x000020u //
|
||||
#define VS_RESERVED 0x000040u //
|
||||
*/
|
||||
#define VS_OPT_FD_NONBLOCKING 0x000080u // Whether the VirtualSocket exhibits non-blocking behaviour
|
||||
/*
|
||||
#define VS_RESERVED 0x000100u //
|
||||
#define VS_RESERVED 0x000200u //
|
||||
#define VS_RESERVED 0x000400u //
|
||||
#define VS_RESERVED 0x000800u //
|
||||
#define VS_RESERVED 0x001000u //
|
||||
#define VS_RESERVED 0x002000u //
|
||||
#define VS_RESERVED 0x004000u //
|
||||
#define VS_RESERVED 0x008000u //
|
||||
#define VS_RESERVED 0x010000u //
|
||||
#define VS_RESERVED 0x020000u //
|
||||
#define VS_RESERVED 0x040000u //
|
||||
#define VS_RESERVED 0x080000u //
|
||||
#define VS_RESERVED 0x100000u //
|
||||
#define VS_RESERVED 0x200000u //
|
||||
#define VS_RESERVED 0x400000u //
|
||||
#define VS_RESERVED 0x800000u //
|
||||
*/
|
||||
|
||||
#define vs_is_nonblocking(vs) (((vs)->optflags & VS_OPT_FD_NONBLOCKING) != 0)
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
class VirtualTap;
|
||||
|
||||
class VirtualSocket
|
||||
{
|
||||
private:
|
||||
int _state = VS_STATE_INACTIVE;
|
||||
public:
|
||||
|
||||
/**
|
||||
* Sets the VirtualSocket's state value
|
||||
*/
|
||||
void apply_state(int state) {
|
||||
_state &= state;
|
||||
}
|
||||
/**
|
||||
* Sets the VirtualSocket's state value
|
||||
*/
|
||||
void set_state(int state) {
|
||||
_state = state;
|
||||
}
|
||||
/**
|
||||
* Gets the VirtualSocket's state value
|
||||
*/
|
||||
int get_state() {
|
||||
return _state;
|
||||
}
|
||||
|
||||
VirtualSocket() {
|
||||
// Only available in experimental branch
|
||||
}
|
||||
~VirtualSocket() {
|
||||
}
|
||||
};
|
||||
void VirtualSocket::apply_state(int state) {
|
||||
// states may be set by application or by stack callbacks, thus this must be guarded
|
||||
_op_m.lock();
|
||||
_state &= state;
|
||||
_op_m.unlock();
|
||||
}
|
||||
#endif
|
||||
|
||||
void VirtualSocket::set_state(int state) {
|
||||
_op_m.lock();
|
||||
_state = state;
|
||||
_op_m.unlock();
|
||||
}
|
||||
|
||||
int VirtualSocket::get_state() {
|
||||
return _state;
|
||||
}
|
||||
|
||||
VirtualSocket::VirtualSocket() {
|
||||
DEBUG_EXTRA("this=%p",this);
|
||||
memset(&local_addr, 0, sizeof(sockaddr_storage));
|
||||
memset(&peer_addr, 0, sizeof(sockaddr_storage));
|
||||
|
||||
// ringbuffer used for incoming and outgoing traffic between app, stack, stack drivers, and ZT
|
||||
TXbuf = new RingBuffer(ZT_TCP_TX_BUF_SZ);
|
||||
RXbuf = new RingBuffer(ZT_TCP_RX_BUF_SZ);
|
||||
|
||||
// socketpair, I/O channel between app and stack drivers
|
||||
ZT_PHY_SOCKFD_TYPE fdpair[2];
|
||||
if (socketpair(PF_LOCAL, SOCK_STREAM, 0, fdpair) < 0) {
|
||||
if (errno < 0) {
|
||||
DEBUG_ERROR("unable to create socketpair, errno=%d", errno);
|
||||
return;
|
||||
}
|
||||
}
|
||||
sdk_fd = fdpair[0];
|
||||
app_fd = fdpair[1];
|
||||
|
||||
// set to non-blocking since these are used as the primary I/O channel
|
||||
if (fcntl(sdk_fd, F_SETFL, O_NONBLOCK) < 0) {
|
||||
DEBUG_ERROR("error while setting virtual socket to NONBLOCKING. exiting", errno);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
VirtualSocket::~VirtualSocket() {
|
||||
DEBUG_EXTRA("this=%p",this);
|
||||
close(app_fd);
|
||||
close(sdk_fd);
|
||||
delete TXbuf;
|
||||
delete RXbuf;
|
||||
TXbuf = RXbuf = NULL;
|
||||
//picosock->priv = NULL;
|
||||
pcb = NULL;
|
||||
}
|
||||
|
||||
#endif // ZT_VIRTUAL_SOCKET
|
||||
|
||||
1250
src/VirtualSocketLayer.cpp
Normal file
1250
src/VirtualSocketLayer.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1061
src/VirtualTap.cpp
1061
src/VirtualTap.cpp
File diff suppressed because it is too large
Load Diff
@@ -1,311 +0,0 @@
|
||||
/*
|
||||
* ZeroTier SDK - Network Virtualization Everywhere
|
||||
* Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* --
|
||||
*
|
||||
* You can be released from the requirements of the license by purchasing
|
||||
* a commercial license. Buying such a license is mandatory as soon as you
|
||||
* develop commercial closed-source software that incorporates or links
|
||||
* directly against ZeroTier software without disclosing the source code
|
||||
* of your own application.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Virtual Ethernet tap device
|
||||
*/
|
||||
|
||||
#ifndef ZT_VIRTUALTAP_HPP
|
||||
#define ZT_VIRTUALTAP_HPP
|
||||
|
||||
#include <ctime>
|
||||
|
||||
#include "Mutex.hpp"
|
||||
#include "MulticastGroup.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "Thread.hpp"
|
||||
#include "Phy.hpp"
|
||||
|
||||
#if defined(__MINGW32__) || defined(__MINGW64__)
|
||||
#include <WinSock2.h>
|
||||
#include <Windows.h>
|
||||
#include <IPHlpApi.h>
|
||||
#include <Ifdef.h>
|
||||
#endif
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
/**
|
||||
* emulates an Ethernet tap device
|
||||
*/
|
||||
class VirtualTap
|
||||
{
|
||||
friend class Phy<VirtualTap *>;
|
||||
|
||||
public:
|
||||
VirtualTap(
|
||||
const char *homePath,
|
||||
const MAC &mac,
|
||||
unsigned int mtu,
|
||||
unsigned int metric,
|
||||
uint64_t nwid,
|
||||
const char *friendlyName,
|
||||
void (*handler)(void *, void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int),
|
||||
void *arg);
|
||||
|
||||
~VirtualTap();
|
||||
|
||||
void setEnabled(bool en);
|
||||
bool enabled() const;
|
||||
|
||||
/**
|
||||
* Registers a device with the given address
|
||||
*/
|
||||
bool registerIpWithStack(const InetAddress &ip);
|
||||
|
||||
/**
|
||||
* Adds an address to the userspace stack interface associated with this VirtualTap
|
||||
* - Starts VirtualTap main thread ONLY if successful
|
||||
*/
|
||||
bool addIp(const InetAddress &ip);
|
||||
|
||||
/**
|
||||
* Removes an address from the userspace stack interface associated with this VirtualTap
|
||||
*/
|
||||
bool removeIp(const InetAddress &ip);
|
||||
|
||||
/**
|
||||
* Presents data to the userspace stack
|
||||
*/
|
||||
void put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,
|
||||
unsigned int len);
|
||||
|
||||
/**
|
||||
* Get VirtualTap device name (e.g. 'libzt4-17d72843bc2c5760')
|
||||
*/
|
||||
std::string deviceName() const;
|
||||
|
||||
/**
|
||||
* Get Node ID (ZT address)
|
||||
*/
|
||||
std::string nodeId() const;
|
||||
|
||||
/**
|
||||
* Set friendly name
|
||||
*/
|
||||
void setFriendlyName(const char *friendlyName);
|
||||
|
||||
/**
|
||||
* Scan multicast groups
|
||||
*/
|
||||
void scanMulticastGroups(std::vector<MulticastGroup> &added,std::vector<MulticastGroup> &removed);
|
||||
|
||||
/**
|
||||
* Set MTU
|
||||
*/
|
||||
void setMtu(unsigned int mtu);
|
||||
|
||||
/**
|
||||
* Calls main network stack loops
|
||||
*/
|
||||
void threadMain()
|
||||
throw();
|
||||
|
||||
#if defined(__MINGW32__)
|
||||
/* The following is merely to make ZeroTier's OneService happy while building on Windows.
|
||||
we won't use these in libzt */
|
||||
NET_LUID _deviceLuid;
|
||||
std::string _deviceInstanceId;
|
||||
|
||||
/**
|
||||
* Returns whether the VirtualTap interface has been initialized
|
||||
*/
|
||||
bool isInitialized() const { return _initialized; };
|
||||
|
||||
inline const NET_LUID &luid() const { return _deviceLuid; }
|
||||
inline const std::string &instanceId() const { return _deviceInstanceId; }
|
||||
#endif
|
||||
/**
|
||||
* For moving data onto the ZeroTier virtual wire
|
||||
*/
|
||||
void (*_handler)(void *, void *, uint64_t, const MAC &, const MAC &, unsigned int, unsigned int,
|
||||
const void *, unsigned int);
|
||||
|
||||
/**
|
||||
* Signals us to close the TcpVirtualSocket associated with this PhySocket
|
||||
*/
|
||||
void phyOnUnixClose(PhySocket *sock, void **uptr);
|
||||
|
||||
/**
|
||||
* Notifies us that there is data to be read from an application's socket
|
||||
*/
|
||||
void phyOnUnixData(PhySocket *sock, void **uptr, void *data, ssize_t len);
|
||||
|
||||
/**
|
||||
* Notifies us that we can write to an application's socket
|
||||
*/
|
||||
void phyOnUnixWritable(PhySocket *sock, void **uptr, bool stack_invoked);
|
||||
|
||||
/**
|
||||
* Adds a route to the virtual tap
|
||||
*/
|
||||
bool routeAdd(const InetAddress &ip, const InetAddress &nm, const InetAddress &gw);
|
||||
|
||||
/**
|
||||
* Deletes a route from the virtual tap
|
||||
*/
|
||||
bool routeDelete(const InetAddress &ip, const InetAddress &nm);
|
||||
|
||||
/**
|
||||
* Assign a VirtualSocket to the VirtualTap
|
||||
*/
|
||||
void addVirtualSocket();
|
||||
|
||||
/**
|
||||
* Remove a VirtualSocket from the VirtualTap
|
||||
*/
|
||||
void removeVirtualSocket();
|
||||
|
||||
/****************************************************************************/
|
||||
/* DNS */
|
||||
/****************************************************************************/
|
||||
|
||||
/**
|
||||
* Registers a DNS nameserver with the network stack
|
||||
*/
|
||||
int add_DNS_Nameserver(struct sockaddr *addr);
|
||||
|
||||
/**
|
||||
* Un-registers a DNS nameserver from the network stack
|
||||
*/
|
||||
int del_DNS_Nameserver(struct sockaddr *addr);
|
||||
|
||||
/****************************************************************************/
|
||||
/* Vars */
|
||||
/****************************************************************************/
|
||||
|
||||
std::vector<std::pair<ZeroTier::InetAddress, ZeroTier::InetAddress>> routes;
|
||||
void *zt1ServiceRef = NULL;
|
||||
|
||||
char vtap_full_name[64];
|
||||
char vtap_abbr_name[16];
|
||||
|
||||
static int devno;
|
||||
size_t ifindex = 0;
|
||||
|
||||
std::vector<InetAddress> ips() const;
|
||||
std::vector<InetAddress> _ips;
|
||||
|
||||
std::string _homePath;
|
||||
void *_arg;
|
||||
volatile bool _initialized;
|
||||
volatile bool _enabled;
|
||||
volatile bool _run;
|
||||
MAC _mac;
|
||||
unsigned int _mtu;
|
||||
uint64_t _nwid;
|
||||
PhySocket *_unixListenSocket;
|
||||
Phy<VirtualTap *> _phy;
|
||||
|
||||
//std::vector<VirtualSocket*> _VirtualSockets;
|
||||
|
||||
Thread _thread;
|
||||
std::string _dev; // path to Unix domain socket
|
||||
|
||||
std::vector<MulticastGroup> _multicastGroups;
|
||||
Mutex _multicastGroups_m;
|
||||
Mutex _ips_m, _tcpconns_m, _rx_buf_m, _close_m;
|
||||
|
||||
/*
|
||||
* Timestamp of last run of housekeeping
|
||||
* SEE: ZT_HOUSEKEEPING_INTERVAL in libzt.h
|
||||
*/
|
||||
std::time_t last_housekeeping_ts = 0;
|
||||
|
||||
/****************************************************************************/
|
||||
/* In these, we will call the stack's corresponding functions, this is */
|
||||
/* where one would put logic to select between different stacks */
|
||||
/****************************************************************************/
|
||||
|
||||
/**
|
||||
* Connect to a remote host via the userspace stack interface associated with this VirtualTap
|
||||
*/
|
||||
int Connect( const struct sockaddr *addr, socklen_t addrlen);
|
||||
|
||||
/**
|
||||
* Bind to the userspace stack interface associated with this VirtualTap
|
||||
*/
|
||||
int Bind(const struct sockaddr *addr, socklen_t addrlen);
|
||||
|
||||
/**
|
||||
* Listen for a VirtualSocket
|
||||
*/
|
||||
int Listen(int backlog);
|
||||
|
||||
/**
|
||||
* Accepts an incoming VirtualSocket
|
||||
*/
|
||||
void Accept();
|
||||
|
||||
/**
|
||||
* Move data from RX buffer to application's "socket"
|
||||
*/
|
||||
int Read(PhySocket *sock,void **uptr,bool stack_invoked);
|
||||
|
||||
/**
|
||||
* Move data from application's "socket" into network stack
|
||||
*/
|
||||
int Write(void *data, ssize_t len);
|
||||
|
||||
/**
|
||||
* Send data to specified host
|
||||
*/
|
||||
int SendTo(const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t addrlen);
|
||||
|
||||
/**
|
||||
* Closes a VirtualSocket
|
||||
*/
|
||||
int Close();
|
||||
|
||||
/**
|
||||
* Shuts down some aspect of a VirtualSocket
|
||||
*/
|
||||
int Shutdown(int how);
|
||||
|
||||
/**
|
||||
* Disposes of previously-closed VirtualSockets
|
||||
*/
|
||||
void Housekeeping();
|
||||
|
||||
/****************************************************************************/
|
||||
/* Not used in this implementation */
|
||||
/****************************************************************************/
|
||||
|
||||
void phyOnDatagram(PhySocket *sock,void **uptr,const struct sockaddr *local_address,
|
||||
const struct sockaddr *from,void *data,unsigned long len);
|
||||
void phyOnTcpConnect(PhySocket *sock,void **uptr,bool success);
|
||||
void phyOnTcpAccept(PhySocket *sockL,PhySocket *sockN,void **uptrL,void **uptrN,
|
||||
const struct sockaddr *from);
|
||||
void phyOnTcpClose(PhySocket *sock,void **uptr);
|
||||
void phyOnTcpData(PhySocket *sock,void **uptr,void *data,unsigned long len);
|
||||
void phyOnTcpWritable(PhySocket *sock,void **uptr);
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif // _H
|
||||
@@ -31,29 +31,27 @@
|
||||
*/
|
||||
|
||||
#include "ZT1Service.h"
|
||||
|
||||
#include "Debug.hpp"
|
||||
#include "libztDebug.h"
|
||||
#include "SysUtils.h"
|
||||
|
||||
#include "Phy.hpp"
|
||||
#include "OneService.hpp"
|
||||
#include "Utilities.h"
|
||||
#include "InetAddress.hpp"
|
||||
#include "OSUtils.hpp"
|
||||
|
||||
std::vector<void*> vtaps;
|
||||
ZeroTier::Mutex _vtaps_lock;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
namespace ZeroTier {
|
||||
std::vector<void*> vtaps;
|
||||
static ZeroTier::OneService *zt1Service;
|
||||
|
||||
static ZeroTier::OneService *zt1Service;
|
||||
std::string homeDir; // Platform-specific dir we *must* use internally
|
||||
std::string netDir; // Where network .conf files are to be written
|
||||
|
||||
std::string homeDir; // Platform-specific dir we *must* use internally
|
||||
std::string netDir; // Where network .conf files are to be written
|
||||
|
||||
ZeroTier::Mutex _vtaps_lock;
|
||||
ZeroTier::Mutex _multiplexer_lock;
|
||||
}
|
||||
ZeroTier::Mutex _multiplexer_lock;
|
||||
|
||||
#if defined(__MINGW32__) || defined(__MINGW64__)
|
||||
WSADATA wsaData;
|
||||
@@ -63,132 +61,152 @@ WSADATA wsaData;
|
||||
/* ZeroTier Core helper functions for libzt - DON'T CALL THESE DIRECTLY */
|
||||
/****************************************************************************/
|
||||
|
||||
std::vector<ZT_VirtualNetworkRoute> *zts_get_network_routes(char *nwid)
|
||||
std::vector<ZT_VirtualNetworkRoute> *zts_get_network_routes(const uint64_t nwid)
|
||||
{
|
||||
uint64_t nwid_int = strtoull(nwid, NULL, 16);
|
||||
return ZeroTier::zt1Service->getRoutes(nwid_int);
|
||||
return zt1Service->getRoutes(nwid);
|
||||
}
|
||||
|
||||
ZeroTier::VirtualTap *getTapByNWID(uint64_t nwid)
|
||||
VirtualTap *getTapByNWID(uint64_t nwid)
|
||||
{
|
||||
ZeroTier::_vtaps_lock.lock();
|
||||
ZeroTier::VirtualTap *s, *tap = nullptr;
|
||||
for (size_t i=0; i<ZeroTier::vtaps.size(); i++) {
|
||||
s = (ZeroTier::VirtualTap*)ZeroTier::vtaps[i];
|
||||
_vtaps_lock.lock();
|
||||
VirtualTap *s, *tap = nullptr;
|
||||
for (size_t i=0; i<vtaps.size(); i++) {
|
||||
s = (VirtualTap*)vtaps[i];
|
||||
if (s->_nwid == nwid) { tap = s; }
|
||||
}
|
||||
ZeroTier::_vtaps_lock.unlock();
|
||||
_vtaps_lock.unlock();
|
||||
return tap;
|
||||
}
|
||||
|
||||
ZeroTier::VirtualTap *getTapByAddr(ZeroTier::InetAddress *addr)
|
||||
VirtualTap *getTapByAddr(ZeroTier::InetAddress *addr)
|
||||
{
|
||||
ZeroTier::_vtaps_lock.lock();
|
||||
ZeroTier::VirtualTap *s, *tap = nullptr;
|
||||
_vtaps_lock.lock();
|
||||
VirtualTap *s, *tap = nullptr;
|
||||
//char ipbuf[64], ipbuf2[64], ipbuf3[64];
|
||||
for (size_t i=0; i<ZeroTier::vtaps.size(); i++) {
|
||||
s = (ZeroTier::VirtualTap*)ZeroTier::vtaps[i];
|
||||
for (size_t i=0; i<vtaps.size(); i++) {
|
||||
s = (VirtualTap*)vtaps[i];
|
||||
// check address schemes
|
||||
for (ssize_t j=0; j<s->_ips.size(); j++) {
|
||||
if ((s->_ips[j].isV4() && addr->isV4()) || (s->_ips[j].isV6() && addr->isV6())) {
|
||||
//DEBUG_EXTRA("looking at tap %s, <addr=%s> --- for <%s>", s->_dev.c_str(), s->_ips[j].toString(ipbuf), addr->toIpString(ipbuf2));
|
||||
/* DEBUG_EXTRA("looking at tap %s, <addr=%s> --- for <%s>", s->_dev.c_str(),
|
||||
s->_ips[j].toString(ipbuf), addr->toIpString(ipbuf2)); */
|
||||
if (s->_ips[j].isEqualPrefix(addr)
|
||||
|| s->_ips[j].ipsEqual(addr)
|
||||
|| s->_ips[j].containsAddress(addr)
|
||||
|| (addr->isV6() && ipv6_in_subnet(&s->_ips[j], addr))
|
||||
|| (addr->isV6() && _ipv6_in_subnet(&s->_ips[j], addr))
|
||||
)
|
||||
{
|
||||
//DEBUG_EXTRA("selected tap %s, <addr=%s>", s->_dev.c_str(), s->_ips[j].toString(ipbuf));
|
||||
ZeroTier::_vtaps_lock.unlock();
|
||||
_vtaps_lock.unlock();
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
// check managed routes
|
||||
if (tap == NULL) {
|
||||
std::vector<ZT_VirtualNetworkRoute> *managed_routes = ZeroTier::zt1Service->getRoutes(s->_nwid);
|
||||
std::vector<ZT_VirtualNetworkRoute> *managed_routes = zt1Service->getRoutes(s->_nwid);
|
||||
ZeroTier::InetAddress target, nm, via;
|
||||
for (size_t i=0; i<managed_routes->size(); i++) {
|
||||
target = managed_routes->at(i).target;
|
||||
nm = target.netmask();
|
||||
via = managed_routes->at(i).via;
|
||||
if (target.containsAddress(addr)) {
|
||||
//DEBUG_EXTRA("chose tap with route <target=%s, nm=%s, via=%s>", target.toString(ipbuf), nm.toString(ipbuf2), via.toString(ipbuf3));
|
||||
ZeroTier::_vtaps_lock.unlock();
|
||||
/* DEBUG_EXTRA("chose tap with route <target=%s, nm=%s, via=%s>", target.toString(ipbuf),
|
||||
nm.toString(ipbuf2), via.toString(ipbuf3)); */
|
||||
_vtaps_lock.unlock();
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ZeroTier::_vtaps_lock.unlock();
|
||||
_vtaps_lock.unlock();
|
||||
return tap;
|
||||
}
|
||||
|
||||
ZeroTier::VirtualTap *getTapByName(char *ifname)
|
||||
VirtualTap *getTapByName(char *ifname)
|
||||
{
|
||||
ZeroTier::_vtaps_lock.lock();
|
||||
ZeroTier::VirtualTap *s, *tap = nullptr;
|
||||
for (size_t i=0; i<ZeroTier::vtaps.size(); i++) {
|
||||
s = (ZeroTier::VirtualTap*)ZeroTier::vtaps[i];
|
||||
_vtaps_lock.lock();
|
||||
VirtualTap *s, *tap = nullptr;
|
||||
for (size_t i=0; i<vtaps.size(); i++) {
|
||||
s = (VirtualTap*)vtaps[i];
|
||||
if (strcmp(s->_dev.c_str(), ifname) == false) {
|
||||
tap = s;
|
||||
}
|
||||
}
|
||||
ZeroTier::_vtaps_lock.unlock();
|
||||
_vtaps_lock.unlock();
|
||||
return tap;
|
||||
}
|
||||
|
||||
ZeroTier::VirtualTap *getTapByIndex(size_t index)
|
||||
VirtualTap *getTapByIndex(size_t index)
|
||||
{
|
||||
ZeroTier::_vtaps_lock.lock();
|
||||
ZeroTier::VirtualTap *s, *tap = nullptr;
|
||||
for (size_t i=0; i<ZeroTier::vtaps.size(); i++) {
|
||||
s = (ZeroTier::VirtualTap*)ZeroTier::vtaps[i];
|
||||
_vtaps_lock.lock();
|
||||
VirtualTap *s, *tap = nullptr;
|
||||
for (size_t i=0; i<vtaps.size(); i++) {
|
||||
s = (VirtualTap*)vtaps[i];
|
||||
if (s->ifindex == index) {
|
||||
tap = s;
|
||||
}
|
||||
}
|
||||
ZeroTier::_vtaps_lock.unlock();
|
||||
_vtaps_lock.unlock();
|
||||
return tap;
|
||||
}
|
||||
|
||||
ZeroTier::VirtualTap *getAnyTap()
|
||||
VirtualTap *getAnyTap()
|
||||
{
|
||||
ZeroTier::_vtaps_lock.lock();
|
||||
ZeroTier::VirtualTap *vtap = NULL;
|
||||
if (ZeroTier::vtaps.size()) {
|
||||
vtap = (ZeroTier::VirtualTap *)ZeroTier::vtaps[0];
|
||||
_vtaps_lock.lock();
|
||||
VirtualTap *vtap = NULL;
|
||||
if (vtaps.size()) {
|
||||
vtap = (VirtualTap *)vtaps[0];
|
||||
}
|
||||
ZeroTier::_vtaps_lock.unlock();
|
||||
_vtaps_lock.unlock();
|
||||
return vtap;
|
||||
}
|
||||
|
||||
int zts_get_id_from_file(const char *filepath, char *devID)
|
||||
/*
|
||||
|
||||
else // Service isn't online, try to read ID from file
|
||||
{
|
||||
std::string fname("identity.public");
|
||||
std::string fpath(homeDir);
|
||||
if (ZeroTier::OSUtils::fileExists((fpath + ZT_PATH_SEPARATOR_S + fname).c_str(),false)) {
|
||||
std::string oldid;
|
||||
ZeroTier::OSUtils::readFile((fpath + ZT_PATH_SEPARATOR_S + fname).c_str(),oldid);
|
||||
memcpy(devID, oldid.c_str(), ZTO_ID_LEN); // first 10 bytes of file
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
int zts_get_id_from_file(const char *filepath, uint64_t *nodeId)
|
||||
{
|
||||
/*
|
||||
DEBUG_EXTRA();
|
||||
std::string fname("identity.public");
|
||||
std::string fpath(filepath);
|
||||
if (ZeroTier::OSUtils::fileExists((fpath + ZT_PATH_SEPARATOR_S + fname).c_str(),false)) {
|
||||
std::string oldid;
|
||||
ZeroTier::OSUtils::readFile((fpath + ZT_PATH_SEPARATOR_S + fname).c_str(),oldid);
|
||||
memcpy(devID, oldid.c_str(), 10); // first 10 bytes of file
|
||||
uint64_t value = Utils::hexStrToU64(oldid);
|
||||
memcpy(nodeId, value, sizeof(uint64_t)); // first 10 bytes of file
|
||||
// TOmorrow
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Starts a ZeroTier service in the background
|
||||
void *zts_start_service(void *thread_id)
|
||||
{
|
||||
DEBUG_INFO("zto-thread, path=%s", ZeroTier::homeDir.c_str());
|
||||
DEBUG_INFO("zto-thread, path=%s", homeDir.c_str());
|
||||
// Where network .conf files will be stored
|
||||
ZeroTier::netDir = ZeroTier::homeDir + "/networks.d";
|
||||
ZeroTier::zt1Service = (ZeroTier::OneService *)0;
|
||||
netDir = homeDir + "/networks.d";
|
||||
zt1Service = (ZeroTier::OneService *)0;
|
||||
// Construct path for network config and supporting service files
|
||||
if (ZeroTier::homeDir.length()) {
|
||||
std::vector<std::string> hpsp(ZeroTier::OSUtils::split(ZeroTier::homeDir.c_str(), ZT_PATH_SEPARATOR_S,"",""));
|
||||
if (homeDir.length()) {
|
||||
std::vector<std::string> hpsp(ZeroTier::OSUtils::split(homeDir.c_str(), ZT_PATH_SEPARATOR_S,"",""));
|
||||
std::string ptmp;
|
||||
if (ZeroTier::homeDir[0] == ZT_PATH_SEPARATOR) {
|
||||
if (homeDir[0] == ZT_PATH_SEPARATOR) {
|
||||
ptmp.push_back(ZT_PATH_SEPARATOR);
|
||||
}
|
||||
for (std::vector<std::string>::iterator pi(hpsp.begin());pi!=hpsp.end();++pi) {
|
||||
@@ -199,7 +217,6 @@ void *zts_start_service(void *thread_id)
|
||||
if ((*pi != ".")&&(*pi != "..")) {
|
||||
if (ZeroTier::OSUtils::mkdir(ptmp) == false) {
|
||||
DEBUG_ERROR("home path does not exist, and could not create");
|
||||
handle_general_failure();
|
||||
perror("error\n");
|
||||
}
|
||||
}
|
||||
@@ -207,7 +224,6 @@ void *zts_start_service(void *thread_id)
|
||||
}
|
||||
else {
|
||||
DEBUG_ERROR("homeDir is empty, could not construct path");
|
||||
handle_general_failure();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -217,27 +233,27 @@ void *zts_start_service(void *thread_id)
|
||||
// TODO: Better port random range selection
|
||||
int servicePort = 9000 + (randp % 1000);
|
||||
for (;;) {
|
||||
ZeroTier::zt1Service = ZeroTier::OneService::newInstance(ZeroTier::homeDir.c_str(),servicePort);
|
||||
switch(ZeroTier::zt1Service->run()) {
|
||||
zt1Service = ZeroTier::OneService::newInstance(homeDir.c_str(),servicePort);
|
||||
switch(zt1Service->run()) {
|
||||
case ZeroTier::OneService::ONE_STILL_RUNNING:
|
||||
case ZeroTier::OneService::ONE_NORMAL_TERMINATION:
|
||||
break;
|
||||
case ZeroTier::OneService::ONE_UNRECOVERABLE_ERROR:
|
||||
DEBUG_ERROR("ZTO service port = %d", servicePort);
|
||||
DEBUG_ERROR("fatal error: %s",ZeroTier::zt1Service->fatalErrorMessage().c_str());
|
||||
DEBUG_ERROR("fatal error: %s",zt1Service->fatalErrorMessage().c_str());
|
||||
break;
|
||||
case ZeroTier::OneService::ONE_IDENTITY_COLLISION: {
|
||||
delete ZeroTier::zt1Service;
|
||||
ZeroTier::zt1Service = (ZeroTier::OneService *)0;
|
||||
delete zt1Service;
|
||||
zt1Service = (ZeroTier::OneService *)0;
|
||||
std::string oldid;
|
||||
ZeroTier::OSUtils::readFile((ZeroTier::homeDir + ZT_PATH_SEPARATOR_S
|
||||
ZeroTier::OSUtils::readFile((homeDir + ZT_PATH_SEPARATOR_S
|
||||
+ "identity.secret").c_str(),oldid);
|
||||
if (oldid.length()) {
|
||||
ZeroTier::OSUtils::writeFile((ZeroTier::homeDir + ZT_PATH_SEPARATOR_S
|
||||
ZeroTier::OSUtils::writeFile((homeDir + ZT_PATH_SEPARATOR_S
|
||||
+ "identity.secret.saved_after_collision").c_str(),oldid);
|
||||
ZeroTier::OSUtils::rm((ZeroTier::homeDir + ZT_PATH_SEPARATOR_S
|
||||
ZeroTier::OSUtils::rm((homeDir + ZT_PATH_SEPARATOR_S
|
||||
+ "identity.secret").c_str());
|
||||
ZeroTier::OSUtils::rm((ZeroTier::homeDir + ZT_PATH_SEPARATOR_S
|
||||
ZeroTier::OSUtils::rm((homeDir + ZT_PATH_SEPARATOR_S
|
||||
+ "identity.public").c_str());
|
||||
}
|
||||
}
|
||||
@@ -245,179 +261,89 @@ void *zts_start_service(void *thread_id)
|
||||
}
|
||||
break; // terminate loop -- normally we don't keep restarting
|
||||
}
|
||||
delete ZeroTier::zt1Service;
|
||||
ZeroTier::zt1Service = (ZeroTier::OneService *)0;
|
||||
delete zt1Service;
|
||||
zt1Service = (ZeroTier::OneService *)0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void disableTaps()
|
||||
void zts_get_address(const uint64_t nwid, struct sockaddr_storage *addr, const size_t addrlen)
|
||||
{
|
||||
DEBUG_EXTRA();
|
||||
ZeroTier::_vtaps_lock.lock();
|
||||
for (size_t i=0; i<ZeroTier::vtaps.size(); i++) {
|
||||
DEBUG_EXTRA("vt=%p", ZeroTier::vtaps[i]);
|
||||
((ZeroTier::VirtualTap*)ZeroTier::vtaps[i])->_enabled = false;
|
||||
if(!zt1Service) {
|
||||
return;
|
||||
}
|
||||
ZeroTier::_vtaps_lock.unlock();
|
||||
}
|
||||
|
||||
void zts_get_ipv4_address(const char *nwid, char *addrstr, const size_t addrlen)
|
||||
{
|
||||
// DEBUG_EXTRA();
|
||||
if (ZeroTier::zt1Service) {
|
||||
uint64_t nwid_int = strtoull(nwid, NULL, 16);
|
||||
ZeroTier::VirtualTap *tap = getTapByNWID(nwid_int);
|
||||
if (tap && tap->_ips.size()) {
|
||||
for (size_t i=0; i<tap->_ips.size(); i++) {
|
||||
if (tap->_ips[i].isV4()) {
|
||||
char ipbuf[INET_ADDRSTRLEN];
|
||||
std::string addr = tap->_ips[i].toString(ipbuf);
|
||||
int len = addrlen < addr.length() ? addrlen : addr.length();
|
||||
memset(addrstr, 0, len);
|
||||
memcpy(addrstr, addr.c_str(), len);
|
||||
return;
|
||||
}
|
||||
VirtualTap *tap = getTapByNWID(nwid);
|
||||
if (tap && tap->_ips.size()) {
|
||||
for (size_t i=0; i<tap->_ips.size(); i++) {
|
||||
if (tap->_ips[i].isV4()) {
|
||||
memcpy(addr, &(tap->_ips[i]), addrlen);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
memcpy(addrstr, "\0", 1);
|
||||
}
|
||||
|
||||
void zts_get_ipv6_address(const char *nwid, char *addrstr, size_t addrlen)
|
||||
int zts_has_address(const uint64_t nwid)
|
||||
{
|
||||
// DEBUG_EXTRA();
|
||||
if (ZeroTier::zt1Service) {
|
||||
uint64_t nwid_int = strtoull(nwid, NULL, 16);
|
||||
ZeroTier::VirtualTap *tap = getTapByNWID(nwid_int);
|
||||
if (tap && tap->_ips.size()) {
|
||||
for (size_t i=0; i<tap->_ips.size(); i++) {
|
||||
if (tap->_ips[i].isV6()) {
|
||||
char ipbuf[INET6_ADDRSTRLEN];
|
||||
std::string addr = tap->_ips[i].toString(ipbuf);
|
||||
int len = addrlen < addr.length() ? addrlen : addr.length();
|
||||
memset(addrstr, 0, len);
|
||||
memcpy(addrstr, addr.c_str(), len);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
memcpy(addrstr, "\0", 1);
|
||||
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;
|
||||
}
|
||||
|
||||
int zts_has_ipv4_address(const char *nwid)
|
||||
void zts_get_6plane_addr(struct sockaddr_storage *addr, const uint64_t nwid, const uint64_t nodeId)
|
||||
{
|
||||
// DEBUG_EXTRA();
|
||||
char ipv4_addr[INET_ADDRSTRLEN];
|
||||
memset(ipv4_addr, 0, INET_ADDRSTRLEN);
|
||||
zts_get_ipv4_address(nwid, ipv4_addr, INET_ADDRSTRLEN);
|
||||
return strcmp(ipv4_addr, "\0");
|
||||
ZeroTier::InetAddress _6planeAddr = ZeroTier::InetAddress::makeIpv66plane(nwid,nodeId);
|
||||
memcpy(addr, _6planeAddr.rawIpData(), sizeof(struct sockaddr_storage));
|
||||
}
|
||||
|
||||
int zts_has_ipv6_address(const char *nwid)
|
||||
void zts_get_rfc4193_addr(struct sockaddr_storage *addr, const uint64_t nwid, const uint64_t nodeId)
|
||||
{
|
||||
// DEBUG_EXTRA();
|
||||
char ipv6_addr[INET6_ADDRSTRLEN];
|
||||
memset(ipv6_addr, 0, INET6_ADDRSTRLEN);
|
||||
zts_get_ipv6_address(nwid, ipv6_addr, INET6_ADDRSTRLEN);
|
||||
return strcmp(ipv6_addr, "\0");
|
||||
ZeroTier::InetAddress _rfc4193Addr = ZeroTier::InetAddress::makeIpv6rfc4193(nwid,nodeId);
|
||||
memcpy(addr, _rfc4193Addr.rawIpData(), sizeof(struct sockaddr_storage));
|
||||
}
|
||||
|
||||
int zts_has_address(const char *nwid)
|
||||
{
|
||||
// DEBUG_EXTRA();
|
||||
return zts_has_ipv4_address(nwid) || zts_has_ipv6_address(nwid);
|
||||
}
|
||||
|
||||
void zts_get_6plane_addr(char *addr, const char *nwid, const char *devID)
|
||||
void zts_join(const uint64_t nwid)
|
||||
{
|
||||
DEBUG_EXTRA();
|
||||
ZeroTier::InetAddress _6planeAddr = ZeroTier::InetAddress::makeIpv66plane(
|
||||
ZeroTier::Utils::hexStrToU64(nwid),ZeroTier::Utils::hexStrToU64(devID));
|
||||
char ipbuf[INET6_ADDRSTRLEN];
|
||||
memcpy(addr, _6planeAddr.toIpString(ipbuf), 40);
|
||||
}
|
||||
|
||||
void zts_get_rfc4193_addr(char *addr, const char *nwid, const char *devID)
|
||||
{
|
||||
DEBUG_EXTRA();
|
||||
ZeroTier::InetAddress _6planeAddr = ZeroTier::InetAddress::makeIpv6rfc4193(
|
||||
ZeroTier::Utils::hexStrToU64(nwid),ZeroTier::Utils::hexStrToU64(devID));
|
||||
char ipbuf[INET6_ADDRSTRLEN];
|
||||
memcpy(addr, _6planeAddr.toIpString(ipbuf), 40);
|
||||
}
|
||||
|
||||
void zts_join(const char * nwid)
|
||||
{
|
||||
DEBUG_EXTRA();
|
||||
if (ZeroTier::zt1Service) {
|
||||
std::string confFile = ZeroTier::zt1Service->givenHomePath() + "/networks.d/" + nwid + ".conf";
|
||||
if (ZeroTier::OSUtils::mkdir(ZeroTier::netDir) == false) {
|
||||
DEBUG_ERROR("unable to create: %s", ZeroTier::netDir.c_str());
|
||||
handle_general_failure();
|
||||
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());
|
||||
handle_general_failure();
|
||||
}
|
||||
ZeroTier::zt1Service->join(nwid);
|
||||
zt1Service->join(nwid);
|
||||
}
|
||||
// provide ZTO service reference to virtual taps
|
||||
// TODO: This might prove to be unreliable, but it works for now
|
||||
for (size_t i=0;i<ZeroTier::vtaps.size(); i++) {
|
||||
ZeroTier::VirtualTap *s = (ZeroTier::VirtualTap*)ZeroTier::vtaps[i];
|
||||
s->zt1ServiceRef=(void*)ZeroTier::zt1Service;
|
||||
for (size_t i=0;i<vtaps.size(); i++) {
|
||||
VirtualTap *s = (VirtualTap*)vtaps[i];
|
||||
s->zt1ServiceRef=(void*)zt1Service;
|
||||
}
|
||||
}
|
||||
|
||||
void zts_join_soft(const char * filepath, const char * nwid)
|
||||
void zts_leave(const uint64_t nwid)
|
||||
{
|
||||
DEBUG_EXTRA();
|
||||
std::string net_dir = std::string(filepath) + "/networks.d/";
|
||||
std::string confFile = net_dir + std::string(nwid) + ".conf";
|
||||
if (ZeroTier::OSUtils::mkdir(net_dir) == false) {
|
||||
DEBUG_ERROR("unable to create: %s", net_dir.c_str());
|
||||
handle_general_failure();
|
||||
}
|
||||
if (ZeroTier::OSUtils::fileExists(confFile.c_str(), false) == false) {
|
||||
if (ZeroTier::OSUtils::writeFile(confFile.c_str(), "") == false) {
|
||||
DEBUG_ERROR("unable to write network conf file: %s", confFile.c_str());
|
||||
handle_general_failure();
|
||||
}
|
||||
if (zt1Service) {
|
||||
zt1Service->leave(nwid);
|
||||
}
|
||||
}
|
||||
|
||||
void zts_leave(const char * nwid)
|
||||
int zts_running()
|
||||
{
|
||||
DEBUG_EXTRA();
|
||||
if (ZeroTier::zt1Service) {
|
||||
ZeroTier::zt1Service->leave(nwid);
|
||||
}
|
||||
}
|
||||
|
||||
void zts_leave_soft(const char * filepath, const char * nwid)
|
||||
{
|
||||
DEBUG_EXTRA();
|
||||
std::string net_dir = std::string(filepath) + "/networks.d/";
|
||||
ZeroTier::OSUtils::rm((net_dir + nwid + ".conf").c_str());
|
||||
}
|
||||
|
||||
int zts_running()
|
||||
{
|
||||
DEBUG_EXTRA();
|
||||
return ZeroTier::zt1Service == NULL ? false : ZeroTier::zt1Service->isRunning();
|
||||
return zt1Service == NULL ? false : zt1Service->isRunning();
|
||||
}
|
||||
|
||||
int zts_start(const char *path, bool blocking = false)
|
||||
{
|
||||
DEBUG_EXTRA();
|
||||
if (ZeroTier::zt1Service) {
|
||||
if (zt1Service) {
|
||||
return 0; // already initialized, ok
|
||||
}
|
||||
if (path) {
|
||||
ZeroTier::homeDir = path;
|
||||
homeDir = path;
|
||||
}
|
||||
#if defined(__MINGW32__) || defined(__MINGW64__)
|
||||
WSAStartup(MAKEWORD(2, 2), &wsaData); // initialize WinSock. Used in Phy for loopback pipe
|
||||
@@ -426,21 +352,21 @@ 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 || ZeroTier::zt1Service->getNode() == NULL) {
|
||||
while (zts_running() == false || zt1Service->getNode() == NULL) {
|
||||
nanosleep((const struct timespec[]) {{0, (ZTO_WRAPPER_CHECK_INTERVAL * 500000)}}, NULL);
|
||||
}
|
||||
while (ZeroTier::zt1Service->getNode()->address() <= 0) {
|
||||
while (zt1Service->getNode()->address() <= 0) {
|
||||
nanosleep((const struct timespec[]) {{0, (ZTO_WRAPPER_CHECK_INTERVAL * 500000)}}, NULL);
|
||||
}
|
||||
while (status.online <= 0) {
|
||||
nanosleep((const struct timespec[]) {{0, (ZTO_WRAPPER_CHECK_INTERVAL * 500000)}}, NULL);
|
||||
ZeroTier::zt1Service->getNode()->status(&status);
|
||||
zt1Service->getNode()->status(&status);
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int zts_startjoin(const char *path, const char *nwid)
|
||||
int zts_startjoin(const char *path, const uint64_t nwid)
|
||||
{
|
||||
DEBUG_EXTRA();
|
||||
int err = zts_start(path, true);
|
||||
@@ -452,7 +378,6 @@ int zts_startjoin(const char *path, const char *nwid)
|
||||
}
|
||||
catch( ... ) {
|
||||
DEBUG_ERROR("there was a problem joining the virtual network %s", nwid);
|
||||
handle_general_failure();
|
||||
}
|
||||
}
|
||||
while (zts_has_address(nwid) == false) {
|
||||
@@ -461,67 +386,53 @@ int zts_startjoin(const char *path, const char *nwid)
|
||||
return err;
|
||||
}
|
||||
|
||||
void zts_stop()
|
||||
void zts_stop()
|
||||
{
|
||||
DEBUG_EXTRA();
|
||||
if (ZeroTier::zt1Service) {
|
||||
ZeroTier::zt1Service->terminate();
|
||||
disableTaps();
|
||||
if (zt1Service) {
|
||||
zt1Service->terminate();
|
||||
// disableTaps();
|
||||
}
|
||||
#if defined(__MINGW32__) || defined(__MINGW64__)
|
||||
WSACleanup(); // clean up WinSock
|
||||
#endif
|
||||
}
|
||||
|
||||
void zts_get_homepath(char *homePath, size_t len)
|
||||
void zts_get_homepath(char *homePath, size_t len)
|
||||
{
|
||||
DEBUG_EXTRA();
|
||||
if (ZeroTier::homeDir.length()) {
|
||||
if (homeDir.length()) {
|
||||
memset(homePath, 0, len);
|
||||
size_t buf_len = len < ZeroTier::homeDir.length() ? len : ZeroTier::homeDir.length();
|
||||
memcpy(homePath, ZeroTier::homeDir.c_str(), buf_len);
|
||||
size_t buf_len = len < homeDir.length() ? len : homeDir.length();
|
||||
memcpy(homePath, homeDir.c_str(), buf_len);
|
||||
}
|
||||
}
|
||||
|
||||
int zts_get_id(char *devID)
|
||||
uint64_t zts_get_node_id()
|
||||
{
|
||||
DEBUG_EXTRA();
|
||||
if (ZeroTier::zt1Service) {
|
||||
char id[ZTO_ID_LEN];
|
||||
sprintf(id, "%lx",ZeroTier::zt1Service->getNode()->address());
|
||||
memcpy(devID, id, ZTO_ID_LEN);
|
||||
return 0;
|
||||
}
|
||||
else // Service isn't online, try to read ID from file
|
||||
{
|
||||
std::string fname("identity.public");
|
||||
std::string fpath(ZeroTier::homeDir);
|
||||
if (ZeroTier::OSUtils::fileExists((fpath + ZT_PATH_SEPARATOR_S + fname).c_str(),false)) {
|
||||
std::string oldid;
|
||||
ZeroTier::OSUtils::readFile((fpath + ZT_PATH_SEPARATOR_S + fname).c_str(),oldid);
|
||||
memcpy(devID, oldid.c_str(), ZTO_ID_LEN); // first 10 bytes of file
|
||||
return 0;
|
||||
}
|
||||
if (zt1Service) {
|
||||
return zt1Service->getNode()->address();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned long zts_get_peer_count()
|
||||
unsigned long zts_get_peer_count()
|
||||
{
|
||||
DEBUG_EXTRA();
|
||||
if (ZeroTier::zt1Service) {
|
||||
return ZeroTier::zt1Service->getNode()->peers()->peerCount;
|
||||
if (zt1Service) {
|
||||
return zt1Service->getNode()->peers()->peerCount;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int zts_get_peer_address(char *peer, const char *devID)
|
||||
int zts_get_peer_address(char *peer, const uint64_t nodeId)
|
||||
{
|
||||
DEBUG_EXTRA();
|
||||
if (ZeroTier::zt1Service) {
|
||||
ZT_PeerList *pl = ZeroTier::zt1Service->getNode()->peers();
|
||||
if (zt1Service) {
|
||||
ZT_PeerList *pl = zt1Service->getNode()->peers();
|
||||
// uint64_t addr;
|
||||
for (size_t i=0; i<pl->peerCount; i++) {
|
||||
// ZT_Peer *p = &(pl->peers[i]);
|
||||
@@ -539,6 +450,37 @@ void zts_allow_http_control(bool allowed)
|
||||
// TODO
|
||||
}
|
||||
|
||||
bool _ipv6_in_subnet(ZeroTier::InetAddress *subnet, ZeroTier::InetAddress *addr)
|
||||
{
|
||||
ZeroTier::InetAddress r(addr);
|
||||
ZeroTier::InetAddress b(subnet);
|
||||
const unsigned int bits = subnet->netmaskBits();
|
||||
switch(r.ss_family) {
|
||||
case AF_INET:
|
||||
reinterpret_cast<struct sockaddr_in *>(&r)->sin_addr.s_addr &= ZeroTier::Utils::hton((uint32_t)(0xffffffff << (32 - bits)));
|
||||
break;
|
||||
case AF_INET6: {
|
||||
uint64_t nm[2];
|
||||
uint64_t nm2[2];
|
||||
memcpy(nm,reinterpret_cast<struct sockaddr_in6 *>(&r)->sin6_addr.s6_addr,16);
|
||||
memcpy(nm2,reinterpret_cast<struct sockaddr_in6 *>(&b)->sin6_addr.s6_addr,16);
|
||||
|
||||
nm[0] &= ZeroTier::Utils::hton((uint64_t)((bits >= 64) ? 0xffffffffffffffffULL : (0xffffffffffffffffULL << (64 - bits))));
|
||||
nm[1] &= ZeroTier::Utils::hton((uint64_t)((bits <= 64) ? 0ULL : (0xffffffffffffffffULL << (128 - bits))));
|
||||
|
||||
nm2[0] &= ZeroTier::Utils::hton((uint64_t)((bits >= 64) ? 0xffffffffffffffffULL : (0xffffffffffffffffULL << (64 - bits))));
|
||||
nm2[1] &= ZeroTier::Utils::hton((uint64_t)((bits <= 64) ? 0ULL : (0xffffffffffffffffULL << (128 - bits))));
|
||||
|
||||
memcpy(reinterpret_cast<struct sockaddr_in6 *>(&r)->sin6_addr.s6_addr,nm,16);
|
||||
memcpy(reinterpret_cast<struct sockaddr_in6 *>(&b)->sin6_addr.s6_addr,nm2,16);
|
||||
}
|
||||
break;
|
||||
}
|
||||
char b0[64], b1[64];
|
||||
memset(b0, 0, 64);
|
||||
memset(b1, 0, 64);
|
||||
return !strcmp(r.toIpString(b0), b.toIpString(b1));
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
1068
src/libzt.cpp
1068
src/libzt.cpp
File diff suppressed because it is too large
Load Diff
333
src/libztJNI.cpp
333
src/libztJNI.cpp
@@ -28,11 +28,9 @@
|
||||
* @file
|
||||
*
|
||||
* Javs JNI wrapper for partially-POSIX-compliant socket API
|
||||
* JNI naming convention: Java_PACKAGENAME_CLASSNAME_METHODNAME
|
||||
* JNI naming convention: Java_PACKAGENAME_CLASSNAME_METHODNAME
|
||||
*/
|
||||
|
||||
#if defined(SDK_JNI)
|
||||
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "libzt.h"
|
||||
@@ -50,14 +48,14 @@ namespace ZeroTier {
|
||||
/* ZeroTier Socket API (for JNI wrapper) */
|
||||
/****************************************************************************/
|
||||
|
||||
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_socket(JNIEnv *env, jobject thisObj,
|
||||
jint family, jint type, jint protocol)
|
||||
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, jstring addrstr, jint port)
|
||||
{
|
||||
struct sockaddr_storage ss;
|
||||
socklen_t namelen = sizeof(ss);
|
||||
@@ -91,8 +89,41 @@ namespace ZeroTier {
|
||||
return zts_connect(fd, (struct sockaddr *)&ss, sizeof(in_addr));
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_bind(JNIEnv *env, jobject thisObj,
|
||||
jint fd, jstring addrstr, jint port)
|
||||
/*
|
||||
|
||||
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, "<init>", "()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, "<init>", "()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)
|
||||
{
|
||||
struct sockaddr_storage ss;
|
||||
socklen_t namelen = sizeof(ss);
|
||||
@@ -125,10 +156,132 @@ namespace ZeroTier {
|
||||
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;
|
||||
}
|
||||
// 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; i<strlen(addr_str); i++) {
|
||||
if(addr_str[i]=='.') {
|
||||
DEBUG_INFO("ipv4, inet_addr");
|
||||
socket_family = AF_INET;
|
||||
in4->sin_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);
|
||||
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)
|
||||
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;
|
||||
@@ -141,8 +294,8 @@ namespace ZeroTier {
|
||||
}
|
||||
#endif
|
||||
|
||||
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_accept(JNIEnv *env, jobject thisObj,
|
||||
jint fd, jstring addrstr, jint port)
|
||||
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
|
||||
@@ -152,14 +305,14 @@ namespace ZeroTier {
|
||||
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_close(JNIEnv *env, jobject thisObj,
|
||||
jint fd)
|
||||
{
|
||||
return zts_close(fd);
|
||||
}
|
||||
@@ -168,20 +321,23 @@ namespace ZeroTier {
|
||||
JNIEnv *env, jobject thisObj, jint fd, jarray buf, jint len, jint flags, jobject ztaddr)
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
jclass cls = (*env).GetObjectClass( ztaddr);
|
||||
jfieldID f = (*env).GetFieldID( cls, "port", "I");
|
||||
addr.sin_port = htons((*env).GetIntField( ztaddr, f));
|
||||
f = (*env).GetFieldID( cls, "_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
|
||||
int sent_bytes = zts_sendto(fd, body, len, flags, (struct sockaddr *)&addr, sizeof(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));
|
||||
}
|
||||
return sent_bytes;
|
||||
}
|
||||
|
||||
@@ -193,16 +349,19 @@ namespace ZeroTier {
|
||||
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)
|
||||
if (rxbytes > 0) {
|
||||
memcpy(body, (jbyte*)buffer + payload_offset, rxbytes);
|
||||
}
|
||||
(*env).ReleaseByteArrayElements( buf, body, 0);
|
||||
// Update fields of Java ZTAddress object
|
||||
jfieldID fid;
|
||||
jclass cls = (*env).GetObjectClass( ztaddr);
|
||||
fid = (*env).GetFieldID( cls, "port", "I");
|
||||
(*env).SetIntField( ztaddr, fid, addr.sin_port);
|
||||
fid = (*env).GetFieldID( cls,"_rawAddr", "J");
|
||||
(*env).SetLongField( ztaddr, fid,addr.sin_addr.s_addr);
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -216,7 +375,7 @@ namespace ZeroTier {
|
||||
return written_bytes;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_write(JNIEnv *env, jobject thisObj,
|
||||
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_write(JNIEnv *env, jobject thisObj,
|
||||
jint fd, jarray buf, jint len)
|
||||
{
|
||||
jbyte *body = (*env).GetByteArrayElements((_jbyteArray *)buf, 0);
|
||||
@@ -227,7 +386,7 @@ namespace ZeroTier {
|
||||
return written_bytes;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_read(JNIEnv *env, jobject thisObj,
|
||||
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_read(JNIEnv *env, jobject thisObj,
|
||||
jint fd, jarray buf, jint len)
|
||||
{
|
||||
jbyte *body = (*env).GetByteArrayElements((_jbyteArray *)buf, 0);
|
||||
@@ -237,48 +396,52 @@ namespace ZeroTier {
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_getsockname(JNIEnv *env, jobject thisObj,
|
||||
jint fd, jobject ztaddr)
|
||||
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_getsockname(JNIEnv *env, jobject thisObj,
|
||||
jint fd, jobject ztaddr)
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
int err = zts_getsockname(fd, (struct sockaddr *)&addr, (socklen_t *)sizeof(struct sockaddr));
|
||||
jfieldID fid;
|
||||
jclass cls = (*env).GetObjectClass(ztaddr);
|
||||
fid = (*env).GetFieldID( cls, "port", "I");
|
||||
(*env).SetIntField( ztaddr, fid, addr.sin_port);
|
||||
fid = (*env).GetFieldID( cls,"_rawAddr", "J");
|
||||
(*env).SetLongField( ztaddr, fid,addr.sin_addr.s_addr);
|
||||
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 err;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_getpeername(JNIEnv *env, jobject thisObj,
|
||||
jint fd, jobject ztaddr)
|
||||
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_getpeername(JNIEnv *env, jobject thisObj,
|
||||
jint fd, jobject ztaddr)
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
int err = zts_getpeername(fd, (struct sockaddr *)&addr, (socklen_t *)sizeof(struct sockaddr));
|
||||
jfieldID fid;
|
||||
jclass cls = (*env).GetObjectClass( ztaddr);
|
||||
fid = (*env).GetFieldID( cls, "port", "I");
|
||||
(*env).SetIntField( ztaddr, fid, addr.sin_port);
|
||||
fid = (*env).GetFieldID( cls,"_rawAddr", "J");
|
||||
(*env).SetLongField( ztaddr, fid,addr.sin_addr.s_addr);
|
||||
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 err;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_fcntl(JNIEnv *env, jobject thisObj,
|
||||
jint fd, jint cmd, jint flags)
|
||||
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_fcntl(JNIEnv *env, jobject thisObj,
|
||||
jint fd, jint cmd, jint flags)
|
||||
{
|
||||
return zts_fcntl(fd,cmd,flags);
|
||||
}
|
||||
@@ -287,21 +450,21 @@ namespace ZeroTier {
|
||||
/* ZeroTier service controls (for JNI wrapper) */
|
||||
/****************************************************************************/
|
||||
|
||||
JNIEXPORT void JNICALL Java_zerotier_ZeroTier_start(JNIEnv *env, jobject thisObj, jstring path, jboolean blocking)
|
||||
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, jstring nwid)
|
||||
JNIEXPORT void JNICALL Java_zerotier_ZeroTier_startjoin(JNIEnv *env, jobject thisObj, jstring path, jstring nwid)
|
||||
{
|
||||
if (path && nwid) {
|
||||
zts_startjoin(env->GetStringUTFChars(path, NULL), env->GetStringUTFChars(nwid, NULL));
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_zerotier_ZeroTier_stop(JNIEnv *env, jobject thisObj)
|
||||
JNIEXPORT void JNICALL Java_zerotier_ZeroTier_stop(JNIEnv *env, jobject thisObj)
|
||||
{
|
||||
zts_stop();
|
||||
}
|
||||
@@ -309,17 +472,17 @@ namespace ZeroTier {
|
||||
JNIEXPORT jboolean JNICALL Java_zerotier_ZeroTier_running(
|
||||
JNIEnv *env, jobject thisObj)
|
||||
{
|
||||
return zts_running();
|
||||
return zts_running();
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_zerotier_ZeroTier_join(JNIEnv *env, jobject thisObj, jstring nwid)
|
||||
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)
|
||||
JNIEXPORT void JNICALL Java_zerotier_ZeroTier_leave(JNIEnv *env, jobject thisObj, jstring nwid)
|
||||
{
|
||||
if (nwid) {
|
||||
zts_leave(env->GetStringUTFChars(nwid, NULL));
|
||||
@@ -334,32 +497,22 @@ namespace ZeroTier {
|
||||
return (*env).NewStringUTF("");
|
||||
}
|
||||
|
||||
JNIEXPORT jobject JNICALL Java_zerotier_ZeroTier_get_ipv4_address(
|
||||
JNIEXPORT jobject JNICALL Java_zerotier_ZeroTier_get_address(
|
||||
JNIEnv *env, jobject thisObj, jstring nwid)
|
||||
{
|
||||
// get address
|
||||
const char *nwid_str = env->GetStringUTFChars(nwid, NULL);
|
||||
char address_string[INET_ADDRSTRLEN];
|
||||
memset(address_string, 0, INET_ADDRSTRLEN);
|
||||
zts_get_ipv4_address(nwid_str, address_string, INET_ADDRSTRLEN);
|
||||
jclass clazz = (*env).FindClass("java/util/ArrayList");
|
||||
jobject addresses = (*env).NewObject(clazz, (*env).GetMethodID(clazz, "<init>", "()V"));
|
||||
jstring _str = (*env).NewStringUTF(address_string);
|
||||
env->CallBooleanMethod(addresses, env->GetMethodID(clazz, "add", "(Ljava/lang/Object;)Z"), _str);
|
||||
return addresses;
|
||||
}
|
||||
|
||||
JNIEXPORT jobject JNICALL Java_zerotier_ZeroTier_get_ipv6_address(
|
||||
JNIEnv *env, jobject thisObj, jstring nwid)
|
||||
{
|
||||
const char *nwid_str = env->GetStringUTFChars(nwid, NULL);
|
||||
char address_string[INET6_ADDRSTRLEN];
|
||||
memset(address_string, 0, INET6_ADDRSTRLEN);
|
||||
zts_get_ipv6_address(nwid_str, address_string, INET6_ADDRSTRLEN);
|
||||
jclass clazz = (*env).FindClass("java/util/ArrayList");
|
||||
jobject addresses = (*env).NewObject(clazz, (*env).GetMethodID(clazz, "<init>", "()V"));
|
||||
jstring _str = (*env).NewStringUTF(address_string);
|
||||
env->CallBooleanMethod(addresses, env->GetMethodID(clazz, "add", "(Ljava/lang/Object;)Z"), _str);
|
||||
return addresses;
|
||||
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");
|
||||
if (c) {
|
||||
jobject addresses = (*env).NewObject(c, (*env).GetMethodID(c, "<init>", "()V"));
|
||||
env->CallBooleanMethod(addresses, env->GetMethodID(c, "add", "(Ljava/lang/Object;)Z"), _str);
|
||||
return addresses;
|
||||
}*/
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JNIEXPORT jint Java_zerotier_ZeroTier_get_id()
|
||||
@@ -368,8 +521,6 @@ namespace ZeroTier {
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SDK_JNI
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
1838
src/lwIP.cpp
1838
src/lwIP.cpp
File diff suppressed because it is too large
Load Diff
1979
src/picoTCP.cpp
Normal file
1979
src/picoTCP.cpp
Normal file
File diff suppressed because it is too large
Load Diff
15
test/dummy.cpp
Normal file
15
test/dummy.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "libzt.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
printf("Starting ZT service");
|
||||
zts_startjoin("ztp","17d709436c2c5367");
|
||||
|
||||
printf("Dummy. Going into infinite loop. Ping me or something\n");
|
||||
while(1) {
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
@@ -1938,15 +1938,12 @@ int ZT_control_semantics_test(bool *passed)
|
||||
int zts_get_id_from_file(const char *filepath, char *devID);
|
||||
void *zts_start_service(void *thread_id);
|
||||
void disableTaps();
|
||||
void zts_get_ipv4_address(const char *nwid, char *addrstr, const size_t addrlen);
|
||||
void zts_get_ipv6_address(const char *nwid, char *addrstr, const size_t addrlen);
|
||||
int zts_has_ipv4_address(const char *nwid);
|
||||
int zts_has_ipv6_address(const char *nwid);
|
||||
void zts_get_address(const char *nwid, struct sockaddr_storage *addr, const size_t addrlen);
|
||||
int zts_has_address(const char *nwid);
|
||||
void zts_get_6plane_addr(char *addr, const char *nwid, const char *devID);
|
||||
void zts_get_rfc4193_addr(char *addr, const char *nwid, const char *devID);
|
||||
void zts_join(const char * nwid);
|
||||
void zts_leave(const char * nwid);
|
||||
void zts_get_6plane_addr(struct sockaddr_storage *addr, const char *nwid, const char *devID);
|
||||
void zts_get_rfc4193_addr(struct sockaddr_storage *addr, const char *nwid, const char *devID);
|
||||
void zts_join(const uin64_t nwid);
|
||||
void zts_leave(const uint64_t nwid);
|
||||
int zts_running();
|
||||
int zts_start(const char *path);
|
||||
int zts_start(const char *path, const char *nwid);
|
||||
@@ -1958,8 +1955,8 @@ int ZT_control_semantics_test(bool *passed)
|
||||
*/
|
||||
|
||||
int n_times = 5;
|
||||
char *nwid = "17d709436c2c5367";
|
||||
char *path = "fake_path";
|
||||
char *nwid = (char*)"17d709436c2c5367";
|
||||
char *path = (char*)"fake_path";
|
||||
/*
|
||||
// Perform operations on ZeroTier before calling zts_start(). Doing this makes absolutely no sense but could happen
|
||||
zts_stop();
|
||||
@@ -1980,8 +1977,8 @@ int ZT_control_semantics_test(bool *passed)
|
||||
sleep(1);
|
||||
*/
|
||||
zts_start(path, false);
|
||||
zts_join(nwid);
|
||||
zts_leave(nwid);
|
||||
zts_join(strtoll(nwid,NULL,16));
|
||||
zts_leave(strtoll(nwid,NULL,16));
|
||||
zts_stop();
|
||||
|
||||
DEBUG_TEST("---\n");
|
||||
@@ -2000,12 +1997,8 @@ int ZT_control_semantics_test(bool *passed)
|
||||
for (int i=0; i<n_times; i++) { zts_stop(); }
|
||||
*/
|
||||
DEBUG_TEST("---\n");
|
||||
sleep(1);
|
||||
|
||||
|
||||
sleep(30); // wait for any aftermath
|
||||
*passed = true;
|
||||
DEBUG_TEST("PASSED");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define SLAM_NUMBER 16
|
||||
@@ -2668,9 +2661,12 @@ void bind_to_localhost_test(int port)
|
||||
int trigger_address_sanitizer()
|
||||
{
|
||||
// Deliberately create a bad read to trigger address sanitizer
|
||||
/*
|
||||
int stack_array[100];
|
||||
stack_array[1] = 0;
|
||||
return stack_array[1 + 100]; // BOOM
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
@@ -2692,7 +2688,7 @@ int main(int argc , char *argv[])
|
||||
std::vector<std::string> results;
|
||||
std::string remote_echo_ipv4, smode;
|
||||
|
||||
std::string nwid, stype;
|
||||
std::string nwidstr, stype;
|
||||
std::string ipstr, ipstr6, local_ipstr, local_ipstr6, remote_ipstr, remote_ipstr6;
|
||||
|
||||
int err = 0;
|
||||
@@ -2723,7 +2719,7 @@ int main(int argc , char *argv[])
|
||||
// get origin details
|
||||
local_ipstr = testConf[me + ".ipv4"];
|
||||
local_ipstr6 = testConf[me + ".ipv6"];
|
||||
nwid = testConf[me + ".nwid"];
|
||||
nwidstr = testConf[me + ".nwid"];
|
||||
path = testConf[me + ".path"];
|
||||
stype = testConf[me + ".test"];
|
||||
smode = testConf[me + ".mode"];
|
||||
@@ -2742,7 +2738,7 @@ int main(int argc , char *argv[])
|
||||
fprintf(stderr, "\tlocal_ipstr6 = %s\n", local_ipstr6.c_str());
|
||||
fprintf(stderr, "\tstart_port = %d\n", start_port);
|
||||
fprintf(stderr, "\tpath = %s\n", path.c_str());
|
||||
fprintf(stderr, "\tnwid = %s\n", nwid.c_str());
|
||||
fprintf(stderr, "\tnwid = %s\n", nwidstr.c_str());
|
||||
fprintf(stderr, "\ttype = %s\n\n", stype.c_str());
|
||||
fprintf(stderr, "DESTINATION:\n\n");
|
||||
fprintf(stderr, "\tremote_ipstr = %s\n", remote_ipstr.c_str());
|
||||
@@ -2753,10 +2749,10 @@ int main(int argc , char *argv[])
|
||||
if (me != "dummy") { // used for testing ZT service wrapper API (before, during, and after coming online)
|
||||
// set start time here since we need to wait for both libzt instances to be online
|
||||
DEBUG_TEST("app-thread, waiting for libzt to come online...\n");
|
||||
zts_startjoin(path.c_str(), nwid.c_str());
|
||||
char device_id[ZTO_ID_LEN];
|
||||
zts_get_id(device_id);
|
||||
DEBUG_TEST("I am %s, %s", device_id, me.c_str());
|
||||
uint64_t nwid = strtoll(nwidstr.c_str(),NULL,16);
|
||||
zts_startjoin(path.c_str(), nwid);
|
||||
uint64_t nodeId = zts_get_node_id();
|
||||
DEBUG_TEST("I am %x, %s", nodeId, me.c_str());
|
||||
if (mode == TEST_MODE_SERVER) {
|
||||
DEBUG_TEST("Ready. You should start selftest program on second host now...\n\n");
|
||||
}
|
||||
|
||||
2
zto
2
zto
Submodule zto updated: ee4783e3fb...e5d1243dd2
Reference in New Issue
Block a user