Preparation for C--, removed classes, namespaces, advanced build options are now controlled via include/libztDefs.h

This commit is contained in:
Joseph Henry
2017-11-06 13:50:20 -08:00
parent 920afa079e
commit e0d4b84dd4
65 changed files with 12208 additions and 2609 deletions

124
Makefile
View File

@@ -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

View File

@@ -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.

View File

@@ -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)

View File

@@ -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);

View File

@@ -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() {

View File

@@ -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()

View File

@@ -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()

View File

@@ -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();

View File

@@ -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();

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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);

View File

@@ -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:

View File

@@ -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>

View File

@@ -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
View 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
View File

@@ -0,0 +1,4 @@
picotcp-bsd
===========
BSD POSIX-compliant socket support for PicoTCP running on any OS.

File diff suppressed because it is too large Load Diff

View 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_ */

View 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
View 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_ */

View 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();
}

View 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());
}

View 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);
}

View 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;
}

View File

@@ -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;

View File

@@ -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 */

View File

@@ -25,7 +25,7 @@
#include "pico_ethernet.h"
#include "pico_mcast.h"
#include "../../../include/Debug.hpp"
#include "../../../include/libztDebug.h"
#ifdef PICO_SUPPORT_IPV4

View File

@@ -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

View File

@@ -10,7 +10,7 @@
#include "pico_protocol.h"
#include "pico_tree.h"
#include "../../../include/Debug.hpp"
#include "../../../include/libztDebug.h"
struct pico_proto_rr
{

View File

@@ -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)

View File

@@ -33,7 +33,7 @@
#include "pico_socket.h"
#include "heap.h"
#include "../../../include/Debug.hpp"
#include "../../../include/libztDebug.h"
/* Mockables */
#if defined UNIT_TEST

View File

@@ -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.

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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
}

View File

@@ -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
}

View 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
View 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

View File

@@ -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
}

View File

@@ -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
/**

View File

@@ -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

View File

@@ -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
View 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

View File

@@ -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

View File

@@ -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
View 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

View File

@@ -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
View 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();
}

View File

@@ -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

View File

@@ -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

View File

@@ -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))
);
}
*/

View File

@@ -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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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

File diff suppressed because it is too large Load Diff

1979
src/picoTCP.cpp Normal file

File diff suppressed because it is too large Load Diff

15
test/dummy.cpp Normal file
View 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);
}
}

View File

@@ -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

Submodule zto updated: ee4783e3fb...e5d1243dd2