Managed Routes now supported, with automatic add/remove

This commit is contained in:
Joseph Henry
2017-08-14 11:25:44 -07:00
parent 0098842b09
commit 8e192c0ee8
20 changed files with 596 additions and 299 deletions

1
.gitignore vendored
View File

@@ -21,6 +21,7 @@ zt3
zt4
zt5
zt6
objs
*.bob
*.alice

48
Jenkinsfile vendored
View File

@@ -16,7 +16,7 @@ parallel 'centos7': {
checkout scm
sh 'git submodule update --init'
stage('linux static lib, no stack') {
sh 'make static_lib NO_STACK=1; make tests'
sh 'make clean; make static_lib NO_STACK=1; make tests'
}
}
catch (err) {
@@ -30,7 +30,7 @@ parallel 'centos7': {
checkout scm
sh 'git submodule update --init'
stage('linux static lib, no stack, ipv4') {
sh 'make static_lib NO_STACK=1 LIBZT_IPV4=1; make tests'
sh 'make clean; make static_lib NO_STACK=1 LIBZT_IPV4=1; make tests'
}
}
catch (err) {
@@ -44,7 +44,7 @@ parallel 'centos7': {
checkout scm
sh 'git submodule update --init'
stage('linux static lib, no stack, ipv6') {
sh 'make static_lib NO_STACK=1 LIBZT_IPV6=1; make tests'
sh 'make clean; make static_lib NO_STACK=1 LIBZT_IPV6=1; make tests'
}
}
catch (err) {
@@ -58,7 +58,7 @@ parallel 'centos7': {
checkout scm
sh 'git submodule update --init'
stage('linux static lib, no stack, ipv4, ipv6') {
sh 'make static_lib NO_STACK=1 LIBZT_IPV4=1 LIBZT_IPV6=1; make tests'
sh 'make clean; make static_lib NO_STACK=1 LIBZT_IPV4=1 LIBZT_IPV6=1; make tests'
}
}
catch (err) {
@@ -74,7 +74,7 @@ parallel 'centos7': {
checkout scm
sh 'git submodule update --init'
stage('linux static lib, picoTCP') {
sh 'make static_lib STACK_PICO=1; make tests'
sh 'make clean; make static_lib STACK_PICO=1; make tests'
}
}
catch (err) {
@@ -88,7 +88,7 @@ parallel 'centos7': {
checkout scm
sh 'git submodule update --init'
stage('linux static lib, picoTCP, ipv4') {
sh 'make static_lib STACK_PICO=1 LIBZT_IPV4=1; make tests'
sh 'make clean; make static_lib STACK_PICO=1 LIBZT_IPV4=1; make tests'
}
}
catch (err) {
@@ -102,7 +102,7 @@ parallel 'centos7': {
checkout scm
sh 'git submodule update --init'
stage('linux static lib, picoTCP, ipv6') {
sh 'make static_lib STACK_PICO=1 LIBZT_IPV6=1; make tests'
sh 'make clean; make static_lib STACK_PICO=1 LIBZT_IPV6=1; make tests'
}
}
catch (err) {
@@ -116,7 +116,7 @@ parallel 'centos7': {
checkout scm
sh 'git submodule update --init'
stage('linux static lib, picoTCP, ipv4, ipv6') {
sh 'make static_lib STACK_PICO=1 LIBZT_IPV4=1 LIBZT_IPV6=1; make tests'
sh 'make clean; make static_lib STACK_PICO=1 LIBZT_IPV4=1 LIBZT_IPV6=1; make tests'
}
}
catch (err) {
@@ -133,7 +133,7 @@ parallel 'centos7': {
checkout scm
sh 'git submodule update --init'
stage('linux static lib lwIP') {
sh 'make static_lib STACK_LWIP=1; make tests'
sh 'make clean; make static_lib STACK_LWIP=1; make tests'
}
}
catch (err) {
@@ -148,7 +148,7 @@ parallel 'centos7': {
checkout scm
sh 'git submodule update --init'
stage('linux static lib lwIP, ipv4') {
sh 'make static_lib STACK_LWIP=1 LIBZT_IPV4=1; make tests'
sh 'make clean; make static_lib STACK_LWIP=1 LIBZT_IPV4=1; make tests'
}
}
catch (err) {
@@ -163,7 +163,7 @@ parallel 'centos7': {
checkout scm
sh 'git submodule update --init'
stage('linux static lib lwIP, ipv6') {
sh 'make static_lib STACK_LWIP=1 LIBZT_IPV6=1; make tests'
sh 'make clean; make static_lib STACK_LWIP=1 LIBZT_IPV6=1; make tests'
}
}
catch (err) {
@@ -178,7 +178,7 @@ parallel 'centos7': {
checkout scm
sh 'git submodule update --init'
stage('linux static lib lwIP, ipv4, ipv6') {
sh 'make static_lib STACK_LWIP=1 LIBZT_IPV4=1 LIBZT_IPV6=1; make tests'
sh 'make clean; make clean; make static_lib STACK_LWIP=1 LIBZT_IPV4=1 LIBZT_IPV6=1; make tests'
}
}
catch (err) {
@@ -214,7 +214,7 @@ parallel 'centos7': {
checkout scm
sh 'git submodule update --init'
stage('macOS static lib, no stack') {
sh 'make static_lib NO_STACK=1; make tests'
sh 'make clean; make static_lib NO_STACK=1; make tests'
}
}
catch (err) {
@@ -228,7 +228,7 @@ parallel 'centos7': {
checkout scm
sh 'git submodule update --init'
stage('macOS static lib, no stack, ipv4') {
sh 'make static_lib NO_STACK=1 LIBZT_IPV4=1; make tests'
sh 'make clean; make static_lib NO_STACK=1 LIBZT_IPV4=1; make tests'
}
}
catch (err) {
@@ -242,7 +242,7 @@ parallel 'centos7': {
checkout scm
sh 'git submodule update --init'
stage('macOS static lib, no stack, ipv6') {
sh 'make static_lib NO_STACK=1 LIBZT_IPV6=1'; make tests
sh 'make clean; make static_lib NO_STACK=1 LIBZT_IPV6=1'; make tests
}
}
catch (err) {
@@ -256,7 +256,7 @@ parallel 'centos7': {
checkout scm
sh 'git submodule update --init'
stage('macOS static lib, no stack, ipv4, ipv6') {
sh 'make static_lib NO_STACK=1 LIBZT_IPV4=1 LIBZT_IPV6=1; make tests'
sh 'make clean; make static_lib NO_STACK=1 LIBZT_IPV4=1 LIBZT_IPV6=1; make tests'
}
}
catch (err) {
@@ -271,7 +271,7 @@ parallel 'centos7': {
checkout scm
sh 'git submodule update --init'
stage('macOS static lib, picoTCP') {
sh 'make static_lib STACK_PICO=1; make tests'
sh 'make clean; make static_lib STACK_PICO=1; make tests'
}
}
catch (err) {
@@ -285,7 +285,7 @@ parallel 'centos7': {
checkout scm
sh 'git submodule update --init'
stage('macOS static lib, picoTCP, ipv4') {
sh 'make static_lib STACK_PICO=1 LIBZT_IPV4=1; make tests'
sh 'make clean; make static_lib STACK_PICO=1 LIBZT_IPV4=1; make tests'
}
}
catch (err) {
@@ -299,7 +299,7 @@ parallel 'centos7': {
checkout scm
sh 'git submodule update --init'
stage('macOS static lib, picoTCP, ipv6') {
sh 'make static_lib STACK_PICO=1 LIBZT_IPV6=1; make tests'
sh 'make clean; make static_lib STACK_PICO=1 LIBZT_IPV6=1; make tests'
}
}
catch (err) {
@@ -313,7 +313,7 @@ parallel 'centos7': {
checkout scm
sh 'git submodule update --init'
stage('macOS static lib, picoTCP, ipv4, ipv6') {
sh 'make static_lib STACK_PICO=1 LIBZT_IPV4=1 LIBZT_IPV6=1'; make tests
sh 'make clean; make static_lib STACK_PICO=1 LIBZT_IPV4=1 LIBZT_IPV6=1'; make tests
}
}
catch (err) {
@@ -330,7 +330,7 @@ parallel 'centos7': {
checkout scm
sh 'git submodule update --init'
stage('macOS static lib, lwIP') {
sh 'make static_lib STACK_LWIP=1; make tests'
sh 'make clean; make static_lib STACK_LWIP=1; make tests'
}
}
catch (err) {
@@ -344,7 +344,7 @@ parallel 'centos7': {
checkout scm
sh 'git submodule update --init'
stage('macOS static lib, lwIP, ipv4') {
sh 'make static_lib STACK_LWIP=1 LIBZT_IPV4=1; make tests'
sh 'make clean; make static_lib STACK_LWIP=1 LIBZT_IPV4=1; make tests'
}
}
catch (err) {
@@ -358,7 +358,7 @@ parallel 'centos7': {
checkout scm
sh 'git submodule update --init'
stage('macOS static lib, lwIP, ipv6') {
sh 'make static_lib STACK_LWIP=1 LIBZT_IPV6=1; make tests'
sh 'make clean; make static_lib STACK_LWIP=1 LIBZT_IPV6=1; make tests'
}
}
catch (err) {
@@ -372,7 +372,7 @@ parallel 'centos7': {
checkout scm
sh 'git submodule update --init'
stage('macOS static lib, lwIP, ipv4, ipv6') {
sh 'make static_lib STACK_LWIP=1 LIBZT_IPV4=1 LIBZT_IPV6=1; make tests'
sh 'make clean; make static_lib STACK_LWIP=1 LIBZT_IPV4=1 LIBZT_IPV6=1; make tests'
}
}
catch (err) {

View File

@@ -1159,7 +1159,7 @@ static int pico_ipv4_frame_sock_push(struct pico_protocol *self, struct pico_fra
}
int MOCKABLE pico_ipv4_route_add(struct pico_ip4 address, struct pico_ip4 netmask, struct pico_ip4 gateway, int metric, struct pico_ipv4_link *link)
extern int MOCKABLE pico_ipv4_route_add(struct pico_ip4 address, struct pico_ip4 netmask, struct pico_ip4 gateway, int metric, struct pico_ipv4_link *link)
{
struct pico_ipv4_route test, *new;
test.dest.addr = address.addr;

View File

@@ -94,6 +94,10 @@ extern "C" {
#endif
int pico_ipv4_link_add(struct pico_device *dev, struct pico_ip4 address, struct pico_ip4 netmask);
int pico_string_to_ipv4(const char *ipstr, uint32_t *ip);
int pico_ipv4_route_add(struct pico_ip4 address, struct pico_ip4 netmask, struct pico_ip4 gateway, int metric, struct pico_ipv4_link *link);
int pico_ipv4_route_del(struct pico_ip4 address, struct pico_ip4 netmask, int metric);
struct pico_ip4 pico_ipv4_route_get_gateway(struct pico_ip4 *addr);
void pico_ipv4_route_set_bcast_link(struct pico_ipv4_link *link);
#ifdef __cplusplus
}
#endif
@@ -108,10 +112,6 @@ struct pico_ipv4_link *pico_ipv4_link_by_dev_next(struct pico_device *dev, struc
struct pico_device *pico_ipv4_link_find(struct pico_ip4 *address);
struct pico_ip4 *pico_ipv4_source_find(const struct pico_ip4 *dst);
struct pico_device *pico_ipv4_source_dev_find(const struct pico_ip4 *dst);
int pico_ipv4_route_add(struct pico_ip4 address, struct pico_ip4 netmask, struct pico_ip4 gateway, int metric, struct pico_ipv4_link *link);
int pico_ipv4_route_del(struct pico_ip4 address, struct pico_ip4 netmask, int metric);
struct pico_ip4 pico_ipv4_route_get_gateway(struct pico_ip4 *addr);
void pico_ipv4_route_set_bcast_link(struct pico_ipv4_link *link);
void pico_ipv4_unreachable(struct pico_frame *f, int err);
int pico_ipv4_mcast_join(struct pico_ip4 *mcast_link, struct pico_ip4 *mcast_group, uint8_t reference_count, uint8_t filter_mode, struct pico_tree *MCASTFilter);

View File

@@ -32,6 +32,11 @@
#include <net/if.h>
#include <stdlib.h>
#include <stdint.h>
#include <vector>
#include "ZeroTierOne.h"
// See test/selftest.cpp for examples
/****************************************************************************/
/* For SOCK_RAW support, it will initially be modeled after linux's API, so */
@@ -463,6 +468,11 @@ int zts_write(ZT_WRITE_SIG);
*/
int zts_shutdown(ZT_SHUTDOWN_SIG);
/*
* Returns a vector of network routes { target, via, metric, etc... }
*/
std::vector<ZT_VirtualNetworkRoute> *zts_get_network_routes(char *nwid);
/****************************************************************************/
/* SDK Socket API Helper functions/objects --- DONT CALL THESE DIRECTLY */
/****************************************************************************/
@@ -515,6 +525,10 @@ ZeroTier::SocketTap *getTapByNWID(uint64_t nwid);
ZeroTier::SocketTap *getTapByAddr(ZeroTier::InetAddress &addr);
ZeroTier::SocketTap *getTapByName(char *ifname);
ZeroTier::SocketTap *getTapByIndex(int index);
/*
* Destroys all virtual tap devices
*/
void dismantleTaps();
/**

View File

@@ -45,14 +45,12 @@
#include "lwip/debug.h"
// IP Protocol version
// It seems using ipv6/ipv4 in the same stack is problematic, for this reason we
// compile for only one or the other using the SDK_IPV4=1/SDK_IPV6=1 flags for now
#if defined(SDK_IPV6)
#if defined(LIBZT_IPV6)
#define LWIP_IPV6 1
#define LWIP_IPV4 0
#endif
#if defined(SDK_IPV4)
#if defined(LIBZT_IPV4)
#define LWIP_IPV4 1
#define LWIP_IPV6 0
#endif

View File

@@ -36,7 +36,6 @@ LWIPARCH=$(CONTRIBDIR)/ports/unix
#default assumes it's a dir named lwip at the same level as the contrib module
LWIPDIR=ext/lwip/src
CCDEP=clang++
# Automagically pick clang or gcc, with preference for clang
@@ -79,14 +78,14 @@ CORE4FILES=$(LWIPDIR)/core/ipv4/autoip.c \
$(LWIPDIR)/core/ipv4/ip4.c \
$(LWIPDIR)/core/ipv4/ip4_addr.c
CORE6FILES=$(LWIPDIR)/core/ipv6/dhcp6.c \
$(LWIPDIR)/core/ipv6/ethip6.c \
CORE6FILES=$(LWIPDIR)/core/ipv6/ethip6.c \
$(LWIPDIR)/core/ipv6/icmp6.c \
$(LWIPDIR)/core/ipv6/inet6.c \
$(LWIPDIR)/core/ipv6/ip6.c \
$(LWIPDIR)/core/ipv6/ip6_addr.c \
$(LWIPDIR)/core/ipv6/ip6_frag.c \
$(LWIPDIR)/core/ipv6/mld6.c \
$(LWIPDIR)/core/ipv6/dhcp6.c \
$(LWIPDIR)/core/ipv6/nd6.c
# APIFILES: The files which implement the sequential and socket APIs.
@@ -113,7 +112,7 @@ SIXLOWPAN=$(LWIPDIR)/netif/lowpan6.c \
ARCHFILES=$(wildcard $(LWIPARCH)/*.c $(LWIPARCH)tapif.c $(LWIPARCH)/netif/list.c $(LWIPARCH)/netif/tcpdump.c)
# LWIPFILES: All the above.
LWIPFILES=$(COREFILES) $(CORE4FILES) $(APIFILES) $(NETIFFILES) $(ARCHFILES)
LWIPFILES=$(COREFILES) $(APIFILES) $(NETIFFILES) $(ARCHFILES)
ifeq ($(IPV4),1)
LWIPFILES+=$(CORE4FILES)
@@ -127,28 +126,21 @@ endif
LWIPFILESW=$(wildcard $(LWIPFILES))
LWIPOBJS=$(notdir $(LWIPFILESW:.c=.o))
LWIPLIB=liblwip.so
%.o:
$(CXX) $(CFLAGS) -Isrc/stack_drivers/lwip -c $(<:.o=.c)
$(CXX) $(CFLAGS) -c $(<:.o=.c) -o obj/$@
all: $(LWIPLIB)
all:
.PHONY: all
clean:
rm -f *.o $(LWIPLIB4) $(LWIPLIB6) *.s .depend* *.core core
rm -f *.o *.s .depend* *.core core
depend dep: .depend
include .depend
$(LWIPLIB): $(LWIPOBJS)
mkdir -p build
$(CXX) -Isrc/stack_drivers/lwip -g -nostartfiles -shared -o build/$@ $^
liblwip.a: $(LWIPOBJS)
echo $(LWIPOBJS)
libtool -static -o $@ $^
#libtool -static -o $@ $^
.depend: $(LWIPFILES)
$(CCDEP) $(CFLAGS) -MM $^ > .depend || rm -f .depend

View File

@@ -121,12 +121,15 @@ ifeq ($(STACK_PICO),1)
ifeq ($(LIBZT_IPV4)$(LIBZT_IPV6),1)
ifeq ($(LIBZT_IPV4),1)
CXXFLAGS+=-DLIBZT_IPV4
STACK_FLAGS+=-IPV4=1 -IPv4=1
endif
ifeq ($(LIBZT_IPV6),1)
CXXFLAGS+=-DLIBZT_IPV6
STACK_FLAGS+=-IPV6=1 -IPv6=1
endif
else
CXXFLAGS+=-DLIBZT_IPV4 -DLIBZT_IPV6
STACK_FLAGS+=-IPV6=1 -IPv6=1 -IPV6=1 -IPv6=1
endif
endif
@@ -135,12 +138,15 @@ ifeq ($(STACK_LWIP),1)
ifeq ($(LIBZT_IPV4)$(LIBZT_IPV6),1)
ifeq ($(LIBZT_IPV4),1)
CXXFLAGS+=-DLIBZT_IPV4
STACK_FLAGS+=IPV4=1 IPv4=1
endif
ifeq ($(LIBZT_IPV6),1)
CXXFLAGS+=-DLIBZT_IPV6
STACK_FLAGS+=IPV6=1 IPv6=1
endif
else
CXXFLAGS+=-DLIBZT_IPV4
STACK_FLAGS+=IPV4=1 IPv4=1
endif
endif
@@ -154,29 +160,14 @@ STACK_DIR:=ext/picotcp
STACK_LIB:=$(STACK_DIR)/build/lib/$(STACK_LIB)
STACK_DRIVER_FILES:=src/picoTCP.cpp
STACK_DRIVER_OBJS+=picoTCP.o
STACK_OBJS+= ext/picotcp/build/lib/pico_device.o \
ext/picotcp/build/lib/pico_frame.o \
ext/picotcp/build/lib/pico_md5.o \
ext/picotcp/build/lib/pico_protocol.o \
ext/picotcp/build/lib/pico_socket_multicast.o \
ext/picotcp/build/lib/pico_socket.o \
ext/picotcp/build/lib/pico_stack.o \
ext/picotcp/build/lib/pico_tree.o \
ext/picotcp/build/modules/*.o
INCLUDES+=-Iext/picotcp/include -Iext/picotcp/build/include
endif
ifeq ($(STACK_LWIP),1)
STACK_FLAGS+=-DLWIP_PREFIX_BYTEORDER_FUNCS
STACK_DRIVER_FLAGS+=-DLWIP_PREFIX_BYTEORDER_FUNCS
CXXFLAGS+=-DSTACK_LWIP
STACK_DRIVER_FILES:=src/lwIP.cpp
STACK_DRIVER_OBJS+=lwIP.o
STACK_OBJS+= init.o def.o dns.o inet_chksum.o ip.o mem.o \
memp.o netif.o pbuf.o raw.o stats.o sys.o tcp.o \
tcp_in.o tcp_out.o timeouts.o udp.o autoip.o \
dhcp.o etharp.o icmp.o igmp.o ip4_frag.o ip4.o \
ip4_addr.o api_lib.o api_msg.o err.o netbuf.o \
netdb.o netifapi.o sockets.o tcpip.o ethernet.o
LWIPARCH=$(CONTRIBDIR)/ports/unix
LWIPDIR=ext/lwip/src
INCLUDES+=-Iext/lwip/src/include/lwip \
@@ -193,6 +184,14 @@ endif
all:
%.o : %.cpp
@mkdir -p $(BUILD) obj
$(CXX) $(CXXFLAGS) -c $^ -o obj/$(@F)
%.o : %.c
@mkdir -p $(BUILD) obj
$(CC) $(CFLAGS) -c $^ -o obj/$(@F)
##############################################################################
## User-Space Stack ##
##############################################################################
@@ -201,7 +200,7 @@ picotcp:
cd $(STACK_DIR); make lib ARCH=shared IPV4=1 IPV6=1
lwip:
-make -f make-liblwip.mk liblwip.a IPV4=1 IPV6=1
-make -f make-liblwip.mk liblwip.a $(STACK_FLAGS)
##############################################################################
## Static Libraries ##
@@ -209,22 +208,27 @@ lwip:
ifeq ($(STACK_PICO),1)
static_lib: picotcp $(ZTO_OBJS)
@mkdir -p $(BUILD)
@mkdir -p $(BUILD) obj
$(CXX) $(CXXFLAGS) $(LIBZT_FILES) $(STACK_DRIVER_FILES) -c
ar rcs -o $(STATIC_LIB) $(ZTO_OBJS) $(STACK_DRIVER_OBJS) $(STACK_OBJS) $(LIBZT_OBJS) $(STACK_LIB)
mv *.o obj
mv ext/picotcp/build/lib/*.o obj
mv ext/picotcp/build/modules/*.o obj
ar rcs -o $(STATIC_LIB) obj/*.o $(STACK_LIB)
endif
ifeq ($(STACK_LWIP),1)
static_lib: lwip $(ZTO_OBJS)
@mkdir -p $(BUILD)
$(CXX) $(CXXFLAGS) $(STACK_FLAGS) $(STACK_INCLUDES) $(LIBZT_FILES) $(STACK_DRIVER_FILES) -c
ar rcs -o $(STATIC_LIB) $(ZTO_OBJS) $(STACK_DRIVER_OBJS) $(STACK_OBJS) $(LIBZT_OBJS) $(STACK_LIB)
@mkdir -p $(BUILD) obj
$(CXX) $(CXXFLAGS) $(STACK_DRIVER_FLAGS) $(STACK_INCLUDES) $(LIBZT_FILES) $(STACK_DRIVER_FILES) -c
mv *.o obj
ar rcs -o $(STATIC_LIB) obj/*.o $(STACK_LIB)
endif
# for layer-2 only (this will omit all userspace network stack code)
ifeq ($(NO_STACK),1)
static_lib: $(ZTO_OBJS)
@mkdir -p $(BUILD)
@mkdir -p $(BUILD) obj
$(CXX) $(CXXFLAGS) $(LIBZT_FILES) -c
ar rcs -o $(STATIC_LIB) $(ZTO_OBJS) $(LIBZT_OBJS)
mv *.o obj
ar rcs -o $(STATIC_LIB) obj/*.o
endif
##############################################################################

View File

@@ -119,12 +119,15 @@ ifeq ($(STACK_PICO),1)
ifeq ($(LIBZT_IPV4)$(LIBZT_IPV6),1)
ifeq ($(LIBZT_IPV4),1)
CXXFLAGS+=-DLIBZT_IPV4
STACK_FLAGS+=-IPV4=1 -IPv4=1
endif
ifeq ($(LIBZT_IPV6),1)
CXXFLAGS+=-DLIBZT_IPV6
STACK_FLAGS+=-IPV6=1 -IPv6=1
endif
else
CXXFLAGS+=-DLIBZT_IPV4 -DLIBZT_IPV6
STACK_FLAGS+=-IPV6=1 -IPv6=1 -IPV6=1 -IPv6=1
endif
endif
@@ -133,12 +136,15 @@ ifeq ($(STACK_LWIP),1)
ifeq ($(LIBZT_IPV4)$(LIBZT_IPV6),1)
ifeq ($(LIBZT_IPV4),1)
CXXFLAGS+=-DLIBZT_IPV4
STACK_FLAGS+=IPV4=1 IPv4=1
endif
ifeq ($(LIBZT_IPV6),1)
CXXFLAGS+=-DLIBZT_IPV6
STACK_FLAGS+=IPV6=1 IPv6=1
endif
else
CXXFLAGS+=-DLIBZT_IPV4
STACK_FLAGS+=IPV4=1 IPv4=1
endif
endif
@@ -152,27 +158,14 @@ STACK_DIR:=ext/picotcp
STACK_LIB:=$(STACK_DIR)/build/lib/$(STACK_LIB)
STACK_DRIVER_FILES:=src/picoTCP.cpp
STACK_DRIVER_OBJS+=picoTCP.o
STACK_OBJS+= ext/picotcp/build/lib/pico_device.o \
ext/picotcp/build/lib/pico_frame.o \
ext/picotcp/build/lib/pico_md5.o \
ext/picotcp/build/lib/pico_protocol.o \
ext/picotcp/build/lib/pico_socket_multicast.o \
ext/picotcp/build/lib/pico_socket.o \
ext/picotcp/build/lib/pico_stack.o \
ext/picotcp/build/lib/pico_tree.o
INCLUDES+=-Iext/picotcp/include -Iext/picotcp/build/include
endif
ifeq ($(STACK_LWIP),1)
STACK_DRIVER_FLAGS+=-DLWIP_PREFIX_BYTEORDER_FUNCS
CXXFLAGS+=-DSTACK_LWIP
STACK_DRIVER_FILES:=src/lwIP.cpp
STACK_DRIVER_OBJS+=lwIP.o
STACK_OBJS+= init.o def.o dns.o inet_chksum.o ip.o mem.o \
memp.o netif.o pbuf.o raw.o stats.o sys.o tcp.o \
tcp_in.o tcp_out.o timeouts.o udp.o autoip.o \
dhcp.o etharp.o icmp.o igmp.o ip4_frag.o ip4.o \
ip4_addr.o api_lib.o api_msg.o err.o netbuf.o \
netdb.o netifapi.o sockets.o tcpip.o ethernet.o
LWIPARCH=$(CONTRIBDIR)/ports/unix
LWIPDIR=ext/lwip/src
INCLUDES+=-Iext/lwip/src/include/lwip \
@@ -189,6 +182,14 @@ endif
all:
%.o : %.cpp
@mkdir -p $(BUILD) obj
$(CXX) $(CXXFLAGS) -c $^ -o obj/$(@F)
%.o : %.c
@mkdir -p $(BUILD) obj
$(CC) $(CFLAGS) -c $^ -o obj/$(@F)
##############################################################################
## User-Space Stack ##
##############################################################################
@@ -203,24 +204,30 @@ lwip:
## Static Libraries ##
##############################################################################
ifeq ($(STACK_PICO),1)
static_lib: picotcp $(ZTO_OBJS)
@mkdir -p $(BUILD)
@mkdir -p $(BUILD) obj
$(CXX) $(CXXFLAGS) $(LIBZT_FILES) $(STACK_DRIVER_FILES) -c
libtool -static -o $(STATIC_LIB) $(ZTO_OBJS) $(STACK_DRIVER_OBJS) $(STACK_OBJS) $(LIBZT_OBJS) $(STACK_LIB)
mv *.o obj
mv ext/picotcp/build/lib/*.o obj
mv ext/picotcp/build/modules/*.o obj
libtool -static -o $(STATIC_LIB) obj/*.o $(STACK_LIB)
endif
ifeq ($(STACK_LWIP),1)
static_lib: lwip $(ZTO_OBJS)
@mkdir -p $(BUILD)
$(CXX) $(CXXFLAGS) $(STACK_INCLUDES) $(LIBZT_FILES) $(STACK_DRIVER_FILES) -c
libtool -static -o $(STATIC_LIB) $(ZTO_OBJS) $(STACK_DRIVER_OBJS) $(STACK_OBJS) $(LIBZT_OBJS) $(STACK_LIB)
@mkdir -p $(BUILD) obj
$(CXX) $(CXXFLAGS) $(STACK_DRIVER_FLAGS) $(STACK_INCLUDES) $(LIBZT_FILES) $(STACK_DRIVER_FILES) -c
mv *.o obj
libtool -static -o $(STATIC_LIB) obj/*.o $(STACK_LIB)
endif
# for layer-2 only (this will omit all userspace network stack code)
ifeq ($(NO_STACK),1)
static_lib: $(ZTO_OBJS)
@mkdir -p $(BUILD)
@mkdir -p $(BUILD) obj
$(CXX) $(CXXFLAGS) $(LIBZT_FILES) -c
libtool -static -o $(STATIC_LIB) $(ZTO_OBJS) $(LIBZT_OBJS)
mv *.o obj
libtool -static -o $(STATIC_LIB) obj/*.o
endif
##############################################################################

View File

@@ -52,6 +52,7 @@
#include <netinet/ether.h>
#endif
#include "OneService.hpp"
#include "Utils.hpp"
#include "OSUtils.hpp"
#include "Constants.hpp"
@@ -59,7 +60,9 @@
class SocketTap;
extern std::vector<void*> vtaps;
//extern ZeroTier::OneService *zt1Service;
namespace ZeroTier {
@@ -277,50 +280,79 @@ namespace ZeroTier {
Read(sock,uptr,stack_invoked);
}
// Adds a route to the virtual tap
bool SocketTap::routeAdd(const InetAddress &addr, const InetAddress &nm, const InetAddress &gw)
{
#if defined(STACK_PICO)
if(picostack)
return picostack->pico_route_add(this, addr, nm, gw, 0);
#endif
#if defined(STACK_LWIP)
return true;
#endif
return false;
}
// Deletes a route from the virtual tap
bool SocketTap::routeDelete(const InetAddress &addr, const InetAddress &nm)
{
#if defined(STACK_PICO)
if(picostack)
return picostack->pico_route_del(this, addr, nm, 0);
#endif
#if defined(STACK_LWIP)
return true;
#endif
return false;
}
/****************************************************************************/
/* SDK Socket API */
/****************************************************************************/
int SocketTap::Connect(Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen) {
// Connect
int SocketTap::Connect(Connection *conn, const struct sockaddr *addr, socklen_t addrlen) {
#if defined(NO_STACK)
return -1;
#endif
Mutex::Lock _l(_tcpconns_m);
#if defined(STACK_PICO)
if(picostack)
return picostack->pico_Connect(conn, fd, addr, addrlen);
Mutex::Lock _l(_tcpconns_m);
return picostack->pico_Connect(conn, addr, addrlen);
#endif
#if defined(STACK_LWIP)
if(lwipstack)
return lwipstack->lwip_Connect(conn, fd, addr, addrlen);
return lwipstack->lwip_Connect(conn, addr, addrlen);
#endif
return ZT_ERR_GENERAL_FAILURE;
}
int SocketTap::Bind(Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen) {
// Bind VirtualSocket to a network stack's interface
int SocketTap::Bind(Connection *conn, const struct sockaddr *addr, socklen_t addrlen) {
#if defined(NO_STACK)
return -1;
#endif
Mutex::Lock _l(_tcpconns_m);
#if defined(STACK_PICO)
if(picostack)
return picostack->pico_Bind(conn, fd, addr, addrlen);
return picostack->pico_Bind(conn, addr, addrlen);
#endif
#if defined(STACK_LWIP)
if(lwipstack)
return lwipstack->lwip_Bind(this, conn, fd, addr, addrlen);
return lwipstack->lwip_Bind(this, conn, addr, addrlen);
#endif
return ZT_ERR_GENERAL_FAILURE;
}
int SocketTap::Listen(Connection *conn, int fd, int backlog) {
// Listen for an incoming connection
int SocketTap::Listen(Connection *conn, int backlog) {
#if defined(NO_STACK)
return -1;
#endif
Mutex::Lock _l(_tcpconns_m);
#if defined(STACK_PICO)
if(picostack)
return picostack->pico_Listen(conn, fd, backlog);
return picostack->pico_Listen(conn, backlog);
return ZT_ERR_GENERAL_FAILURE;
#endif
#if defined(STACK_LWIP)
@@ -331,13 +363,14 @@ namespace ZeroTier {
return ZT_ERR_GENERAL_FAILURE;
}
// Accept a connection
Connection* SocketTap::Accept(Connection *conn) {
#if defined(NO_STACK)
return NULL;
#endif
Mutex::Lock _l(_tcpconns_m);
#if defined(STACK_PICO)
if(picostack)
Mutex::Lock _l(_tcpconns_m);
return picostack->pico_Accept(conn);
return NULL;
#endif
@@ -349,6 +382,7 @@ namespace ZeroTier {
return NULL;
}
// Read from stack/buffers into the app's socket
int SocketTap::Read(PhySocket *sock,void **uptr,bool stack_invoked) {
#if defined(STACK_PICO)
if(picostack)
@@ -361,6 +395,7 @@ namespace ZeroTier {
return -1;
}
// Write data from app socket to the virtual wire, either raw over VL2, or via network stack
int SocketTap::Write(Connection *conn, void *data, ssize_t len) {
// VL2, SOCK_RAW, no network stack
if(conn->socket_type == SOCK_RAW) {
@@ -372,7 +407,6 @@ namespace ZeroTier {
_handler(_arg,NULL,_nwid,src_mac,dest_mac, Utils::ntoh((uint16_t)eh->ether_type),0, ((char*)data) + sizeof(struct ether_header),len - sizeof(struct ether_header));
return len;
}
#if defined(STACK_PICO)
if(picostack)
return picostack->pico_Write(conn, data, len);
@@ -384,6 +418,26 @@ namespace ZeroTier {
return -1;
}
// Send data to a specified host
int SocketTap::SendTo(Connection *conn, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t addrlen)
{
// TODO: flags
int err = 0;
DEBUG_INFO();
#if defined(STACK_PICO)
if(picostack) {
err = picostack->pico_Connect(conn, addr, addrlen); // implicit
err = picostack->pico_Write(conn, (void*)buf, len);
}
#endif
#if defined(STACK_LWIP)
if(lwipstack)
err = lwipstack->lwip_Connect(conn, addr, addrlen); // implicit
err = lwipstack->lwip_Write(conn, (void*)buf, len);
#endif
return err;
}
int SocketTap::Close(Connection *conn) {
#if defined(STACK_PICO)
if(!conn) {
@@ -427,21 +481,66 @@ namespace ZeroTier {
void SocketTap::Housekeeping()
{
#if defined(STACK_PICO)
Mutex::Lock _l(_tcpconns_m);
std::time_t current_ts = std::time(nullptr);
if(current_ts > last_housekeeping_ts + ZT_HOUSEKEEPING_INTERVAL) {
// Clean up old Connection objects
for(size_t i=0;i<_Connections.size();++i) {
if(_Connections[i]->closure_ts != -1 && (current_ts > _Connections[i]->closure_ts + ZT_CONNECTION_DELETE_WAIT_TIME)) {
// DEBUG_ERROR("deleting %p object, _Connections.size() = %d", _Connections[i], _Connections.size());
delete _Connections[i];
_Connections.erase(_Connections.begin() + i);
// update managed routes (add/del from network stacks)
if(zt1ServiceRef) {
std::vector<ZT_VirtualNetworkRoute> *managed_routes = ((ZeroTier::OneService *)zt1ServiceRef)->getRoutes(this->_nwid);
ZeroTier::InetAddress target_addr;
ZeroTier::InetAddress via_addr;
ZeroTier::InetAddress null_addr;
ZeroTier::InetAddress nm;
null_addr.fromString("");
bool found;
char ipbuf[64], ipbuf2[64], ipbuf3[64];
// TODO: Rework this when we have time
// check if pushed route exists in tap (add)
for(int i=0; i<ZT_MAX_NETWORK_ROUTES; i++) {
found = false;
target_addr = managed_routes->at(i).target;
via_addr = managed_routes->at(i).via;
nm = target_addr.netmask();
for(int j=0; j<routes.size(); j++) {
if(via_addr.ipsEqual(null_addr) || target_addr.ipsEqual(null_addr)) {
found=true;
continue;
}
if(routes[j].first.ipsEqual(target_addr) && routes[j].second.ipsEqual(nm)) {
found=true;
}
}
if(!found) {
if(!via_addr.ipsEqual(null_addr)) {
DEBUG_INFO("adding route <target=%s, nm=%s, via=%s>", target_addr.toString(ipbuf), nm.toString(ipbuf2), via_addr.toString(ipbuf3));
routes.push_back(std::pair<ZeroTier::InetAddress,ZeroTier::InetAddress>(target_addr, nm));
routeAdd(target_addr, nm, via_addr);
}
}
}
// check if route exists in tap but not in pushed routes (remove)
for(int i=0; i<routes.size(); i++) {
found = false;
for(int j=0; j<ZT_MAX_NETWORK_ROUTES; j++) {
target_addr = managed_routes->at(j).target;
via_addr = managed_routes->at(j).via;
nm = target_addr.netmask();
if(routes[i].first.ipsEqual(target_addr) && routes[i].second.ipsEqual(nm)) {
found=true;
}
}
if(!found) {
DEBUG_INFO("removing route to <target=%s>", routes[i].first.toString(ipbuf), routes[i].second.toString(ipbuf2));
routes.erase(routes.begin() + i);
routeDelete(routes[i].first, routes[i].second);
}
}
}
// TODO: Clean up Connection objects
last_housekeeping_ts = std::time(nullptr);
}
#endif
}
/****************************************************************************/

View File

@@ -155,6 +155,16 @@ namespace ZeroTier {
*/
void phyOnUnixWritable(PhySocket *sock, void **uptr, bool lwip_invoked);
/*
* Adds a route to the virtual tap
*/
bool routeAdd(const InetAddress &addr, const InetAddress &nm, const InetAddress &gw);
/*
* Deletes a route from the virtual tap
*/
bool routeDelete(const InetAddress &addr, const InetAddress &nm);
/****************************************************************************/
/* Vars */
/****************************************************************************/
@@ -183,6 +193,9 @@ namespace ZeroTier {
netif lwipdev6;
#endif
std::vector<std::pair<ZeroTier::InetAddress, ZeroTier::InetAddress>> routes;
void *zt1ServiceRef;
static int devno;
int ifindex;
@@ -222,17 +235,17 @@ namespace ZeroTier {
/*
* Connect to a remote host via the userspace stack interface associated with this SocketTap
*/
int Connect(Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen);
int Connect(Connection *conn, const struct sockaddr *addr, socklen_t addrlen);
/*
* Bind to the userspace stack interface associated with this SocketTap
*/
int Bind(Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen);
int Bind(Connection *conn, const struct sockaddr *addr, socklen_t addrlen);
/*
* Listen for a Connection
*/
int Listen(Connection *conn, int fd, int backlog);
int Listen(Connection *conn, int backlog);
/*
* Accepts an incoming Connection
@@ -249,6 +262,11 @@ namespace ZeroTier {
*/
int Write(Connection *conn, void *data, ssize_t len);
/*
* Send data to specified host
*/
int SendTo(Connection *conn, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t addrlen);
/*
* Closes a Connection
*/

View File

@@ -27,6 +27,30 @@
#ifndef UTILITIES_HPP
#define UTILITIES_HPP
#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)
// 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))
);
}
#endif
#if defined(STACK_LWIP) && defined(LIBZT_IPV4)
#include "lwip/ip_addr.h"

View File

@@ -74,9 +74,10 @@ for applications to use. See also: include/libzt.h */
extern "C" {
#endif
static ZeroTier::OneService *zt1Service;
namespace ZeroTier {
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
@@ -98,7 +99,7 @@ namespace ZeroTier {
std::map<int, std::pair<Connection*,SocketTap*>*> fdmap;
/*
*
* Virtual tap interfaces, one per virtual network
*/
std::vector<void*> vtaps;
@@ -113,7 +114,7 @@ namespace ZeroTier {
void zts_start(const char *path)
{
if(zt1Service)
if(ZeroTier::zt1Service)
return;
#if defined(STACK_PICO)
if(ZeroTier::picostack)
@@ -142,15 +143,15 @@ void zts_simple_start(const char *path, const char *nwid)
}
void zts_stop() {
if(zt1Service) {
zt1Service->terminate();
if(ZeroTier::zt1Service) {
ZeroTier::zt1Service->terminate();
dismantleTaps();
}
}
void zts_join(const char * nwid) {
if(zt1Service) {
std::string confFile = zt1Service->givenHomePath() + "/networks.d/" + nwid + ".conf";
if(ZeroTier::zt1Service) {
std::string confFile = ZeroTier::zt1Service->givenHomePath() + "/networks.d/" + nwid + ".conf";
if(!ZeroTier::OSUtils::mkdir(ZeroTier::netDir)) {
DEBUG_ERROR("unable to create: %s", ZeroTier::netDir.c_str());
handle_general_failure();
@@ -159,7 +160,13 @@ void zts_join(const char * nwid) {
DEBUG_ERROR("unable to write network conf file: %s", confFile.c_str());
handle_general_failure();
}
zt1Service->join(nwid);
ZeroTier::zt1Service->join(nwid);
}
// provide ZTO service reference to virtual taps
// TODO: This might prove to be unreliable, but it works for now
for(int i=0;i<ZeroTier::vtaps.size(); i++) {
ZeroTier::SocketTap *s = (ZeroTier::SocketTap*)ZeroTier::vtaps[i];
s->zt1ServiceRef=(void*)ZeroTier::zt1Service;
}
}
@@ -179,8 +186,8 @@ void zts_join_soft(const char * filepath, const char * nwid) {
}
void zts_leave(const char * nwid) {
if(zt1Service)
zt1Service->leave(nwid);
if(ZeroTier::zt1Service)
ZeroTier::zt1Service->leave(nwid);
}
void zts_leave_soft(const char * filepath, const char * nwid) {
@@ -206,9 +213,9 @@ void zts_lib_version(char *ver) {
}
int zts_get_device_id(char *devID) {
if(zt1Service) {
if(ZeroTier::zt1Service) {
char id[ZT_ID_LEN+1];
sprintf(id, "%lx",zt1Service->getNode()->address());
sprintf(id, "%lx",ZeroTier::zt1Service->getNode()->address());
memcpy(devID, id, ZT_ID_LEN+1);
return 0;
}
@@ -228,7 +235,7 @@ int zts_get_device_id(char *devID) {
}
int zts_running() {
return !zt1Service ? false : zt1Service->isRunning();
return !ZeroTier::zt1Service ? false : ZeroTier::zt1Service->isRunning();
}
int zts_has_ipv4_address(const char *nwid)
@@ -254,7 +261,7 @@ int zts_has_address(const char *nwid)
void zts_get_ipv4_address(const char *nwid, char *addrstr, const int addrlen)
{
if(zt1Service) {
if(ZeroTier::zt1Service) {
uint64_t nwid_int = strtoull(nwid, NULL, 16);
ZeroTier::SocketTap *tap = getTapByNWID(nwid_int);
if(tap && tap->_ips.size()){
@@ -276,7 +283,7 @@ void zts_get_ipv4_address(const char *nwid, char *addrstr, const int addrlen)
void zts_get_ipv6_address(const char *nwid, char *addrstr, const int addrlen)
{
if(zt1Service) {
if(ZeroTier::zt1Service) {
uint64_t nwid_int = strtoull(nwid, NULL, 16);
ZeroTier::SocketTap *tap = getTapByNWID(nwid_int);
if(tap && tap->_ips.size()){
@@ -313,15 +320,15 @@ void zts_get_rfc4193_addr(char *addr, const char *nwid, const char *devID)
}
unsigned long zts_get_peer_count() {
if(zt1Service)
return zt1Service->getNode()->peers()->peerCount;
if(ZeroTier::zt1Service)
return ZeroTier::zt1Service->getNode()->peers()->peerCount;
else
return 0;
}
int zts_get_peer_address(char *peer, const char *devID) {
if(zt1Service) {
ZT_PeerList *pl = zt1Service->getNode()->peers();
if(ZeroTier::zt1Service) {
ZT_PeerList *pl = ZeroTier::zt1Service->getNode()->peers();
// uint64_t addr;
for(int i=0; i<pl->peerCount; i++) {
// ZT_Peer *p = &(pl->peers[i]);
@@ -374,7 +381,7 @@ int zts_socket(ZT_SOCKET_SIG) {
return -1;
}
int err = 0;
if(!zt1Service) {
if(!ZeroTier::zt1Service) {
DEBUG_ERROR("cannot create socket, no service running. call zts_start() first.");
errno = EMFILE; // could also be ENFILE
return -1;
@@ -417,7 +424,6 @@ int zts_socket(ZT_SOCKET_SIG) {
#if defined(STACK_LWIP)
// TODO: check for max lwIP timers/sockets
ZeroTier::Connection *conn = new ZeroTier::Connection();
void *pcb;
err = ZeroTier::lwipstack->lwip_Socket(&pcb, socket_family, socket_type, protocol);
if(pcb) {
@@ -493,15 +499,14 @@ Linux:
*/
int zts_connect(ZT_CONNECT_SIG) {
#if defined(STACK_PICO)
//DEBUG_INFO("fd = %d", fd);
DEBUG_INFO("fd = %d", fd);
int err = 0;
if(fd < 0) {
errno = EBADF;
DEBUG_ERROR("EBADF");
return -1;
}
if(!zt1Service) {
if(!ZeroTier::zt1Service) {
DEBUG_ERROR("Service not started. Call zts_start(path) first");
errno = EBADF;
return -1;
@@ -539,9 +544,13 @@ int zts_connect(ZT_CONNECT_SIG) {
err = -1;
}
else {
#if defined(STACK_PICO)
// pointer to tap we use in callbacks from the stack
conn->picosock->priv = new ZeroTier::ConnectionPair(tap, conn);
err = tap->Connect(conn, fd, addr, addrlen);
#endif
#if defined(STACK_LWIP)
#endif
err = tap->Connect(conn, addr, addrlen);
if(err == 0) {
tap->_Connections.push_back(conn); // Give this Connection to the tap we decided on
conn->tap = tap;
@@ -549,7 +558,6 @@ int zts_connect(ZT_CONNECT_SIG) {
// Wrap the socketpair we created earlier
// For I/O loop participation and referencing the PhySocket's parent Connection in callbacks
conn->sock = tap->_phy.wrapSocket(conn->sdk_fd, conn);
//DEBUG_ERROR("sock->fd = %d", tap->_phy.getDescriptor(conn->sock));
}
}
else {
@@ -575,7 +583,6 @@ int zts_connect(ZT_CONNECT_SIG) {
else {
blocking = !(f_err & O_NONBLOCK);
}
// non-blocking
if(err == 0 && !blocking) {
DEBUG_EXTRA("EINPROGRESS, not a real error, assuming non-blocking mode");
@@ -596,11 +603,15 @@ int zts_connect(ZT_CONNECT_SIG) {
tap->_tcpconns_m.lock();
for(int i=0; i<tap->_Connections.size(); i++)
{
#if defined(STACK_PICO)
if(tap->_Connections[i]->state == PICO_ERR_ECONNRESET) {
errno = ECONNRESET;
DEBUG_ERROR("ECONNRESET");
err = -1;
}
#endif
#if defined(STACK_LWIP)
#endif
if(tap->_Connections[i]->state == ZT_SOCK_STATE_UNHANDLED_CONNECTED) {
tap->_Connections[i]->state = ZT_SOCK_STATE_CONNECTED;
errno = 0;
@@ -615,8 +626,6 @@ int zts_connect(ZT_CONNECT_SIG) {
}
}
return err;
#endif
return 0;
}
/*
@@ -640,7 +649,7 @@ int zts_bind(ZT_BIND_SIG) {
errno = EBADF;
return -1;
}
if(!zt1Service) {
if(!ZeroTier::zt1Service) {
DEBUG_ERROR("Service not started. Call zts_start(path) first");
errno = EBADF;
return -1;
@@ -677,7 +686,7 @@ int zts_bind(ZT_BIND_SIG) {
else {
conn->picosock->priv = new ZeroTier::ConnectionPair(tap, conn);
tap->_Connections.push_back(conn); // Give this Connection to the tap we decided on
err = tap->Bind(conn, fd, addr, addrlen);
err = tap->Bind(conn, addr, addrlen);
conn->tap = tap;
if(err == 0) { // success
ZeroTier::unmap.erase(fd);
@@ -688,7 +697,7 @@ int zts_bind(ZT_BIND_SIG) {
#if defined(STACK_LWIP)
else {
tap->_Connections.push_back(conn);
err = tap->Bind(conn, fd, addr, addrlen);
err = tap->Bind(conn, addr, addrlen);
conn->tap = tap;
if(err == 0) { // success
ZeroTier::unmap.erase(fd);
@@ -731,7 +740,7 @@ int zts_listen(ZT_LISTEN_SIG) {
errno = EBADF;
return -1;
}
if(!zt1Service) {
if(!ZeroTier::zt1Service) {
DEBUG_ERROR("service not started. call zts_start(path) first");
errno = EACCES;
return -1;
@@ -752,7 +761,7 @@ int zts_listen(ZT_LISTEN_SIG) {
}
if(!err) {
backlog = backlog > 128 ? 128 : backlog; // See: /proc/sys/net/core/somaxconn
err = tap->Listen(conn, fd, backlog);
err = tap->Listen(conn, backlog);
conn->state = ZT_SOCK_STATE_LISTENING;
ZeroTier::_multiplexer_lock.unlock();
}
@@ -998,7 +1007,7 @@ int zts_close(ZT_CLOSE_SIG)
}
else
{
if(!zt1Service) {
if(!ZeroTier::zt1Service) {
DEBUG_ERROR("cannot close socket. service not started. call zts_start(path) first");
errno = EBADF;
err = -1;
@@ -1221,12 +1230,46 @@ ssize_t zts_sendto(ZT_SENDTO_SIG)
err = -1;
}
else {
ZeroTier::Connection *conn = ZeroTier::unmap[fd];
ZeroTier::InetAddress iaddr;
ZeroTier::SocketTap *tap;
char ipstr[INET6_ADDRSTRLEN];
int port;
memset(ipstr, 0, INET6_ADDRSTRLEN);
if(conn->socket_type == SOCK_DGRAM) {
if(conn->socket_family == AF_INET) {
inet_ntop(AF_INET,
(const void *)&((struct sockaddr_in *)addr)->sin_addr.s_addr, ipstr, INET_ADDRSTRLEN);
iaddr.fromString(ipstr);
port = ((struct sockaddr_in*)addr)->sin_port;
}
if(conn->socket_family == AF_INET6) {
inet_ntop(AF_INET6,
(const void *)&((struct sockaddr_in6 *)addr)->sin6_addr.s6_addr, ipstr, INET6_ADDRSTRLEN);
// TODO: This is a hack, determine a proper way to do this
char addrstr[64];
sprintf(addrstr, "%s%s", ipstr, std::string("/88").c_str());
iaddr.fromString(addrstr);
port = ((struct sockaddr_in6*)addr)->sin6_port;
}
tap = getTapByAddr(iaddr);
if(tap) {
tap->SendTo(conn, buf, len, flags, addr, addrlen);
}
else {
DEBUG_INFO("SOCK_DGRAM, tap not found");
errno = EDESTADDRREQ; // TODO: double check this is the best errno to report
return -1;
}
}
if(conn->socket_type == SOCK_RAW)
{
struct sockaddr_ll *socket_address = (struct sockaddr_ll *)addr;
ZeroTier::SocketTap *tap = getTapByIndex(socket_address->sll_ifindex);
if(tap)
{
DEBUG_INFO("found interface of ifindex=%d", tap->ifindex);
ZeroTier::Connection *conn = ZeroTier::unmap[fd];
if(conn) {
DEBUG_INFO("located connection object for fd=%d", fd);
err = tap->Write(conn, (void*)buf, len);
@@ -1245,6 +1288,7 @@ ssize_t zts_sendto(ZT_SENDTO_SIG)
}
//err = sendto(fd, buf, len, flags, addr, addrlen);
}
}
return err;
}
@@ -1319,7 +1363,7 @@ int zts_shutdown(ZT_SHUTDOWN_SIG)
}
else
{
if(!zt1Service) {
if(!ZeroTier::zt1Service) {
DEBUG_ERROR("cannot shutdown socket. service not started. call zts_start(path) first");
errno = EBADF;
err = -1;
@@ -1406,7 +1450,7 @@ namespace ZeroTier {
}
// Shuts down ZeroTier service and SOCKS5 Proxy server
JNIEXPORT void JNICALL Java_zerotier_ZeroTier_ztjni_1stop(JNIEnv *env, jobject thisObj) {
if(zt1Service)
if(ZeroTier::zt1Service)
zts_stop();
}
@@ -1652,7 +1696,7 @@ namespace ZeroTier {
int zts_get_pico_socket(int fd, struct pico_socket **s)
{
int err = 0;
if(!zt1Service) {
if(!ZeroTier::zt1Service) {
DEBUG_ERROR("cannot locate socket. service not started. call zts_start(path) first");
errno = EBADF;
err = -1;
@@ -1700,6 +1744,7 @@ bool can_provision_new_socket()
// TODO: Add check here (see lwipopts.h)
return true;
#endif
return false;
}
int zts_nsockets()
@@ -1723,6 +1768,12 @@ int zts_maxsockets()
/* ZeroTier Core helper functions for libzt - DON'T CALL THESE DIRECTLY */
/****************************************************************************/
std::vector<ZT_VirtualNetworkRoute> *zts_get_network_routes(char *nwid)
{
uint64_t nwid_int = strtoull(nwid, NULL, 16);
return ZeroTier::zt1Service->getRoutes(nwid_int);
}
ZeroTier::SocketTap *getTapByNWID(uint64_t nwid)
{
ZeroTier::_vtaps_lock.lock();
@@ -1739,14 +1790,33 @@ ZeroTier::SocketTap *getTapByAddr(ZeroTier::InetAddress &addr)
{
ZeroTier::_vtaps_lock.lock();
ZeroTier::SocketTap *s, *tap = nullptr;
char ipbuf[64], ipbuf2[64], ipbuf3[64];
for(int i=0; i<ZeroTier::vtaps.size(); i++) {
s = (ZeroTier::SocketTap*)ZeroTier::vtaps[i];
// check address schemes
for(int j=0; j<s->_ips.size(); j++) {
if(s->_ips[j].isEqualPrefix(addr)
|| s->_ips[j].ipsEqual(addr)
|| s->_ips[j].containsAddress(addr))
{
DEBUG_INFO("chose tap <addr=%s>", s->_ips[j].toString(ipbuf));
tap = s;
break;
}
}
// check managed routes
if(!tap) {
std::vector<ZT_VirtualNetworkRoute> *managed_routes = ZeroTier::zt1Service->getRoutes(s->_nwid);
ZeroTier::InetAddress target, nm, via;
for(int 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_INFO("chose tap with route <target=%s, nm=%s, via=%s>", target.toString(ipbuf), nm.toString(ipbuf2), via.toString(ipbuf3));
tap = s;
break;
}
}
}
}
@@ -1797,7 +1867,7 @@ void *zts_start_service(void *thread_id) {
DEBUG_INFO("homeDir=%s", ZeroTier::homeDir.c_str());
// Where network .conf files will be stored
ZeroTier::netDir = ZeroTier::homeDir + "/networks.d";
zt1Service = (ZeroTier::OneService *)0;
ZeroTier::zt1Service = (ZeroTier::OneService *)0;
// Construct path for network config and supporting service files
if (ZeroTier::homeDir.length()) {
@@ -1832,17 +1902,17 @@ void *zts_start_service(void *thread_id) {
int servicePort = 9000 + (randp % 1000);
for(;;) {
zt1Service = ZeroTier::OneService::newInstance(ZeroTier::homeDir.c_str(),servicePort);
switch(zt1Service->run()) {
ZeroTier::zt1Service = ZeroTier::OneService::newInstance(ZeroTier::homeDir.c_str(),servicePort);
switch(ZeroTier::zt1Service->run()) {
case ZeroTier::OneService::ONE_STILL_RUNNING:
case ZeroTier::OneService::ONE_NORMAL_TERMINATION:
break;
case ZeroTier::OneService::ONE_UNRECOVERABLE_ERROR:
DEBUG_ERROR("fatal error: %s",zt1Service->fatalErrorMessage().c_str());
DEBUG_ERROR("fatal error: %s",ZeroTier::zt1Service->fatalErrorMessage().c_str());
break;
case ZeroTier::OneService::ONE_IDENTITY_COLLISION: {
delete zt1Service;
zt1Service = (ZeroTier::OneService *)0;
delete ZeroTier::zt1Service;
ZeroTier::zt1Service = (ZeroTier::OneService *)0;
std::string oldid;
ZeroTier::OSUtils::readFile((ZeroTier::homeDir + ZT_PATH_SEPARATOR_S
+ "identity.secret").c_str(),oldid);
@@ -1859,8 +1929,8 @@ void *zts_start_service(void *thread_id) {
}
break; // terminate loop -- normally we don't keep restarting
}
delete zt1Service;
zt1Service = (ZeroTier::OneService *)0;
delete ZeroTier::zt1Service;
ZeroTier::zt1Service = (ZeroTier::OneService *)0;
return NULL;
}

View File

@@ -36,6 +36,13 @@
#include "netif/ethernet.h"
#include "lwip/etharp.h"
#if defined(LIBZT_IPV6)
#include "lwip/ethip6.h"
#include "lwip/nd6.h"
#endif
void nd6_tmr(void);
err_t tapif_init(struct netif *netif)
{
DEBUG_INFO();
@@ -82,6 +89,7 @@ namespace ZeroTier
if (std::find(tap->_ips.begin(),tap->_ips.end(),ip) == tap->_ips.end()) {
tap->_ips.push_back(ip);
std::sort(tap->_ips.begin(),tap->_ips.end());
char ipbuf[64], nmbuf[64];
#if defined(LIBZT_IPV4)
if (ip.isV4()) {
// Set IP
@@ -101,13 +109,11 @@ namespace ZeroTier
tap->lwipdev.flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_IGMP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP;
netif_set_default(&(tap->lwipdev));
netif_set_up(&(tap->lwipdev));
char ipbuf[64];
DEBUG_INFO("addr=%s, netmask=%s", ip.toString(ipbuf), ip.netmask().toString(ipbuf));
DEBUG_INFO("addr=%s, netmask=%s", ip.toString(ipbuf), ip.netmask().toString(nmbuf));
}
#endif
#if defined(LIBZT_IPV6)
if(ip.isV6()) {
DEBUG_INFO("local_addr=%s", ip.toString().c_str());
static ip6_addr_t addr6;
struct sockaddr_in6 in6;
memcpy(in6.sin6_addr.s6_addr,ip.rawIpData(),16);
@@ -128,8 +134,7 @@ namespace ZeroTier
tap->lwipdev6.output_ip6 = ethip6_output;
tap->lwipdev6.state = tap;
tap->lwipdev6.flags = NETIF_FLAG_LINK_UP | NETIF_FLAG_UP;
char ipbuf[64];
DEBUG_INFO("addr=%s, netmask=%s", ip.toString(ipbuf), ip.netmask().toString(ipbuf));
DEBUG_INFO("addr=%s, netmask=%s", ip.toString(ipbuf), ip.netmask().toString(nmbuf));
}
#endif
}
@@ -138,13 +143,12 @@ namespace ZeroTier
void lwIP::lwip_loop(SocketTap *tap)
{
DEBUG_INFO();
uint64_t prev_tcp_time = 0, prev_status_time = 0, prev_discovery_time = 0;
uint64_t prev_tcp_time = 0, prev_discovery_time = 0;
while(tap->_run)
{
uint64_t now = OSUtils::now();
uint64_t since_tcp = now - prev_tcp_time;
uint64_t since_discovery = now - prev_discovery_time;
uint64_t since_status = now - prev_status_time;
uint64_t tcp_remaining = LWIP_TCP_TIMER_INTERVAL;
uint64_t discovery_remaining = 5000;
@@ -173,6 +177,7 @@ namespace ZeroTier
discovery_remaining = DISCOVERY_INTERVAL - since_discovery;
}
tap->_phy.poll((unsigned long)std::min(tcp_remaining,discovery_remaining));
tap->Housekeeping();
}
}
@@ -244,7 +249,7 @@ namespace ZeroTier
return -1;
}
int lwIP::lwip_Connect(Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen)
int lwIP::lwip_Connect(Connection *conn, const struct sockaddr *addr, socklen_t addrlen)
{
DEBUG_INFO();
ip_addr_t ba;
@@ -252,9 +257,8 @@ namespace ZeroTier
int port = 0, err = 0;
#if defined(LIBZT_IPV4)
struct sockaddr_in *in4;
struct sockaddr_in *in4 = (struct sockaddr_in *)addr;
if(addr->sa_family == AF_INET) {
in4 = (struct sockaddr_in *)addr;
inet_ntop(AF_INET, &(in4->sin_addr), addrstr, INET_ADDRSTRLEN);
DEBUG_INFO("%s:%d", addrstr, lwip_ntohs(in4->sin_port));
}
@@ -336,9 +340,10 @@ namespace ZeroTier
return -1;
}
}
return err;
}
int lwIP::lwip_Bind(SocketTap *tap, Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen)
int lwIP::lwip_Bind(SocketTap *tap, Connection *conn, const struct sockaddr *addr, socklen_t addrlen)
{
DEBUG_INFO();
ip_addr_t ba;
@@ -346,9 +351,8 @@ namespace ZeroTier
int port = 0, err = 0;
#if defined(LIBZT_IPV4)
struct sockaddr_in *in4;
struct sockaddr_in *in4 = (struct sockaddr_in *)addr;
if(addr->sa_family == AF_INET) {
in4 = (struct sockaddr_in *)addr;
inet_ntop(AF_INET, &(in4->sin_addr), addrstr, INET_ADDRSTRLEN);
DEBUG_INFO("%s:%d", addrstr, lwip_ntohs(in4->sin_port));
}
@@ -422,7 +426,6 @@ namespace ZeroTier
Connection* lwIP::lwip_Accept(Connection *conn)
{
DEBUG_EXTRA("conn=%p", conn);
if(!conn) {
DEBUG_ERROR("invalid conn");
handle_general_failure();
@@ -430,9 +433,7 @@ namespace ZeroTier
}
// Retreive first of queued Connections from parent connection
Connection *new_conn = NULL;
DEBUG_INFO("locking...");
Mutex::Lock _l(conn->tap->_tcpconns_m);
DEBUG_INFO("locked.");
if(conn->_AcceptedConnections.size()) {
new_conn = conn->_AcceptedConnections.front();
conn->_AcceptedConnections.pop();
@@ -443,6 +444,7 @@ namespace ZeroTier
int lwIP::lwip_Read(Connection *conn, bool lwip_invoked)
{
DEBUG_EXTRA("conn=%p", conn);
int err = 0;
if(!conn) {
DEBUG_ERROR("no connection");
return -1;
@@ -458,49 +460,39 @@ namespace ZeroTier
int n = conn->tap->_phy.streamSend(conn->sock, conn->RXbuf->get_buf(), wr);
char str[22];
memcpy(str, conn->RXbuf->get_buf(), 22);
DEBUG_INFO("string = %s", str);
DEBUG_INFO("n =%d", n);
conn->RXbuf->consume(n);
//if(n == max)
//{
//if(conn->socket_type == SOCK_DGRAM){
// conn->tap->_phy.setNotifyWritable(conn->sock, false);
//}
if(conn->socket_type == SOCK_DGRAM)
{
// TODO
}
if(conn->socket_type == SOCK_STREAM) { // Only acknolwedge receipt of TCP packets
tcp_recved((struct tcp_pcb*)conn->pcb, n);
DEBUG_TRANS("TCP RX %ld bytes", n);
DEBUG_TRANS("TCP RX %d bytes", n);
}
//}
}
if(conn->RXbuf->count() == 0) {
DEBUG_INFO("wrote everything");
conn->tap->_phy.setNotifyWritable(conn->sock, false); // nothing else to send to the app
}
if(!lwip_invoked) {
DEBUG_INFO("unlocking...");
conn->tap->_tcpconns_m.unlock();
conn->_rx_m.unlock();
}
/*
int payload_sz, addr_sz_offset = sizeof(struct sockaddr_storage);
memcpy(&payload_sz, conn->rxbuf + addr_sz_offset, sizeof(int)); // OPT:
// extract address
struct sockaddr_storage addr;
memcpy(&addr, conn->rxbuf, addr_sz_offset);
*/
return err;
}
int lwIP::lwip_Write(Connection *conn, void *data, ssize_t len)
{
DEBUG_EXTRA("conn=%p", (void*)&conn);
DEBUG_EXTRA("conn=%p, len=%d", (void*)&conn, len);
int err = 0;
if(!conn) {
DEBUG_ERROR("no connection");
return -1;
}
if(conn->socket_type == SOCK_DGRAM)
{
DEBUG_ERROR("socket_type==SOCK_DGRAM");
// TODO: Packet re-assembly hasn't yet been tested with lwIP so UDP packets are limited to MTU-sized chunks
int udp_trans_len = std::min((ssize_t)conn->TXbuf->count(), (ssize_t)ZT_MAX_MTU);
DEBUG_EXTRA("allocating pbuf chain of size=%d for UDP packet, txsz=%d", udp_trans_len, conn->TXbuf->count());
@@ -526,24 +518,27 @@ namespace ZeroTier
}
if(conn->socket_type == SOCK_STREAM)
{
DEBUG_ERROR("socket_type==SOCK_STREAM");
// How much we are currently allowed to write to the connection
ssize_t sndbuf = ((struct tcp_pcb*)conn->pcb)->snd_buf;
int err, sz, r;
int err, r;
if(!sndbuf) {
// PCB send buffer is full, turn off readability notifications for the
// corresponding PhySocket until nc_sent() is called and confirms that there is
// now space on the buffer
DEBUG_ERROR(" LWIP stack is full, sndbuf == 0");
DEBUG_ERROR("lwIP stack is full, sndbuf == 0");
conn->tap->_phy.setNotifyReadable(conn->sock, false);
return -1;
}
if(conn->TXbuf->count() <= 0)
return -1; // Nothing to write
//if(!conn->listening)
// tcp_output(conn->TCP_pcb);
int buf_w = conn->TXbuf->write((const unsigned char*)data, len);
if (buf_w != len) {
// because we checked ZT_TCP_TX_BUF_SZ above, this should not happen
DEBUG_ERROR("TX wrote only %d but expected to write %d", buf_w, len);
exit(0);
}
if(conn->TXbuf->count() <= 0) {
return -1; // nothing to write
}
if(conn->sock) {
r = std::min((ssize_t)conn->TXbuf->count(), sndbuf);
// Writes data pulled from the client's socket buffer to LWIP. This merely sends the
@@ -552,9 +547,9 @@ namespace ZeroTier
err = tcp_write((struct tcp_pcb*)conn->pcb, conn->TXbuf->get_buf(), r, TCP_WRITE_FLAG_COPY);
tcp_output((struct tcp_pcb*)conn->pcb);
if(err != ERR_OK) {
DEBUG_ERROR(" error while writing to PCB, err=%d", err);
DEBUG_ERROR("error while writing to lwIP tcp_pcb, err=%d", err);
if(err == -1)
DEBUG_ERROR("out of memory");
DEBUG_ERROR("lwIP out of memory");
return -1;
} else {
conn->TXbuf->consume(r); // success
@@ -563,6 +558,7 @@ namespace ZeroTier
}
}
}
return err;
}
int lwIP::lwip_Close(Connection *conn)
@@ -580,7 +576,6 @@ namespace ZeroTier
DEBUG_EXTRA("ignoring close request. invalid PCB state for this operation. sock=%p", conn->sock);
return -1;
}
// DEBUG_BLANK("__tcp_close(...)");
struct tcp_pcb* tpcb = (struct tcp_pcb*)conn->pcb;
if(tcp_close(tpcb) == ERR_OK) {
// Unregister callbacks for this PCB
@@ -614,14 +609,9 @@ namespace ZeroTier
//Mutex::Lock _l(conn->tap->_tcpconns_m);
//Mutex::Lock _l2(conn->_rx_m);
DEBUG_INFO("locking...");
conn->tap->_tcpconns_m.lock();
conn->_rx_m.lock();
DEBUG_INFO("locked.");
struct pbuf* q = p;
if(p == NULL) {
if(((struct tcp_pcb*)conn->pcb)->state == CLOSE_WAIT) {
@@ -725,14 +715,13 @@ namespace ZeroTier
{
DEBUG_ERROR("err=%d", err);
Connection *conn = (Connection *)arg;
Mutex::Lock _l(conn->tap->_tcpconns_m);
if(!conn){
DEBUG_ERROR("conn==NULL");
errno = -1; // FIXME: Find more appropriate value
}
Mutex::Lock _l(conn->tap->_tcpconns_m);
int fd = conn->tap->_phy.getDescriptor(conn->sock);
DEBUG_ERROR("conn=%p, pcb=%p, err=%d", conn, conn->pcb, err);
DEBUG_ERROR("conn=%p, pcb=%p, fd=%d, err=%d", conn, conn->pcb, fd, err);
DEBUG_ERROR("closing connection");
conn->tap->Close(conn);
switch(err)
@@ -781,19 +770,19 @@ namespace ZeroTier
// TODO: Below are errors which don't have a standard errno correlate
case ERR_RST:
//l->tap->sendReturnValue(fd, -1, -1);
// -1
break;
case ERR_CLSD:
//l->tap->sendReturnValue(fd, -1, -1);
// -1
break;
case ERR_CONN:
//l->tap->sendReturnValue(fd, -1, -1);
// -1
break;
case ERR_ARG:
//l->tap->sendReturnValue(fd, -1, -1);
// -1
break;
case ERR_IF:
//l->tap->sendReturnValue(fd, -1, -1);
// -1
break;
default:
break;

View File

@@ -56,6 +56,7 @@ struct netif;
#endif
#if defined(LIBZT_IPV6)
#include "lwip/ip6_addr.h"
#include "ethip6.h"
#define LWIP_NETIF_ADD_SIG struct netif *netif, void *state, netif_init_fn init, netif_input_fn input
#define LWIP_ETHIP6_OUTPUT_SIG struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr
#define LWIP_ETHARP_OUTPUT_SIG struct netif *netif, struct pbuf *q, const ip6_addr_t *ipaddr
@@ -109,9 +110,9 @@ struct netif;
#endif
#if defined(LIBZT_IPV6)
extern "C" void nd6_tmr(void);
extern "C" void netif_ip6_addr_set_state(LWIP_NETIF_IP6_ADDR_SET_STATE_SIG);
//extern "C" void netif_ip6_addr_set_state(LWIP_NETIF_IP6_ADDR_SET_STATE_SIG);
extern "C" void netif_create_ip6_linklocal_address(LWIP_NETIF_CREATE_IP6_LINKLOCAL_ADDRESS_SIG);
extern "C" err_t _ethip6_output(LWIP_ETHIP6_OUTPUT_SIG);
extern "C" err_t ethip6_output(LWIP_ETHIP6_OUTPUT_SIG);
#endif
extern "C" void lwip_init();
@@ -185,8 +186,8 @@ namespace ZeroTier {
void lwip_rx(SocketTap *tap, const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len);
int lwip_Socket(void **pcb, int socket_family, int socket_type, int protocol);
int lwip_Connect(Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen);
int lwip_Bind(SocketTap *tap, Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen);
int lwip_Connect(Connection *conn, const struct sockaddr *addr, socklen_t addrlen);
int lwip_Bind(SocketTap *tap, Connection *conn, const struct sockaddr *addr, socklen_t addrlen);
int lwip_Listen(Connection *conn, int backlog);
Connection* lwip_Accept(Connection *conn);
int lwip_Read(Connection *conn, bool lwip_invoked);

View File

@@ -48,12 +48,12 @@
#include "Constants.hpp"
#include "Phy.hpp"
int pico_ipv4_to_string(PICO_IPV4_TO_STRING_SIG);
extern "C" int pico_stack_init(void);
extern "C" void pico_stack_tick(void);
int pico_ipv4_to_string(PICO_IPV4_TO_STRING_SIG);
extern "C" int pico_ipv4_link_add(PICO_IPV4_LINK_ADD_SIG);
extern "C" int pico_ipv4_route_add(PICO_IPV4_ROUTE_ADD_SIG);
extern "C" int pico_ipv4_route_del(PICO_IPV4_ROUTE_DEL_SIG);
extern "C" int pico_device_init(PICO_DEVICE_INIT_SIG);
extern "C" int pico_string_to_ipv4(PICO_STRING_TO_IPV4_SIG);
extern "C" int pico_string_to_ipv6(PICO_STRING_TO_IPV6_SIG);
@@ -132,13 +132,46 @@ namespace ZeroTier {
return false;
}
// TODO:
// pico_ipv6_route_add
// pico_ipv6_route_del
bool picoTCP::pico_route_add(SocketTap *tap, const InetAddress &addr, const InetAddress &nm, const InetAddress &gw, int metric)
{
struct pico_ipv4_link *link = NULL;
struct pico_ip4 address;
address.addr = *((uint32_t *)addr.rawIpData());
struct pico_ip4 netmask;
netmask.addr = *((uint32_t *)nm.rawIpData());
struct pico_ip4 gateway;
gateway.addr = *((uint32_t *)gw.rawIpData());
int err = pico_ipv4_route_add(address, netmask, gateway, metric, link);
if(err) {
DEBUG_ERROR("err=%d, %s", err, beautify_pico_error(pico_err));
}
return err;
}
bool picoTCP::pico_route_del(SocketTap *tap, const InetAddress &addr, const InetAddress &nm, int metric)
{
struct pico_ip4 address;
address.addr = *((uint32_t *)addr.rawIpData());
struct pico_ip4 netmask;
netmask.addr = *((uint32_t *)nm.rawIpData());
int err = pico_ipv4_route_del(address, netmask, metric);
if(err) {
DEBUG_ERROR("err=%d, %s", err, beautify_pico_error(pico_err));
}
return err;
}
void picoTCP::pico_loop(SocketTap *tap)
{
while(tap->_run)
{
tap->_phy.poll(ZT_PHY_POLL_INTERVAL);
pico_stack_tick();
//tap->Housekeeping();
tap->Housekeeping();
}
}
@@ -521,7 +554,7 @@ namespace ZeroTier {
protocol_version = PICO_PROTO_IPV6;
if(socket_type == SOCK_DGRAM) {
DEBUG_ERROR("SOCK_DGRAM");
DEBUG_INFO("SOCK_DGRAM");
psock = pico_socket_open(
protocol_version, PICO_PROTO_UDP, &ZeroTier::picoTCP::pico_cb_socket_activity);
if(psock) { // configure size of UDP SND/RCV buffers
@@ -555,7 +588,7 @@ namespace ZeroTier {
return err;
}
int picoTCP::pico_Connect(Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen)
int picoTCP::pico_Connect(Connection *conn, const struct sockaddr *addr, socklen_t addrlen)
{
if(!conn || !conn->picosock) {
DEBUG_ERROR("invalid conn or conn->picosock");
@@ -582,6 +615,9 @@ namespace ZeroTier {
pico_string_to_ipv6(ipv6_str, zaddr.addr);
err = pico_socket_connect(conn->picosock, &zaddr, in6->sin6_port);
}
if(err) {
DEBUG_ERROR("err=%d, %s", err, beautify_pico_error(pico_err));
}
memcpy(&(conn->peer_addr), &addr, sizeof(struct sockaddr_storage));
if(err == PICO_ERR_EPROTONOSUPPORT)
@@ -593,7 +629,7 @@ namespace ZeroTier {
return err;
}
int picoTCP::pico_Bind(Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen)
int picoTCP::pico_Bind(Connection *conn, const struct sockaddr *addr, socklen_t addrlen)
{
//DEBUG_INFO();
if(!conn || !conn->picosock) {
@@ -647,7 +683,7 @@ namespace ZeroTier {
return err;
}
int picoTCP::pico_Listen(Connection *conn, int fd, int backlog)
int picoTCP::pico_Listen(Connection *conn, int backlog)
{
//DEBUG_INFO();
if(!conn || !conn->picosock) {
@@ -776,7 +812,7 @@ namespace ZeroTier {
{
int err = 0;
// TODO: Add RingBuffer overflow checks
//DEBUG_INFO("conn=%p, len = %d", conn, len);
DEBUG_INFO("conn=%p, len=%d", conn, len);
Mutex::Lock _l(conn->_tx_m);
if(len <= 0) {
DEBUG_ERROR("invalid write length (len=%d)", len);
@@ -793,14 +829,26 @@ namespace ZeroTier {
return -1;
}
if(conn->socket_type == SOCK_DGRAM)
{
int r;
if((r = pico_socket_write(conn->picosock, data, len)) < 0) {
DEBUG_ERROR("unable to write to picosock=%p, r=%d", conn->picosock, r);
err = -1;
}
else {
err = r; // successful write
}
DEBUG_TRANS("[ UDP TX -> STACK] :: conn=%p, len=%d, err=%s", conn, r, beautify_pico_error(pico_err));
}
if(conn->socket_type == SOCK_STREAM)
{
int original_txsz = conn->TXbuf->count();
if(original_txsz + len >= ZT_TCP_TX_BUF_SZ) {
DEBUG_ERROR("txsz = %d, len = %d", original_txsz, len);
DEBUG_ERROR("txsz=%d, len=%d", original_txsz, len);
DEBUG_ERROR("TX buffer is too small, try increasing ZT_TCP_TX_BUF_SZ in libzt.h");
exit(0);
}
int buf_w = conn->TXbuf->write((const unsigned char*)data, len);
if (buf_w != len) {
// because we checked ZT_TCP_TX_BUF_SZ above, this should not happen
@@ -810,9 +858,6 @@ namespace ZeroTier {
//DEBUG_INFO("TXbuf->count() = %d", conn->TXbuf->count());
int txsz = conn->TXbuf->count();
//if(original_txsz > 0)
// return; // don't write here, we already have stuff in the queue, a callback will handle it
int r, max_write_len = std::min(std::min(txsz, ZT_SDK_MTU),ZT_STACK_SOCKET_WR_MAX);
//int buf_r = conn->TXbuf->read(conn->tmptxbuf, max_write_len);
@@ -823,21 +868,17 @@ namespace ZeroTier {
else {
err = r; // successful write
}
if(conn->socket_type == SOCK_STREAM) {
//DEBUG_TRANS("[ TCP TX -> STACK] :: conn = %p, len = %d", conn, r);
}
if(conn->socket_type == SOCK_DGRAM) {
//DEBUG_TRANS("[ UDP TX -> STACK] :: conn = %p, len = %d", conn, r);
}
if(r>0)
if(r>0){
conn->TXbuf->consume(r);
}
DEBUG_TRANS("[ TCP TX -> STACK] :: conn=%p, len=%d", conn, r);
}
return err;
}
int picoTCP::pico_Close(Connection *conn)
{
DEBUG_INFO("conn = %p, picosock=%p, fd = %d", conn, conn->picosock, conn->app_fd);
DEBUG_INFO("conn=%p, picosock=%p, fd=%d", conn, conn->picosock, conn->app_fd);
if(!conn || !conn->picosock)
return ZT_ERR_GENERAL_FAILURE;
int err = 0;

View File

@@ -67,6 +67,10 @@
#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
namespace ZeroTier
{
@@ -92,6 +96,16 @@ namespace ZeroTier
*/
bool pico_init_interface(ZeroTier::SocketTap *tap, const ZeroTier::InetAddress &ip);
/*
* Adds a route to the picoTCP device
*/
bool pico_route_add(SocketTap *tap, const InetAddress &addr, const InetAddress &nm, const InetAddress &gw, int metric);
/*
* Deletes a route from the picoTCP device
*/
bool pico_route_del(SocketTap *tap, const InetAddress &addr, const InetAddress &nm, int metric);
/*
* Main stack loop
*/
@@ -130,17 +144,17 @@ namespace ZeroTier
/*
* Connect to remote host via userspace network stack interface - Called from SocketTap
*/
int pico_Connect(Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen);
int pico_Connect(Connection *conn, const struct sockaddr *addr, socklen_t addrlen);
/*
* Bind to a userspace network stack interface - Called from SocketTap
*/
int pico_Bind(Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen);
int pico_Bind(Connection *conn, const struct sockaddr *addr, socklen_t addrlen);
/*
* Listen for incoming connections - Called from SocketTap
*/
int pico_Listen(Connection *conn, int fd, int backlog);
int pico_Listen(Connection *conn, int backlog);
/*
* Accept an incoming connection - Called from SocketTap

View File

@@ -57,6 +57,10 @@ int main(int argc , char *argv[])
}
fprintf(stderr, "Created raw socket (%d)\n", fd);
#if defined(__APPLE__)
fprintf(stderr, "SOCK_RAW not supported on mac builds yet. exiting");
exit(0);
#endif
#if defined(__linux__) // The rest of this file isn't yet supported on non-linux platforms
// get interface index to bind on
struct ifreq if_idx;

View File

@@ -345,7 +345,7 @@ void udp_client_4(UNIT_TEST_SIG_4)
if((sockfd = zts_socket(AF_INET, SOCK_DGRAM, 0)) < 0)
DEBUG_ERROR("error creating ZeroTier socket");
w = zts_sendto(sockfd, str, strlen(str), 0, (struct sockaddr *)&addr, sizeof(addr));
w = zts_sendto(sockfd, str, strlen(str), 0, (struct sockaddr *)addr, sizeof(addr));
memset(rbuf, 0, sizeof(rbuf));
int serverlen = sizeof(addr);
r = zts_recvfrom(sockfd, rbuf, STR_SIZE, 0, (struct sockaddr *)&addr, (socklen_t *)&serverlen);
@@ -367,10 +367,13 @@ void udp_server_4(UNIT_TEST_SIG_4)
if((sockfd = zts_socket(AF_INET, SOCK_DGRAM, 0)) < 0)
DEBUG_ERROR("error creating ZeroTier socket");
if((err = zts_bind(sockfd, (struct sockaddr *)addr, sizeof(struct sockaddr_in)) < 0))
DEBUG_ERROR("error binding to interface (%d)", err);
int serverlen = sizeof(addr);
r = zts_recvfrom(sockfd, rbuf, STR_SIZE, 0, (struct sockaddr *)&addr, (socklen_t *)&serverlen);
memset(rbuf, 0, sizeof(rbuf));
w = zts_sendto(sockfd, str, strlen(str), 0, (struct sockaddr *)&addr, sizeof(addr));
w = zts_sendto(sockfd, str, strlen(str), 0, (struct sockaddr *)addr, sizeof(addr));
sleep(WAIT_FOR_TRANSMISSION_TO_COMPLETE);
err = zts_close(sockfd);
@@ -1159,6 +1162,23 @@ int obscure_api_test()
return err;
}
void get_network_routes(char *nwid)
{
// Retreive managed routes for a given ZeroTier network
std::vector<ZT_VirtualNetworkRoute> *routes = zts_get_network_routes(nwid);
for(int i=0; i<routes->size(); i++) {
struct sockaddr_in *target = (struct sockaddr_in*)&(routes->at(i).target);
struct sockaddr_in *via = (struct sockaddr_in*)&(routes->at(i).via);
char target_str[INET6_ADDRSTRLEN];
memset(target_str, 0, INET6_ADDRSTRLEN);
inet_ntop(AF_INET, (const void *)&((struct sockaddr_in *)target)->sin_addr.s_addr, target_str, INET_ADDRSTRLEN);
char via_str[INET6_ADDRSTRLEN];
memset(via_str, 0, INET6_ADDRSTRLEN);
inet_ntop(AF_INET, (const void *)&((struct sockaddr_in *)via)->sin_addr.s_addr, via_str, INET_ADDRSTRLEN);
DEBUG_INFO("<target=%s, via=%s, flags=%d>", target_str, via_str, routes->at(i).flags);
}
}
/****************************************************************************/
/* RANDOMIZED API TEST */
@@ -1433,6 +1453,7 @@ int main(int argc , char *argv[])
// ipv4 client/server
ipv = 4;
if(mode == TEST_MODE_SERVER) {
create_addr(local_ipstr, port, ipv, (struct sockaddr *)&addr);
@@ -1459,7 +1480,7 @@ int main(int argc , char *argv[])
port++;
// UDP
/*
if(mode == TEST_MODE_SERVER) {
create_addr(local_ipstr, port, ipv, (struct sockaddr *)&addr);
udp_server_4((struct sockaddr_in *)&addr, operation, count, delay, details, &passed); // tcp_server_4
@@ -1483,7 +1504,7 @@ int main(int argc , char *argv[])
}
RECORD_RESULTS(&test_number, passed, details, &results);
port++;
*/
// ipv4 sustained transfer
ipv = 4;
if(mode == TEST_MODE_SERVER) {