diff --git a/Makefile b/Makefile index 078d22d..b44e227 100644 --- a/Makefile +++ b/Makefile @@ -227,19 +227,6 @@ ifeq ($(STACK_LWIP),1) ifeq ($(NS_DEBUG),1) STACK_DEFS+=LWIP_DEBUG=1 endif -ifeq ($(LIBZT_IPV4)$(LIBZT_IPV6),1) -ifeq ($(LIBZT_IPV4),1) -STACK_DRIVER_DEFS+=-DLIBZT_IPV4 -DLWIP_IPV4=1 -STACK_DEFS+=LIBZT_IPV4=1 IPV4=1 -endif -ifeq ($(LIBZT_IPV6),1) -STACK_DRIVER_DEFS+=-DLIBZT_IPV6 -DLWIP_IPV6=1 -STACK_DEFS+=LIBZT_IPV6=1 IPV6=1 -endif -else -STACK_DRIVER_DEFS+=-DLIBZT_IPV4 -DLWIP_IPV4=1 -STACK_DEFS+=LIBZT_IPV4=1 -endif STACK_DRIVER_DEFS+=-DLWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS STACK_DRIVER_DEFS+=-DSTACK_LWIP STACK_DRIVER_FILES:=src/lwIP.cpp @@ -256,6 +243,9 @@ 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 + ############################################################################## ## Targets ## ############################################################################## diff --git a/ext/lwip/src/api/sockets.c b/ext/lwip/src/api/sockets.c index bfc1b17..d72724f 100755 --- a/ext/lwip/src/api/sockets.c +++ b/ext/lwip/src/api/sockets.c @@ -573,12 +573,9 @@ lwip_bind(int s, const struct sockaddr *name, socklen_t namelen) } /* check size, family and alignment of 'name' */ -/* LWIP_ERROR("lwip_bind: invalid address", (IS_SOCK_ADDR_LEN_VALID(namelen) && IS_SOCK_ADDR_TYPE_VALID(name) && IS_SOCK_ADDR_ALIGNED(name)), sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); -*/ - LWIP_UNUSED_ARG(namelen); SOCKADDR_TO_IPADDR_PORT(name, &local_addr, local_port); @@ -661,19 +658,10 @@ lwip_connect(int s, const struct sockaddr *name, socklen_t namelen) } LWIP_UNUSED_ARG(namelen); - - if ( -#ifdef __MINGW32__ - false -#else - name->sa_family == AF_UNSPEC -#endif - ) - { + if (name->sa_family == AF_UNSPEC) { LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, AF_UNSPEC)\n", s)); err = netconn_disconnect(sock->conn); - } - else { + } else { ip_addr_t remote_addr; u16_t remote_port; @@ -1158,12 +1146,10 @@ lwip_sendto(int s, const void *data, size_t size, int flags, /* @todo: split into multiple sendto's? */ LWIP_ASSERT("lwip_sendto: size must fit in u16_t", size <= 0xffff); short_size = (u16_t)size; - /* LWIP_ERROR("lwip_sendto: invalid address", (((to == NULL) && (tolen == 0)) || (IS_SOCK_ADDR_LEN_VALID(tolen) && IS_SOCK_ADDR_TYPE_VALID(to) && IS_SOCK_ADDR_ALIGNED(to))), sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); - */ LWIP_UNUSED_ARG(tolen); /* initialize a buffer */ diff --git a/include/lwipopts.h b/include/lwipopts.h index 194d680..ab35bab 100644 --- a/include/lwipopts.h +++ b/include/lwipopts.h @@ -47,7 +47,7 @@ /* * Provides core locking machinery */ -#define LWIP_TCPIP_CORE_LOCKING 1 +#define LWIP_TCPIP_CORE_LOCKING 0 /* * Provides a macro to spoof the names of the lwip socket functions @@ -78,14 +78,8 @@ #include "lwip/debug.h" // IP Protocol version -#if defined(LIBZT_IPV6) - #define LWIP_IPV6 1 - #define LWIP_IPV4 0 -#endif -#if defined(LIBZT_IPV4) - #define LWIP_IPV4 1 - #define LWIP_IPV6 0 -#endif +#define LWIP_IPV6 1 +#define LWIP_IPV4 1 // --- DEBUG --- @@ -182,7 +176,7 @@ remote peer. #define TCP_WND 0xffff // max = 0xffff, min = TCP_MSS*2 -//#define LWIP_NOASSERT 1 +#define LWIP_NOASSERT 1 #define TCP_LISTEN_BACKLOG 0 /*------------------------------------------------------------------------------ diff --git a/make-liblwip.mk b/make-liblwip.mk index 07c03a6..0a8fe69 100644 --- a/make-liblwip.mk +++ b/make-liblwip.mk @@ -68,12 +68,12 @@ CFLAGS=$(WINDEFS) -Wno-format -Wno-deprecated -O3 -g -Wall -fPIC $(LWIPINCLUDES) ifeq ($(NS_DEBUG),1) CFLAGS+=-DLWIP_DEBUG=1 endif -ifeq ($(IPV4),1) -CFLAGS+=-DLWIP_IPV4=1 -DLWIP_IPV6=0 -DIPv4 -endif -ifeq ($(IPV6),1) -CFLAGS+=-DLWIP_IPV4=0 -DLWIP_IPV6=1 -DIPv6 -endif +#ifeq ($(IPV4),1) +CFLAGS+=-DLWIP_IPV4=1 -DIPv4 +#endif +#ifeq ($(IPV6),1) +CFLAGS+=-DLWIP_IPV6=1 -DIPv6 +#endif UNIXLIB=liblwip.a diff --git a/src/VirtualBindingPair.cpp b/src/VirtualBindingPair.cpp index f0ca48d..7917e2f 100644 --- a/src/VirtualBindingPair.cpp +++ b/src/VirtualBindingPair.cpp @@ -30,22 +30,4 @@ * */ -/* -#include "VirtualSocket.h" -#include "VirtualTap.hpp" - -#ifdef __cplusplus -extern "C" { -#endif - -struct VirtualBindingPair -{ - VirtualTap *tap; - VirtualSocket *vs; - VirtualBindingPair(VirtualTap *_tap, VirtualSocket *_vs) : tap(_tap), vs(_vs) {} -}; - -#ifdef __cplusplus -} -#endif -*/ +// Only available in experimental branch diff --git a/src/VirtualSocket.cpp b/src/VirtualSocket.cpp index f19edc4..8d48e80 100644 --- a/src/VirtualSocket.cpp +++ b/src/VirtualSocket.cpp @@ -114,6 +114,7 @@ namespace ZeroTier { } VirtualSocket() { + // Only available in experimental branch } ~VirtualSocket() { } diff --git a/src/ZT1Service.cpp b/src/ZT1Service.cpp index 64b025d..8fc33a4 100644 --- a/src/ZT1Service.cpp +++ b/src/ZT1Service.cpp @@ -180,7 +180,7 @@ int zts_get_id_from_file(const char *filepath, char *devID) // Starts a ZeroTier service in the background void *zts_start_service(void *thread_id) { - DEBUG_INFO("path=%s", ZeroTier::homeDir.c_str()); + DEBUG_INFO("zto-thread, path=%s", ZeroTier::homeDir.c_str()); // Where network .conf files will be stored ZeroTier::netDir = ZeroTier::homeDir + "/networks.d"; ZeroTier::zt1Service = (ZeroTier::OneService *)0; @@ -437,6 +437,7 @@ int zts_start(const char *path, bool blocking = false) ZeroTier::zt1Service->getNode()->status(&status); } } + return err; } int zts_startjoin(const char *path, const char *nwid) diff --git a/src/libzt.cpp b/src/libzt.cpp index 6d4a9da..d808dec 100644 --- a/src/libzt.cpp +++ b/src/libzt.cpp @@ -49,58 +49,66 @@ extern "C" { #endif -#if defined(STACK_LWIP) -void sys2lwip(int fd, const struct sockaddr *orig, struct sockaddr *modified) +/* The rationale for the following correctional methods is as follows: + + Since we don't want the user of this library to worry about naming conflicts + with their native OS/platform's socket facilities we deliberately isolate what + is used by the userspace network stack and stack drivers from the user's + application. As a result of this, we must compensate for a few things on our + side. For instance, differing values for AF_INET6 on major operating systems, and + differing structure definitions for sockaddr. +*/ + +/* adjust socket_family value (when AF_INET6) for various platforms: + linux : 10 + macOS : 30 + windows: 23 +*/ +int platform_adjusted_socket_family(int family) { - /* Inelegant fix for lwIP 'sequential' API address error check (in sockets.c). For some reason - lwIP seems to lose track of the sa_family for the socket internally, when lwip_connect() - is called, it thus receives an AF_UNSPEC socket which fails. Here we use lwIP's own facilities - to get the sa_family ourselves and rebuild the address structure and pass it to lwip_connect(). - I suspect this is due to a struct memory alignment issue or my own misuse of the API */ - struct sockaddr_storage ss; - socklen_t namelen = sizeof(ss); - int err = 0; - if ((err = lwip_getsockname(fd, (struct sockaddr*)&ss, &namelen)) < 0) { - DEBUG_ERROR("error while determining socket family"); - return; - } -#if defined(LIBZT_IPV4) - if (ss.ss_family == AF_INET) { -#if defined(__linux__) || defined(__MINGW32__) - struct sockaddr_in *p4 = (struct sockaddr_in *)modified; - struct sockaddr_in *addr4 = (struct sockaddr_in*)orig; - p4->sin_len = sizeof(struct sockaddr_in); - p4->sin_family = ss.ss_family; - p4->sin_port = addr4->sin_port; - p4->sin_addr.s_addr = addr4->sin_addr.s_addr; -#endif // __linux__ - memcpy(modified, orig, sizeof(struct sockaddr_in)); - } -#endif // LIBZT_IPV4 - -#if defined(LIBZT_IPV6) - if (ss.ss_family == AF_INET6) { -#if defined(__linux__) || defined(__MINGW32__) - struct sockaddr_in6 *p6 = (struct sockaddr_in6 *)modified; - struct sockaddr_in6 *addr6 = (struct sockaddr_in6*)orig; - p6->sin6_len = sizeof(struct sockaddr_in6); - p6->sin6_family = ss.ss_family; - p6->sin6_port = addr6->sin6_port; - //p6->sin6_addr.s6_addr = addr6->sin6_addr.s6_addr; -#endif // __linux__ - memcpy(modified, orig, sizeof(struct sockaddr_in6)); - } -#endif // LIBZT_IPV6 - +#if defined(__linux__) + return family; // do nothing +#endif +#if defined(__APPLE__) + return family == 30 ? AF_INET6 : family; // 10 +#endif +#if defined(__MINGW32__) || defined(__MINGW64__) + return family == 23 ? AF_INET6 : family; // 10 +#endif +} + +void fix_addr_socket_family(struct sockaddr *addr) +{ +#if defined(__linux__) + /* linux's socket.h's sockaddr definition doesn't contain an sa_len field + so we must compensate here before feeding it into the stack. Due to this limitation + we must cast the pointer to the address into two different address + */ + if (addr->sa_len == 2) { + if (addr->sa_family == 0) { + addr->sa_family = addr->sa_len; + addr->sa_len = 0; + } + } + if (addr->sa_len == 10 || addr->sa_len == 23 || addr->sa_len == 30) { + if (addr->sa_family == 0) { + addr->sa_family = addr->sa_len; + addr->sa_len = 0; + } + } + /* once we've moved the value to its anticipated location, convert it from + its platform-specific value to one that the network stack can work with */ +#endif + addr->sa_family = platform_adjusted_socket_family(addr->sa_family); } -#endif // STACK_LWIP int zts_socket(int socket_family, int socket_type, int protocol) { int err = -1; + int socket_family_adj = platform_adjusted_socket_family(socket_family); DEBUG_EXTRA("family=%d, type=%d, proto=%d", socket_family, socket_type, protocol); #if defined(STACK_LWIP) - err = lwip_socket(socket_family, socket_type, protocol); + err = lwip_socket(socket_family_adj, socket_type, protocol); #endif #if defined(STCK_PICO) #endif @@ -115,7 +123,8 @@ int zts_connect(int fd, const struct sockaddr *addr, socklen_t addrlen) DEBUG_EXTRA("fd=%d",fd); #if defined(STACK_LWIP) struct sockaddr_storage ss; - sys2lwip(fd, addr, (struct sockaddr*)&ss); + memcpy(&ss, addr, addrlen); + fix_addr_socket_family((struct sockaddr*)&ss); err = lwip_connect(fd, (struct sockaddr*)&ss, addrlen); #endif #if defined(STCK_PICO) @@ -131,7 +140,8 @@ int zts_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) DEBUG_EXTRA("fd=%d", fd); #if defined(STACK_LWIP) struct sockaddr_storage ss; - sys2lwip(fd, addr, (struct sockaddr*)&ss); + memcpy(&ss, addr, addrlen); + fix_addr_socket_family((struct sockaddr*)&ss); err = lwip_bind(fd, (struct sockaddr*)&ss, addrlen); #endif #if defined(STCK_PICO) @@ -343,13 +353,20 @@ int zts_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, int zts_fcntl(int fd, int cmd, int flags) { int err = -1; - DEBUG_EXTRA("fd=%p, cmd=%d, flags=%d", cmd, flags); + DEBUG_EXTRA("fd=%d, cmd=%d, flags=%d", fd, cmd, flags); #if defined(STACK_LWIP) - // translation required since lwIP uses different flag values + // translation from platform flag values to stack flag values int translated_flags = 0; +#if defined(__linux__) if (flags == 2048) { translated_flags = 1; } +#endif +#if defined(__APPLE__) + if (flags == 4) { + translated_flags = 1; + } +#endif err = lwip_fcntl(fd, cmd, translated_flags); #endif #if defined(STCK_PICO) @@ -380,7 +397,8 @@ ssize_t zts_sendto(int fd, const void *buf, size_t len, int flags, DEBUG_TRANS("fd=%d, len=%d", fd, len); #if defined(STACK_LWIP) struct sockaddr_storage ss; - sys2lwip(fd, addr, (struct sockaddr*)&ss); + memcpy(&ss, addr, addrlen); + fix_addr_socket_family((struct sockaddr*)&ss); err = lwip_sendto(fd, buf, len, flags, (struct sockaddr*)&ss, addrlen); #endif #if defined(STCK_PICO) @@ -508,10 +526,10 @@ int zts_add_dns_nameserver(struct sockaddr *addr) int err = -1; #if defined(STACK_LWIP) && defined(LIBZT_IPV4) struct sockaddr_in *in4 = (struct sockaddr_in*)&addr; - static ip_addr_t ipaddr; + static ip4_addr_t ipaddr; ipaddr.addr = in4->sin_addr.s_addr; // TODO: manage DNS server indices - dns_setserver(0, &ipaddr); + dns_setserver(0, (const ip_addr_t*)&ipaddr); err = 0; #endif #if defined(STCK_PICO) diff --git a/src/lwIP.cpp b/src/lwIP.cpp index e02d26a..5ac40e7 100644 --- a/src/lwIP.cpp +++ b/src/lwIP.cpp @@ -90,10 +90,10 @@ static void tcp_timeout(void *data) // callback for when the TCPIP thread has been successfully started static void tcpip_init_done(void *arg) { + DEBUG_EXTRA("tcpip-thread"); sys_sem_t *sem; sem = (sys_sem_t *)arg; netif_set_up(&lwipdev); - DEBUG_EXTRA("lwIP stack driver initialized"); lwip_driver_initialized = true; driver_m.unlock(); // sys_timeout(5000, tcp_timeout, NULL); @@ -101,7 +101,7 @@ static void tcpip_init_done(void *arg) } // main thread which starts the initialization process -static void main_network_stack_thread(void *arg) +static void main_thread(void *arg) { sys_sem_t sem; LWIP_UNUSED_ARG(arg); @@ -110,13 +110,14 @@ static void main_network_stack_thread(void *arg) } tcpip_init(tcpip_init_done, &sem); sys_sem_wait(&sem); - DEBUG_EXTRA("tcpip thread started"); - sys_sem_wait(&sem); + DEBUG_EXTRA("stack thread init complete"); + sys_sem_wait(&sem); // block forever } // initialize the lwIP stack void lwip_driver_init() { + DEBUG_EXTRA(); driver_m.lock(); // unlocked from callback indicating completion of driver init if (lwip_driver_initialized == true) { return; @@ -124,13 +125,12 @@ void lwip_driver_init() #if defined(__MINGW32__) sys_init(); // required for win32 initializtion of critical sections #endif - sys_thread_new("main_network_stack_thread", main_network_stack_thread, + sys_thread_new("main_thread", main_thread, NULL, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO); } err_t lwip_eth_tx(struct netif *netif, struct pbuf *p) { - DEBUG_INFO(); struct pbuf *q; char buf[ZT_MAX_MTU+32]; char *bufptr; @@ -187,7 +187,7 @@ void lwip_init_interface(void *tapref, const ZeroTier::MAC &mac, const ZeroTier: char ipbuf[INET6_ADDRSTRLEN], nmbuf[INET6_ADDRSTRLEN]; #if defined(LIBZT_IPV4) if (ip.isV4()) { - static ip_addr_t ipaddr, netmask, gw; + static ip4_addr_t ipaddr, netmask, gw; IP4_ADDR(&gw,127,0,0,1); ipaddr.addr = *((u32_t *)ip.rawIpData()); netmask.addr = *((u32_t *)ip.netmask().rawIpData()); @@ -215,7 +215,7 @@ void lwip_init_interface(void *tapref, const ZeroTier::MAC &mac, const ZeroTier: #endif #if defined(LIBZT_IPV6) if (ip.isV6()) { - static ip_addr_t ipaddr; + static ip6_addr_t ipaddr; memcpy(&(ipaddr.addr), ip.rawIpData(), sizeof(ipaddr.addr)); lwipdev6.mtu = ZT_MAX_MTU; @@ -226,7 +226,7 @@ void lwip_init_interface(void *tapref, const ZeroTier::MAC &mac, const ZeroTier: lwipdev6.ip6_autoconfig_enabled = 1; mac.copyTo(lwipdev6.hwaddr, lwipdev6.hwaddr_len); - netif_add(&lwipdev6, NULL, tapif_init, ethernet_input); + netif_add(&lwipdev6, NULL, NULL, NULL, NULL, tapif_init, ethernet_input); lwipdev6.output_ip6 = ethip6_output; lwipdev6.state = tapref; @@ -291,13 +291,20 @@ void lwip_eth_rx(ZeroTier::VirtualTap *tap, const ZeroTier::MAC &from, const Zer // TODO: Routing logic #if defined(LIBZT_IPV4) - if (lwipdev.input(p, &lwipdev) != ERR_OK) { - DEBUG_ERROR("error while feeding frame into stack interface (ipv4)"); + // feed in IPV4 and ARP + if (ZeroTier::Utils::ntoh(ethhdr.type) == 0x800 || ZeroTier::Utils::ntoh(ethhdr.type) == 0x0806) { + DEBUG_INFO("Inputting to lwipdev"); + if (lwipdev.input(p, &lwipdev) != ERR_OK) { + DEBUG_ERROR("error while feeding frame into stack interface (ipv4)"); + } } #endif #if defined(LIBZT_IPV6) - if (lwipdev6.input(p, &lwipdev6) != ERR_OK) { - DEBUG_ERROR("error while feeding frame into stack interface (ipv6)"); + if (ZeroTier::Utils::ntoh(ethhdr.type) == 0x86dd) { + DEBUG_INFO("Inputting to lwipdev6"); + if (lwipdev6.input(p, &lwipdev6) != ERR_OK) { + DEBUG_ERROR("error while feeding frame into stack interface (ipv6)"); + } } #endif }