From 2ac133b435f2bf65ef79a48ebb303b49e5139b23 Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Fri, 25 Jan 2019 10:38:39 -0800 Subject: [PATCH] Removed files from attic/ --- attic/SysUtils.cpp | 45 - attic/SysUtils.h | 72 -- attic/Utilities.cpp | 266 ----- attic/Utilities.h | 73 -- attic/VirtualBindingPair.h | 54 - attic/VirtualSocket.cpp | 105 -- attic/VirtualSocket.h | 159 --- attic/VirtualSocketLayer.cpp | 1250 --------------------- attic/VirtualSocketLayer.h | 443 -------- attic/ZT1Service.cpp | 712 ------------ attic/ZT1Service.h | 33 - attic/libztJNI.cpp | 541 ---------- attic/picoTCP.cpp | 1979 ---------------------------------- attic/picoTCP.h | 222 ---- 14 files changed, 5954 deletions(-) delete mode 100644 attic/SysUtils.cpp delete mode 100644 attic/SysUtils.h delete mode 100644 attic/Utilities.cpp delete mode 100644 attic/Utilities.h delete mode 100644 attic/VirtualBindingPair.h delete mode 100644 attic/VirtualSocket.cpp delete mode 100644 attic/VirtualSocket.h delete mode 100644 attic/VirtualSocketLayer.cpp delete mode 100644 attic/VirtualSocketLayer.h delete mode 100644 attic/ZT1Service.cpp delete mode 100644 attic/ZT1Service.h delete mode 100644 attic/libztJNI.cpp delete mode 100644 attic/picoTCP.cpp delete mode 100644 attic/picoTCP.h diff --git a/attic/SysUtils.cpp b/attic/SysUtils.cpp deleted file mode 100644 index 767f0cf..0000000 --- a/attic/SysUtils.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2018 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 . - * - * -- - * - * 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 - * - * Platform-specific implementations of common functions - */ - -/* -#if defined(__linux__) || defined(__APPLE__) -#include -#include -#endif - -#include - -#ifdef __linux__ -#include -#include -#endif -*/ \ No newline at end of file diff --git a/attic/SysUtils.h b/attic/SysUtils.h deleted file mode 100644 index 6ff0855..0000000 --- a/attic/SysUtils.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2018 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 . - * - * -- - * - * 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 - * - * Platform-specific implementations of common functions - */ - -#ifndef LIBZT_SYSUTILS_H -#define LIBZT_SYSUTILS_H - -#include - -#ifdef _WIN32 -#include -#else -#include -#endif - -/** - * @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 _WIN32 - 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 diff --git a/attic/Utilities.cpp b/attic/Utilities.cpp deleted file mode 100644 index 6c7daee..0000000 --- a/attic/Utilities.cpp +++ /dev/null @@ -1,266 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2018 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 . - * - * -- - * - * 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 - * - * Misc utilities - */ - -/* -#include "Utilities.h" - -#if defined(_WIN32_FALSE) - -#include -#include -#include - -int inet_pton4(const char *src, void *dst) -{ - uint8_t tmp[NS_INADDRSZ], *tp; - - int saw_digit = 0; - int octets = 0; - *(tp = tmp) = 0; - - int ch; - while ((ch = *src++) != '\0') - { - if (ch >= '0' && ch <= '9') - { - uint32_t n = *tp * 10 + (ch - '0'); - - if (saw_digit && *tp == 0) - return 0; - - if (n > 255) - return 0; - - *tp = n; - if (!saw_digit) - { - if (++octets > 4) - return 0; - saw_digit = 1; - } - } - else if (ch == '.' && saw_digit) - { - if (octets == 4) - return 0; - *++tp = 0; - saw_digit = 0; - } - else - return 0; - } - if (octets < 4) - return 0; - - memcpy(dst, tmp, NS_INADDRSZ); - - return 1; -} -*/ - -/* -int inet_pton6(const char *src, void *dst) -{ - static const char xdigits[] = "0123456789abcdef"; - uint8_t tmp[NS_IN6ADDRSZ]; - - uint8_t *tp = (uint8_t*) memset(tmp, '\0', NS_IN6ADDRSZ); - uint8_t *endp = tp + NS_IN6ADDRSZ; - uint8_t *colonp = NULL; - - // Leading :: requires some special handling. - if (*src == ':') - { - if (*++src != ':') - return 0; - } - - const char *curtok = src; - int saw_xdigit = 0; - uint32_t val = 0; - int ch; - while ((ch = tolower(*src++)) != '\0') - { - const char *pch = strchr(xdigits, ch); - if (pch != NULL) - { - val <<= 4; - val |= (pch - xdigits); - if (val > 0xffff) - return 0; - saw_xdigit = 1; - continue; - } - if (ch == ':') - { - curtok = src; - if (!saw_xdigit) - { - if (colonp) - return 0; - colonp = tp; - continue; - } - else if (*src == '\0') - { - return 0; - } - if (tp + NS_INT16SZ > endp) - return 0; - *tp++ = (uint8_t) (val >> 8) & 0xff; - *tp++ = (uint8_t) val & 0xff; - saw_xdigit = 0; - val = 0; - continue; - } - if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && - inet_pton4(curtok, (char*) tp) > 0) - { - tp += NS_INADDRSZ; - saw_xdigit = 0; - break; // '\0' was seen by inet_pton4(). - } - return 0; - } - if (saw_xdigit) - { - if (tp + NS_INT16SZ > endp) - return 0; - *tp++ = (uint8_t) (val >> 8) & 0xff; - *tp++ = (uint8_t) val & 0xff; - } - if (colonp != NULL) - { - // - // Since some memmove()'s erroneously fail to handle - // overlapping regions, we'll do the shift by hand. - // - const int n = tp - colonp; - - if (tp == endp) - return 0; - - for (int i = 1; i <= n; i++) - { - endp[-i] = colonp[n - i]; - colonp[n - i] = 0; - } - tp = endp; - } - if (tp != endp) - return 0; - - memcpy(dst, tmp, NS_IN6ADDRSZ); - - return 1; -} -*/ - -/* -int inet_pton(int af, const char *src, void *dst) -{ - switch (af) - { - case AF_INET: - return inet_pton4(src, dst); - case AF_INET6: - return inet_pton6(src, dst); - default: - return -1; - } -} - -#endif - -char *beautify_eth_proto_nums(int proto) -{ - if (proto == 0x0800) return (char*)"IPv4"; - if (proto == 0x0806) return (char*)"ARP"; - if (proto == 0x0842) return (char*)"Wake-on-LAN"; - if (proto == 0x22F3) return (char*)"IETF TRILL Protocol"; - if (proto == 0x22EA) return (char*)"Stream Reservation Protocol"; - if (proto == 0x6003) return (char*)"DECnet Phase IV"; - if (proto == 0x8035) return (char*)"Reverse Address Resolution Protocol"; - if (proto == 0x809B) return (char*)"AppleTalk (Ethertalk)"; - if (proto == 0x80F3) return (char*)"AppleTalk Address Resolution Protocol (AARP)"; - if (proto == 0x8100) return (char*)"VLAN-tagged frame (IEEE 802.1Q) and Shortest Path Bridging IEEE 802.1aq with NNI compatibility"; - if (proto == 0x8137) return (char*)"IPX"; - if (proto == 0x8204) return (char*)"QNX Qnet"; - if (proto == 0x86DD) return (char*)"IPv6"; - if (proto == 0x8808) return (char*)"Ethernet flow control"; - if (proto == 0x8809) return (char*)"Ethernet Slow Protocols"; - if (proto == 0x8819) return (char*)"CobraNet"; - if (proto == 0x8847) return (char*)"MPLS unicast"; - if (proto == 0x8848) return (char*)"MPLS multicast"; - if (proto == 0x8863) return (char*)"PPPoE Discovery Stage"; - if (proto == 0x8864) return (char*)"PPPoE Session Stage"; - if (proto == 0x886D) return (char*)"Intel Advanced Networking Services"; - if (proto == 0x8870) return (char*)"Jumbo Frames (Obsoleted draft-ietf-isis-ext-eth-01)"; - if (proto == 0x887B) return (char*)"HomePlug 1.0 MME"; - if (proto == 0x888E) return (char*)"EAP over LAN (IEEE 802.1X)"; - if (proto == 0x8892) return (char*)"PROFINET Protocol"; - if (proto == 0x889A) return (char*)"HyperSCSI (SCSI over Ethernet)"; - if (proto == 0x88A2) return (char*)"ATA over Ethernet"; - if (proto == 0x88A4) return (char*)"EtherCAT Protocol"; - if (proto == 0x88A8) return (char*)"Provider Bridging (IEEE 802.1ad) & Shortest Path Bridging IEEE 802.1aq"; - if (proto == 0x88AB) return (char*)"Ethernet Powerlink[citation needed]"; - if (proto == 0x88B8) return (char*)"GOOSE (Generic Object Oriented Substation event)"; - if (proto == 0x88B9) return (char*)"GSE (Generic Substation Events) Management Services"; - if (proto == 0x88BA) return (char*)"SV (Sampled Value Transmission)"; - if (proto == 0x88CC) return (char*)"Link Layer Discovery Protocol (LLDP)"; - if (proto == 0x88CD) return (char*)"SERCOS III"; - if (proto == 0x88DC) return (char*)"WSMP, WAVE Short Message Protocol"; - if (proto == 0x88E1) return (char*)"HomePlug AV MME[citation needed]"; - if (proto == 0x88E3) return (char*)"Media Redundancy Protocol (IEC62439-2)"; - if (proto == 0x88E5) return (char*)"MAC security (IEEE 802.1AE)"; - if (proto == 0x88E7) return (char*)"Provider Backbone Bridges (PBB) (IEEE 802.1ah)"; - if (proto == 0x88F7) return (char*)"Precision Time Protocol (PTP) over Ethernet (IEEE 1588)"; - if (proto == 0x88FB) return (char*)"Parallel Redundancy Protocol (PRP)"; - if (proto == 0x8902) return (char*)"IEEE 802.1ag Connectivity Fault Management (CFM) Protocol / ITU-T Recommendation Y.1731 (OAM)"; - if (proto == 0x8906) return (char*)"Fibre Channel over Ethernet (FCoE)"; - if (proto == 0x8914) return (char*)"FCoE Initialization Protocol"; - if (proto == 0x8915) return (char*)"RDMA over Converged Ethernet (RoCE)"; - if (proto == 0x891D) return (char*)"TTEthernet Protocol Control Frame (TTE)"; - if (proto == 0x892F) return (char*)"High-availability Seamless Redundancy (HSR)"; - if (proto == 0x9000) return (char*)"Ethernet Configuration Testing Protocol"; - if (proto == 0x9100) return (char*)"VLAN-tagged (IEEE 802.1Q) frame with double tagging"; - return (char*)"UNKNOWN"; -} -*/ - -/* -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]); -} -*/ diff --git a/attic/Utilities.h b/attic/Utilities.h deleted file mode 100644 index 12601bd..0000000 --- a/attic/Utilities.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2018 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 . - * - * -- - * - * 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 - * - * Misc utilities - */ - -#ifndef LIBZT_UTILITIES_H -#define LIBZT_UTILITIES_H - -#include - -namespace ZeroTier { - struct InetAddress; -} - -#if defined(_WIN32_FALSE) - -#define NS_INADDRSZ 4 -#define NS_IN6ADDRSZ 16 -#define NS_INT16SZ 2 - -int inet_pton4(const char *src, void *dst); -int inet_pton6(const char *src, void *dst); -int inet_pton(int af, const char *src, void *dst); -#endif - -/** - * @brief Convert protocol numbers to human-readable strings - * - * @usage For internal use only. - * @param proto - * @return - */ -char *beautify_eth_proto_nums(int proto); - -/** - * @brief Convert a raw MAC address byte array into a human-readable string - * - * @usage For internal use only. - * @param macbuf - * @param len - * @param addr - * @return - */ -void mac2str(char *macbuf, int len, unsigned char* addr); - -#endif // _H diff --git a/attic/VirtualBindingPair.h b/attic/VirtualBindingPair.h deleted file mode 100644 index c852278..0000000 --- a/attic/VirtualBindingPair.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2018 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 . - * - * -- - * - * 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 - * - * - */ - -#ifndef LIBZT_VIRTUALBINDINGPAIR_H -#define LIBZT_VIRTUALBINDINGPAIR_H - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * 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 -} -#endif - -#endif // _H diff --git a/attic/VirtualSocket.cpp b/attic/VirtualSocket.cpp deleted file mode 100644 index dc287df..0000000 --- a/attic/VirtualSocket.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2018 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 . - * - * -- - * - * 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 - * - * Platform- and stack-agnostic implementation of a socket-like object - */ - -#include "libztDefs.h" - -#ifdef ZT_VIRTUAL_SOCKET - -#include -#include - -#include "Phy.hpp" - -#include "libzt.h" -#include "libztDebug.h" -#include "VirtualSocket.h" -#include "VirtualTap.h" -#include "RingBuffer.h" - -class VirtualTap; - -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(); -} - -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 diff --git a/attic/VirtualSocket.h b/attic/VirtualSocket.h deleted file mode 100644 index 1b7fc0e..0000000 --- a/attic/VirtualSocket.h +++ /dev/null @@ -1,159 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2018 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 . - * - * -- - * - * 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 - * - * Platform- and stack-agnostic implementation of a socket-like object - */ - -#ifndef LIBZT_VIRTUALSOCKET_H -#define LIBZT_VIRTUALSOCKET_H - -#include - -#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 - -/** - * An abstraction of a socket that operates between the application-exposed platform-sockets - * 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 -{ - 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 _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 -} -#endif - -#endif // _H diff --git a/attic/VirtualSocketLayer.cpp b/attic/VirtualSocketLayer.cpp deleted file mode 100644 index 02bee0a..0000000 --- a/attic/VirtualSocketLayer.cpp +++ /dev/null @@ -1,1250 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2018 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 . - * - * -- - * - * 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 "libztDefs.h" - -#ifdef ZT_VIRTUAL_SOCKET - -#ifdef __linux__ -#include -#include -#include -#endif - -extern int errno; - -#include "libzt.h" -#include "VirtualTap.h" -#include "RingBuffer.h" -#include "VirtualSocket.h" -#include "VirtualSocketLayer.h" -#include "VirtualBindingPair.h" -#include "ZT1Service.h" -#include "Utilities.h" - -#ifdef STACK_LWIP -#include "lwIP.h" -//#include "lwip/sockets.h" -#endif - -#ifdef STACK_PICO -#include "picoTCP.h" -#include "pico_stack.h" -#include "pico_socket.h" -#endif - -#include -#include - -std::map*> fdmap; -std::map unmap; - -// externs from VirtualSocketLayer.h -//std::map unmap; -//std::map*> fdmap; - -// int socket_family, int socket_type, int protocol -int virt_socket(int socket_family, int socket_type, int protocol) { - DEBUG_EXTRA(); - int err = errno = 0; - if (socket_family < 0 || socket_type < 0 || protocol < 0) { - errno = EINVAL; - return -1; - } - if (socket_type == SOCK_SEQPACKET) { - DEBUG_ERROR("SOCK_SEQPACKET not yet supported."); - errno = EPROTONOSUPPORT; // seemingly closest match - return -1; - } - if (socket_type == SOCK_RAW) { - // VirtualSocket is only used to associate a socket with a VirtualTap, it has no other implication - VirtualSocket *vs = new VirtualSocket(); - vs->socket_family = socket_family; - vs->socket_type = socket_type; - vs->protocol = protocol; - add_unassigned_virt_socket(vs->app_fd, vs); - return vs->app_fd; - } -#if defined(STACK_PICO) - struct pico_socket *p; - err = rd_pico_socket(&p, socket_family, socket_type, protocol); - if (err == false && p) { - VirtualSocket *vs = new VirtualSocket(); - vs->socket_family = socket_family; - vs->socket_type = socket_type; - vs->pcb = p; - add_unassigned_virt_socket(vs->app_fd, vs); - err = vs->app_fd; // return one end of the socketpair - } - else { - DEBUG_ERROR("failed to create pico_socket"); - errno = ENOMEM; - err = -1; - } -#endif -#if defined(STACK_LWIP) - // TODO: check for max lwIP timers/sockets - void *pcb; - err = rd_lwip_socket(&pcb, socket_family, socket_type, protocol); - if (pcb) { - VirtualSocket *vs = new VirtualSocket(); - vs->socket_family = socket_family; - vs->socket_type = socket_type; - vs->pcb = pcb; - add_unassigned_virt_socket(vs->app_fd, vs); - // return one end of the socketpair for the app to use - err = vs->app_fd; - } - else { - DEBUG_ERROR("failed to create lwip pcb"); - errno = ENOMEM; - err = -1; - } -#endif - -//#if defined(DEFAULT_VS_LINGER) - /* - if (socket_type == SOCK_STREAM) { - linger lin; - unsigned int y=sizeof(lin); - lin.l_onoff=1; - lin.l_linger=10; - int fd = err; - if ((err = virt_setsockopt(fd, SOL_SOCKET, SO_LINGER, (void*)(&lin), y)) < 0) { - DEBUG_ERROR("error while setting default linger time on socket"); - errno = -1; // TODO - return -1; - } - err = fd; - } - */ -//#endif - return err; -} - -int virt_connect(int fd, const struct sockaddr *addr, socklen_t addrlen) { - DEBUG_INFO("fd=%d",fd); - int err = errno = 0; - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - VirtualSocket *vs = get_virt_socket(fd); - if (vs == NULL) { - DEBUG_ERROR("invalid socket, unable to locate VirtualSocket for fd=%d", fd); - errno = EBADF; - return -1; - } - struct pico_socket *ps = (struct pico_socket*)(vs->pcb); - if (addr == NULL) { - DEBUG_ERROR("invalid address for fd=%d", fd); - errno = EINVAL; - return -1; - } - if (addrlen <= 0) { - DEBUG_ERROR("invalid address length for fd=%d", fd); - errno = EINVAL; - return -1; - } - // TODO: Handle bad address lengths, right now this call will still - // succeed with a complete connect despite a bad address length. - // DEBUG_EXTRA("fd = %d, %s : %d", fd, ipstr, ntohs(port)); - ZeroTier::InetAddress inet; - sockaddr2inet(vs->socket_family, addr, &inet); - VirtualTap *tap = getTapByAddr(&inet); - if (tap == NULL) { - DEBUG_ERROR("no route to host, could not find appropriate VirtualTap for fd=%d", fd); - errno = ENETUNREACH; - return -1; - } - -#if defined(STACK_PICO) - // pointer to virtual tap we use in callbacks from the stack - - ps->priv = new VirtualBindingPair(tap, vs); -#endif -#if defined(STACK_LWIP) -#endif - - if ((err = tap->Connect(vs, addr, addrlen)) < 0) { - DEBUG_ERROR("error while connecting socket"); - // errno will be set by tap->Connect - return -1; - } - // assign this VirtualSocket to the tap we decided on - tap->_VirtualSockets.push_back(vs); - vs->tap = tap; - vs->sock = tap->_phy.wrapSocket(vs->sdk_fd, vs); - - // TODO: Consolidate these calls - del_unassigned_virt_socket(fd); - add_assigned_virt_socket(tap, vs, fd); - - // save peer addr, for calls like getpeername - memcpy(&(vs->peer_addr), addr, sizeof(vs->peer_addr)); - - // Below will simulate BLOCKING/NON-BLOCKING behaviour - - // NOTE: pico_socket_connect() will return 0 if no error happens immediately, but that doesn't indicate - // the connection was completed, for that we must wait for a callback from the stack. During that - // callback we will place the VirtualSocket in a VS_STATE_UNHANDLED_CONNECTED state to signal - // to the multiplexer logic that this connection is complete and a success value can be sent to the - // user application - - int f_err, blocking = 1; - if ((f_err = fcntl(fd, F_GETFL, 0)) < 0) { - DEBUG_ERROR("fcntl error, err=%s, errno=%d", f_err, errno); - // errno will be set by fcntl - return -1; - } - blocking = !(f_err & O_NONBLOCK); - if (blocking == false) { - errno = EINPROGRESS; // can't connect immediately - err = -1; - } - if (blocking == true) { - bool complete = false; - while (true) { - // FIXME: locking and unlocking so often might cause significant performance overhead while outgoing VirtualSockets - // are being established (also applies to accept()) - nanosleep((const struct timespec[]) {{0, (ZT_CONNECT_RECHECK_DELAY * 1000000)}}, NULL); - tap->_tcpconns_m.lock(); - for (int i=0; i_VirtualSockets.size(); i++) { -#if defined(STACK_PICO) - DEBUG_EXTRA("checking tap->_VirtualSockets[i]=%p", tap->_VirtualSockets[i]); - if (tap->_VirtualSockets[i]->get_state() == PICO_ERR_ECONNRESET) { - errno = ECONNRESET; - DEBUG_ERROR("ECONNRESET"); - err = -1; - } -#endif -#if defined(STACK_LWIP) -#endif - if (tap->_VirtualSockets[i]->get_state() == VS_STATE_UNHANDLED_CONNECTED) { - tap->_VirtualSockets[i]->set_state(VS_STATE_CONNECTED); - complete = true; - } - } - tap->_tcpconns_m.unlock(); - if (complete) { - break; - } - } - } - return err; -} - -int virt_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) { - int err = errno = 0; - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - VirtualSocket *vs = get_virt_socket(fd); - if (vs == NULL) { - DEBUG_ERROR("no VirtualSocket for fd=%d", fd); - errno = ENOTSOCK; - return -1; - } - struct pico_socket *ps = (struct pico_socket*)(vs->pcb); - // detect local interface binds - VirtualTap *tap = NULL; - if (vs->socket_family == AF_INET) { - struct sockaddr_in *in4 = (struct sockaddr_in *)addr; - if (in4->sin_addr.s_addr == INADDR_ANY) { - DEBUG_EXTRA("AF_INET, INADDR_ANY, binding to all interfaces"); - // grab first vtap - if (vtaps.size()) { - tap = (VirtualTap*)(vtaps[0]); // pick any vtap - } - } - if (in4->sin_addr.s_addr == 0x7f000001) { - DEBUG_EXTRA("127.0.0.1, will bind to appropriate vtap when connection is inbound"); - if (vtaps.size()) { - tap = (VirtualTap*)(vtaps[0]); // pick any vtap - } - } - } - if (vs->socket_family == AF_INET6) { - struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)addr; - if (memcmp((void*)&(in6->sin6_addr), (void*)&(in6addr_any), sizeof(in6addr_any)) == 0) { - DEBUG_EXTRA("AF_INET6, in6addr_any, binding to all interfaces"); - if (vtaps.size()) { - tap = (VirtualTap*)(vtaps[0]); // pick any vtap - } - } - } - - ZeroTier::InetAddress inet; - sockaddr2inet(vs->socket_family, addr, &inet); - if (tap == NULL) { - tap = getTapByAddr(&inet); - } - if (tap == NULL) { - DEBUG_ERROR("no matching interface to bind to, could not find appropriate VirtualTap for fd=%d", fd); - errno = ENETUNREACH; - return -1; - } -#if defined(STACK_PICO) - // used in callbacks from network stack - ps->priv = new VirtualBindingPair(tap, vs); -#endif - tap->addVirtualSocket(vs); - err = tap->Bind(vs, addr, addrlen); - if (err == 0) { // success - vs->tap = tap; - del_unassigned_virt_socket(fd); - add_assigned_virt_socket(tap, vs, fd); - } - return err; -} - -int virt_listen(int fd, int backlog) { - DEBUG_EXTRA("fd=%d", fd); - int err = errno = 0; - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - VirtualSocket *vs = get_virt_socket(fd); - if (vs == NULL) { - DEBUG_ERROR("!vs"); - return -1; - } - //std::pair *p = get_assigned_virtual_pair(fd); - _multiplexer_lock.lock(); - VirtualTap *tap = vs->tap; - if (tap == NULL || vs == NULL) { - DEBUG_ERROR("unable to locate tap interface for file descriptor"); - errno = EBADF; - return -1; - } - backlog = backlog > 128 ? 128 : backlog; // See: /proc/sys/net/core/somaxconn - err = tap->Listen(vs, backlog); - vs->set_state(VS_STATE_LISTENING); - _multiplexer_lock.unlock(); - return err; -} - -int virt_accept(int fd, struct sockaddr *addr, socklen_t *addrlen) { - int err = errno = 0; - DEBUG_EXTRA("fd=%d", fd); - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - if (addr && *addrlen <= 0) { - DEBUG_ERROR("invalid address length given"); - errno = EINVAL; // TODO, not actually a valid error for this function - return -1; - } - if (virt_can_provision_new_socket(SOCK_STREAM) == false) { - DEBUG_ERROR("cannot provision additional socket due to limitation of network stack"); - errno = EMFILE; - return -1; - } - - //std::pair *p = get_assigned_virtual_pair(fd); - VirtualSocket *vs = get_virt_socket(fd); - if (vs == NULL) { - DEBUG_ERROR("!vs"); - return -1; - } - _multiplexer_lock.lock(); - //std::pair *p = get_assigned_virtual_pair(fd); - VirtualTap *tap = vs->tap; - // BLOCKING: loop and keep checking until we find a newly accepted VirtualSocket - int f_err, blocking = 1; - if ((f_err = fcntl(fd, F_GETFL, 0)) < 0) { - DEBUG_ERROR("fcntl error, err = %s, errno = %d", f_err, errno); - err = -1; - } - else { - blocking = !(f_err & O_NONBLOCK); - } - VirtualSocket *accepted_vs; - if (err == false) { - if (blocking == false) { // non-blocking - DEBUG_EXTRA("EWOULDBLOCK, assuming non-blocking mode"); - errno = EWOULDBLOCK; - err = -1; - accepted_vs = tap->Accept(vs); - } - else { // blocking - while (true) { - nanosleep((const struct timespec[]) {{0, (ZT_ACCEPT_RECHECK_DELAY * 1000000)}}, NULL); - accepted_vs = tap->Accept(vs); - if (accepted_vs) - break; // accepted fd = err - } - } - if (accepted_vs) { - add_assigned_virt_socket(tap, accepted_vs, accepted_vs->app_fd); - err = accepted_vs->app_fd; - } - } - if (err > 0) { - if (addr && *addrlen) { - *addrlen = *addrlen < sizeof(accepted_vs->peer_addr) ? *addrlen : sizeof(accepted_vs->peer_addr); - // copy address into provided address buffer and len buffer - memcpy(addr, &(accepted_vs->peer_addr), *addrlen); - } - } - return err; -} - -#if defined(__linux__) -int virt_accept4(int fd, struct sockaddr *addr, socklen_t *addrlen, int flags) -{ - errno = 0; - //DEBUG_INFO("fd=%d", fd); - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - if (flags & SOCK_NONBLOCK) { - fcntl(fd, F_SETFL, O_NONBLOCK); - } - if (flags & SOCK_CLOEXEC) { - fcntl(fd, F_SETFL, FD_CLOEXEC); - } - addrlen = !addr ? 0 : addrlen; - return virt_accept(fd, addr, addrlen); -} -#endif - -int virt_setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen) -{ - DEBUG_EXTRA("fd=%d, level=%d, optname=%d", fd, level, optname); - int err = errno = 0; - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - VirtualSocket *vs = get_virt_socket(fd); - if (vs == NULL) { - DEBUG_ERROR("invalid fd=%d", fd); - errno = EBADF; - return -1; - } -#if defined(STACK_PICO) - err = rd_pico_setsockopt(vs, level, optname, optval, optlen); -#endif -#if defined(STACK_LWIP) - err = rd_lwip_setsockopt(vs, level, optname, optval, optlen); -#endif - return err; -} - -int virt_getsockopt(int fd, int level, int optname, void *optval, socklen_t *optlen) -{ - DEBUG_EXTRA("fd=%d, level=%d, optname=%d", fd, level, optname); - int err = errno = 0; - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - VirtualSocket *vs = get_virt_socket(fd); - if (vs == NULL) { - DEBUG_ERROR("invalid fd=%d", fd); - errno = EBADF; - return -1; - } -#if defined(STACK_PICO) - err = rd_pico_getsockopt(vs, level, optname, optval, optlen); -#endif -#if defined(STACK_LWIP) - err = rd_lwip_getsockopt(vs, level, optname, optval, optlen); -#endif - return err; -} - -int virt_getsockname(int fd, struct sockaddr *addr, socklen_t *addrlen) -{ - int err = errno = 0; - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - // TODO - return err; -} - -int virt_getpeername(int fd, struct sockaddr *addr, socklen_t *addrlen) -{ - DEBUG_INFO("fd=%d", fd); - int err = errno = 0; - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - VirtualSocket *vs = get_virt_socket(fd); - if (vs == NULL) { - errno = ENOTCONN; - return -1; - } - memcpy(addr, &(vs->peer_addr), sizeof(struct sockaddr_storage)); - return err; -} - -int virt_gethostname(char *name, size_t len) -{ - errno = 0; - return gethostname(name, len); -} - -int virt_sethostname(const char *name, size_t len) -{ - errno = 0; - return sethostname(name, len); -} - -int virt_close(int fd) -{ - DEBUG_EXTRA("fd=%d", fd); - int err = errno = 0; - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - VirtualSocket *vs = get_virt_socket(fd); - if (vs == NULL) { - DEBUG_ERROR("no vs found for fd=%d", fd); - errno = EBADF; - return -1; - } - del_virt_socket(fd); - if (vs->tap) { - vs->tap->Close(vs); - } - delete vs; - vs = NULL; - return err; -} - -/* -int virt_poll(struct pollfd *fds, nfds_t nfds, int timeout) -{ - errno = 0; - return poll(fds, nfds, timeout); -} -*/ - -int virt_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) -{ - errno = 0; - return select(nfds, readfds, writefds, exceptfds, timeout); -} - -int virt_fcntl(int fd, int cmd, int flags) -{ - int err = errno = 0; - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - VirtualSocket *vs = get_virt_socket(fd); - if (vs == NULL) { - DEBUG_ERROR("invalid vs for fd=%d", fd); - errno = EBADF; - return -1; - } - err = fcntl(fd, cmd, flags); - return err; -} - -int virt_ioctl(int fd, unsigned long request, void *argp) -{ - int err = errno = -1; - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - else { -#if defined(__linux__) - /* - if (argp) - { - struct ifreq *ifr = (struct ifreq *)argp; - VirtualTap *tap = getTapByName(ifr->ifr_name); - if (tap == NULL) { - DEBUG_ERROR("unable to locate tap interface with that name"); - err = -1; - errno = EINVAL; - } - // index of VirtualTap interface - if (request == SIOCGIFINDEX) { - ifr->ifr_ifindex = tap->ifindex; - err = 0; - } - // MAC addres or VirtualTap - if (request == SIOCGIFHWADDR) { - tap->_mac.copyTo(&(ifr->ifr_hwaddr.sa_data), sizeof(ifr->ifr_hwaddr.sa_data)); - err = 0; - } - // IP address of VirtualTap - if (request == SIOCGIFADDR) { - struct sockaddr_in *in4 = (struct sockaddr_in *)&(ifr->ifr_addr); - memcpy(&(in4->sin_addr.s_addr), tap->_ips[0].rawIpData(), sizeof(ifr->ifr_addr)); - err = 0; - } - } - else { - DEBUG_INFO("!argp"); - } - */ -#else - // err = ioctl(fd, request, argp); - err = -1; -#endif - } - return err; -} - -ssize_t virt_sendto(int fd, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t addrlen) -{ - //DEBUG_TRANS("fd=%d", fd); - int err = errno = 0; - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - if (len == 0) { - return 0; - } - if (len > ZT_SOCKET_MSG_BUF_SZ) { - DEBUG_ERROR("msg is too long to be sent atomically (len=%d)", len); - errno = EMSGSIZE; - return -1; - } - if (buf == NULL) { - DEBUG_ERROR("msg buf is null"); - errno = EINVAL; - return -1; - } - VirtualSocket *vs = get_virt_socket(fd); - if (vs == NULL) { - DEBUG_ERROR("no vs found for fd=%x", fd); - errno = EBADF; - return -1; - } - ZeroTier::InetAddress iaddr; - VirtualTap *tap; - - if (vs->socket_type == SOCK_DGRAM) { - if (vs->socket_family == AF_INET) - { - char ipstr[INET_ADDRSTRLEN]; - memset(ipstr, 0, INET_ADDRSTRLEN); - inet_ntop(AF_INET, - (const void *)&((struct sockaddr_in *)addr)->sin_addr.s_addr, ipstr, INET_ADDRSTRLEN); - iaddr.fromString(ipstr); - } - if (vs->socket_family == AF_INET6) - { - char ipstr[INET6_ADDRSTRLEN]; - memset(ipstr, 0, INET6_ADDRSTRLEN); - 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[INET6_ADDRSTRLEN]; - sprintf(addrstr, "%s%s", ipstr, std::string("/40").c_str()); - iaddr.fromString(addrstr); - } - // get tap - tap = getTapByAddr(&iaddr); - if (tap == NULL) { - DEBUG_INFO("SOCK_DGRAM, tap not found"); - errno = EDESTADDRREQ; // TODO: double check this is the best errno to report - return -1; - } - // write - if ((err = tap->SendTo(vs, buf, len, flags, addr, addrlen)) < 0) { - DEBUG_ERROR("error while attempting to sendto"); - errno = EINVAL; // TODO: Not correct, but what else could we use? - } - } - if (vs->socket_type == SOCK_RAW) - { - struct sockaddr_ll *socket_address = (struct sockaddr_ll *)addr; - VirtualTap *tap = getTapByIndex(socket_address->sll_ifindex); - if (tap) { - DEBUG_INFO("found interface of ifindex=%d", tap->ifindex); - err = tap->Write(vs, (void*)buf, len); - } - else { - DEBUG_ERROR("unable to locate tap of ifindex=%d", socket_address->sll_ifindex); - err = -1; - errno = EINVAL; - } - } - return err; -} - -ssize_t virt_send(int fd, const void *buf, size_t len, int flags) -{ - // DEBUG_TRANS("fd=%d", fd); - int err = errno = 0; - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - if (len == 0) { - return 0; - } - if (len > ZT_SOCKET_MSG_BUF_SZ) { - DEBUG_ERROR("msg is too long to be sent atomically (len=%d)", len); - errno = EMSGSIZE; - return -1; - } - VirtualSocket *vs = get_virt_socket(fd); - if (vs == NULL) { - DEBUG_ERROR("invalid vs for fd=%d", fd); - errno = EBADF; - return -1; - } - if (vs->socket_type != SOCK_STREAM) { - DEBUG_ERROR("the socket is not connection-mode, and no peer address is set for fd=%d", fd); - errno = EDESTADDRREQ; - return -1; - } - if (flags & MSG_DONTROUTE) { - DEBUG_INFO("MSG_DONTROUTE not implemented yet"); - errno = EINVAL; - return -1; - } - if (flags & MSG_DONTWAIT) { - // The stack drivers and stack are inherently non-blocking by design, but we - // still need to modify the unix pipe connecting them to the application: - fcntl(fd, F_SETFL, O_NONBLOCK); - } - if (flags & MSG_EOR) { - DEBUG_INFO("MSG_EOR not implemented yet"); - errno = EINVAL; - return -1; - } - if (flags & MSG_OOB) { - DEBUG_INFO("MSG_OOB not implemented yet"); - errno = EINVAL; - return -1; - } -#if defined(__linux__) - if (flags & MSG_CONFIRM) { - DEBUG_INFO("MSG_CONFIRM not implemented yet"); - errno = EINVAL; - return -1; - } - if (flags & MSG_MORE) { - DEBUG_INFO("MSG_MORE not implemented yet"); - errno = EINVAL; - return -1; - } - if (flags & MSG_NOSIGNAL) { - DEBUG_INFO("MSG_NOSIGNAL not implemented yet"); - errno = EINVAL; - return -1; - } -#endif - - err = write(fd, buf, len); - // restore "per-call" flags - - if (flags & MSG_DONTWAIT) { - int saved_flags = fcntl(fd, F_GETFL); - if (fcntl(fd, F_SETFL, saved_flags & ~O_NONBLOCK) < 0) { // mask out the blocking flag - return -1; - } - } - return err; -} - -// TODO -ssize_t virt_sendmsg(int fd, const struct msghdr *msg, int flags) -{ - DEBUG_TRANS("fd=%d", fd); - int err = errno = 0; - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - else { - err = sendmsg(fd, msg, flags); - } - return err; -} - -ssize_t virt_recv(int fd, void *buf, size_t len, int flags) -{ - DEBUG_TRANS("fd=%d", fd); - int err = errno = 0; - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - VirtualSocket *vs = get_virt_socket(fd); - if (vs == NULL) { - DEBUG_ERROR("invalid vs for fd=%d", fd); - errno = EBADF; - return -1; - } - if (vs->socket_type != SOCK_STREAM) { - DEBUG_ERROR("the socket is not connection-mode, and no peer address is set for fd=%d", fd); - errno = EDESTADDRREQ; - return -1; - } - if (vs->get_state() != VS_STATE_CONNECTED) { - DEBUG_ERROR("the socket is not in a connected state, fd=%d", fd); - errno = ENOTCONN; - return -1; - } - if (flags & MSG_DONTWAIT) { - // The stack drivers and stack are inherently non-blocking by design, but we - // still need to modify the unix pipe connecting them to the application: - fcntl(fd, F_SETFL, O_NONBLOCK); - } - if (flags & MSG_OOB) { - DEBUG_INFO("MSG_OOB not implemented yet"); - errno = EINVAL; - return -1; - } - if (flags & MSG_TRUNC) { - DEBUG_INFO("MSG_TRUNC not implemented yet"); - errno = EINVAL; - return -1; - } - if (flags & MSG_WAITALL) { - DEBUG_INFO("MSG_WAITALL not implemented yet"); - errno = EINVAL; - return -1; - } -#if defined(__linux__) - if (flags & MSG_ERRQUEUE) { - DEBUG_INFO("MSG_ERRQUEUE not implemented yet"); - errno = EINVAL; - return -1; - } -#endif - - if (flags & MSG_PEEK) { - // MSG_PEEK doesn't require any special stack-related machinery so we can just - // pass it to a regular recv() call with no issue - err = recv(fd, buf, len, MSG_PEEK); - } - - // restore "per-call" flags - - if (flags & MSG_DONTWAIT) { - int saved_flags = fcntl(fd, F_GETFL); - if (fcntl(fd, F_SETFL, saved_flags & ~O_NONBLOCK) < 0) { // mask out the blocking flag - return -1; - } - } - return err; -} - -ssize_t virt_recvfrom(int fd, void *buf, size_t len, int flags, struct sockaddr *addr, socklen_t *addrlen) -{ - //DEBUG_TRANS("fd=%d", fd); - int32_t r = 0; - errno = 0; - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - if (len == 0) { - return 0; - } - if (buf == NULL) { - DEBUG_ERROR("buf is null"); - errno = EINVAL; - return -1; - } - char udp_msg_buf[ZT_SOCKET_MSG_BUF_SZ]; - char *msg_ptr = udp_msg_buf; - memset(msg_ptr, 0, sizeof(int32_t)); // zero only len portion - - int32_t udp_msg_len = 0; - - // PEEK at the buffer and see if we can read a length, if not, err out - r = recv(fd, msg_ptr, sizeof(int32_t), MSG_PEEK); - if (r != sizeof(int32_t)) { - errno = EIO; // TODO: test for this - return -1; - } - // read of sizeof(int32_t) for the length of the datagram (including address) - r = read(fd, msg_ptr, sizeof(int32_t)); - // copy to length variable - memcpy(&udp_msg_len, msg_ptr, sizeof(int32_t)); - msg_ptr+=sizeof(int32_t); - - if (udp_msg_len <= 0) { - DEBUG_ERROR("invalid datagram"); - errno = EIO; // TODO: test for this - return -1; - } - // there is a datagram to read, so let's read it - // zero remainder of buffer - memset(msg_ptr, 0, ZT_SOCKET_MSG_BUF_SZ- sizeof(int32_t)); - if ((r = read(fd, msg_ptr, udp_msg_len)) < 0) { - DEBUG_ERROR("invalid datagram"); - errno = EIO; // TODO: test for this - return -1; - } - // get address - if (addr) { - if (*addrlen < sizeof(struct sockaddr_storage)) { - DEBUG_ERROR("invalid address length provided"); - errno = EINVAL; - return -1; - } - *addrlen = sizeof(struct sockaddr_storage); - memcpy(addr, msg_ptr, *addrlen); - } - msg_ptr+=sizeof(struct sockaddr_storage); - // get payload - int32_t payload_sz = udp_msg_len - *addrlen; - int32_t write_sz = len < payload_sz ? len : payload_sz; - memcpy(buf, msg_ptr, write_sz); - return write_sz; -} - -// TODO -ssize_t virt_recvmsg(int fd, struct msghdr *msg,int flags) -{ - //DEBUG_TRANS("fd=%d", fd); - int err = errno = 0; - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - else { - err = recvmsg(fd, msg, flags); - } - return err; -} - -int virt_read(int fd, void *buf, size_t len) { - DEBUG_TRANS("fd=%d", fd); - errno = 0; - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - VirtualSocket *vs = get_virt_socket(fd); - if (vs == NULL) { - DEBUG_ERROR("invalid vs for fd=%d", fd); - errno = EBADF; - return -1; - } - return read(fd, buf, len); -} - -int virt_write(int fd, const void *buf, size_t len) { - DEBUG_TRANS("fd=%d", fd); - errno = 0; - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - VirtualSocket *vs = get_virt_socket(fd); - if (vs == NULL) { - DEBUG_ERROR("invalid vs for fd=%d", fd); - errno = EBADF; - return -1; - } - return write(fd, buf, len); -} - -int virt_shutdown(int fd, int how) -{ - int err = errno = 0; - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - if (how != SHUT_RD && how != SHUT_WR && how != SHUT_RDWR) { - errno = EINVAL; - return -1; - } - VirtualSocket *vs = get_virt_socket(fd); - if (vs == NULL) { - DEBUG_ERROR("invalid vs for fd=%d", fd); - errno = EBADF; - return -1; - } - if (vs->get_state() != VS_STATE_CONNECTED || vs->socket_type != SOCK_STREAM) { - DEBUG_ERROR("the socket is either not in a connected state, or isn't connection-based, fd=%d", fd); - errno = ENOTCONN; - return -1; - } - if (vs->tap) { - err = vs->tap->Shutdown(vs, how); - } - return err; -} - -/****************************************************************************/ -/* Socket API Helper functions --- DON'T CALL THESE DIRECTLY */ -/****************************************************************************/ - -bool virt_can_provision_new_socket(int socket_type) -{ - int can = false; -#if defined(STACK_PICO) - return !(pico_ntimers()+1 > PICO_MAX_TIMERS); -#endif -#if defined(STACK_LWIP) - if (socket_type == SOCK_STREAM) { - return !(rd_lwip_num_current_tcp_pcbs()+1 > MEMP_NUM_TCP_PCB); - } - if (socket_type == SOCK_DGRAM) { - return !(rd_lwip_num_current_udp_pcbs()+1 > MEMP_NUM_UDP_PCB); - } - if (socket_type == SOCK_RAW) { - return !(rd_lwip_num_current_raw_pcbs()+1 > MEMP_NUM_RAW_PCB); - } - can = true; -#endif -#if defined(NO_STACK) - // always true since there's no network stack timer/memory limitation - can = true; -#endif - return can; -} - -int virt_num_active_sockets() -{ - _multiplexer_lock.lock(); - int num = unmap.size() + fdmap.size(); - _multiplexer_lock.unlock(); - return num; -} - -int virt_maxsockets(int socket_type) -{ - int max = 0; -#if defined(STACK_PICO) - // TODO: This is only an approximation - // TODO: distinquish by type - max = PICO_MAX_TIMERS - 10; -#endif -#if defined(STACK_LWIP) - if (socket_type == SOCK_STREAM) { - max = MEMP_NUM_TCP_PCB; - } - if (socket_type == SOCK_DGRAM) { - max = MEMP_NUM_UDP_PCB; - } -#endif -#if defined(NO_STACK) - // arbitrary -#if defined(__linux__) - max = RLIMIT_NOFILE; -#endif -#if defined(__APPLE__) - max = 1024; -#endif -#endif - return max; -} - -/****************************************************************************/ -/* VirtualSocket / VirtualTap helper functions - DON'T CALL THESE DIRECTLY */ -/****************************************************************************/ - -VirtualSocket *get_virt_socket(int fd) -{ - DEBUG_EXTRA("fd=%d", fd); - _multiplexer_lock.lock(); - // try to locate in unmapped set - VirtualSocket *vs = unmap[fd]; - if (vs == NULL) { - // if not, try to find in mapped set (bind to vtap has been performed) - std::pair *p = fdmap[fd]; - if (p) { - vs = p->first; - } - else { - DEBUG_ERROR("unable to locate virtual socket"); - } - } - _multiplexer_lock.unlock(); - return vs; -} - -int del_virt_socket(int fd) -{ - DEBUG_EXTRA("fd=%d", fd); - int err = 0; - _multiplexer_lock.lock(); - try { - std::map::iterator un_iter = unmap.find(fd); - if (un_iter != unmap.end()) { - unmap.erase(un_iter); - } - std::map*>::iterator fd_iter = fdmap.find(fd); - if (fd_iter != fdmap.end()) { - fdmap.erase(fd_iter); - } - } - catch( ... ) { - DEBUG_ERROR("unable to remove virtual socket"); - err = -1; - } - _multiplexer_lock.unlock(); - return err; -} - -int add_unassigned_virt_socket(int fd, VirtualSocket *vs) -{ - DEBUG_EXTRA("fd=%d, vs=%p", fd, vs); - int err = 0; - _multiplexer_lock.lock(); - try { - std::map::iterator un_iter = unmap.find(fd); - if (un_iter == unmap.end()) { - unmap[fd] = vs; - } - else { - DEBUG_ERROR("fd=%d already contained in map", fd); - } - } - catch( ... ) { - DEBUG_ERROR("unable to add virtual socket"); - err = -1; - } - _multiplexer_lock.unlock(); - return err; -} - -int del_unassigned_virt_socket(int fd) -{ - DEBUG_EXTRA("fd=%d", fd); - int err = 0; - _multiplexer_lock.lock(); - try { - std::map::iterator un_iter = unmap.find(fd); - if (un_iter != unmap.end()) { - unmap.erase(un_iter); - } - } - catch( ... ) { - DEBUG_ERROR("unable to remove virtual socket"); - err = -1; - } - _multiplexer_lock.unlock(); - return err; -} - -int add_assigned_virt_socket(void *tap_ptr, VirtualSocket *vs, int fd) -{ - VirtualTap *tap = (VirtualTap*)tap_ptr; - DEBUG_EXTRA("tap=%p, vs=%p, fd=%d", tap, vs, fd); - int err = 0; - _multiplexer_lock.lock(); - try { - std::map*>::iterator fd_iter; - fd_iter = fdmap.find(fd); - if (fd_iter == fdmap.end()) { - fdmap[fd] = new std::pair(vs, tap); - } - else { - DEBUG_ERROR("fd=%d already contained in > map", fd); - } - } - catch( ... ) { - DEBUG_ERROR("unable to add virtual socket"); - err = -1; - } - _multiplexer_lock.unlock(); - return err; -} - -int del_assigned_virt_socket(VirtualTap *tap, VirtualSocket *vs, int fd) -{ - DEBUG_EXTRA("tap=%p, vs=%p, fd=%d", tap, vs, fd); - int err = 0; - _multiplexer_lock.lock(); - try { - std::map*>::iterator fd_iter; - fd_iter = fdmap.find(fd); - if (fd_iter != fdmap.end()) { - fdmap.erase(fd_iter); - } - } - catch( ... ) { - DEBUG_ERROR("unable to remove virtual socket"); - err = -1; - } - _multiplexer_lock.unlock(); - return err; -} - -/* -std::pair *get_assigned_virtual_pair(int fd) -{ - _multiplexer_lock.lock(); - std::pair *p = fdmap[fd]; - _multiplexer_lock.unlock(); - return p; -} -*/ - -void disableTaps() -{ - _vtaps_lock.lock(); - for (int i=0; i_enabled = false; - } - _vtaps_lock.unlock(); -} - -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); - } -} - -#endif // ZT_VIRTUAL_SOCKET diff --git a/attic/VirtualSocketLayer.h b/attic/VirtualSocketLayer.h deleted file mode 100644 index 3f734c4..0000000 --- a/attic/VirtualSocketLayer.h +++ /dev/null @@ -1,443 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2018 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 . - * - * -- - * - * 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 "libztDefs.h" - -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); - diff --git a/attic/ZT1Service.cpp b/attic/ZT1Service.cpp deleted file mode 100644 index 9d03ebe..0000000 --- a/attic/ZT1Service.cpp +++ /dev/null @@ -1,712 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2018 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 . - * - * -- - * - * 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 - * - * ZeroTier One service control wrapper - */ - -/* -#include "libzt.h" -#include "ZT1Service.h" - -#include "Phy.hpp" -#include "OneService.hpp" -#include "InetAddress.hpp" -#include "OSUtils.hpp" -#include "Mutex.hpp" - -#include -*/ - - -/* -std::vector vtaps; -ZeroTier::Mutex _vtaps_lock; -ZeroTier::Mutex _service_lock; -*/ -/* - -#ifdef __cplusplus -extern "C" { -#endif - -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 - -ZeroTier::Mutex _multiplexer_lock; - -int servicePort = LIBZT_DEFAULT_PORT; -bool _freeHasBeenCalled = false; -bool _serviceIsShuttingDown = false; - -#if defined(_WIN32) -WSADATA wsaData; -#include -#endif - -void api_sleep(int interval_ms); - -pthread_t service_thread; - -////////////////////////////////////////////////////////////////////////////// -// ZeroTier Core helper functions for libzt - DON'T CALL THESE DIRECTLY // -////////////////////////////////////////////////////////////////////////////// - -std::vector *zts_get_network_routes(const uint64_t nwid) -{ - return zt1Service->getRoutes(nwid); -} - -VirtualTap *getTapByNWID(uint64_t nwid) -{ - _vtaps_lock.lock(); - VirtualTap *s, *tap = nullptr; - for (size_t i=0; i_nwid == nwid) { tap = s; } - } - _vtaps_lock.unlock(); - return tap; -} - -VirtualTap *getTapByAddr(ZeroTier::InetAddress *addr) -{ - _vtaps_lock.lock(); - VirtualTap *s, *tap = nullptr; - //char ipbuf[64], ipbuf2[64], ipbuf3[64]; - for (size_t i=0; i_ips.size()); j++) { - if ((s->_ips[j].isV4() && addr->isV4()) || (s->_ips[j].isV6() && addr->isV6())) { - // DEBUG_INFO("looking at tap %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)) - ) - { - //DEBUG_INFO("selected tap %s, ", s->_dev.c_str(), s->_ips[j].toString(ipbuf)); - _vtaps_lock.unlock(); - return s; - } - } - } - // check managed routes - if (tap == NULL) { - std::vector *managed_routes = zt1Service->getRoutes(s->_nwid); - ZeroTier::InetAddress target, nm, via; - for (size_t i=0; isize(); 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.toString(ipbuf), - // nm.toString(ipbuf2), via.toString(ipbuf3)); - _vtaps_lock.unlock(); - return s; - } - } - } - } - _vtaps_lock.unlock(); - return tap; -} - -VirtualTap *getTapByName(char *ifname) -{ - _vtaps_lock.lock(); - VirtualTap *s, *tap = nullptr; - for (size_t i=0; i_dev.c_str(), ifname) == false) { - tap = s; - } - } - _vtaps_lock.unlock(); - return tap; -} - -VirtualTap *getTapByIndex(size_t index) -{ - _vtaps_lock.lock(); - VirtualTap *s, *tap = nullptr; - for (size_t i=0; iifindex == index) { - tap = s; - } - } - _vtaps_lock.unlock(); - return tap; -} - -VirtualTap *getAnyTap() -{ - _vtaps_lock.lock(); - VirtualTap *vtap = NULL; - if (vtaps.size()) { - vtap = (VirtualTap *)vtaps[0]; - } - _vtaps_lock.unlock(); - return vtap; -} - -// Starts a ZeroTier service in the background -#if defined(_WIN32) -DWORD WINAPI zts_start_service(LPVOID thread_id) -#else -void *zts_start_service(void *thread_id) -#endif -{ - void *retval; - DEBUG_INFO("identities are stored in path (%s)", homeDir.c_str()); - netDir = homeDir + "/networks.d"; - zt1Service = (ZeroTier::OneService *)0; - - if (!homeDir.length()) { - DEBUG_ERROR("homeDir is empty, could not construct path"); - retval = NULL; - } if (zt1Service) { - DEBUG_INFO("service already started, doing nothing"); - retval = NULL; - } - - try { - std::vector hpsp(ZeroTier::OSUtils::split(homeDir.c_str(), ZT_PATH_SEPARATOR_S,"","")); - std::string ptmp; - if (homeDir[0] == ZT_PATH_SEPARATOR) { - ptmp.push_back(ZT_PATH_SEPARATOR); - } - for (std::vector::iterator pi(hpsp.begin());pi!=hpsp.end();++pi) { - if (ptmp.length() > 0) { - ptmp.push_back(ZT_PATH_SEPARATOR); - } - ptmp.append(*pi); - if ((*pi != ".")&&(*pi != "..")) { - if (ZeroTier::OSUtils::mkdir(ptmp) == false) { - DEBUG_ERROR("home path does not exist, and could not create"); - perror("error\n"); - } - } - } - for(;;) { - _service_lock.lock(); - zt1Service = OneService::newInstance(homeDir.c_str(),servicePort); - _service_lock.unlock(); - switch(zt1Service->run()) { - case OneService::ONE_STILL_RUNNING: // shouldn't happen, run() won't return until done - case OneService::ONE_NORMAL_TERMINATION: - break; - case OneService::ONE_UNRECOVERABLE_ERROR: - fprintf(stderr,"fatal error: %s" ZT_EOL_S,zt1Service->fatalErrorMessage().c_str()); - break; - case OneService::ONE_IDENTITY_COLLISION: { - delete zt1Service; - zt1Service = (OneService *)0; - std::string oldid; - OSUtils::readFile((homeDir + ZT_PATH_SEPARATOR_S + "identity.secret").c_str(),oldid); - if (oldid.length()) { - OSUtils::writeFile((homeDir + ZT_PATH_SEPARATOR_S + "identity.secret.saved_after_collision").c_str(),oldid); - OSUtils::rm((homeDir + ZT_PATH_SEPARATOR_S + "identity.secret").c_str()); - OSUtils::rm((homeDir + ZT_PATH_SEPARATOR_S + "identity.public").c_str()); - } - } continue; // restart! - } - break; // terminate loop -- normally we don't keep restarting - } - _serviceIsShuttingDown = true; - _service_lock.lock(); - delete zt1Service; - zt1Service = (OneService *)0; - _service_lock.unlock(); - _serviceIsShuttingDown = false; - } catch ( ... ) { - fprintf(stderr,"unexpected exception starting main OneService instance" ZT_EOL_S); - } - pthread_exit(NULL); -} - -int zts_get_num_assigned_addresses(const uint64_t nwid) -{ - if (!zt1Service) { - return -1; - } - VirtualTap *tap = getTapByNWID(nwid); - if (!tap) { - return -1; - } - int sz; - _vtaps_lock.lock(); - sz = tap->_ips.size(); - _vtaps_lock.unlock(); - return sz; -} - -int zts_get_address_at_index( - const uint64_t nwid, const int index, struct sockaddr *addr, socklen_t *addrlen) -{ - if (!zt1Service) { - return -1; - } - VirtualTap *tap = getTapByNWID(nwid); - int err = -1; - if (!tap) { - return err; - } - _vtaps_lock.lock(); - if (index > -1 && index <= (int)tap->_ips.size()) { - memcpy(addr, &(tap->_ips[index]), *addrlen); - *addrlen = tap->_ips[index].isV4() ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6); - err = 0; - } - _vtaps_lock.unlock(); - return err; -} - -////////////////////////////////////////////////////////////////////////////// -// ZeroTier Service Controls // -////////////////////////////////////////////////////////////////////////////// - -zts_err_t zts_set_service_port(int portno) -{ - zts_err_t retval = ZTS_ERR_OK; - _service_lock.lock(); - if (zt1Service) { - DEBUG_INFO("please stop service before attempting to change port"); - retval = ZTS_ERR_SERVICE; - } - else { - if (portno > -1 && portno < ZTS_MAX_PORT) { - // 0 is allowed, signals to ZT service to bind to a random port - servicePort = portno; - retval = ZTS_ERR_OK; - } - } - _service_lock.unlock(); - return retval; -} - -int zts_get_service_port() -{ - return servicePort; -} - -int zts_get_address(const uint64_t nwid, struct sockaddr_storage *addr, - const int address_family) -{ - int err = -1; - if (!zt1Service) { - return ZTS_ERR_SERVICE; - } - VirtualTap *tap = getTapByNWID(nwid); - if (!tap) { - return -1; - } - _vtaps_lock.lock(); - socklen_t addrlen = address_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6); - for (size_t i=0; i_ips.size(); i++) { - if (address_family == AF_INET) { - if (tap->_ips[i].isV4()) { - memcpy(addr, &(tap->_ips[i]), addrlen); - addr->ss_family = AF_INET; - err = 0; - break; - } - } - if (address_family == AF_INET6) { - if (tap->_ips[i].isV6()) { - memcpy(addr, &(tap->_ips[i]), addrlen); - addr->ss_family = AF_INET6; - err = 0; - break; - } - } - } - _vtaps_lock.unlock(); - return err; // nothing found -} - -int zts_has_address(const uint64_t nwid) -{ - struct sockaddr_storage ss; - memset(&ss, 0, sizeof(ss)); - zts_get_address(nwid, &ss, AF_INET); - if (ss.ss_family == AF_INET) { - return true; - } - zts_get_address(nwid, &ss, AF_INET6); - if (ss.ss_family == AF_INET6) { - return true; - } - return false; -} - -void zts_get_6plane_addr(struct sockaddr_storage *addr, const uint64_t nwid, const uint64_t nodeId) -{ - ZeroTier::InetAddress _6planeAddr = ZeroTier::InetAddress::makeIpv66plane(nwid,nodeId); - memcpy(addr, _6planeAddr.rawIpData(), sizeof(struct sockaddr_storage)); -} - -void zts_get_rfc4193_addr(struct sockaddr_storage *addr, const uint64_t nwid, const uint64_t nodeId) -{ - ZeroTier::InetAddress _rfc4193Addr = ZeroTier::InetAddress::makeIpv6rfc4193(nwid,nodeId); - memcpy(addr, _rfc4193Addr.rawIpData(), sizeof(struct sockaddr_storage)); -} - -zts_err_t zts_join(const uint64_t nwid, int blocking) -{ - zts_err_t retval = ZTS_ERR_OK; - _service_lock.lock(); - if (blocking) { - if (!zt1Service) { - retval = ZTS_ERR_SERVICE; - } else { - while (!_zts_node_online()) { - if (_serviceIsShuttingDown) { - retval = ZTS_ERR_SERVICE; - break; - } - api_sleep(ZTO_WRAPPER_CHECK_INTERVAL); - } - } - } else { - if (!zt1Service || !_zts_node_online()) { - retval = ZTS_ERR_SERVICE; - } - } - if (!retval) { - DEBUG_INFO("joining %llx", (unsigned long long)nwid); - if (nwid == 0) { - retval = ZTS_ERR_INVALID_ARG; - } - if (zt1Service) { - zt1Service->join(nwid); - } - // provide ZTO service reference to virtual taps - // TODO: This might prove to be unreliable, but it works for now - _vtaps_lock.lock(); - for (size_t i=0;izt1ServiceRef=(void*)zt1Service; - } - _vtaps_lock.unlock(); - } - _service_lock.unlock(); - return retval; -} - -zts_err_t zts_leave(const uint64_t nwid, int blocking) -{ - zts_err_t retval = ZTS_ERR_OK; - _service_lock.lock(); - if (blocking) { - if (!zt1Service) { - retval = ZTS_ERR_SERVICE; - } else { - while (!_zts_node_online()) { - if (_serviceIsShuttingDown) { - retval = ZTS_ERR_SERVICE; - break; - } - api_sleep(ZTO_WRAPPER_CHECK_INTERVAL); - } - } - } else { - if (!zt1Service || !_zts_node_online()) { - retval = ZTS_ERR_SERVICE; - } - } - if (!retval) { - DEBUG_INFO("leaving %llx", (unsigned long long)nwid); - if (nwid == 0) { - retval = ZTS_ERR_INVALID_ARG; - } - if (zt1Service) { - zt1Service->leave(nwid); - } - } - _service_lock.unlock(); - return retval; -} - -int zts_core_running() -{ - _service_lock.lock(); - int retval = zt1Service == NULL ? false : zt1Service->isRunning(); - _service_lock.unlock(); - return retval; -} - -int zts_stack_running() -{ - // PENDING: what if no networks are joined, the stack is still running. semantics need to change here - _service_lock.lock(); - _vtaps_lock.lock(); - // PENDING: Perhaps a more robust way to check for this - int running = vtaps.size() > 0 ? true : false; - _vtaps_lock.unlock(); - _service_lock.unlock(); - return running; -} - -int zts_ready() -{ - return zts_core_running() && zts_stack_running(); -} - -zts_err_t zts_start(const char *path, int blocking = false) -{ - zts_err_t retval = ZTS_ERR_OK; - if (zt1Service) { - return ZTS_ERR_SERVICE; // already initialized - } - if (_freeHasBeenCalled) { - return ZTS_ERR_INVALID_OP; // stack (presumably lwIP) has been dismantled, an application restart is required now - } - if (path) { - homeDir = path; - } -#if defined(_WIN32) - WSAStartup(MAKEWORD(2, 2), &wsaData); // initialize WinSock. Used in Phy for loopback pipe - HANDLE thr = CreateThread(NULL, 0, zts_start_service, NULL, 0, NULL); -#else - retval = pthread_create(&service_thread, NULL, zts_start_service, NULL); - // PENDING: Wait for confirmation that the ZT service has been initialized, - // this wait condition is so brief and so rarely used that it should be - // acceptable even in a non-blocking context. - while(!zt1Service) { - api_sleep(10); - } -#endif - - if (blocking) { // block to prevent service calls before we're ready - ZT_NodeStatus status; - status.online = 0; - DEBUG_INFO("waiting for zerotier service thread to start"); - while (zts_core_running() == false || zt1Service->getNode() == NULL) { - api_sleep(ZTO_WRAPPER_CHECK_INTERVAL); - } - DEBUG_INFO("waiting for node address assignment"); - while (zt1Service->getNode()->address() <= 0) { - api_sleep(ZTO_WRAPPER_CHECK_INTERVAL); - } - DEBUG_INFO("waiting for node to come online. ensure the node is authorized to join the network"); - while (true) { - _service_lock.lock(); - if (zt1Service && zt1Service->getNode() && zt1Service->getNode()->online()) { - DEBUG_INFO("node is fully online"); - _service_lock.unlock(); - break; - } - api_sleep(ZTO_WRAPPER_CHECK_INTERVAL); - _service_lock.unlock(); - } - DEBUG_INFO("node=%llx", (unsigned long long)zts_get_node_id()); - } - return retval; -} - -zts_err_t zts_startjoin(const char *path, const uint64_t nwid) -{ - zts_err_t retval = ZTS_ERR_OK; - if ((retval = zts_start(path, true)) < 0) { - return retval; - } - while (true) { - try { - zts_join(nwid); - break; - } - catch( ... ) { - DEBUG_ERROR("there was a problem joining the virtual network %llx", - (unsigned long long)nwid); - api_sleep(ZTO_WRAPPER_CHECK_INTERVAL); - } - } - while (zts_has_address(nwid) == false) { - api_sleep(ZTO_WRAPPER_CHECK_INTERVAL); - } - return retval; -} - -zts_err_t zts_stop(int blocking) -{ - zts_err_t ret = ZTS_ERR_OK; - _service_lock.lock(); - VirtualTap *s; - if (zt1Service) { - zt1Service->terminate(); - vtaps.clear(); - } - else { - ret = ZTS_ERR_SERVICE; // nothing to do - } -#if defined(_WIN32) - WSACleanup(); -#endif - _service_lock.unlock(); - if (blocking) { - // block until service thread successfully exits - pthread_join(service_thread, NULL); - } - return ret; -} - -zts_err_t zts_free() -{ - zts_err_t retval = 0; - _service_lock.lock(); - if (_freeHasBeenCalled) { - retval = ZTS_ERR_INVALID_OP; - _service_lock.unlock(); - } else { - _freeHasBeenCalled = true; - _service_lock.unlock(); - retval = zts_stop(); - } - // PENDING: add stack shutdown logic - return retval; -} - -zts_err_t zts_get_path(char *homePath, size_t *len) -{ - zts_err_t retval = ZTS_ERR_OK; - if (!homePath || *len <= 0 || *len > ZT_HOME_PATH_MAX_LEN) { - *len = 0; // signal that nothing was copied to the buffer - retval = ZTS_ERR_INVALID_ARG; - } else if (homeDir.length()) { - memset(homePath, 0, *len); - size_t buf_len = *len < homeDir.length() ? *len : homeDir.length(); - memcpy(homePath, homeDir.c_str(), buf_len); - *len = buf_len; - } - return retval; -} - -uint64_t zts_get_node_id() -{ - uint64_t nodeId = 0; - _service_lock.lock(); - if (_can_perform_service_operation()) { - nodeId = zt1Service->getNode()->address(); - } - _service_lock.unlock(); - return nodeId; -} - -uint64_t zts_get_node_id_from_file(const char *filepath) -{ - std::string fname("identity.public"); - std::string fpath(filepath); - std::string oldid; - if (ZeroTier::OSUtils::fileExists((fpath + ZT_PATH_SEPARATOR_S + fname).c_str(), false)) { - ZeroTier::OSUtils::readFile((fpath + ZT_PATH_SEPARATOR_S + fname).c_str(), oldid); - return Utils::hexStrToU64(oldid.c_str()); - } - return 0; -} - -int zts_get_peer_count() -{ - unsigned int peerCount = 0; - _service_lock.lock(); - if (_can_perform_service_operation()) { - peerCount = zt1Service->getNode()->peers()->peerCount; - } else { - peerCount = ZTS_ERR_SERVICE; - } - _service_lock.unlock(); - return peerCount; -} - -////////////////////////////////////////////////////////////////////////////// -// Internal ZeroTier Service Controls (user application shall not use these)// -////////////////////////////////////////////////////////////////////////////// - -int _zts_node_online() -{ - return zt1Service && zt1Service->getNode() && zt1Service->getNode()->online(); -} - -int _can_perform_service_operation() -{ - return zt1Service && zt1Service->isRunning() && zt1Service->getNode() && zt1Service->getNode()->online() && !_serviceIsShuttingDown; -} - -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(&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(&r)->sin6_addr.s6_addr,16); - memcpy(nm2,reinterpret_cast(&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(&r)->sin6_addr.s6_addr,nm,16); - memcpy(reinterpret_cast(&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 api_sleep(int interval_ms) -{ -#if defined(_WIN32) - Sleep(interval_ms); -#else - struct timespec sleepValue = {0}; - sleepValue.tv_nsec = interval_ms * 500000; - nanosleep(&sleepValue, NULL); -#endif -} - -#ifdef __cplusplus -} -#endif - -*/ diff --git a/attic/ZT1Service.h b/attic/ZT1Service.h deleted file mode 100644 index 2ee2189..0000000 --- a/attic/ZT1Service.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2018 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 . - * - * -- - * - * 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 - * - * ZeroTier One service control wrapper header file - */ - - diff --git a/attic/libztJNI.cpp b/attic/libztJNI.cpp deleted file mode 100644 index b178839..0000000 --- a/attic/libztJNI.cpp +++ /dev/null @@ -1,541 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2018 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 . - * - * -- - * - * 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 - * - * Javs JNI wrapper for POSIX-like socket API - * JNI naming convention: Java_PACKAGENAME_CLASSNAME_METHODNAME - */ - -#ifdef SDK_JNI - -#if defined(_MSC_VER) -// -#else -#include -#include -#include -#endif - -#include "libzt.h" - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -namespace ZeroTier { - - void ss2zta(JNIEnv *env, struct sockaddr_storage *ss, jobject addr); - void zta2ss(JNIEnv *env, struct sockaddr_storage *ss, jobject addr); - void ztfdset2fdset(JNIEnv *env, int nfds, jobject src_ztfd_set, fd_set *dest_fd_set); - void fdset2ztfdset(JNIEnv *env, int nfds, fd_set *src_fd_set, jobject dest_ztfd_set); - - ////////////////////////////////////////////////////////////////////////////// - // ZeroTier service controls // - ////////////////////////////////////////////////////////////////////////////// -/* - JNIEXPORT void JNICALL Java_com_zerotier_libzt_ZeroTier_set_1service_1port( - JNIEnv *env, jobject thisObj, jint port) - { - zts_set_service_port(port); - } - - JNIEXPORT void JNICALL Java_com_zerotier_libzt_ZeroTier_get_1service_1port( - JNIEnv *env, jobject thisObj, jint port) - { - return zts_get_service_port(); - } -*/ - JNIEXPORT void JNICALL Java_com_zerotier_libzt_ZeroTier_start( - JNIEnv *env, jobject thisObj, jstring path, jboolean blocking) - { - if (path) { - const char* utf_string = env->GetStringUTFChars(path, NULL); - zts_start(utf_string, blocking); - env->ReleaseStringUTFChars(path, utf_string); - } - } - - JNIEXPORT void JNICALL Java_com_zerotier_libzt_ZeroTier_startjoin( - JNIEnv *env, jobject thisObj, jstring path, jlong nwid) - { - if (path && nwid) { - const char* utf_string = env->GetStringUTFChars(path, NULL); - zts_startjoin(utf_string, (uint64_t)nwid); - env->ReleaseStringUTFChars(path, utf_string); - } - } - - JNIEXPORT void JNICALL Java_com_zerotier_libzt_ZeroTier_stop( - JNIEnv *env, jobject thisObj) - { - zts_stop(); - } - - JNIEXPORT void JNICALL Java_com_zerotier_libzt_ZeroTier_free( - JNIEnv *env, jobject thisObj) - { - zts_free(); - } - - JNIEXPORT jboolean JNICALL Java_com_zerotier_libzt_ZeroTier_core_1running( - JNIEnv *env, jobject thisObj) - { - return zts_core_running(); - } - - JNIEXPORT jboolean JNICALL Java_com_zerotier_libzt_ZeroTier_stack_1running( - JNIEnv *env, jobject thisObj) - { - return zts_stack_running(); - } - - JNIEXPORT jboolean JNICALL Java_com_zerotier_libzt_ZeroTier_ready( - JNIEnv *env, jobject thisObj) - { - return zts_ready(); - } - - JNIEXPORT void JNICALL Java_com_zerotier_libzt_ZeroTier_get_1service_1port( - JNIEnv *env, jobject thisObj, jint port) - { - return zts_get_num_joined_networks(); - }xxx - - JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_join( - JNIEnv *env, jobject thisObj, jlong nwid) - { - return zts_join((uint64_t)nwid); - } - - JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_leave( - JNIEnv *env, jobject thisObj, jlong nwid) - { - return zts_leave((uint64_t)nwid); - } - - JNIEXPORT jstring JNICALL Java_com_zerotier_libzt_ZeroTier_get_1path( - JNIEnv *env, jobject thisObj) - { - char pathBuf[ZT_HOME_PATH_MAX_LEN]; - zts_get_path(pathBuf, ZT_HOME_PATH_MAX_LEN); - return env->NewStringUTF(pathBuf); - } - - JNIEXPORT jlong JNICALL Java_com_zerotier_libzt_ZeroTier_get_1node_1id( - JNIEnv *env, jobject thisObj) - { - return zts_get_node_id(); - } - - JNIEXPORT jboolean JNICALL Java_com_zerotier_libzt_ZeroTier_get_1num_1assigned_1addresses( - JNIEnv *env, jobject thisObj, jlong nwid) - { - return zts_get_num_assigned_addresses(nwid); - } - - JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_get_1address_1at_1index( - JNIEnv *env, jobject thisObj, jlong nwid, jint index, jobject addr) - { - struct sockaddr_storage ss; - socklen_t addrlen = sizeof(struct sockaddr_storage); - int err = zts_get_address_at_index(nwid, index, (struct sockaddr*)&ss, &addrlen); - ss2zta(env, &ss, addr); - return err; - } - - JNIEXPORT jboolean JNICALL Java_com_zerotier_libzt_ZeroTier_has_1address( - JNIEnv *env, jobject thisObj, jlong nwid) - { - return zts_has_address(nwid); - } - - JNIEXPORT jboolean JNICALL Java_com_zerotier_libzt_ZeroTier_get_1address( - JNIEnv *env, jobject thisObj, jlong nwid, jint address_family, jobject addr) - { - struct sockaddr_storage ss; - int err = zts_get_address((uint64_t)nwid, &ss, address_family); - ss2zta(env, &ss, addr); - return err; - } - - JNIEXPORT void JNICALL Java_com_zerotier_libzt_ZeroTier_get_16plane_1addr( - JNIEnv *env, jobject thisObj, jlong nwid, jlong nodeId, jobject addr) - { - struct sockaddr_storage ss; - zts_get_6plane_addr(&ss, nwid, nodeId); - ss2zta(env, &ss, addr); - } - - JNIEXPORT void JNICALL Java_com_zerotier_libzt_ZeroTier_get_1rfc4193_1addr( - JNIEnv *env, jobject thisObj, jlong nwid, jlong nodeId, jobject addr) - { - struct sockaddr_storage ss; - zts_get_rfc4193_addr(&ss, nwid, nodeId); - ss2zta(env, &ss, addr); - } - - JNIEXPORT jlong JNICALL Java_com_zerotier_libzt_ZeroTier_get_1peer_1count( - JNIEnv *env, jobject thisObj) - { - return zts_get_peer_count(); - } - - ////////////////////////////////////////////////////////////////////////////// - // ZeroTier Socket API // - ////////////////////////////////////////////////////////////////////////////// - - JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_socket( - JNIEnv *env, jobject thisObj, jint family, jint type, jint protocol) - { - return zts_socket(family, type, protocol); - } - - JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_connect( - JNIEnv *env, jobject thisObj, jint fd, jobject addr) - { - struct sockaddr_storage ss; - zta2ss(env, &ss, addr); - socklen_t addrlen = ss.ss_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6); - return zts_connect(fd, (struct sockaddr *)&ss, addrlen); - } - - JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_bind( - JNIEnv *env, jobject thisObj, jint fd, jobject addr) - { - struct sockaddr_storage ss; - zta2ss(env, &ss, addr); - socklen_t addrlen = ss.ss_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6); - return zts_bind(fd, (struct sockaddr*)&ss, addrlen); - } - - JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_listen( - JNIEnv *env, jobject thisObj, jint fd, int backlog) - { - return zts_listen(fd, backlog); - } - - JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_accept( - JNIEnv *env, jobject thisObj, jint fd, jobject addr, jint port) - { - struct sockaddr_storage ss; - socklen_t addrlen = sizeof(struct sockaddr_storage); - int err = zts_accept(fd, (struct sockaddr *)&ss, &addrlen); - ss2zta(env, &ss, addr); - return err; - } - -#if defined(__linux__) - JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_accept4( - JNIEnv *env, jobject thisObj, jint fd, jobject addr, jint port, jint flags) - { - struct sockaddr_storage ss; - socklen_t addrlen = sizeof(struct sockaddr_storage); - int err = zts_accept4(fd, (struct sockaddr *)&ss, &addrlen, flags); - ss2zta(env, &ss, addr); - return err; - } -#endif - - JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_setsockopt( - JNIEnv *env, jobject thisObj, jint fd, jint level, jint optname, jint optval, jint optlen) - { - return zts_setsockopt(fd, level, optname, (void*)(uintptr_t)optval, optlen); - } - - JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_getsockopt( - JNIEnv *env, jobject thisObj, jint fd, jint level, jint optname, jint optval, jint optlen) - { - return zts_getsockopt(fd, level, optname, (void*)(uintptr_t)optval, (socklen_t *)optlen); - } - - JNIEXPORT jboolean JNICALL Java_com_zerotier_libzt_ZeroTier_getsockname(JNIEnv *env, jobject thisObj, - jint fd, jobject addr) - { - struct sockaddr_storage ss; - socklen_t addrlen = sizeof(struct sockaddr_storage); - int err = zts_getsockname(fd, (struct sockaddr *)&ss, &addrlen); - ss2zta(env, &ss, addr); - return err; - } - - JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_getpeername(JNIEnv *env, jobject thisObj, - jint fd, jobject addr) - { - struct sockaddr_storage ss; - int err = zts_getpeername(fd, (struct sockaddr *)&ss, (socklen_t *)sizeof(struct sockaddr_storage)); - ss2zta(env, &ss, addr); - return err; - } - - JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_close( - JNIEnv *env, jobject thisObj, jint fd) - { - return zts_close(fd); - } - - JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_fcntl( - JNIEnv *env, jobject thisObj, jint fd, jint cmd, jint flags) - { - return zts_fcntl(fd, cmd, flags); - } - - JNIEXPORT int JNICALL Java_com_zerotier_libzt_ZeroTier_ioctl(jint fd, jlong request, void *argp) - { - return zts_ioctl(fd, request, argp); - } - - JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_send( - JNIEnv *env, jobject thisObj, jint fd, jbyteArray buf, int flags) - { - void *data = env->GetPrimitiveArrayCritical(buf, NULL); - int w = zts_send(fd, data, env->GetArrayLength(buf), flags); - env->ReleasePrimitiveArrayCritical(buf, data, 0); - return w; - } - - JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_sendto( - JNIEnv *env, jobject thisObj, jint fd, jbyteArray buf, jint flags, jobject addr) - { - void *data = env->GetPrimitiveArrayCritical(buf, NULL); - struct sockaddr_storage ss; - zta2ss(env, &ss, addr); - socklen_t addrlen = ss.ss_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6); - int w = zts_sendto(fd, data, env->GetArrayLength(buf), flags, (struct sockaddr *)&ss, addrlen); - env->ReleasePrimitiveArrayCritical(buf, data, 0); - return w; - } - - JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_recv(JNIEnv *env, jobject thisObj, - jint fd, jbyteArray buf, jint flags) - { - void *data = env->GetPrimitiveArrayCritical(buf, NULL); - int r = zts_recv(fd, data, env->GetArrayLength(buf), flags); - env->ReleasePrimitiveArrayCritical(buf, data, 0); - return r; - } - - JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_recvfrom( - JNIEnv *env, jobject thisObj, jint fd, jbyteArray buf, jint flags, jobject addr) - { - socklen_t addrlen = sizeof(struct sockaddr_storage); - struct sockaddr_storage ss; - void *data = env->GetPrimitiveArrayCritical(buf, NULL); - int r = zts_recvfrom(fd, data, env->GetArrayLength(buf), flags, (struct sockaddr *)&ss, &addrlen); - env->ReleasePrimitiveArrayCritical(buf, data, 0); - ss2zta(env, &ss, addr); - return r; - } - - JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_read(JNIEnv *env, jobject thisObj, - jint fd, jbyteArray buf) - { - void *data = env->GetPrimitiveArrayCritical(buf, NULL); - int r = zts_read(fd, data, env->GetArrayLength(buf)); - env->ReleasePrimitiveArrayCritical(buf, data, 0); - return r; - } - - JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_write(JNIEnv *env, jobject thisObj, - jint fd, jbyteArray buf) - { - void *data = env->GetPrimitiveArrayCritical(buf, NULL); - int w = zts_write(fd, data, env->GetArrayLength(buf)); - env->ReleasePrimitiveArrayCritical(buf, data, 0); - return w; - } - - JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_shutdown( - JNIEnv *env, jobject thisObj, int fd, int how) - { - return zts_shutdown(fd, how); - } - - JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_select(JNIEnv *env, jobject thisObj, - jint nfds, jobject readfds, jobject writefds, jobject exceptfds, jint timeout_sec, jint timeout_usec) - { - struct timeval _timeout; - _timeout.tv_sec = timeout_sec; - _timeout.tv_usec = timeout_usec; - fd_set _readfds, _writefds, _exceptfds; - fd_set *r = NULL; - fd_set *w = NULL; - fd_set *e = NULL; - if (readfds) { - r = &_readfds; - ztfdset2fdset(env, nfds, readfds, &_readfds); - } - if (writefds) { - w = &_writefds; - ztfdset2fdset(env, nfds, writefds, &_writefds); - } - if (exceptfds) { - e = &_exceptfds; - ztfdset2fdset(env, nfds, exceptfds, &_exceptfds); - } - int err = zts_select(nfds, r, w, e, &_timeout); - if (readfds) { - fdset2ztfdset(env, nfds, &_readfds, readfds); - } - if (writefds) { - fdset2ztfdset(env, nfds, &_writefds, writefds); - } - if (exceptfds) { - fdset2ztfdset(env, nfds, &_exceptfds, exceptfds); - } - return err; - } -} - -void ztfdset2fdset(JNIEnv *env, int nfds, jobject src_ztfd_set, fd_set *dest_fd_set) -{ - jclass c = (*env).GetObjectClass(src_ztfd_set); - if (!c) { - return; - } - FD_ZERO(dest_fd_set); - jfieldID fid = env->GetFieldID(c, "fds_bits", "[B"); - jobject fdData = (*env).GetObjectField (src_ztfd_set, fid); - jbyteArray * arr = reinterpret_cast(&fdData); - char *data = (char*)(*env).GetByteArrayElements(*arr, NULL); - for (int i=0; iGetFieldID(c, "fds_bits", "[B"); - jobject fdData = (*env).GetObjectField (dest_ztfd_set, fid); - jbyteArray * arr = reinterpret_cast(&fdData); - char *data = (char*)(*env).GetByteArrayElements(*arr, NULL); - for (int i=0; iss_family == AF_INET) - { - struct sockaddr_in *in4 = (struct sockaddr_in*)ss; - jfieldID fid = (*env).GetFieldID(c, "_port", "I"); - (*env).SetIntField(addr, fid, ntohs(in4->sin_port)); - fid = (*env).GetFieldID(c,"_family", "I"); - (*env).SetIntField(addr, fid, (in4->sin_family)); - fid = env->GetFieldID(c, "_ip4", "[B"); - jobject ipData = (*env).GetObjectField (addr, fid); - jbyteArray * arr = reinterpret_cast(&ipData); - char *data = (char*)(*env).GetByteArrayElements(*arr, NULL); - memcpy(data, &(in4->sin_addr.s_addr), 4); - (*env).ReleaseByteArrayElements(*arr, (jbyte*)data, 0); - - return; - } - if(ss->ss_family == AF_INET6) - { - struct sockaddr_in6 *in6 = (struct sockaddr_in6*)ss; - jfieldID fid = (*env).GetFieldID(c, "_port", "I"); - (*env).SetIntField(addr, fid, ntohs(in6->sin6_port)); - fid = (*env).GetFieldID(c,"_family", "I"); - (*env).SetIntField(addr, fid, (in6->sin6_family)); - fid = env->GetFieldID(c, "_ip6", "[B"); - jobject ipData = (*env).GetObjectField (addr, fid); - jbyteArray * arr = reinterpret_cast(&ipData); - char *data = (char*)(*env).GetByteArrayElements(*arr, NULL); - memcpy(data, &(in6->sin6_addr.s6_addr), 16); - (*env).ReleaseByteArrayElements(*arr, (jbyte*)data, 0); - return; - } -} - -void zta2ss(JNIEnv *env, struct sockaddr_storage *ss, jobject addr) -{ - jclass c = (*env).GetObjectClass(addr); - if (!c) { - return; - } - jfieldID fid = (*env).GetFieldID(c, "_family", "I"); - int family = (*env).GetIntField(addr, fid); - if (family == AF_INET) - { - struct sockaddr_in *in4 = (struct sockaddr_in*)ss; - fid = (*env).GetFieldID(c, "_port", "I"); - in4->sin_port = htons((*env).GetIntField(addr, fid)); - in4->sin_family = AF_INET; - fid = env->GetFieldID(c, "_ip4", "[B"); - jobject ipData = (*env).GetObjectField (addr, fid); - jbyteArray * arr = reinterpret_cast(&ipData); - char *data = (char*)(*env).GetByteArrayElements(*arr, NULL); - memcpy(&(in4->sin_addr.s_addr), data, 4); - (*env).ReleaseByteArrayElements(*arr, (jbyte*)data, 0); - return; - } - if (family == AF_INET6) - { - struct sockaddr_in6 *in6 = (struct sockaddr_in6*)ss; - jfieldID fid = (*env).GetFieldID(c, "_port", "I"); - in6->sin6_port = htons((*env).GetIntField(addr, fid)); - fid = (*env).GetFieldID(c,"_family", "I"); - in6->sin6_family = AF_INET6; - fid = env->GetFieldID(c, "_ip6", "[B"); - jobject ipData = (*env).GetObjectField (addr, fid); - jbyteArray * arr = reinterpret_cast(&ipData); - char *data = (char*)(*env).GetByteArrayElements(*arr, NULL); - memcpy(&(in6->sin6_addr.s6_addr), data, 16); - (*env).ReleaseByteArrayElements(*arr, (jbyte*)data, 0); - return; - } -} - -#ifdef __cplusplus -} -#endif - -#endif // SDK_JNI \ No newline at end of file diff --git a/attic/picoTCP.cpp b/attic/picoTCP.cpp deleted file mode 100644 index ce62929..0000000 --- a/attic/picoTCP.cpp +++ /dev/null @@ -1,1979 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2018 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 . - * - * -- - * - * 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 - * - * picoTCP stack driver - */ - -#include "libztDefs.h" - -#ifdef STACK_PICO - -#include -#include - -#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" -#include "pico_tcp.h" -#include "pico_dns_client.h" - -int errno; - -#include "libzt.h" -#include "SysUtils.h" -#include "Utilities.h" -#include "VirtualTap.h" -#include "picoTCP.h" -#include "RingBuffer.h" -#include "VirtualSocket.h" -#include "VirtualBindingPair.h" -#include "VirtualSocketLayer.h" -#include "ZT1Service.h" - -#include "Utils.hpp" -#include "Mutex.hpp" -#include "Constants.hpp" -#include "Phy.hpp" -#include "InetAddress.hpp" - -using namespace ZeroTier; - -int pico_ipv4_to_string(PICO_IPV4_TO_STRING_SIG); -extern "C" int pico_stack_init(void); -extern "C" void pico_stack_tick(void); -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); -extern "C" int pico_socket_recvfrom(PICO_SOCKET_RECVFROM_SIG); -extern "C" struct pico_socket * pico_socket_open(PICO_SOCKET_OPEN_SIG); -extern "C" int pico_socket_connect(PICO_SOCKET_CONNECT_SIG); -extern "C" int pico_socket_listen(PICO_SOCKET_LISTEN_SIG); -extern "C" int pico_socket_write(PICO_SOCKET_WRITE_SIG); -extern "C" int pico_socket_close(PICO_SOCKET_CLOSE_SIG); -extern "C" struct pico_ipv6_link * pico_ipv6_link_add(PICO_IPV6_LINK_ADD_SIG); -extern "C" int pico_dns_client_nameserver(PICO_DNS_CLIENT_NAMESERVER_SIG); - -/* -int pico_stack_recv(PICO_STACK_RECV_SIG); -int pico_icmp4_ping(PICO_ICMP4_PING_SIG); -int pico_socket_setoption(PICO_SOCKET_SETOPTION_SIG); -uint32_t pico_timer_add(PICO_TIMER_ADD_SIG); -int pico_socket_send(PICO_SOCKET_SEND_SIG); -int pico_socket_sendto(PICO_SOCKET_SENDTO_SIG); -int pico_socket_recv(PICO_SOCKET_RECV_SIG); -int pico_socket_bind(PICO_SOCKET_BIND_SIG); -int pico_socket_read(PICO_SOCKET_READ_SIG); -int pico_socket_shutdown(PICO_SOCKET_SHUTDOWN_SIG); -struct pico_socket * pico_socket_accept(PICO_SOCKET_ACCEPT_SIG); -*/ - -extern std::vector vtaps; - -/* - * Whether our picoTCP device has been initialized - */ -static bool picodev_initialized; - -struct pico_device picodev; -ZeroTier::Mutex _picostack_driver_lock; - -bool pico_init_interface(VirtualTap *tap) -{ - bool err = false; - _picostack_driver_lock.lock(); - // give right to vtap to start the stack - // only one stack loop is permitted - if (picodev_initialized == false) { - tap->should_start_stack = true; - picodev.send = rd_pico_eth_tx; // tx - picodev.poll = rd_pico_eth_poll; // calls pico_eth_rx - picodev.mtu = tap->_mtu; - picodev.tap = tap; - uint8_t mac[PICO_SIZE_ETH]; - tap->_mac.copyTo(mac, PICO_SIZE_ETH); - if (pico_device_init(&picodev, tap->vtap_abbr_name, mac) != 0) { - DEBUG_ERROR("dev init failed"); - err = false; - } - picodev_initialized = true; - err = true; - } - _picostack_driver_lock.unlock(); - return err; -} - -bool pico_register_address(VirtualTap *tap, const InetAddress &ip) -{ - _picostack_driver_lock.lock(); - bool err = false; - char ipbuf[INET6_ADDRSTRLEN]; - uint8_t hwaddr[6]; - // register addresses - if (ip.isV4()) { - struct pico_ip4 ipaddr, netmask; - ipaddr.addr = *((uint32_t *)ip.rawIpData()); - netmask.addr = *((uint32_t *)ip.netmask().rawIpData()); - pico_ipv4_link_add(&picodev, ipaddr, netmask); - DEBUG_INFO("addr=%s", ip.toString(ipbuf)); - tap->_mac.copyTo(hwaddr, 6); - char macbuf[ZT_MAC_ADDRSTRLEN]; - mac2str(macbuf, ZT_MAC_ADDRSTRLEN, hwaddr); - DEBUG_INFO("mac=%s", macbuf); - err = true; - } - if (ip.isV6()) { - char ipv6_str[INET6_ADDRSTRLEN], nm_str[INET6_ADDRSTRLEN]; - inet_ntop(AF_INET6, ip.rawIpData(), ipv6_str, INET6_ADDRSTRLEN); - inet_ntop(AF_INET6, ip.netmask().rawIpData(), nm_str, INET6_ADDRSTRLEN); - struct pico_ip6 ipaddr, netmask; - pico_string_to_ipv6(ipv6_str, ipaddr.addr); - pico_string_to_ipv6(nm_str, netmask.addr); - pico_ipv6_link_add(&picodev, ipaddr, netmask); - DEBUG_INFO("addr=%s", ipv6_str); - tap->_mac.copyTo(hwaddr, 6); - char macbuf[ZT_MAC_ADDRSTRLEN]; - mac2str(macbuf, ZT_MAC_ADDRSTRLEN, hwaddr); - DEBUG_INFO("mac=%s", macbuf); - err = true; - } - _picostack_driver_lock.unlock(); - return err; -} - -// TODO: -// pico_ipv6_route_add -// pico_ipv6_route_del - -bool rd_pico_route_add(VirtualTap *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 rd_pico_route_del(VirtualTap *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; -} - -int rd_pico_add_dns_nameserver(struct sockaddr *addr) -{ - int err = errno = 0; - // TODO: De-complexify this - struct pico_ip4 ns; - memset(&ns, 0, sizeof (struct pico_ip4)); - struct sockaddr_in *in4 = (struct sockaddr_in*)addr; - char ipv4_str[INET_ADDRSTRLEN]; - inet_ntop(AF_INET, (const void *)&in4->sin_addr.s_addr, ipv4_str, INET_ADDRSTRLEN); - uint32_t ipval = 0; - pico_string_to_ipv4(ipv4_str, &ipval); - ns.addr = ipval; - if ((err = pico_dns_client_nameserver(&ns, PICO_DNS_NS_ADD)) < 0) { - DEBUG_ERROR("error while adding DNS nameserver, err=%d, pico_err=%d, %s", - err, pico_err, beautify_pico_error(pico_err)); - map_pico_err_to_errno(pico_err); - } - return err; -} - -int rd_pico_del_dns_nameserver(struct sockaddr *addr) -{ - int err = errno = 0; - // TODO: De-complexify this - struct pico_ip4 ns; - memset(&ns, 0, sizeof (struct pico_ip4)); - struct sockaddr_in *in4 = (struct sockaddr_in*)addr; - char ipv4_str[INET_ADDRSTRLEN]; - inet_ntop(AF_INET, (const void *)&in4->sin_addr.s_addr, ipv4_str, INET_ADDRSTRLEN); - uint32_t ipval = 0; - pico_string_to_ipv4(ipv4_str, &ipval); - ns.addr = ipval; - if ((err = pico_dns_client_nameserver(&ns, PICO_DNS_NS_DEL)) < 0) { - DEBUG_ERROR("error while removing DNS nameserver, err=%d, pico_err=%d, %s", - err, pico_err, beautify_pico_error(pico_err)); - } - return err; -} - -void rd_pico_loop(VirtualTap *tap) -{ - while (tap->_run) - { - tap->_phy.poll(ZT_PHY_POLL_INTERVAL); - pico_stack_tick(); - tap->Housekeeping(); - } -} - -// from stack socket to app socket -void rd_pico_cb_tcp_read(VirtualTap *tap, struct pico_socket *s) -{ - VirtualSocket *vs = (VirtualSocket*)(((VirtualBindingPair*)s->priv)->vs); - if (vs == NULL) { - DEBUG_ERROR("s->priv yielded no valid vs"); - return; - } - Mutex::Lock _l(vs->_rx_m); - if (tap == NULL) { - DEBUG_ERROR("invalid tap"); - return; - } - if (vs == NULL) { - DEBUG_ERROR("invalid vs"); - return; - } - int r; - uint16_t port = 0; - union { - struct pico_ip4 ip4; - struct pico_ip6 ip6; - } peer; - - do { - int n = 0; - int avail = ZT_TCP_RX_BUF_SZ - vs->RXbuf->count(); - if (avail) { - r = pico_socket_recvfrom(s, vs->RXbuf->get_buf(), ZT_STACK_SOCKET_RD_MAX, - (void *)&peer.ip4.addr, &port); - if (r > 0) - { - vs->RXbuf->produce(r); - n = tap->_phy.streamSend(vs->sock, vs->RXbuf->get_buf(), r); - - if (n>0) - vs->RXbuf->consume(n); - } - if (vs->RXbuf->count() == 0) { - tap->_phy.setNotifyWritable(vs->sock, false); - } - else { - tap->_phy.setNotifyWritable(vs->sock, true); - } - } - else { - //tap->_phy.setNotifyWritable(vs->sock, false); - DEBUG_ERROR("not enough space left on I/O RX buffer for pico_socket(%p)", s); - } - } - while (r > 0); -} - -// from stack socket to app socket -void rd_pico_cb_udp_read(VirtualTap *tap, struct pico_socket *s) -{ - // DEBUG_INFO(); - VirtualSocket *vs = (VirtualSocket*)(((VirtualBindingPair*)s->priv)->vs); - if (vs == NULL) { - DEBUG_ERROR("s->priv yielded no valid vs"); - return; - } - Mutex::Lock _l(vs->_rx_m); - if (tap == NULL) { - DEBUG_ERROR("invalid tap"); - return; - } - if (vs == NULL) { - DEBUG_ERROR("invalid vs"); - return; - } - - uint16_t port = 0; - union { - struct pico_ip4 ip4; - struct pico_ip6 ip6; - } peer; - int r = 0, w = 0; - // TODO: Consolidate this - if (vs->socket_family == AF_INET) { - struct sockaddr_in in4; - char udp_payload_buf[ZT_MAX_MTU]; - if ((r = pico_socket_recvfrom(s, udp_payload_buf, ZT_SDK_MTU, (void *)&peer.ip4.addr, &port)) < 0) { - DEBUG_ERROR("err=%d, %s", r, beautify_pico_error(pico_err)); - } - in4.sin_addr.s_addr = peer.ip4.addr; - in4.sin_port = port; - // immediately attempt to write addr and payload to app socket. The idea is that the zts_recvfrom() has - // been called and will pick this up and correctly handle it - char udp_msg_buf[ZT_SOCKET_MSG_BUF_SZ]; // [sz : addr : payload] - int32_t len = sizeof(struct sockaddr_storage) + r; - int32_t tot_len = sizeof(int32_t) + len; - memcpy(udp_msg_buf, &len, sizeof(int32_t)); // len: sockaddr+payload - memcpy(udp_msg_buf + sizeof(int32_t), &in4, sizeof(struct sockaddr_storage)); // sockaddr - memcpy(udp_msg_buf + sizeof(int32_t) + sizeof(struct sockaddr_storage), &udp_payload_buf, r); // payload - if ((w = write(vs->sdk_fd, udp_msg_buf, tot_len)) < 0) { - DEBUG_ERROR("write()=%d, errno=%d", w, errno); - } - } - if (vs->socket_family == AF_INET6) { - struct sockaddr_in6 in6; - char udp_payload_buf[ZT_MAX_MTU]; - if ((r = pico_socket_recvfrom(s, udp_payload_buf, ZT_SDK_MTU, (void *)&peer.ip6.addr, &port)) < 0) { - DEBUG_ERROR("err=%d, %s", r, beautify_pico_error(pico_err)); - } - memcpy(&(in6.sin6_addr.s6_addr), &(peer.ip6.addr), sizeof(peer.ip6.addr)); - in6.sin6_port = port; - // immediately attempt to write addr and payload to app socket. The idea is that the zts_recvfrom() has - // been called and will pick this up and correctly handle it - char udp_msg_buf[ZT_SOCKET_MSG_BUF_SZ]; // [sz : addr : payload] - int32_t len = sizeof(struct sockaddr_storage) + r; - int32_t tot_len = sizeof(int32_t) + len; - memcpy(udp_msg_buf, &len, sizeof(int32_t)); // len: sockaddr+payload - memcpy(udp_msg_buf + sizeof(int32_t), &in6, sizeof(struct sockaddr_storage)); // sockaddr - memcpy(udp_msg_buf + sizeof(int32_t) + sizeof(struct sockaddr_storage), &udp_payload_buf, r); // payload - if ((w = write(vs->sdk_fd, udp_msg_buf, tot_len)) < 0) { - DEBUG_ERROR("write()=%d, errno=%d", w, errno); - } - } -} - -void rd_pico_cb_tcp_write(VirtualTap *tap, struct pico_socket *s) -{ - VirtualSocket *vs = (VirtualSocket*)(((VirtualBindingPair*)s->priv)->vs); - if (vs == NULL) { - DEBUG_EXTRA("vs == NULL"); - return; - } - struct pico_socket *ps = (struct pico_socket*)(vs->pcb); - if (ps != s) { - DEBUG_ERROR("ps != s, bad callback"); - return; - } - // we will get the vs->TXBuf->get_buf() reference from within pico_Write - rd_pico_write(vs, NULL, vs->TXbuf->count()); -} - -void rd_pico_cb_socket_ev(uint16_t ev, struct pico_socket *s) -{ - int err = 0; - //DEBUG_EXTRA("s=%p, s->state=%d %s", s, s->state, beautify_pico_state(s->state)); - - // --- handle error events --- - - // PICO_SOCK_EV_FIN - triggered when the socket is closed. No further communication is - // possible from this point on the socket. - if (ev & PICO_SOCK_EV_FIN) { - DEBUG_EXTRA("PICO_SOCK_EV_FIN (socket closed), picosock=%p", s); - //DEBUG_EXTRA("PICO_SOCK_EV_FIN (socket closed), picosock=%p, vs=%p, app_fd=%d, sdk_fd=%d", s, vs, vs->app_fd, vs->sdk_fd); - } - - // PICO_SOCK_EV_ERR - triggered when an error occurs. - if (ev & PICO_SOCK_EV_ERR) { - if (pico_err == PICO_ERR_ECONNRESET) { - DEBUG_ERROR("PICO_ERR_ECONNRESET"); - } - //DEBUG_ERROR("PICO_SOCK_EV_ERR, err=%s, picosock=%p, app_fd=%d, sdk_fd=%d", - // beautify_pico_error(pico_err), s, vs->app_fd, vs->sdk_fd); - } - // PICO_SOCK_EV_CLOSE - triggered when a FIN segment is received (TCP only). This event - // indicates that the oher endpont has closed the VirtualSocket, so the local TCP layer is only - // allowed to send new data until a local shutdown or close is initiated. PicoTCP is able to - // keep the VirtualSocket half-open (only for sending) after the FIN packet has been received, - // allowing new data to be sent in the TCP CLOSE WAIT state. - - VirtualBindingPair *vbp = (VirtualBindingPair*)(s->priv); - if (vbp == NULL) { - DEBUG_ERROR("s->priv yielded no valid vbp"); - return; - } - VirtualTap *tap = static_cast(vbp->tap); - VirtualSocket *vs = static_cast(vbp->vs); - - if (ev & PICO_SOCK_EV_CLOSE) { - vs->set_state(VS_STATE_CLOSED); - if ((err = pico_socket_shutdown(s, PICO_SHUT_RDWR)) < 0) { - DEBUG_ERROR("error while shutting down socket"); - } - if ((err = pico_socket_close(s)) < 0) { - DEBUG_ERROR("pico_socket_close()=%d, pico_err=%d, %s", err, pico_err, beautify_pico_error(pico_err)); - } - DEBUG_EXTRA("PICO_SOCK_EV_CLOSE (socket closure) err=%d (%s), picosock=%p", pico_err, beautify_pico_error(pico_err), s); - return; - } - - // --- handle non-error events --- - - if (vs == NULL) { - DEBUG_ERROR("invalid VirtualSocket"); - return; - } - // PICO_SOCK_EV - triggered when VirtualSocket is established (TCP only). This event is - // received either after a successful call to pico socket vsect to indicate that the VirtualSocket - // has been established, or on a listening socket, indicating that a call to pico socket accept - // may now be issued in order to accept the incoming VirtualSocket from a remote host. - if (ev & PICO_SOCK_EV_CONN) { - DEBUG_EXTRA("PICO_SOCK_EV_CONN"); - if (vs->get_state() == VS_STATE_LISTENING) { - uint16_t port; - struct pico_socket *client_psock = nullptr; - struct pico_ip4 orig4; - struct pico_ip6 orig6; - if (vs->socket_family == AF_INET) { // NOTE: p->net->proto_number == PICO_PROTO_IPV4 - client_psock = pico_socket_accept(s, &orig4, &port); - } - if (vs->socket_family == AF_INET6) { // NOTE: p->net->proto_number == PICO_PROTO_IPV4 - client_psock = pico_socket_accept(s, &orig6, &port); - } - if (client_psock == NULL) { - DEBUG_ERROR("pico_socket_accept(): pico_socket=%p, pico_err=%d, %s", s, pico_err, beautify_pico_error(pico_err)); - return; - } - // Create a new VirtualSocket and add it to the queue, - // some time in the future a call to zts_multiplex_accept() will pick up - // this new VirtualSocket, add it to the VirtualSocket list and return its - // VirtualSocket->sock to the application - VirtualSocket *new_vs = new VirtualSocket(); - new_vs->socket_type = SOCK_STREAM; - struct pico_socket *new_ps = (struct pico_socket*)(new_vs->pcb); - new_ps = client_psock; - // TODO: Condense this - if (vs->socket_family == AF_INET) { - char addrstr[INET_ADDRSTRLEN]; - struct sockaddr_storage ss4; - struct sockaddr_in *in4 = (struct sockaddr_in *)&ss4; - in4->sin_addr.s_addr = orig4.addr; - in4->sin_port = Utils::hton(port); - memcpy(&(new_vs->peer_addr), in4, sizeof(new_vs->peer_addr)); - inet_ntop(AF_INET, &(in4->sin_addr), addrstr, INET_ADDRSTRLEN); - DEBUG_EXTRA("accepted connection from: %s : %d", addrstr, port); - ZeroTier::InetAddress inet; - inet.fromString(addrstr); - new_vs->tap = getTapByAddr(&inet); // assign to tap based on incoming address - } - if (vs->socket_family == AF_INET6) { - char addrstr[INET6_ADDRSTRLEN]; - struct sockaddr_in6 in6; - memcpy(&(in6.sin6_addr.s6_addr), &orig6, sizeof(in6.sin6_addr.s6_addr)); - in6.sin6_port = Utils::hton(port); - memcpy(&(new_vs->peer_addr), &in6, sizeof(new_vs->peer_addr)); - inet_ntop(AF_INET6, &(in6.sin6_addr), addrstr, INET6_ADDRSTRLEN); - DEBUG_EXTRA("accepted connection from: %s : %d", addrstr, port); - ZeroTier::InetAddress inet; - inet.fromString(addrstr); - new_vs->tap = getTapByAddr(&inet); // assign to tap based on incoming address - } - if (new_vs->tap == NULL) { - DEBUG_ERROR("no valid VirtualTap could be found"); - return; - } - // Assign this VirtualSocket to the appropriate VirtualTap - new_ps->priv = new VirtualBindingPair(new_vs->tap,new_vs); - new_vs->tap->addVirtualSocket(new_vs); - vs->_AcceptedConnections.push(new_vs); - new_vs->sock = new_vs->tap->_phy.wrapSocket(new_vs->sdk_fd, new_vs); - } - if (vs->get_state() != VS_STATE_LISTENING) { - // set state so socket multiplexer logic will pick this up - vs->set_state(VS_STATE_UNHANDLED_CONNECTED); - } - } - // PICO_SOCK_EV_RD - triggered when new data arrives on the socket. A new receive action - // can be taken by the socket owner because this event indicates there is new data to receive. - if (ev & PICO_SOCK_EV_RD) { - if (vs->socket_type==SOCK_STREAM) - rd_pico_cb_tcp_read(tap, s); - if (vs->socket_type==SOCK_DGRAM) - rd_pico_cb_udp_read(tap, s); - } - // PICO_SOCK_EV_WR - triggered when ready to write to the socket. Issuing a write/send call - // will now succeed if the buffer has enough space to allocate new outstanding data - if (ev & PICO_SOCK_EV_WR) { - rd_pico_cb_tcp_write(tap, s); - } -} - -int rd_pico_eth_tx(struct pico_device *dev, void *buf, int len) -{ - //DEBUG_TRANS(); - //_picostack_driver_lock.lock(); - VirtualTap *tap = static_cast(dev->tap); - if (tap == NULL) { - DEBUG_ERROR("invalid dev->tap"); - return ZT_ERR_GENERAL_FAILURE; - } - struct pico_eth_hdr *ethhdr; - ethhdr = (struct pico_eth_hdr *)buf; - MAC src_mac; - MAC dest_mac; - src_mac.setTo(ethhdr->saddr, 6); - dest_mac.setTo(ethhdr->daddr, 6); - if (ZT_MSG_TRANSFER == true) { - char macBuf[ZT_MAC_ADDRSTRLEN], nodeBuf[ZTO_ID_LEN]; - mac2str(macBuf, ZT_MAC_ADDRSTRLEN, ethhdr->daddr); - ZeroTier::MAC mac; - mac.setTo(ethhdr->daddr, 6); - mac.toAddress(tap->_nwid).toString(nodeBuf); - - char flagbuf[32]; - memset(&flagbuf, 0, 32); -/* - struct pico_tcp_hdr *hdr; - void * tcp_hdr_ptr; - if (Utils::ntoh(ethhdr->proto) == 0x86dd) { // tcp, ipv6 - tcp_hdr_ptr = ðhdr + PICO_SIZE_ETHHDR + PICO_SIZE_IP4HDR; - } - - if (Utils::ntoh(ethhdr->proto) == 0x0800) // tcp - { - tcp_hdr_ptr = &buf + PICO_SIZE_ETHHDR + PICO_SIZE_IP4HDR; - hdr = (struct pico_tcp_hdr *)tcp_hdr_ptr; - - if (hdr) { - char *flag_ptr = flagbuf; - - if (hdr->flags & PICO_TCP_PSH) { - sprintf(flag_ptr, "PSH "); - flag_ptr+=4; - } - if (hdr->flags & PICO_TCP_SYN) { - sprintf(flag_ptr, "SYN "); - flag_ptr+=4; - } - if (hdr->flags & PICO_TCP_ACK) { - sprintf(flag_ptr, "ACK "); - flag_ptr+=4; - } - if (hdr->flags & PICO_TCP_FIN) { - sprintf(flag_ptr, "FIN "); - flag_ptr+=4; - } - if (hdr->flags & PICO_TCP_RST) { - sprintf(flag_ptr, "RST "); - flag_ptr+=4; - } - } - } -*/ - DEBUG_TRANS("len=%5d dst=%s [%s TX <-- %s] proto=0x%04x %s %s", len, macBuf, nodeBuf, tap->nodeId().c_str(), - Utils::ntoh(ethhdr->proto), beautify_eth_proto_nums(Utils::ntoh(ethhdr->proto)), flagbuf); - } - tap->_handler(tap->_arg,NULL,tap->_nwid,src_mac,dest_mac, - Utils::ntoh((uint16_t)ethhdr->proto), 0, ((char*)buf) - + sizeof(struct pico_eth_hdr),len - sizeof(struct pico_eth_hdr)); - //_picostack_driver_lock.unlock(); - return len; -} - -// receive frames from zerotier virtual wire and copy them to a guarded buffer awaiting placement into network stack -void rd_pico_eth_rx(VirtualTap *tap, const MAC &from,const MAC &to,unsigned int etherType, - const void *data,unsigned int len) -{ - //DEBUG_TRANS(); - //_picostack_driver_lock.lock(); - if (tap == NULL) { - DEBUG_ERROR("invalid tap"); - return; - } - // Since picoTCP only allows the reception of frames from within the polling function, we - // must enqueue each frame into a memory structure shared by both threads. This structure will - Mutex::Lock _l(tap->_pico_frame_rxbuf_m); - // assemble new eth header - struct pico_eth_hdr ethhdr; - from.copyTo(ethhdr.saddr, 6); - to.copyTo(ethhdr.daddr, 6); - ethhdr.proto = Utils::hton((uint16_t)etherType); - int32_t msg_len = len + sizeof(int32_t) + sizeof(struct pico_eth_hdr); - - if (ZT_MSG_TRANSFER == true) { - char macBuf[ZT_MAC_ADDRSTRLEN], nodeBuf[ZTO_ID_LEN]; - mac2str(macBuf, sizeof(macBuf), ethhdr.saddr); - ZeroTier::MAC mac; - mac.setTo(ethhdr.saddr, 6); - mac.toAddress(tap->_nwid).toString(nodeBuf); - - char flagbuf[64]; - memset(&flagbuf, 0, 64); -/* - struct pico_tcp_hdr *hdr; - void * tcp_hdr_ptr; - if (etherType == 0x86dd) { // tcp, ipv6 - tcp_hdr_ptr = ðhdr + PICO_SIZE_ETHHDR + PICO_SIZE_IP4HDR; - } - - if (etherType == 0x0800) // tcp, ipv4 - { - tcp_hdr_ptr = ðhdr + PICO_SIZE_ETHHDR + PICO_SIZE_IP4HDR; - hdr = (struct pico_tcp_hdr *)tcp_hdr_ptr; - if (hdr) { - char *flag_ptr = flagbuf; - - if (hdr->flags & PICO_TCP_PSH) { - sprintf(flag_ptr, "PSH "); - flag_ptr+=4; - } - if (hdr->flags & PICO_TCP_SYN) { - sprintf(flag_ptr, "SYN "); - flag_ptr+=4; - } - if (hdr->flags & PICO_TCP_ACK) { - sprintf(flag_ptr, "ACK "); - flag_ptr+=4; - } - if (hdr->flags & PICO_TCP_FIN) { - sprintf(flag_ptr, "FIN "); - flag_ptr+=4; - } - if (hdr->flags & PICO_TCP_RST) { - sprintf(flag_ptr, "RST "); - flag_ptr+=4; - } - } - } -*/ - DEBUG_TRANS("len=%5d src=%s [%s RX --> %s] proto=0x%04x %s %s", len, macBuf, nodeBuf, tap->nodeId().c_str(), - etherType, beautify_eth_proto_nums(etherType), flagbuf); - } - // write virtual ethernet frame to guarded buffer (emptied by pico_eth_poll()) - memcpy(tap->pico_frame_rxbuf + tap->pico_frame_rxbuf_tot, &msg_len, sizeof(int32_t)); // size of frame + meta - memcpy(tap->pico_frame_rxbuf + tap->pico_frame_rxbuf_tot + sizeof(int32_t), ðhdr, sizeof(ethhdr)); // new eth header - memcpy(tap->pico_frame_rxbuf + tap->pico_frame_rxbuf_tot + sizeof(int32_t) + sizeof(ethhdr), data, len); // frame data - tap->pico_frame_rxbuf_tot += msg_len; - //_picostack_driver_lock.unlock(); -} - -// feed frames on the guarded RX buffer (from zerotier virtual wire) into the network stack -int rd_pico_eth_poll(struct pico_device *dev, int loop_score) -{ - VirtualTap *tap = static_cast(dev->tap); - if (tap == NULL) { - DEBUG_ERROR("invalid dev->tap"); - return ZT_ERR_GENERAL_FAILURE; - } - // TODO: Optimize (use Ringbuffer) - Mutex::Lock _l(tap->_pico_frame_rxbuf_m); - unsigned char frame[ZT_SDK_MTU]; - int32_t len, err = 0; - while (tap->pico_frame_rxbuf_tot > 0 && loop_score > 0) { - memset(frame, 0, sizeof(frame)); - len = 0; - // get frame len - memcpy(&len, tap->pico_frame_rxbuf, sizeof(int32_t)); - if (len > sizeof(int32_t)) { // meaning, since we package the len in the msg, we don't want to recv a 0-(sizeof(int32_t)) sized frame - memcpy(frame, tap->pico_frame_rxbuf + sizeof(int32_t), len-(sizeof(int32_t)) ); // get frame data - memmove(tap->pico_frame_rxbuf, tap->pico_frame_rxbuf + len, MAX_PICO_FRAME_RX_BUF_SZ-len); // shift buffer - if ((err = pico_stack_recv(dev, (uint8_t*)frame, (len-sizeof(int32_t)))) < 0) { - DEBUG_ERROR("pico_stack_recv(), err=%d, pico_err=%d, %s", err, pico_err, picostack->beautify_pico_error(pico_err)); - } - tap->pico_frame_rxbuf_tot-=len; - } - else { - DEBUG_ERROR("invalid frame size (%d)",len); - } - loop_score--; - } - return loop_score; -} - -int rd_pico_socket(struct pico_socket **p, int socket_family, int socket_type, int protocol) -{ - int err = 0; - if (virt_can_provision_new_socket(socket_type) == false) { - DEBUG_ERROR("cannot create additional socket, see PICO_MAX_TIMERS. current=%d", pico_ntimers()); - errno = EMFILE; - err = -1; - } - else { - int protocol_version = 0; - struct pico_socket *psock; - if (socket_family == AF_INET) { - protocol_version = PICO_PROTO_IPV4; - } - if (socket_family == AF_INET6) { - protocol_version = PICO_PROTO_IPV6; - } - if (socket_type == SOCK_DGRAM) { - psock = pico_socket_open(protocol_version, PICO_PROTO_UDP, &rd_pico_cb_socket_ev); - if (psock) { - // configure size of UDP SND/RCV buffers - // TODO - } - } - if (socket_type == SOCK_STREAM) { - psock = pico_socket_open(protocol_version, PICO_PROTO_TCP, &rd_pico_cb_socket_ev); - if (psock) { - // configure size of TCP SND/RCV buffers - int tx_buf_sz = ZT_STACK_TCP_SOCKET_TX_SZ; - int rx_buf_sz = ZT_STACK_TCP_SOCKET_RX_SZ; - int t_err = 0; - if ((t_err = pico_socket_setoption(psock, PICO_SOCKET_OPT_SNDBUF, &tx_buf_sz)) < 0) { - DEBUG_ERROR("unable to set SNDBUF size, err=%d, pico_err=%d, %s", - t_err, pico_err, beautify_pico_error(pico_err)); - } - if ((t_err = pico_socket_setoption(psock, PICO_SOCKET_OPT_RCVBUF, &rx_buf_sz)) < 0) { - DEBUG_ERROR("unable to set RCVBUF size, err=%d, pico_err=%d, %s", - t_err, pico_err, beautify_pico_error(pico_err)); - } - } - } - *p = psock; - } - return err; -} - -int rd_pico_connect(VirtualSocket *vs, const struct sockaddr *addr, socklen_t addrlen) -{ - if (vs == NULL || vs->pcb == NULL) { - DEBUG_ERROR("invalid vs or ps"); - return ZT_ERR_GENERAL_FAILURE; - } - struct pico_socket *ps = (struct pico_socket*)(vs->pcb); - int err = 0; - if (vs->socket_family == AF_INET) { - struct pico_ip4 zaddr; - memset(&zaddr, 0, sizeof (struct pico_ip4)); - struct sockaddr_in *in4 = (struct sockaddr_in*)addr; - char ipv4_str[INET_ADDRSTRLEN]; - inet_ntop(AF_INET, (const void *)&in4->sin_addr.s_addr, ipv4_str, INET_ADDRSTRLEN); - uint32_t ipval = 0; - pico_string_to_ipv4(ipv4_str, &ipval); - zaddr.addr = ipval; - if (vs->socket_type == SOCK_STREAM) { // connect is an implicit call for non-connection-based VirtualSockets - DEBUG_EXTRA("connecting to addr=%s port=%d", ipv4_str, Utils::ntoh(in4->sin_port)); - } - err = pico_socket_connect(ps, &zaddr, in4->sin_port); - } - if (vs->socket_family == AF_INET6) { - struct pico_ip6 zaddr; - struct sockaddr_in6 *in6 = (struct sockaddr_in6*)addr; - char ipv6_str[INET6_ADDRSTRLEN]; - inet_ntop(AF_INET6, &(in6->sin6_addr), ipv6_str, INET6_ADDRSTRLEN); - pico_string_to_ipv6(ipv6_str, zaddr.addr); - if (vs->socket_type == SOCK_STREAM) { - DEBUG_EXTRA("connecting to addr=%s port=%d", ipv6_str, Utils::ntoh(in6->sin6_port)); - } - err = pico_socket_connect(ps, &zaddr, in6->sin6_port); - } - if (err) { - DEBUG_ERROR("error connecting pico_socket=%p, err=%d, pico_err=%d, %s", - ps, err, pico_err, beautify_pico_error(pico_err)); - return map_pico_err_to_errno(pico_err); - } - memcpy(&(vs->peer_addr), &addr, sizeof(struct sockaddr_storage)); - return err; -} - -int rd_pico_bind(VirtualSocket *vs, const struct sockaddr *addr, socklen_t addrlen) -{ - if (vs == NULL || vs->pcb == NULL) { - DEBUG_ERROR("invalid vs or ps"); - return ZT_ERR_GENERAL_FAILURE; - } - struct pico_socket *ps = (struct pico_socket*)(vs->pcb); - int err = 0; - if (vs->socket_family == AF_INET) { - struct pico_ip4 zaddr; - uint32_t tempaddr; - memset(&zaddr, 0, sizeof (struct pico_ip4)); - struct sockaddr_in *in4 = (struct sockaddr_in*)addr; - char ipv4_str[INET_ADDRSTRLEN]; - inet_ntop(AF_INET, (const void *)&in4->sin_addr.s_addr, ipv4_str, INET_ADDRSTRLEN); - pico_string_to_ipv4(ipv4_str, &tempaddr); - zaddr.addr = tempaddr; - DEBUG_EXTRA("binding to addr=%s port=%d", ipv4_str, Utils::ntoh(in4->sin_port)); - err = pico_socket_bind(ps, &zaddr, (uint16_t *)&(in4->sin_port)); - } - if (vs->socket_family == AF_INET6) { - struct pico_ip6 pip6; - struct sockaddr_in6 *in6 = (struct sockaddr_in6*)addr; - char ipv6_str[INET6_ADDRSTRLEN]; - inet_ntop(AF_INET6, &(in6->sin6_addr), ipv6_str, INET6_ADDRSTRLEN); - // TODO: This isn't proper - pico_string_to_ipv6("::", pip6.addr); - DEBUG_EXTRA("binding to addr=%s port=%d", ipv6_str, Utils::ntoh(in6->sin6_port)); - err = pico_socket_bind(ps, &pip6, (uint16_t *)&(in6->sin6_port)); - } - if (err < 0) { - DEBUG_ERROR("unable to bind pico_socket=%p, err=%d, pico_err=%d, %s", - (ps), err, pico_err, beautify_pico_error(pico_err)); - return map_pico_err_to_errno(pico_err); - } - return err; -} - -int rd_pico_listen(VirtualSocket *vs, int backlog) -{ - if (vs == NULL || vs->pcb == NULL) { - DEBUG_ERROR("invalid vs or ps"); - return ZT_ERR_GENERAL_FAILURE; - } - struct pico_socket *ps = (struct pico_socket*)(vs->pcb); - int err = 0; - if ((err = pico_socket_listen(ps, backlog)) < 0) { - DEBUG_ERROR("error putting pico_socket=%p into listening state. err=%d, pico_err=%d, %s", - ps, err, pico_err, beautify_pico_error(pico_err)); - return map_pico_err_to_errno(pico_err); - } - vs->set_state(VS_STATE_LISTENING); - return ZT_ERR_OK; -} - -VirtualSocket* rd_pico_accept(VirtualSocket *vs) -{ - if (vs == NULL) { - DEBUG_ERROR("invalid vs"); - return NULL; - } - // Retreive first of queued VirtualSockets from parent VirtualSocket - VirtualSocket *new_vs = NULL; - if (vs->_AcceptedConnections.size()) { - new_vs = vs->_AcceptedConnections.front(); - vs->_AcceptedConnections.pop(); - } - return new_vs; -} - -int rd_pico_read(VirtualTap *tap, PhySocket *sock, VirtualSocket* vs, bool stack_invoked) -{ - // DEBUG_INFO(); - // Vestigial - return 0; -} - -int rd_pico_write(VirtualSocket *vs, void *data, ssize_t len) -{ - int err = 0; - void *src_buf = NULL; - // TODO: Add RingBuffer overflow checks - DEBUG_EXTRA("vs=%p, fd=%d, data=%p, len=%d", vs, vs->app_fd, data, len); - if (vs == NULL) { - DEBUG_ERROR("invalid vs"); - return ZT_ERR_GENERAL_FAILURE; - } - struct pico_socket *ps = (struct pico_socket*)(vs->pcb); - Mutex::Lock _l(vs->_tx_m); - if (ps == NULL) { - DEBUG_ERROR("ps == NULL"); - return -1; - } - if (vs->app_fd <= 0) { - DEBUG_EXTRA("invalid fd"); - return -1; - } - if (ps->state & PICO_SOCKET_STATE_CLOSED) { - DEBUG_ERROR("socket is PICO_SOCKET_STATE_CLOSED, this pico_tcp_write() will fail"); - return -1; - } - if (vs == NULL) { - DEBUG_ERROR("invalid VirtualSocket (len=%d)", len); - return -1; - } - if (vs->socket_type == SOCK_DGRAM) { - if (data == NULL) { - DEBUG_ERROR("data == NULL"); - return -1; - } - if (len <= 0) { - DEBUG_ERROR("invalid write len=%d for SOCK_DGRAM", len); - return -1; - } - int r; - if ((r = pico_socket_write(ps, data, len)) < 0) { - DEBUG_ERROR("unable to write to picosock=%p, err=%d, pico_err=%d, %s", - ps, r, pico_err, beautify_pico_error(pico_err)); - err = -1; - } - else { - err = r; // successful write - } - if (vs->socket_type == SOCK_DGRAM) { - DEBUG_TRANS("len=%5d buf_len=N/A [APPFDS --> NSPICO] proto=0x%04x (UDP)", r, PICO_PROTO_TCP); - } - } - if (vs->socket_type == SOCK_STREAM) { - if (len > 0 && data != NULL) { - - src_buf = data; // --- Data source: poll loop I/O buffer --- - - // in this case, we've recieved data on the 'data' buffer, add it to TX ringbuffer, then try to handle it from there - int original_txsz = vs->TXbuf->count(); - if (original_txsz + len >= ZT_TCP_TX_BUF_SZ) { - 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"); - return ZT_ERR_GENERAL_FAILURE; - } - int buf_w = vs->TXbuf->write((const char*)data, len); - if (buf_w != len) { - // because we checked ZT_TCP_TX_BUF_SZ above, this should not happen - DEBUG_ERROR("wrote only len=%d but expected to write len=%d", buf_w, len); - return ZT_ERR_GENERAL_FAILURE; - } - } else if (len == 0 && data == NULL) { - DEBUG_EXTRA("len=0 => write request from poll loop or callback"); - - src_buf = vs->TXbuf->get_buf(); // --- Data source: TX ringbuffer --- - - // do nothing, all the data we need is already on the TX ringbuffer - } else if (len < 0) { - DEBUG_ERROR("invalid write len=%d for SOCK_STREAM", len); - } - - int txsz = vs->TXbuf->count(); - int r, max_write_len = std::min(std::min(txsz, ZT_SDK_MTU),ZT_STACK_SOCKET_WR_MAX); - if ((r = pico_socket_write(ps, src_buf, max_write_len)) < 0) { - DEBUG_ERROR("unable to write to picosock=%p, err=%d, pico_err=%d, %s", - ps, r, pico_err, beautify_pico_error(pico_err)); - err = -1; - } - else { - err = r; // successful write - } - if (r>0) { - vs->TXbuf->consume(r); - if (vs->socket_type == SOCK_STREAM) { - DEBUG_TRANS("len=%5d buf_len=%13d [VSTXBF --> NSPICO] proto=0x%04x (TCP)", r, vs->TXbuf->count(), PICO_PROTO_TCP); - } - } - } - return err; -} - -int rd_pico_close(VirtualSocket *vs) -{ - DEBUG_EXTRA(); - if (vs == NULL) { - DEBUG_ERROR("invalid vs"); - return ZT_ERR_GENERAL_FAILURE; - } - struct pico_socket *ps = (struct pico_socket*)(vs->pcb); - if (vs->get_state() == VS_STATE_CLOSED) { - DEBUG_EXTRA("socket already in VS_STATE_CLOSED state"); - return 0; - } - if (ps == NULL) { - DEBUG_EXTRA("ps == NULL"); - return 0; - } - if (ps->state & PICO_SOCKET_STATE_CLOSED) { - DEBUG_EXTRA("ps already closed, ps=%p", ps); - return 0; - } - DEBUG_EXTRA("vs=%p, picosock=%p, fd=%d", vs, ps, vs->app_fd); - if (vs == NULL || ps == NULL) - return ZT_ERR_GENERAL_FAILURE; - int err = 0; - Mutex::Lock _l(vs->tap->_tcpconns_m); - if ((err = pico_socket_close(ps)) < 0) { - errno = pico_err; - DEBUG_ERROR("error closing pico_socket, err=%d, pico_err=%d, %s", - err, pico_err, beautify_pico_error(pico_err)); - } - return err; -} - -int rd_pico_shutdown(VirtualSocket *vs, int how) -{ - DEBUG_EXTRA("vs=%p, how=%d", vs, how); - struct pico_socket *ps = (struct pico_socket*)(vs->pcb); - int err = 0, mode = 0; - if (how == SHUT_RD) { - mode = PICO_SHUT_RD; - } - if (how == SHUT_WR) { - mode = PICO_SHUT_WR; - } - if (how == SHUT_RDWR) { - mode = PICO_SHUT_RDWR; - } - if ((err = pico_socket_shutdown(ps, mode)) < 0) { - DEBUG_ERROR("error while shutting down socket, fd=%d, pico_err=%d, %s", vs->app_fd, pico_err, beautify_pico_error(pico_err)); - } - return err; -} - -int rd_pico_setsockopt(VirtualSocket *vs, int level, int optname, const void *optval, socklen_t optlen) -{ - int err = -1; - errno = 0; - if (vs == NULL) { - DEBUG_ERROR("invalid vs"); - return -1; - } else { - DEBUG_EXTRA("fd=%d, level=%d, optname=%d", vs->app_fd, level, optname); - } - struct pico_socket *ps = (struct pico_socket*)(vs->pcb); - if (level == SOL_SOCKET) - { - /* Turns on recording of debugging information. This option enables or disables debugging in the underlying - protocol modules. This option takes an int value. This is a Boolean option.*/ - if (optname == SO_DEBUG) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Specifies that the rules used in validating addresses supplied to bind() should allow reuse of local - addresses, if this is supported by the protocol. This option takes an int value. This is a Boolean option.*/ - if (optname == SO_REUSEADDR) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Keeps connections active by enabling the periodic transmission of messages, if this is supported by the - protocol. This option takes an int value. */ - if (optname == SO_KEEPALIVE) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Requests that outgoing messages bypass the standard routing facilities. */ - if (optname == SO_DONTROUTE) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Lingers on a close() if data is present. */ - if (optname == SO_LINGER) - { - int linger_time_ms = *((const int*)optval); - if ((err = pico_socket_setoption(ps, PICO_SOCKET_OPT_LINGER, &linger_time_ms)) < 0) { - DEBUG_ERROR("unable to set LINGER, err=%d, pico_err=%d, %s", - err, pico_err, beautify_pico_error(pico_err)); - } - return err; - } - /* Permits sending of broadcast messages, if this is supported by the protocol. This option takes an int - value. This is a Boolean option. */ - if (optname == SO_BROADCAST) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Leaves received out-of-band data (data marked urgent) inline. This option takes an int value. This is a - Boolean option. */ - if (optname == SO_OOBINLINE) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Sets send buffer size. This option takes an int value. */ - if (optname == SO_SNDBUF) - { - int no_delay = *((const int*)optval); - if ((err = pico_socket_setoption(ps, PICO_SOCKET_OPT_SNDBUF, &no_delay) < 0)) { - if (err == PICO_ERR_EINVAL) { - DEBUG_ERROR("error while setting PICO_SOCKET_OPT_SNDBUF"); - errno = EINVAL; - err = -1; - } - } - return err; - } - /* Sets receive buffer size. This option takes an int value. */ - if (optname == SO_RCVBUF) - { - int no_delay = *((const int*)optval); - if ((err = pico_socket_setoption(ps, PICO_SOCKET_OPT_RCVBUF, &no_delay) < 0)) { - if (err == PICO_ERR_EINVAL) { - DEBUG_ERROR("error while setting PICO_SOCKET_OPT_RCVBUF"); - errno = EINVAL; - err = -1; - } - } - return err; - } - /* */ - if (optname == SO_STYLE) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* */ - if (optname == SO_TYPE) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Get error status and clear */ - if (optname == SO_ERROR) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - } - if (level == IPPROTO_IP) - { - if (optname == IP_ADD_MEMBERSHIP) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_ADD_SOURCE_MEMBERSHIP) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_BIND_ADDRESS_NO_PORT) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_BLOCK_SOURCE) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_DROP_MEMBERSHIP) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_DROP_SOURCE_MEMBERSHIP) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_FREEBIND) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_HDRINCL) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_MSFILTER) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_MTU) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_MTU_DISCOVER) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_MULTICAST_ALL) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_MULTICAST_IF) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_MULTICAST_LOOP) { - int loop = *((const int*)optval); - if ((err = pico_socket_setoption(ps, PICO_IP_MULTICAST_LOOP, &loop) < 0)) { - if (err == PICO_ERR_EINVAL) { - DEBUG_ERROR("error while setting PICO_IP_MULTICAST_TTL"); - errno = EINVAL; - err = -1; - } - } - return err; - } - if (optname == IP_MULTICAST_TTL) { - int ttl = *((const int*)optval); - if ((err = pico_socket_setoption(ps, PICO_IP_MULTICAST_TTL, &ttl) < 0)) { - if (err == PICO_ERR_EINVAL) { - DEBUG_ERROR("error while setting PICO_IP_MULTICAST_TTL"); - errno = EINVAL; - err = -1; - } - } - return err; - } - if (optname == IP_NODEFRAG) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_OPTIONS) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_PKTINFO) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_RECVOPTS) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_RECVORIGDSTADDR) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_RECVTOS) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_RECVTTL) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_RETOPTS) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_ROUTER_ALERT) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_TOS) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_TRANSPARENT) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_TTL) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_UNBLOCK_SOURCE) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - // TODO - return -1; - } - if (level == IPPROTO_TCP) - { - struct pico_socket *p = ps; - if (p == NULL) { - return -1; - } - /* If set, don't send out partial frames. */ - if (optname == TCP_CORK) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Allow a listener to be awakened only when data arrives on the socket. */ - if (optname == TCP_DEFER_ACCEPT) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Used to collect information about this socket. The kernel returns a struct tcp_info as defined in the - file /usr/include/linux/tcp.h.*/ - if (optname == TCP_INFO) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* The maximum number of keepalive probes TCP should send before dropping the connection.*/ - if (optname == TCP_KEEPCNT) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* The time (in seconds) the connection needs to remain idle before TCP starts sending keepalive probes, - if the socket option SO_KEEPALIVE has been set on this socket. */ - if (optname == TCP_KEEPIDLE) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* The time (in seconds) between individual keepalive probes.*/ - if (optname == TCP_KEEPINTVL) { - // TODO - return -1; - } - /* The lifetime of orphaned FIN_WAIT2 state sockets. */ - if (optname == TCP_LINGER2) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* The maximum segment size for outgoing TCP packets. */ - if (optname == TCP_MAXSEG) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* If set, disable the Nagle algorithm. */ - if (optname == TCP_NODELAY) { - int no_delay = *((const int*)optval); - if ((err = pico_socket_setoption(ps, PICO_TCP_NODELAY, &no_delay) < 0)) { - if (err == PICO_ERR_EINVAL) { - DEBUG_ERROR("error while disabling Nagle's algorithm"); - errno = EINVAL; - err = -1; - } - } - return err; - } - /* Enable quickack mode if set or disable quickack mode if cleared. */ - if (optname == TCP_QUICKACK) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Set the number of SYN retransmits that TCP should send before aborting the attempt to connect. It - cannot exceed 255. */ - if (optname == TCP_SYNCNT) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Bound the size of the advertised window to this value. The kernel imposes a minimum size of - SOCK_MIN_RCVBUF/2. */ - if (optname == TCP_WINDOW_CLAMP) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - } - if (level == IPPROTO_UDP) - { - /*If this option is enabled, then all data output on this socket is accumulated into a single - datagram that is transmitted when the option is disabled. */ - if (optname == UDP_CORK) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - } - return err; -} - -int rd_pico_getsockopt(VirtualSocket *vs, int level, int optname, void *optval, socklen_t *optlen) -{ - int err = -1, optval_tmp = 0; - errno = 0; - if (vs == NULL) { - DEBUG_ERROR("invalid vs"); - return -1; - } else { - DEBUG_EXTRA("fd=%d, level=%d, optname=%d", vs->app_fd, level, optname); - } - struct pico_socket *ps = (struct pico_socket*)(vs->pcb); - if (level == SOL_SOCKET) - { - /* Turns on recording of debugging information. This option enables or disables debugging in the underlying - protocol modules. This option takes an int value. This is a Boolean option.*/ - if (optname == SO_DEBUG) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Specifies that the rules used in validating addresses supplied to bind() should allow reuse of local - addresses, if this is supported by the protocol. This option takes an int value. This is a Boolean option.*/ - if (optname == SO_REUSEADDR) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Keeps connections active by enabling the periodic transmission of messages, if this is supported by the - protocol. This option takes an int value. */ - if (optname == SO_KEEPALIVE) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Requests that outgoing messages bypass the standard routing facilities. */ - if (optname == SO_DONTROUTE) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Lingers on a close() if data is present. */ - if (optname == SO_LINGER) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Permits sending of broadcast messages, if this is supported by the protocol. This option takes an int - value. This is a Boolean option. */ - if (optname == SO_BROADCAST) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Leaves received out-of-band data (data marked urgent) inline. This option takes an int value. This is a - Boolean option. */ - if (optname == SO_OOBINLINE) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Sets send buffer size. This option takes an int value. */ - if (optname == SO_SNDBUF) - { - if ((err = pico_socket_getoption(ps, PICO_SOCKET_OPT_SNDBUF, &optval_tmp)) < 0) { - if (err == PICO_ERR_EINVAL) { - DEBUG_ERROR("error while getting PICO_SOCKET_OPT_SNDBUF"); - errno = ENOPROTOOPT; - err = -1; - } - } - memcpy(optval, &optval_tmp, *optlen); - } - /* Sets receive buffer size. This option takes an int value. */ - if (optname == SO_RCVBUF) - { - if ((err = pico_socket_getoption(ps, PICO_SOCKET_OPT_SNDBUF, &optval_tmp)) < 0) { - if (err == PICO_ERR_EINVAL) { - DEBUG_ERROR("error while getting PICO_SOCKET_OPT_RCVBUF"); - errno = ENOPROTOOPT; - err = -1; - } - } - memcpy(optval, &optval_tmp, *optlen); - } - /* */ - if (optname == SO_STYLE) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* */ - if (optname == SO_TYPE) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Get error status and clear */ - if (optname == SO_ERROR) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - } - if (level == IPPROTO_IP) - { - if (optname == IP_ADD_MEMBERSHIP) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_ADD_SOURCE_MEMBERSHIP) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_BIND_ADDRESS_NO_PORT) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_BLOCK_SOURCE) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_DROP_MEMBERSHIP) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_DROP_SOURCE_MEMBERSHIP) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_FREEBIND) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_HDRINCL) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_MSFILTER) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_MTU) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_MTU_DISCOVER) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_MULTICAST_ALL) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_MULTICAST_IF) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_MULTICAST_LOOP) { - if ((err = pico_socket_getoption(ps, PICO_IP_MULTICAST_LOOP, &optval_tmp)) < 0) { - if (err == PICO_ERR_EINVAL) { - DEBUG_ERROR("error while getting PICO_IP_MULTICAST_TTL"); - errno = ENOPROTOOPT; - err = -1; - } - } - memcpy(optval, &optval_tmp, *optlen); - } - if (optname == IP_MULTICAST_TTL) { - if ((err = pico_socket_getoption(ps, PICO_IP_MULTICAST_TTL, &optval_tmp)) < 0) { - if (err == PICO_ERR_EINVAL) { - DEBUG_ERROR("error while getting PICO_IP_MULTICAST_TTL"); - errno = ENOPROTOOPT; - err = -1; - } - } - memcpy(optval, &optval_tmp, *optlen); - } - if (optname == IP_NODEFRAG) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_OPTIONS) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_PKTINFO) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_RECVOPTS) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_RECVORIGDSTADDR) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_RECVTOS) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_RECVTTL) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_RETOPTS) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_ROUTER_ALERT) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_TOS) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_TRANSPARENT) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_TTL) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_UNBLOCK_SOURCE) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - // TODO - return -1; - } - if (level == IPPROTO_TCP) - { - struct pico_socket *p = ps; - if (p == NULL) { - return -1; - } - /* If set, don't send out partial frames. */ - if (optname == TCP_CORK) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Allow a listener to be awakened only when data arrives on the socket. */ - if (optname == TCP_DEFER_ACCEPT) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Used to collect information about this socket. */ - if (optname == TCP_INFO) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* The maximum number of keepalive probes TCP should send before dropping the connection.*/ - if (optname == TCP_KEEPCNT) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* The time (in seconds) the connection needs to remain idle before TCP starts sending keepalive probes, - if the socket option SO_KEEPALIVE has been set on this socket. */ - if (optname == TCP_KEEPIDLE) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* The time (in seconds) between individual keepalive probes.*/ - if (optname == TCP_KEEPINTVL) { - // TODO - return -1; - } - /* The lifetime of orphaned FIN_WAIT2 state sockets. */ - if (optname == TCP_LINGER2) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* The maximum segment size for outgoing TCP packets. */ - if (optname == TCP_MAXSEG) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* If set, disable the Nagle algorithm. */ - if (optname == TCP_NODELAY) { - if ((err = pico_socket_getoption(ps, PICO_TCP_NODELAY, &optval_tmp)) < 0) { - if (err == PICO_ERR_EINVAL) { - DEBUG_ERROR("error while disabling Nagle's algorithm"); - errno = ENOPROTOOPT; - err = -1; - } - } - memcpy(optval, &optval_tmp, *optlen); - return err; - } - /* Enable quickack mode if set or disable quickack mode if cleared. */ - if (optname == TCP_QUICKACK) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Set the number of SYN retransmits that TCP should send before aborting the attempt to connect. It - cannot exceed 255. */ - if (optname == TCP_SYNCNT) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Bound the size of the advertised window to this value. The kernel imposes a minimum size of - SOCK_MIN_RCVBUF/2. */ - if (optname == TCP_WINDOW_CLAMP) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - } - if (level == IPPROTO_UDP) - { - /*If this option is enabled, then all data output on this socket is accumulated into a single - datagram that is transmitted when the option is disabled. */ - if (optname == UDP_CORK) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - } - return err; -} - -int map_pico_err_to_errno(int err) -{ - if (err == PICO_ERR_NOERR) { errno = 0; return 0; } // - if (err == PICO_ERR_EPERM) { errno = ENXIO; } - if (err == PICO_ERR_ENOENT) { errno = ENXIO; } - if (err == PICO_ERR_EINTR) { errno = ENXIO; } - if (err == PICO_ERR_EIO) { errno = ENXIO; } - if (err == PICO_ERR_ENXIO) { errno = ENXIO; } // - if (err == PICO_ERR_EAGAIN) { errno = ENXIO; } - if (err == PICO_ERR_ENOMEM) { errno = ENOMEM; } // - if (err == PICO_ERR_EACCESS) { errno = ENXIO; } - if (err == PICO_ERR_EFAULT) { errno = ENXIO; } - if (err == PICO_ERR_EBUSY) { errno = ENXIO; } - if (err == PICO_ERR_EEXIST) { errno = ENXIO; } - if (err == PICO_ERR_EINVAL) { errno = EINVAL; } // - if (err == PICO_ERR_ENONET) { errno = ENXIO; } - if (err == PICO_ERR_EPROTO) { errno = ENXIO; } - if (err == PICO_ERR_ENOPROTOOPT) { errno = ENXIO; } - if (err == PICO_ERR_EPROTONOSUPPORT) { errno = ENXIO; } - if (err == PICO_ERR_EOPNOTSUPP) { errno = ENXIO; } - if (err == PICO_ERR_EADDRINUSE) { errno = ENXIO; } - if (err == PICO_ERR_EADDRNOTAVAIL) { errno = ENXIO; } - if (err == PICO_ERR_ENETDOWN) { errno = ENXIO; } - if (err == PICO_ERR_ENETUNREACH) { errno = ENXIO; } - if (err == PICO_ERR_ECONNRESET) { errno = ENXIO; } - if (err == PICO_ERR_EISCONN) { errno = ENXIO; } - if (err == PICO_ERR_ENOTCONN) { errno = ENXIO; } - if (err == PICO_ERR_ESHUTDOWN) { errno = ENXIO; } - if (err == PICO_ERR_ETIMEDOUT) { errno = ENXIO; } - if (err == PICO_ERR_ECONNREFUSED) { errno = ENXIO; } - if (err == PICO_ERR_EHOSTDOWN) { errno = ENXIO; } - if (err == PICO_ERR_EHOSTUNREACH) { errno = ENXIO; } - return -1; -} - -char *beautify_pico_error(int err) -{ - if (err== 0) return (char*)"PICO_ERR_NOERR"; - if (err== 1) return (char*)"PICO_ERR_EPERM"; - if (err== 2) return (char*)"PICO_ERR_ENOENT"; - // ... - if (err== 4) return (char*)"PICO_ERR_EINTR"; - if (err== 5) return (char*)"PICO_ERR_EIO"; - if (err== 6) return (char*)"PICO_ERR_ENXIO (no such device or address)"; - // ... - if (err== 11) return (char*)"PICO_ERR_EAGAIN"; - if (err== 12) return (char*)"PICO_ERR_ENOMEM (not enough space)"; - if (err== 13) return (char*)"PICO_ERR_EACCESS"; - if (err== 14) return (char*)"PICO_ERR_EFAULT"; - // ... - if (err== 16) return (char*)"PICO_ERR_EBUSY"; - if (err== 17) return (char*)"PICO_ERR_EEXIST"; - // ... - if (err== 22) return (char*)"PICO_ERR_EINVAL (invalid argument)"; - // ... - if (err== 64) return (char*)"PICO_ERR_ENONET"; - // ... - if (err== 71) return (char*)"PICO_ERR_EPROTO"; - // ... - if (err== 92) return (char*)"PICO_ERR_ENOPROTOOPT"; - if (err== 93) return (char*)"PICO_ERR_EPROTONOSUPPORT"; - // ... - if (err== 95) return (char*)"PICO_ERR_EOPNOTSUPP"; - if (err== 98) return (char*)"PICO_ERR_EADDRINUSE"; - if (err== 99) return (char*)"PICO_ERR_EADDRNOTAVAIL"; - if (err==100) return (char*)"PICO_ERR_ENETDOWN"; - if (err==101) return (char*)"PICO_ERR_ENETUNREACH"; - // ... - if (err==104) return (char*)"PICO_ERR_ECONNRESET"; - // ... - if (err==106) return (char*)"PICO_ERR_EISCONN"; - if (err==107) return (char*)"PICO_ERR_ENOTCONN"; - if (err==108) return (char*)"PICO_ERR_ESHUTDOWN"; - // ... - if (err==110) return (char*)"PICO_ERR_ETIMEDOUT"; - if (err==111) return (char*)"PICO_ERR_ECONNREFUSED"; - if (err==112) return (char*)"PICO_ERR_EHOSTDOWN"; - if (err==113) return (char*)"PICO_ERR_EHOSTUNREACH"; - return (char*)"UNKNOWN_ERROR"; -} - -/* - -#define PICO_SOCKET_STATE_UNDEFINED 0x0000u -#define PICO_SOCKET_STATE_SHUT_LOCAL 0x0001u -#define PICO_SOCKET_STATE_SHUT_REMOTE 0x0002u -#define PICO_SOCKET_STATE_BOUND 0x0004u -#define PICO_SOCKET_STATE_CONNECTED 0x0008u -#define PICO_SOCKET_STATE_CLOSING 0x0010u -#define PICO_SOCKET_STATE_CLOSED 0x0020u - -# define PICO_SOCKET_STATE_TCP 0xFF00u -# define PICO_SOCKET_STATE_TCP_UNDEF 0x00FFu -# define PICO_SOCKET_STATE_TCP_CLOSED 0x0100u -# define PICO_SOCKET_STATE_TCP_LISTEN 0x0200u -# define PICO_SOCKET_STATE_TCP_SYN_SENT 0x0300u -# define PICO_SOCKET_STATE_TCP_SYN_RECV 0x0400u -# define PICO_SOCKET_STATE_TCP_ESTABLISHED 0x0500u -# define PICO_SOCKET_STATE_TCP_CLOSE_WAIT 0x0600u -# define PICO_SOCKET_STATE_TCP_LAST_ACK 0x0700u -# define PICO_SOCKET_STATE_TCP_FIN_WAIT1 0x0800u -# define PICO_SOCKET_STATE_TCP_FIN_WAIT2 0x0900u -# define PICO_SOCKET_STATE_TCP_CLOSING 0x0a00u -# define PICO_SOCKET_STATE_TCP_TIME_WAIT 0x0b00u -# define PICO_SOCKET_STATE_TCP_ARRAYSIZ 0x0cu - -*/ -char *beautify_pico_state(int state) -{ - static char state_str[512]; - char *str_ptr = state_str; - - if (state & PICO_SOCKET_STATE_UNDEFINED) { - sprintf(str_ptr, "UNDEFINED "); - str_ptr += strlen("UNDEFINED "); - } - if (state & PICO_SOCKET_STATE_SHUT_LOCAL) { - sprintf(str_ptr, "SHUT_LOCAL "); - str_ptr += strlen("SHUT_LOCAL "); - } - if (state & PICO_SOCKET_STATE_SHUT_REMOTE) { - sprintf(str_ptr, "SHUT_REMOTE "); - str_ptr += strlen("SHUT_REMOTE "); - } - if (state & PICO_SOCKET_STATE_BOUND) { - sprintf(str_ptr, "BOUND "); - str_ptr += strlen("BOUND "); - } - if (state & PICO_SOCKET_STATE_CONNECTED) { - sprintf(str_ptr, "CONNECTED "); - str_ptr += strlen("CONNECTED "); - } - if (state & PICO_SOCKET_STATE_CLOSING) { - sprintf(str_ptr, "CLOSING "); - str_ptr += strlen("CLOSING "); - } - if (state & PICO_SOCKET_STATE_CLOSED) { - sprintf(str_ptr, "CLOSED "); - str_ptr += strlen("CLOSED "); - } - - - if (state & PICO_SOCKET_STATE_TCP) { - sprintf(str_ptr, "TCP "); - str_ptr += strlen("TCP "); - } - if (state & PICO_SOCKET_STATE_TCP_UNDEF) { - sprintf(str_ptr, "TCP_UNDEF "); - str_ptr += strlen("TCP_UNDEF "); - } - if (state & PICO_SOCKET_STATE_TCP_CLOSED) { - sprintf(str_ptr, "TCP_CLOSED "); - str_ptr += strlen("TCP_CLOSED "); - } - if (state & PICO_SOCKET_STATE_TCP_LISTEN) { - sprintf(str_ptr, "TCP_LISTEN "); - str_ptr += strlen("TCP_LISTEN "); - } - if (state & PICO_SOCKET_STATE_TCP_SYN_SENT) { - sprintf(str_ptr, "TCP_SYN_SENT "); - str_ptr += strlen("TCP_SYN_SENT "); - } - if (state & PICO_SOCKET_STATE_TCP_SYN_RECV) { - sprintf(str_ptr, "TCP_SYN_RECV "); - str_ptr += strlen("TCP_SYN_RECV "); - } - if (state & PICO_SOCKET_STATE_TCP_ESTABLISHED) { - sprintf(str_ptr, "TCP_ESTABLISHED "); - str_ptr += strlen("TCP_ESTABLISHED "); - } - if (state & PICO_SOCKET_STATE_TCP_CLOSE_WAIT) { - sprintf(str_ptr, "TCP_CLOSE_WAIT "); - str_ptr += strlen("TCP_CLOSE_WAIT "); - } - if (state & PICO_SOCKET_STATE_TCP_LAST_ACK) { - sprintf(str_ptr, "TCP_LAST_ACK "); - str_ptr += strlen("TCP_LAST_ACK "); - } - if (state & PICO_SOCKET_STATE_TCP_FIN_WAIT1) { - sprintf(str_ptr, "TCP_FIN_WAIT1 "); - str_ptr += strlen("TCP_FIN_WAIT1 "); - } - if (state & PICO_SOCKET_STATE_TCP_FIN_WAIT2) { - sprintf(str_ptr, "TCP_FIN_WAIT2 "); - str_ptr += strlen("TCP_FIN_WAIT2 "); - } - if (state & PICO_SOCKET_STATE_TCP_CLOSING) { - sprintf(str_ptr, "TCP_CLOSING "); - str_ptr += strlen("TCP_CLOSING "); - } - if (state & PICO_SOCKET_STATE_TCP_TIME_WAIT) { - sprintf(str_ptr, "TCP_TIME_WAIT "); - str_ptr += strlen("TCP_TIME_WAIT "); - } - if (state & PICO_SOCKET_STATE_TCP_ARRAYSIZ) { - sprintf(str_ptr, "TCP_ARRAYSIZ "); - str_ptr += strlen("TCP_ARRAYSIZ "); - } - return (char*)state_str; -} - -#endif // STACK_PICO diff --git a/attic/picoTCP.h b/attic/picoTCP.h deleted file mode 100644 index a390ef3..0000000 --- a/attic/picoTCP.h +++ /dev/null @@ -1,222 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2018 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 . - * - * -- - * - * 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