diff --git a/include/Debug.hpp b/include/Debug.hpp index 0afe59e..c9593e7 100644 --- a/include/Debug.hpp +++ b/include/Debug.hpp @@ -41,123 +41,123 @@ // Debug output colors #if defined(__APPLE__) - #include "TargetConditionals.h" + #include "TargetConditionals.h" #endif #if defined(ZT_COLOR) && !defined(__ANDROID__) && !defined(TARGET_OS_IPHONE) && !defined(TARGET_IPHONE_SIMULATOR) && !defined(__APP_FRAMEWORK__) - #define ZT_RED "\x1B[31m" - #define ZT_GRN "\x1B[32m" - #define ZT_YEL "\x1B[33m" - #define ZT_BLU "\x1B[34m" - #define ZT_MAG "\x1B[35m" - #define ZT_CYN "\x1B[36m" - #define ZT_WHT "\x1B[37m" - #define ZT_RESET "\x1B[0m" + #define ZT_RED "\x1B[31m" + #define ZT_GRN "\x1B[32m" + #define ZT_YEL "\x1B[33m" + #define ZT_BLU "\x1B[34m" + #define ZT_MAG "\x1B[35m" + #define ZT_CYN "\x1B[36m" + #define ZT_WHT "\x1B[37m" + #define ZT_RESET "\x1B[0m" #else - #define ZT_RED - #define ZT_GRN - #define ZT_YEL - #define ZT_BLU - #define ZT_MAG - #define ZT_CYN - #define ZT_WHT - #define ZT_RESET + #define ZT_RED + #define ZT_GRN + #define ZT_YEL + #define ZT_BLU + #define ZT_MAG + #define ZT_CYN + #define ZT_WHT + #define ZT_RESET #endif #define ZT_FILENAME (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) // short /* #ifdef __linux__ - #define ZT_THREAD_ID 0 // (long)getpid() + #define ZT_THREAD_ID 0 // (long)getpid() #elif __FreeBSD__ - #define ZT_THREAD_ID 0 // (long)getpid() + #define ZT_THREAD_ID 0 // (long)getpid() #elif __APPLE__ - #define ZT_THREAD_ID 0 // (long)syscall(SYS_thread_selfid) + #define ZT_THREAD_ID 0 // (long)syscall(SYS_thread_selfid) #endif */ #define ZT_THREAD_ID 0 #if defined(__JNI_LIB__) - #include + #include #endif #if defined(__ANDROID__) - #include - #define ZT_LOG_TAG "ZTSDK" + #include + #define ZT_LOG_TAG "ZTSDK" #endif - #if ZT_DEBUG_LEVEL >= ZT_MSG_TEST - #define DEBUG_TEST(fmt, args...) fprintf(stderr, ZT_CYN "TEST [%d] : %16s:%5d:%25s: " fmt \ - "\n" ZT_RESET, ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args) - #else - #define DEBUG_ERROR(fmt, args...) - #endif +#if ZT_DEBUG_LEVEL >= ZT_MSG_TEST + #define DEBUG_TEST(fmt, args...) fprintf(stderr, ZT_CYN "TEST [%d] : %16s:%5d:%25s: " fmt \ + "\n" ZT_RESET, ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args) +#else + #define DEBUG_ERROR(fmt, args...) +#endif - #if ZT_DEBUG_LEVEL >= ZT_MSG_ERROR - #define DEBUG_ERROR(fmt, args...) fprintf(stderr, ZT_RED "ERROR[%d] : %16s:%5d:%25s: " fmt \ - "\n" ZT_RESET, ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args) - #else - #define DEBUG_ERROR(fmt, args...) - #endif +#if ZT_DEBUG_LEVEL >= ZT_MSG_ERROR + #define DEBUG_ERROR(fmt, args...) fprintf(stderr, ZT_RED "ERROR[%d] : %16s:%5d:%25s: " fmt \ + "\n" ZT_RESET, ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args) +#else + #define DEBUG_ERROR(fmt, args...) +#endif - #if ZT_DEBUG_LEVEL >= ZT_MSG_INFO - #if defined(__ANDROID__) - #define DEBUG_INFO(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \ - "INFO : %16s:%5d:%20s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args)) - #define DEBUG_BLANK(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \ - "INFO : %16s:%5d:" fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args)) - #define DEBUG_ATTN(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \ - "INFO : %16s:%5d:%25s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args)) - #define DEBUG_STACK(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \ - "STACK: %16s:%5d:%25s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args)) - #else - #define DEBUG_INFO(fmt, args...) fprintf(stderr, \ - "INFO [%d] : %16s:%5d:%25s: " fmt "\n", ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args) - #define DEBUG_ATTN(fmt, args...) fprintf(stderr, ZT_CYN \ - "ATTN [%d] : %16s:%5d:%25s: " fmt "\n" ZT_RESET, ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args) - #define DEBUG_STACK(fmt, args...) fprintf(stderr, ZT_YEL \ - "STACK[%d] : %16s:%5d:%25s: " fmt "\n" ZT_RESET, ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args) - #define DEBUG_BLANK(fmt, args...) fprintf(stderr, \ - "INFO [%d] : %16s:%5d:" fmt "\n", ZT_THREAD_ID, ZT_FILENAME, __LINE__, ##args) - #endif - #else - #define DEBUG_INFO(fmt, args...) - #define DEBUG_BLANK(fmt, args...) - #define DEBUG_ATTN(fmt, args...) - #define DEBUG_STACK(fmt, args...) - #endif - - #if ZT_DEBUG_LEVEL >= ZT_MSG_TRANSFER - #if defined(__ANDROID__) - #define DEBUG_TRANS(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \ - "TRANS : %16s:%5d:%25s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args)) - #else - #define DEBUG_TRANS(fmt, args...) fprintf(stderr, ZT_GRN "TRANS[%ld] : %16s:%5d:%25s: " fmt \ - "\n" ZT_RESET, ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args) - #endif - #else - #define DEBUG_TRANS(fmt, args...) - #endif - - #if ZT_DEBUG_LEVEL >= ZT_MSG_EXTRA - #if defined(__ANDROID__) - #define DEBUG_EXTRA(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \ - "EXTRA : %16s:%5d:%25s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args)) - #else - #define DEBUG_EXTRA(fmt, args...) fprintf(stderr, \ - "EXTRA[%d] : %16s:%5d:%25s: " fmt "\n", ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args) - #endif - #else - #define DEBUG_EXTRA(fmt, args...) - #endif +#if ZT_DEBUG_LEVEL >= ZT_MSG_INFO + #if defined(__ANDROID__) + #define DEBUG_INFO(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \ + "INFO : %16s:%5d:%20s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args)) + #define DEBUG_BLANK(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \ + "INFO : %16s:%5d:" fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args)) + #define DEBUG_ATTN(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \ + "INFO : %16s:%5d:%25s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args)) + #define DEBUG_STACK(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \ + "STACK: %16s:%5d:%25s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args)) + #else + #define DEBUG_INFO(fmt, args...) fprintf(stderr, \ + "INFO [%d] : %16s:%5d:%25s: " fmt "\n", ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args) + #define DEBUG_ATTN(fmt, args...) fprintf(stderr, ZT_CYN \ + "ATTN [%d] : %16s:%5d:%25s: " fmt "\n" ZT_RESET, ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args) + #define DEBUG_STACK(fmt, args...) fprintf(stderr, ZT_YEL \ + "STACK[%d] : %16s:%5d:%25s: " fmt "\n" ZT_RESET, ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args) + #define DEBUG_BLANK(fmt, args...) fprintf(stderr, \ + "INFO [%d] : %16s:%5d:" fmt "\n", ZT_THREAD_ID, ZT_FILENAME, __LINE__, ##args) +#endif +#else + #define DEBUG_INFO(fmt, args...) + #define DEBUG_BLANK(fmt, args...) + #define DEBUG_ATTN(fmt, args...) + #define DEBUG_STACK(fmt, args...) +#endif + +#if ZT_DEBUG_LEVEL >= ZT_MSG_TRANSFER + #if defined(__ANDROID__) + #define DEBUG_TRANS(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \ + "TRANS : %16s:%5d:%25s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args)) + #else + #define DEBUG_TRANS(fmt, args...) fprintf(stderr, ZT_GRN "TRANS[%ld] : %16s:%5d:%25s: " fmt \ + "\n" ZT_RESET, ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args) + #endif +#else + #define DEBUG_TRANS(fmt, args...) +#endif + +#if ZT_DEBUG_LEVEL >= ZT_MSG_EXTRA + #if defined(__ANDROID__) + #define DEBUG_EXTRA(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \ + "EXTRA : %16s:%5d:%25s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args)) + #else + #define DEBUG_EXTRA(fmt, args...) fprintf(stderr, \ + "EXTRA[%d] : %16s:%5d:%25s: " fmt "\n", ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args) + #endif +#else + #define DEBUG_EXTRA(fmt, args...) +#endif #if ZT_DEBUG_LEVEL >= ZT_MSG_FLOW - #if defined(__ANDROID__) - #define DEBUG_FLOW(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \ - "FLOW : %16s:%5d:%25s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args)) - #else - #define DEBUG_FLOW(fmt, args...) fprintf(stderr, "FLOW [%ld] : %16s:%5d:%25s: " fmt "\n", \ - ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args) - #endif - #else - #define DEBUG_FLOW(fmt, args...) - #endif \ No newline at end of file + #if defined(__ANDROID__) + #define DEBUG_FLOW(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \ + "FLOW : %16s:%5d:%25s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args)) + #else + #define DEBUG_FLOW(fmt, args...) fprintf(stderr, "FLOW [%ld] : %16s:%5d:%25s: " fmt "\n", \ + ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args) + #endif + #else + #define DEBUG_FLOW(fmt, args...) +#endif \ No newline at end of file diff --git a/include/libzt.h b/include/libzt.h index d37adbc..6807fad 100644 --- a/include/libzt.h +++ b/include/libzt.h @@ -45,33 +45,33 @@ // Normally defined in linux/if_packet.h, defined here so we can offer a linux-like // raw socket API on non-linux platforms struct sockaddr_ll { - unsigned short sll_family; /* Always AF_PACKET */ - unsigned short sll_protocol; /* Physical layer protocol */ - int sll_ifindex; /* Interface number */ - unsigned short sll_hatype; /* ARP hardware type */ - unsigned char sll_pkttype; /* Packet type */ - unsigned char sll_halen; /* Length of address */ - unsigned char sll_addr[8]; /* Physical layer address */ + unsigned short sll_family; /* Always AF_PACKET */ + unsigned short sll_protocol; /* Physical layer protocol */ + int sll_ifindex; /* Interface number */ + unsigned short sll_hatype; /* ARP hardware type */ + unsigned char sll_pkttype; /* Packet type */ + unsigned char sll_halen; /* Length of address */ + unsigned char sll_addr[8]; /* Physical layer address */ }; /* struct zts_ifreq { - char ifr_name[IFNAMSIZ]; // Interface name - union { - struct sockaddr ifr_addr; - struct sockaddr ifr_dstaddr; - struct sockaddr ifr_broadaddr; - struct sockaddr ifr_netmask; - struct sockaddr ifr_hwaddr; - short ifr_flags; - int ifr_ifindex; - int ifr_metric; - int ifr_mtu; - struct ifmap ifr_map; - char ifr_slave[IFNAMSIZ]; - char ifr_newname[IFNAMSIZ]; - char *ifr_data; - }; + char ifr_name[IFNAMSIZ]; // Interface name + union { + struct sockaddr ifr_addr; + struct sockaddr ifr_dstaddr; + struct sockaddr ifr_broadaddr; + struct sockaddr ifr_netmask; + struct sockaddr ifr_hwaddr; + short ifr_flags; + int ifr_ifindex; + int ifr_metric; + int ifr_mtu; + struct ifmap ifr_map; + char ifr_slave[IFNAMSIZ]; + char ifr_newname[IFNAMSIZ]; + char *ifr_data; + }; }; */ @@ -467,14 +467,14 @@ int zts_shutdown(ZT_SHUTDOWN_SIG); namespace ZeroTier { - class picoTCP; - extern ZeroTier::picoTCP *picostack; + class picoTCP; + extern ZeroTier::picoTCP *picostack; - class lwIP; - extern ZeroTier::lwIP *lwipstack; + class lwIP; + extern ZeroTier::lwIP *lwipstack; - class SocketTap; - struct InetAddress; + class SocketTap; + struct InetAddress; } /* diff --git a/src/RingBuffer.hpp b/src/RingBuffer.hpp index 39b32ce..bd53dbc 100644 --- a/src/RingBuffer.hpp +++ b/src/RingBuffer.hpp @@ -32,158 +32,158 @@ namespace ZeroTier { - template class RingBuffer { + template class RingBuffer { - private: - T * buf; - size_t size; - size_t begin; - size_t end; - bool wrap; + private: + T * buf; + size_t size; + size_t begin; + size_t end; + bool wrap; - public: - /** - * create a RingBuffer with space for up to size elements. - */ - explicit RingBuffer(size_t size) - : size(size), - begin(0), - end(0), - wrap(false) - { - buf = new T[size]; - } + public: + /** + * create a RingBuffer with space for up to size elements. + */ + explicit RingBuffer(size_t size) + : size(size), + begin(0), + end(0), + wrap(false) + { + buf = new T[size]; + } - RingBuffer(const RingBuffer & ring) - { - this(ring.size); - begin = ring.begin; - end = ring.end; - memcpy(buf, ring.buf, sizeof(T) * size); - } + RingBuffer(const RingBuffer & ring) + { + this(ring.size); + begin = ring.begin; + end = ring.end; + memcpy(buf, ring.buf, sizeof(T) * size); + } - ~RingBuffer() - { - delete[] buf; - } + ~RingBuffer() + { + delete[] buf; + } - // get a reference to the underlying buffer - T* get_buf() - { - return buf + begin; - } + // get a reference to the underlying buffer + T* get_buf() + { + return buf + begin; + } - // adjust buffer index pointer as if we copied data in - size_t produce(size_t n) - { - n = std::min(n, getFree()); + // adjust buffer index pointer as if we copied data in + size_t produce(size_t n) + { + n = std::min(n, getFree()); - if (n == 0) { - return n; - } + if (n == 0) { + return n; + } - const size_t first_chunk = std::min(n, size - end); - end = (end + first_chunk) % size; + const size_t first_chunk = std::min(n, size - end); + end = (end + first_chunk) % size; - if (first_chunk < n) { - const size_t second_chunk = n - first_chunk; - end = (end + second_chunk) % size; - } + if (first_chunk < n) { + const size_t second_chunk = n - first_chunk; + end = (end + second_chunk) % size; + } - if (begin == end) { - wrap = true; - } + if (begin == end) { + wrap = true; + } - return n; - } + return n; + } - // adjust buffer index pointer as if we copied data out - size_t consume(size_t n) - { - n = std::min(n, count()); + // adjust buffer index pointer as if we copied data out + size_t consume(size_t n) + { + n = std::min(n, count()); - if (n == 0) { - return n; - } + if (n == 0) { + return n; + } - if (wrap) { - wrap = false; - } + if (wrap) { + wrap = false; + } - const size_t first_chunk = std::min(n, size - begin); - begin = (begin + first_chunk) % size; + const size_t first_chunk = std::min(n, size - begin); + begin = (begin + first_chunk) % size; - if (first_chunk < n) { - const size_t second_chunk = n - first_chunk; - begin = (begin + second_chunk) % size; - } - return n; - } + if (first_chunk < n) { + const size_t second_chunk = n - first_chunk; + begin = (begin + second_chunk) % size; + } + return n; + } - size_t write(const T * data, size_t n) - { - n = std::min(n, getFree()); + size_t write(const T * data, size_t n) + { + n = std::min(n, getFree()); - if (n == 0) { - return n; - } + if (n == 0) { + return n; + } - const size_t first_chunk = std::min(n, size - end); - memcpy(buf + end, data, first_chunk * sizeof(T)); - end = (end + first_chunk) % size; + const size_t first_chunk = std::min(n, size - end); + memcpy(buf + end, data, first_chunk * sizeof(T)); + end = (end + first_chunk) % size; - if (first_chunk < n) { - const size_t second_chunk = n - first_chunk; - memcpy(buf + end, data + first_chunk, second_chunk * sizeof(T)); - end = (end + second_chunk) % size; - } + if (first_chunk < n) { + const size_t second_chunk = n - first_chunk; + memcpy(buf + end, data + first_chunk, second_chunk * sizeof(T)); + end = (end + second_chunk) % size; + } - if (begin == end) { - wrap = true; - } + if (begin == end) { + wrap = true; + } - return n; - } + return n; + } - size_t read(T * dest, size_t n) - { - n = std::min(n, count()); + size_t read(T * dest, size_t n) + { + n = std::min(n, count()); - if (n == 0) { - return n; - } + if (n == 0) { + return n; + } - if (wrap) { - wrap = false; - } + if (wrap) { + wrap = false; + } - const size_t first_chunk = std::min(n, size - begin); - memcpy(dest, buf + begin, first_chunk * sizeof(T)); - begin = (begin + first_chunk) % size; + const size_t first_chunk = std::min(n, size - begin); + memcpy(dest, buf + begin, first_chunk * sizeof(T)); + begin = (begin + first_chunk) % size; - if (first_chunk < n) { - const size_t second_chunk = n - first_chunk; - memcpy(dest + first_chunk, buf + begin, second_chunk * sizeof(T)); - begin = (begin + second_chunk) % size; - } - return n; - } + if (first_chunk < n) { + const size_t second_chunk = n - first_chunk; + memcpy(dest + first_chunk, buf + begin, second_chunk * sizeof(T)); + begin = (begin + second_chunk) % size; + } + return n; + } - size_t count() { - if (end == begin) { - return wrap ? size : 0; - } - else if (end > begin) { - return end - begin; - } - else { - return size + end - begin; - } - } + size_t count() { + if (end == begin) { + return wrap ? size : 0; + } + else if (end > begin) { + return end - begin; + } + else { + return size + end - begin; + } + } - size_t getFree() { - return size - count(); - } - }; + size_t getFree() { + return size - count(); + } + }; } #endif // ZT_RINGBUFFER_HPP diff --git a/src/SocketTap.cpp b/src/SocketTap.cpp index b5c06ef..c57c918 100644 --- a/src/SocketTap.cpp +++ b/src/SocketTap.cpp @@ -81,7 +81,7 @@ namespace ZeroTier { void (*handler)(void *,void*,uint64_t,const MAC &,const MAC &, unsigned int,unsigned int,const void *,unsigned int), void *arg) : - _handler(handler), + _handler(handler), _homePath(homePath), _arg(arg), _enabled(true), @@ -185,12 +185,12 @@ namespace ZeroTier { const void *data,unsigned int len) { #if defined(STACK_PICO) - if(picostack) - picostack->pico_rx(this,from,to,etherType,data,len); + if(picostack) + picostack->pico_rx(this,from,to,etherType,data,len); #endif #if defined(STACK_LWIP) - if(lwipstack) - lwipstack->lwip_rx(this,from,to,etherType,data,len); + if(lwipstack) + lwipstack->lwip_rx(this,from,to,etherType,data,len); #endif } @@ -264,11 +264,11 @@ namespace ZeroTier { Connection *conn = (Connection*)*uptr; if(!conn) return; - if(len){ + if(len){ - Write(conn, data, len); - } - return; + Write(conn, data, len); + } + return; } void SocketTap::phyOnUnixWritable(PhySocket *sock,void **uptr,bool stack_invoked) @@ -337,13 +337,13 @@ namespace ZeroTier { int SocketTap::Write(Connection *conn, void *data, ssize_t len) { if(conn->socket_type == SOCK_RAW) { // we don't want to use a stack, just VL2 - struct ether_header *eh = (struct ether_header *) data; - MAC src_mac; - MAC dest_mac; - src_mac.setTo(eh->ether_shost, 6); - dest_mac.setTo(eh->ether_dhost, 6); - _handler(_arg,NULL,_nwid,src_mac,dest_mac, Utils::ntoh((uint16_t)eh->ether_type),0, ((char*)data) + sizeof(struct ether_header),len - sizeof(struct ether_header)); - return len; + struct ether_header *eh = (struct ether_header *) data; + MAC src_mac; + MAC dest_mac; + src_mac.setTo(eh->ether_shost, 6); + dest_mac.setTo(eh->ether_dhost, 6); + _handler(_arg,NULL,_nwid,src_mac,dest_mac, Utils::ntoh((uint16_t)eh->ether_type),0, ((char*)data) + sizeof(struct ether_header),len - sizeof(struct ether_header)); + return len; } #if defined(STACK_PICO) diff --git a/src/SocketTap.hpp b/src/SocketTap.hpp index 1a9f03c..dc28e68 100644 --- a/src/SocketTap.hpp +++ b/src/SocketTap.hpp @@ -137,22 +137,22 @@ namespace ZeroTier { /* * For moving data onto the ZeroTier virtual wire */ - void (*_handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int, - const void *,unsigned int); + void (*_handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int, + const void *,unsigned int); /* - * Signals us to close the TcpConnection associated with this PhySocket - */ + * Signals us to close the TcpConnection associated with this PhySocket + */ void phyOnUnixClose(PhySocket *sock,void **uptr); - /* - * Notifies us that there is data to be read from an application's socket - */ + /* + * Notifies us that there is data to be read from an application's socket + */ void phyOnUnixData(PhySocket *sock,void **uptr,void *data,ssize_t len); /* - * Notifies us that we can write to an application's socket - */ + * Notifies us that we can write to an application's socket + */ void phyOnUnixWritable(PhySocket *sock,void **uptr,bool lwip_invoked); /****************************************************************************/ @@ -173,14 +173,14 @@ namespace ZeroTier { /* Guarded RX Frame Buffer for picoTCP */ /****************************************************************************/ - unsigned char pico_frame_rxbuf[MAX_PICO_FRAME_RX_BUF_SZ]; - int pico_frame_rxbuf_tot; - Mutex _pico_frame_rxbuf_m; + unsigned char pico_frame_rxbuf[MAX_PICO_FRAME_RX_BUF_SZ]; + int pico_frame_rxbuf_tot; + Mutex _pico_frame_rxbuf_m; #endif #if defined(STACK_LWIP) - netif lwipdev; - netif lwipdev6; + netif lwipdev; + netif lwipdev6; #endif static int devno; @@ -190,13 +190,13 @@ namespace ZeroTier { std::vector _ips; std::string _homePath; - void *_arg; + void *_arg; volatile bool _enabled; volatile bool _run; MAC _mac; - unsigned int _mtu; - uint64_t _nwid; - PhySocket *_unixListenSocket; + unsigned int _mtu; + uint64_t _nwid; + PhySocket *_unixListenSocket; Phy _phy; std::vector _Connections; @@ -245,14 +245,14 @@ namespace ZeroTier { int Read(PhySocket *sock,void **uptr,bool stack_invoked); /* - * Move data from application's "socket" into network stack - */ + * Move data from application's "socket" into network stack + */ int Write(Connection *conn, void *data, ssize_t len); /* * Closes a Connection */ - int Close(Connection *conn); + int Close(Connection *conn); /* * Disposes of previously-closed Connections diff --git a/src/Utilities.hpp b/src/Utilities.hpp index f9e89d0..3bc0f33 100644 --- a/src/Utilities.hpp +++ b/src/Utilities.hpp @@ -38,14 +38,14 @@ #define ip4_addr4b(ipaddr) (((u8_t*)(ipaddr))[3]) inline ip_addr_t convert_ip(struct sockaddr_in * addr) { - ip_addr_t conn_addr; - struct sockaddr_in *ipv4 = addr; - short a = ip4_addr1b(&(ipv4->sin_addr)); - short b = ip4_addr2b(&(ipv4->sin_addr)); - short c = ip4_addr3b(&(ipv4->sin_addr)); - short d = ip4_addr4b(&(ipv4->sin_addr)); - IP4_ADDR(&conn_addr, a,b,c,d); - return conn_addr; + ip_addr_t conn_addr; + struct sockaddr_in *ipv4 = addr; + short a = ip4_addr1b(&(ipv4->sin_addr)); + short b = ip4_addr2b(&(ipv4->sin_addr)); + short c = ip4_addr3b(&(ipv4->sin_addr)); + short d = ip4_addr4b(&(ipv4->sin_addr)); + IP4_ADDR(&conn_addr, a,b,c,d); + return conn_addr; } #endif // STACK_LWIP && LIBZT_IPV4 diff --git a/src/libzt.cpp b/src/libzt.cpp index 61dd5cf..9b2b502 100644 --- a/src/libzt.cpp +++ b/src/libzt.cpp @@ -77,34 +77,34 @@ extern "C" { static ZeroTier::OneService *zt1Service; namespace ZeroTier { - std::string homeDir; // Platform-specific dir we *must* use internally - std::string netDir; // Where network .conf files are to be written + std::string homeDir; // Platform-specific dir we *must* use internally + std::string netDir; // Where network .conf files are to be written #if defined(STACK_PICO) - picoTCP *picostack = NULL; + picoTCP *picostack = NULL; #endif #if defined(STACK_LWIP) - lwIP *lwipstack = NULL; + lwIP *lwipstack = NULL; #endif - /* - * "sockets" that have been created but not bound to a SocketTap interface yet - */ - std::map unmap; + /* + * "sockets" that have been created but not bound to a SocketTap interface yet + */ + std::map unmap; - /* - * For fast lookup of Connections and SocketTaps via given file descriptor - */ - std::map*> fdmap; + /* + * For fast lookup of Connections and SocketTaps via given file descriptor + */ + std::map*> fdmap; - /* - * - */ - std::vector vtaps; + /* + * + */ + std::vector vtaps; - ZeroTier::Mutex _vtaps_lock; - ZeroTier::Mutex _multiplexer_lock; - ZeroTier::Mutex _accepted_connection_lock; + ZeroTier::Mutex _vtaps_lock; + ZeroTier::Mutex _multiplexer_lock; + ZeroTier::Mutex _accepted_connection_lock; } /****************************************************************************/ @@ -113,234 +113,234 @@ namespace ZeroTier { void zts_start(const char *path) { - if(zt1Service) - return; + if(zt1Service) + return; #if defined(STACK_PICO) - if(ZeroTier::picostack) - return; - ZeroTier::picostack = new ZeroTier::picoTCP(); - pico_stack_init(); + if(ZeroTier::picostack) + return; + ZeroTier::picostack = new ZeroTier::picoTCP(); + pico_stack_init(); #endif #if defined(STACK_LWIP) - ZeroTier::lwipstack = new ZeroTier::lwIP(); - lwip_init(); + ZeroTier::lwipstack = new ZeroTier::lwIP(); + lwip_init(); #endif - if(path) - ZeroTier::homeDir = path; - pthread_t service_thread; - pthread_create(&service_thread, NULL, zts_start_service, (void *)(path)); + if(path) + ZeroTier::homeDir = path; + pthread_t service_thread; + pthread_create(&service_thread, NULL, zts_start_service, (void *)(path)); } void zts_simple_start(const char *path, const char *nwid) { - zts_start(path); - while(!zts_running()) - usleep(ZT_API_CHECK_INTERVAL * 1000); - zts_join(nwid); - while(!zts_has_address(nwid)) - usleep(ZT_API_CHECK_INTERVAL * 1000); + zts_start(path); + while(!zts_running()) + usleep(ZT_API_CHECK_INTERVAL * 1000); + zts_join(nwid); + while(!zts_has_address(nwid)) + usleep(ZT_API_CHECK_INTERVAL * 1000); } void zts_stop() { - if(zt1Service) { - zt1Service->terminate(); - dismantleTaps(); - } + if(zt1Service) { + zt1Service->terminate(); + dismantleTaps(); + } } void zts_join(const char * nwid) { - if(zt1Service) { - std::string confFile = zt1Service->givenHomePath() + "/networks.d/" + nwid + ".conf"; - if(!ZeroTier::OSUtils::mkdir(ZeroTier::netDir)) { - DEBUG_ERROR("unable to create: %s", ZeroTier::netDir.c_str()); - handle_general_failure(); - } - if(!ZeroTier::OSUtils::writeFile(confFile.c_str(), "")) { - DEBUG_ERROR("unable to write network conf file: %s", confFile.c_str()); - handle_general_failure(); - } - zt1Service->join(nwid); - } + if(zt1Service) { + std::string confFile = zt1Service->givenHomePath() + "/networks.d/" + nwid + ".conf"; + if(!ZeroTier::OSUtils::mkdir(ZeroTier::netDir)) { + DEBUG_ERROR("unable to create: %s", ZeroTier::netDir.c_str()); + handle_general_failure(); + } + if(!ZeroTier::OSUtils::writeFile(confFile.c_str(), "")) { + DEBUG_ERROR("unable to write network conf file: %s", confFile.c_str()); + handle_general_failure(); + } + zt1Service->join(nwid); + } } void zts_join_soft(const char * filepath, const char * nwid) { - std::string net_dir = std::string(filepath) + "/networks.d/"; - std::string confFile = net_dir + std::string(nwid) + ".conf"; - if(!ZeroTier::OSUtils::mkdir(net_dir)) { - DEBUG_ERROR("unable to create: %s", net_dir.c_str()); - handle_general_failure(); - } - if(!ZeroTier::OSUtils::fileExists(confFile.c_str(),false)) { - if(!ZeroTier::OSUtils::writeFile(confFile.c_str(), "")) { - DEBUG_ERROR("unable to write network conf file: %s", confFile.c_str()); - handle_general_failure(); - } - } + std::string net_dir = std::string(filepath) + "/networks.d/"; + std::string confFile = net_dir + std::string(nwid) + ".conf"; + if(!ZeroTier::OSUtils::mkdir(net_dir)) { + DEBUG_ERROR("unable to create: %s", net_dir.c_str()); + handle_general_failure(); + } + if(!ZeroTier::OSUtils::fileExists(confFile.c_str(),false)) { + if(!ZeroTier::OSUtils::writeFile(confFile.c_str(), "")) { + DEBUG_ERROR("unable to write network conf file: %s", confFile.c_str()); + handle_general_failure(); + } + } } void zts_leave(const char * nwid) { - if(zt1Service) - zt1Service->leave(nwid); + if(zt1Service) + zt1Service->leave(nwid); } void zts_leave_soft(const char * filepath, const char * nwid) { - std::string net_dir = std::string(filepath) + "/networks.d/"; - ZeroTier::OSUtils::rm((net_dir + nwid + ".conf").c_str()); + std::string net_dir = std::string(filepath) + "/networks.d/"; + ZeroTier::OSUtils::rm((net_dir + nwid + ".conf").c_str()); } void zts_get_homepath(char *homePath, int len) { - if(ZeroTier::homeDir.length()) { - memset(homePath, 0, len); - memcpy(homePath, ZeroTier::homeDir.c_str(), len < ZeroTier::homeDir.length() ? len : ZeroTier::homeDir.length()); - } + if(ZeroTier::homeDir.length()) { + memset(homePath, 0, len); + memcpy(homePath, ZeroTier::homeDir.c_str(), len < ZeroTier::homeDir.length() ? len : ZeroTier::homeDir.length()); + } } void zts_core_version(char *ver) { - int major, minor, revision; - ZT_version(&major, &minor, &revision); - sprintf(ver, "%d.%d.%d", major, minor, revision); + int major, minor, revision; + ZT_version(&major, &minor, &revision); + sprintf(ver, "%d.%d.%d", major, minor, revision); } void zts_lib_version(char *ver) { - sprintf(ver, "%d.%d.%d", ZT_LIB_VERSION_MAJOR, ZT_LIB_VERSION_MINOR, ZT_LIB_VERSION_REVISION); + sprintf(ver, "%d.%d.%d", ZT_LIB_VERSION_MAJOR, ZT_LIB_VERSION_MINOR, ZT_LIB_VERSION_REVISION); } int zts_get_device_id(char *devID) { - if(zt1Service) { - char id[ZT_ID_LEN+1]; - sprintf(id, "%lx",zt1Service->getNode()->address()); - memcpy(devID, id, ZT_ID_LEN+1); - return 0; - } - else // Service isn't online, try to read ID from file - { - std::string fname("identity.public"); - std::string fpath(ZeroTier::homeDir); + if(zt1Service) { + char id[ZT_ID_LEN+1]; + sprintf(id, "%lx",zt1Service->getNode()->address()); + memcpy(devID, id, ZT_ID_LEN+1); + return 0; + } + else // Service isn't online, try to read ID from file + { + std::string fname("identity.public"); + std::string fpath(ZeroTier::homeDir); - if(ZeroTier::OSUtils::fileExists((fpath + ZT_PATH_SEPARATOR_S + fname).c_str(),false)) { - std::string oldid; - ZeroTier::OSUtils::readFile((fpath + ZT_PATH_SEPARATOR_S + fname).c_str(),oldid); - memcpy(devID, oldid.c_str(), ZT_ID_LEN); // first 10 bytes of file - return 0; - } - } - return -1; + if(ZeroTier::OSUtils::fileExists((fpath + ZT_PATH_SEPARATOR_S + fname).c_str(),false)) { + std::string oldid; + ZeroTier::OSUtils::readFile((fpath + ZT_PATH_SEPARATOR_S + fname).c_str(),oldid); + memcpy(devID, oldid.c_str(), ZT_ID_LEN); // first 10 bytes of file + return 0; + } + } + return -1; } int zts_running() { - return !zt1Service ? false : zt1Service->isRunning(); + return !zt1Service ? false : zt1Service->isRunning(); } int zts_has_ipv4_address(const char *nwid) { - char ipv4_addr[ZT_MAX_IPADDR_LEN]; - memset(ipv4_addr, 0, ZT_MAX_IPADDR_LEN); - zts_get_ipv4_address(nwid, ipv4_addr, ZT_MAX_IPADDR_LEN); - return strcmp(ipv4_addr, "\0"); + char ipv4_addr[ZT_MAX_IPADDR_LEN]; + memset(ipv4_addr, 0, ZT_MAX_IPADDR_LEN); + zts_get_ipv4_address(nwid, ipv4_addr, ZT_MAX_IPADDR_LEN); + return strcmp(ipv4_addr, "\0"); } int zts_has_ipv6_address(const char *nwid) { - char ipv6_addr[ZT_MAX_IPADDR_LEN]; - memset(ipv6_addr, 0, ZT_MAX_IPADDR_LEN); - zts_get_ipv6_address(nwid, ipv6_addr, ZT_MAX_IPADDR_LEN); - return strcmp(ipv6_addr, "\0"); + char ipv6_addr[ZT_MAX_IPADDR_LEN]; + memset(ipv6_addr, 0, ZT_MAX_IPADDR_LEN); + zts_get_ipv6_address(nwid, ipv6_addr, ZT_MAX_IPADDR_LEN); + return strcmp(ipv6_addr, "\0"); } int zts_has_address(const char *nwid) { - return zts_has_ipv4_address(nwid) || zts_has_ipv6_address(nwid); + return zts_has_ipv4_address(nwid) || zts_has_ipv6_address(nwid); } void zts_get_ipv4_address(const char *nwid, char *addrstr, const int addrlen) { - if(zt1Service) { - uint64_t nwid_int = strtoull(nwid, NULL, 16); - ZeroTier::SocketTap *tap = getTapByNWID(nwid_int); - if(tap && tap->_ips.size()){ - for(int i=0; i_ips.size(); i++) { - if(tap->_ips[i].isV4()) { - char ipbuf[64]; - std::string addr = tap->_ips[i].toString(ipbuf); - int len = addrlen < addr.length() ? addrlen : addr.length(); - memset(addrstr, 0, len); - memcpy(addrstr, addr.c_str(), len); - return; - } - } - } - } - else - memcpy(addrstr, "\0", 1); + if(zt1Service) { + uint64_t nwid_int = strtoull(nwid, NULL, 16); + ZeroTier::SocketTap *tap = getTapByNWID(nwid_int); + if(tap && tap->_ips.size()){ + for(int i=0; i_ips.size(); i++) { + if(tap->_ips[i].isV4()) { + char ipbuf[64]; + std::string addr = tap->_ips[i].toString(ipbuf); + int len = addrlen < addr.length() ? addrlen : addr.length(); + memset(addrstr, 0, len); + memcpy(addrstr, addr.c_str(), len); + return; + } + } + } + } + else + memcpy(addrstr, "\0", 1); } void zts_get_ipv6_address(const char *nwid, char *addrstr, const int addrlen) { - if(zt1Service) { - uint64_t nwid_int = strtoull(nwid, NULL, 16); - ZeroTier::SocketTap *tap = getTapByNWID(nwid_int); - if(tap && tap->_ips.size()){ - for(int i=0; i_ips.size(); i++) { - if(tap->_ips[i].isV6()) { - char ipbuf[64]; - std::string addr = tap->_ips[i].toString(ipbuf); - int len = addrlen < addr.length() ? addrlen : addr.length(); - memset(addrstr, 0, len); - memcpy(addrstr, addr.c_str(), len); - return; - } - } - } - } - else - memcpy(addrstr, "\0", 1); + if(zt1Service) { + uint64_t nwid_int = strtoull(nwid, NULL, 16); + ZeroTier::SocketTap *tap = getTapByNWID(nwid_int); + if(tap && tap->_ips.size()){ + for(int i=0; i_ips.size(); i++) { + if(tap->_ips[i].isV6()) { + char ipbuf[64]; + std::string addr = tap->_ips[i].toString(ipbuf); + int len = addrlen < addr.length() ? addrlen : addr.length(); + memset(addrstr, 0, len); + memcpy(addrstr, addr.c_str(), len); + return; + } + } + } + } + else + memcpy(addrstr, "\0", 1); } void zts_get_6plane_addr(char *addr, const char *nwid, const char *devID) { - ZeroTier::InetAddress _6planeAddr = ZeroTier::InetAddress::makeIpv66plane( - ZeroTier::Utils::hexStrToU64(nwid),ZeroTier::Utils::hexStrToU64(devID)); - char ipbuf[64]; - memcpy(addr, _6planeAddr.toIpString(ipbuf), 40); + ZeroTier::InetAddress _6planeAddr = ZeroTier::InetAddress::makeIpv66plane( + ZeroTier::Utils::hexStrToU64(nwid),ZeroTier::Utils::hexStrToU64(devID)); + char ipbuf[64]; + memcpy(addr, _6planeAddr.toIpString(ipbuf), 40); } void zts_get_rfc4193_addr(char *addr, const char *nwid, const char *devID) { - ZeroTier::InetAddress _6planeAddr = ZeroTier::InetAddress::makeIpv6rfc4193( - ZeroTier::Utils::hexStrToU64(nwid),ZeroTier::Utils::hexStrToU64(devID)); - char ipbuf[64]; - memcpy(addr, _6planeAddr.toIpString(ipbuf), 40); + ZeroTier::InetAddress _6planeAddr = ZeroTier::InetAddress::makeIpv6rfc4193( + ZeroTier::Utils::hexStrToU64(nwid),ZeroTier::Utils::hexStrToU64(devID)); + char ipbuf[64]; + memcpy(addr, _6planeAddr.toIpString(ipbuf), 40); } unsigned long zts_get_peer_count() { - if(zt1Service) - return zt1Service->getNode()->peers()->peerCount; - else - return 0; + if(zt1Service) + return zt1Service->getNode()->peers()->peerCount; + else + return 0; } int zts_get_peer_address(char *peer, const char *devID) { - if(zt1Service) { - ZT_PeerList *pl = zt1Service->getNode()->peers(); - // uint64_t addr; - for(int i=0; ipeerCount; i++) { - // ZT_Peer *p = &(pl->peers[i]); - // DEBUG_INFO("peer[%d] = %lx", i, p->address); - } - return pl->peerCount; - } - else - return -1; + if(zt1Service) { + ZT_PeerList *pl = zt1Service->getNode()->peers(); + // uint64_t addr; + for(int i=0; ipeerCount; i++) { + // ZT_Peer *p = &(pl->peers[i]); + // DEBUG_INFO("peer[%d] = %lx", i, p->address); + } + return pl->peerCount; + } + else + return -1; } void zts_enable_http_control_plane() { - // TODO + // TODO } void zts_disable_http_control_plane() { - // TODO + // TODO } /****************************************************************************/ @@ -356,86 +356,86 @@ void zts_disable_http_control_plane() Darwin: - [ ] [EACCES] Permission to create a socket of the specified type and/or protocol is denied. - [ ] [EAFNOSUPPORT] The specified address family is not supported. - [--] [EMFILE] The per-process descriptor table is full. - [NA] [ENFILE] The system file table is full. - [ ] [ENOBUFS] Insufficient buffer space is available. The socket cannot be created until sufficient resources are freed. - [ ] [ENOMEM] Insufficient memory was available to fulfill the request. - [--] [EPROTONOSUPPORT] The protocol type or the specified protocol is not supported within this domain. - [ ] [EPROTOTYPE] The socket type is not supported by the protocol. + [ ] [EACCES] Permission to create a socket of the specified type and/or protocol is denied. + [ ] [EAFNOSUPPORT] The specified address family is not supported. + [--] [EMFILE] The per-process descriptor table is full. + [NA] [ENFILE] The system file table is full. + [ ] [ENOBUFS] Insufficient buffer space is available. The socket cannot be created until sufficient resources are freed. + [ ] [ENOMEM] Insufficient memory was available to fulfill the request. + [--] [EPROTONOSUPPORT] The protocol type or the specified protocol is not supported within this domain. + [ ] [EPROTOTYPE] The socket type is not supported by the protocol. */ // int socket_family, int socket_type, int protocol int zts_socket(ZT_SOCKET_SIG) { - errno = 0; - if(socket_family < 0 || socket_type < 0 || protocol < 0) { - errno = EINVAL; - return -1; - } - int err = 0; - if(!zt1Service) { - DEBUG_ERROR("cannot create socket, no service running. call zts_start() first."); - errno = EMFILE; // could also be ENFILE - return -1; - } - if(socket_type == SOCK_SEQPACKET) { - DEBUG_ERROR("SOCK_SEQPACKET not yet supported."); - errno = EPROTONOSUPPORT; // seemingly closest match - return -1; - } + errno = 0; + if(socket_family < 0 || socket_type < 0 || protocol < 0) { + errno = EINVAL; + return -1; + } + int err = 0; + if(!zt1Service) { + DEBUG_ERROR("cannot create socket, no service running. call zts_start() first."); + errno = EMFILE; // could also be ENFILE + return -1; + } + if(socket_type == SOCK_SEQPACKET) { + DEBUG_ERROR("SOCK_SEQPACKET not yet supported."); + errno = EPROTONOSUPPORT; // seemingly closest match + return -1; + } - ZeroTier::_multiplexer_lock.lock(); + ZeroTier::_multiplexer_lock.lock(); - if(socket_type == SOCK_RAW) - { - // Connection is only used to associate a socket with a SocketTap, it has no other implication - ZeroTier::Connection *conn = new ZeroTier::Connection(); - conn->socket_family = socket_family; - conn->socket_type = socket_type; - conn->protocol = protocol; - ZeroTier::unmap[conn->app_fd] = conn; - return conn->app_fd; - } + if(socket_type == SOCK_RAW) + { + // Connection is only used to associate a socket with a SocketTap, it has no other implication + ZeroTier::Connection *conn = new ZeroTier::Connection(); + conn->socket_family = socket_family; + conn->socket_type = socket_type; + conn->protocol = protocol; + ZeroTier::unmap[conn->app_fd] = conn; + return conn->app_fd; + } #if defined(STACK_PICO) - struct pico_socket *p; - err = ZeroTier::picostack->pico_Socket(&p, socket_family, socket_type, protocol); - if(p) { - ZeroTier::Connection *conn = new ZeroTier::Connection(); - conn->socket_family = socket_family; - conn->socket_type = socket_type; - conn->picosock = p; - ZeroTier::unmap[conn->app_fd] = conn; - err = conn->app_fd; // return one end of the socketpair - } - else { - DEBUG_ERROR("failed to create pico_socket"); - err = -1; - } + struct pico_socket *p; + err = ZeroTier::picostack->pico_Socket(&p, socket_family, socket_type, protocol); + if(p) { + ZeroTier::Connection *conn = new ZeroTier::Connection(); + conn->socket_family = socket_family; + conn->socket_type = socket_type; + conn->picosock = p; + ZeroTier::unmap[conn->app_fd] = conn; + err = conn->app_fd; // return one end of the socketpair + } + else { + DEBUG_ERROR("failed to create pico_socket"); + err = -1; + } #endif #if defined(STACK_LWIP) - // TODO: check for max lwIP timers/sockets - ZeroTier::Connection *conn = new ZeroTier::Connection(); - void *pcb; - err = ZeroTier::lwipstack->lwip_Socket(&pcb, socket_family, socket_type, protocol); - if(pcb) { - ZeroTier::Connection *conn = new ZeroTier::Connection(); - conn->socket_family = socket_family; - conn->socket_type = socket_type; - conn->pcb = pcb; - ZeroTier::unmap[conn->app_fd] = conn; - err = conn->app_fd; // return one end of the socketpair - } - else { - DEBUG_ERROR("failed to create lwip pcb"); - err = -1; - } + // TODO: check for max lwIP timers/sockets + ZeroTier::Connection *conn = new ZeroTier::Connection(); + void *pcb; + err = ZeroTier::lwipstack->lwip_Socket(&pcb, socket_family, socket_type, protocol); + if(pcb) { + ZeroTier::Connection *conn = new ZeroTier::Connection(); + conn->socket_family = socket_family; + conn->socket_type = socket_type; + conn->pcb = pcb; + ZeroTier::unmap[conn->app_fd] = conn; + err = conn->app_fd; // return one end of the socketpair + } + else { + DEBUG_ERROR("failed to create lwip pcb"); + err = -1; + } #endif - ZeroTier::_multiplexer_lock.unlock(); - return err; + ZeroTier::_multiplexer_lock.unlock(); + return err; } @@ -443,401 +443,401 @@ int zts_socket(ZT_SOCKET_SIG) { Darwin: - [ ] [EACCES] The destination address is a broadcast address and the socket option SO_BROADCAST is not set. - [ ] [EADDRINUSE] The address is already in use. - [ ] [EADDRNOTAVAIL] The specified address is not available on this machine. - [ ] [EAFNOSUPPORT] Addresses in the specified address family cannot be used with this socket. - [ ] [EALREADY] The socket is non-blocking and a previous connection attempt has not yet been completed. - [--] [EBADF] socket is not a valid descriptor. - [ ] [ECONNREFUSED] The attempt to connect was ignored (because the target is not listening for connections) or explicitly rejected. - [ ] [EFAULT] The address parameter specifies an area outside the process address space. - [ ] [EHOSTUNREACH] The target host cannot be reached (e.g., down, disconnected). - [--] [EINPROGRESS] The socket is non-blocking and the connection cannot be completed immediately. - It is possible to select(2) for completion by selecting the socket for writing. - [NA] [EINTR] Its execution was interrupted by a signal. - [ ] [EINVAL] An invalid argument was detected (e.g., address_len is not valid for the address family, the specified address family is invalid). - [ ] [EISCONN] The socket is already connected. - [ ] [ENETDOWN] The local network interface is not functioning. - [--] [ENETUNREACH] The network isn't reachable from this host. - [ ] [ENOBUFS] The system call was unable to allocate a needed memory buffer. - [ ] [ENOTSOCK] socket is not a file descriptor for a socket. - [ ] [EOPNOTSUPP] Because socket is listening, no connection is allowed. - [ ] [EPROTOTYPE] address has a different type than the socket that is bound to the specified peer address. - [ ] [ETIMEDOUT] Connection establishment timed out without establishing a connection. - [ ] [ECONNRESET] Remote host reset the connection request. + [ ] [EACCES] The destination address is a broadcast address and the socket option SO_BROADCAST is not set. + [ ] [EADDRINUSE] The address is already in use. + [ ] [EADDRNOTAVAIL] The specified address is not available on this machine. + [ ] [EAFNOSUPPORT] Addresses in the specified address family cannot be used with this socket. + [ ] [EALREADY] The socket is non-blocking and a previous connection attempt has not yet been completed. + [--] [EBADF] socket is not a valid descriptor. + [ ] [ECONNREFUSED] The attempt to connect was ignored (because the target is not listening for connections) or explicitly rejected. + [ ] [EFAULT] The address parameter specifies an area outside the process address space. + [ ] [EHOSTUNREACH] The target host cannot be reached (e.g., down, disconnected). + [--] [EINPROGRESS] The socket is non-blocking and the connection cannot be completed immediately. + It is possible to select(2) for completion by selecting the socket for writing. + [NA] [EINTR] Its execution was interrupted by a signal. + [ ] [EINVAL] An invalid argument was detected (e.g., address_len is not valid for the address family, the specified address family is invalid). + [ ] [EISCONN] The socket is already connected. + [ ] [ENETDOWN] The local network interface is not functioning. + [--] [ENETUNREACH] The network isn't reachable from this host. + [ ] [ENOBUFS] The system call was unable to allocate a needed memory buffer. + [ ] [ENOTSOCK] socket is not a file descriptor for a socket. + [ ] [EOPNOTSUPP] Because socket is listening, no connection is allowed. + [ ] [EPROTOTYPE] address has a different type than the socket that is bound to the specified peer address. + [ ] [ETIMEDOUT] Connection establishment timed out without establishing a connection. + [ ] [ECONNRESET] Remote host reset the connection request. Linux: - [ ] [EACCES] For UNIX domain sockets, which are identified by pathname: Write permission is denied on the socket file, - or search permission is denied for one of the directories in the path prefix. (See also path_resolution(7).) - [ ] [EACCES, EPERM] The user tried to connect to a broadcast address without having the socket broadcast flag enabled or the - connection request failed because of a local firewall rule. - [ ] [EADDRINUSE] Local address is already in use. - [ ] [EAFNOSUPPORT] The passed address didn't have the correct address family in its sa_family field. - [ ] [EAGAIN] No more free local ports or insufficient entries in the routing cache. For AF_INET see the description - of /proc/sys/net/ipv4/ip_local_port_range ip(7) for information on how to increase the number of local ports. - [ ] [EALREADY] The socket is nonblocking and a previous connection attempt has not yet been completed. - [ ] [EBADF] The file descriptor is not a valid index in the descriptor table. - [ ] [ECONNREFUSED] No-one listening on the remote address. - [ ] [EFAULT] The socket structure address is outside the user's address space. - [ ] [EINPROGRESS] The socket is nonblocking and the connection cannot be completed immediately. It is possible to select(2) or - poll(2) for completion by selecting the socket for writing. After select(2) indicates writability, use getsockopt(2) - to read the SO_ERROR option at level SOL_SOCKET to determine whether connect() completed successfully (SO_ERROR is zero) - or unsuccessfully (SO_ERROR is one of the usual error codes listed here, explaining the reason for the failure). - [ ] [EINTR] The system call was interrupted by a signal that was caught; see signal(7). - [ ] [EISCONN] The socket is already connected. - [ ] [ENETUNREACH] Network is unreachable. - [ ] [ENOTSOCK] The file descriptor is not associated with a socket. - [ ] [ETIMEDOUT] Timeout while attempting connection. The server may be too busy to accept new connections. Note that for - IP sockets the timeout may be very long when syncookies are enabled on the server. + [ ] [EACCES] For UNIX domain sockets, which are identified by pathname: Write permission is denied on the socket file, + or search permission is denied for one of the directories in the path prefix. (See also path_resolution(7).) + [ ] [EACCES, EPERM] The user tried to connect to a broadcast address without having the socket broadcast flag enabled or the + connection request failed because of a local firewall rule. + [ ] [EADDRINUSE] Local address is already in use. + [ ] [EAFNOSUPPORT] The passed address didn't have the correct address family in its sa_family field. + [ ] [EAGAIN] No more free local ports or insufficient entries in the routing cache. For AF_INET see the description + of /proc/sys/net/ipv4/ip_local_port_range ip(7) for information on how to increase the number of local ports. + [ ] [EALREADY] The socket is nonblocking and a previous connection attempt has not yet been completed. + [ ] [EBADF] The file descriptor is not a valid index in the descriptor table. + [ ] [ECONNREFUSED] No-one listening on the remote address. + [ ] [EFAULT] The socket structure address is outside the user's address space. + [ ] [EINPROGRESS] The socket is nonblocking and the connection cannot be completed immediately. It is possible to select(2) or + poll(2) for completion by selecting the socket for writing. After select(2) indicates writability, use getsockopt(2) + to read the SO_ERROR option at level SOL_SOCKET to determine whether connect() completed successfully (SO_ERROR is zero) + or unsuccessfully (SO_ERROR is one of the usual error codes listed here, explaining the reason for the failure). + [ ] [EINTR] The system call was interrupted by a signal that was caught; see signal(7). + [ ] [EISCONN] The socket is already connected. + [ ] [ENETUNREACH] Network is unreachable. + [ ] [ENOTSOCK] The file descriptor is not associated with a socket. + [ ] [ETIMEDOUT] Timeout while attempting connection. The server may be too busy to accept new connections. Note that for + IP sockets the timeout may be very long when syncookies are enabled on the server. */ int zts_connect(ZT_CONNECT_SIG) { #if defined(STACK_PICO) - //DEBUG_INFO("fd = %d", fd); - int err = 0; - if(fd < 0) { - errno = EBADF; - DEBUG_ERROR("EBADF"); - return -1; - } - if(!zt1Service) { - DEBUG_ERROR("Service not started. Call zts_start(path) first"); - errno = EBADF; - return -1; - } - ZeroTier::_multiplexer_lock.lock(); - ZeroTier::Connection *conn = ZeroTier::unmap[fd]; - ZeroTier::SocketTap *tap; + //DEBUG_INFO("fd = %d", fd); + int err = 0; + if(fd < 0) { + errno = EBADF; + DEBUG_ERROR("EBADF"); + return -1; + } + if(!zt1Service) { + DEBUG_ERROR("Service not started. Call zts_start(path) first"); + errno = EBADF; + return -1; + } + ZeroTier::_multiplexer_lock.lock(); + ZeroTier::Connection *conn = ZeroTier::unmap[fd]; + ZeroTier::SocketTap *tap; - if(conn) { - char ipstr[INET6_ADDRSTRLEN]; - memset(ipstr, 0, INET6_ADDRSTRLEN); - ZeroTier::InetAddress iaddr; - int port = 0; + if(conn) { + char ipstr[INET6_ADDRSTRLEN]; + memset(ipstr, 0, INET6_ADDRSTRLEN); + ZeroTier::InetAddress iaddr; + int port = 0; - if(conn->socket_family == AF_INET) { - inet_ntop(AF_INET, - (const void *)&((struct sockaddr_in *)addr)->sin_addr.s_addr, ipstr, INET_ADDRSTRLEN); - iaddr.fromString(ipstr); - port = ((struct sockaddr_in*)addr)->sin_port; - } - if(conn->socket_family == AF_INET6) { - inet_ntop(AF_INET6, - (const void *)&((struct sockaddr_in6 *)addr)->sin6_addr.s6_addr, ipstr, INET6_ADDRSTRLEN); - // TODO: This is a hack, determine a proper way to do this - char addrstr[64]; - sprintf(addrstr, "%s%s", ipstr, std::string("/88").c_str()); - iaddr.fromString(addrstr); - port = ((struct sockaddr_in6*)addr)->sin6_port; - } - DEBUG_EXTRA("fd = %d, %s : %d", fd, ipstr, ntohs(port)); - tap = getTapByAddr(iaddr); - if(!tap) { - DEBUG_ERROR("no route to host"); - errno = ENETUNREACH; - err = -1; - } - else { - // pointer to tap we use in callbacks from the stack - conn->picosock->priv = new ZeroTier::ConnectionPair(tap, conn); - err = tap->Connect(conn, fd, addr, addrlen); - if(err == 0) { - tap->_Connections.push_back(conn); // Give this Connection to the tap we decided on - conn->tap = tap; - } - // Wrap the socketpair we created earlier - // For I/O loop participation and referencing the PhySocket's parent Connection in callbacks - conn->sock = tap->_phy.wrapSocket(conn->sdk_fd, conn); - //DEBUG_ERROR("sock->fd = %d", tap->_phy.getDescriptor(conn->sock)); - } - } - else { - DEBUG_ERROR("unable to locate connection"); - errno = EBADF; - err = -1; - } - ZeroTier::unmap.erase(fd); - ZeroTier::fdmap[fd] = new std::pair(conn, tap); - ZeroTier::_multiplexer_lock.unlock(); + if(conn->socket_family == AF_INET) { + inet_ntop(AF_INET, + (const void *)&((struct sockaddr_in *)addr)->sin_addr.s_addr, ipstr, INET_ADDRSTRLEN); + iaddr.fromString(ipstr); + port = ((struct sockaddr_in*)addr)->sin_port; + } + if(conn->socket_family == AF_INET6) { + inet_ntop(AF_INET6, + (const void *)&((struct sockaddr_in6 *)addr)->sin6_addr.s6_addr, ipstr, INET6_ADDRSTRLEN); + // TODO: This is a hack, determine a proper way to do this + char addrstr[64]; + sprintf(addrstr, "%s%s", ipstr, std::string("/88").c_str()); + iaddr.fromString(addrstr); + port = ((struct sockaddr_in6*)addr)->sin6_port; + } + DEBUG_EXTRA("fd = %d, %s : %d", fd, ipstr, ntohs(port)); + tap = getTapByAddr(iaddr); + if(!tap) { + DEBUG_ERROR("no route to host"); + errno = ENETUNREACH; + err = -1; + } + else { + // pointer to tap we use in callbacks from the stack + conn->picosock->priv = new ZeroTier::ConnectionPair(tap, conn); + err = tap->Connect(conn, fd, addr, addrlen); + if(err == 0) { + tap->_Connections.push_back(conn); // Give this Connection to the tap we decided on + conn->tap = tap; + } + // Wrap the socketpair we created earlier + // For I/O loop participation and referencing the PhySocket's parent Connection in callbacks + conn->sock = tap->_phy.wrapSocket(conn->sdk_fd, conn); + //DEBUG_ERROR("sock->fd = %d", tap->_phy.getDescriptor(conn->sock)); + } + } + else { + DEBUG_ERROR("unable to locate connection"); + errno = EBADF; + err = -1; + } + ZeroTier::unmap.erase(fd); + ZeroTier::fdmap[fd] = new std::pair(conn, tap); + ZeroTier::_multiplexer_lock.unlock(); - // 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 Connection in a ZT_SOCK_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 + // 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 Connection in a ZT_SOCK_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); - err = -1; - } - else { - blocking = !(f_err & O_NONBLOCK); - } + 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); + } - // non-blocking - if(err == 0 && !blocking) { - DEBUG_EXTRA("EINPROGRESS, not a real error, assuming non-blocking mode"); - errno = EINPROGRESS; - err = -1; - } - else // blocking - { - // FIXME: Double check that accept/connect queues in multithreaded apps don't get mixed up - if(err == 0 && blocking) { - bool complete = false; - while(true) - { - // FIXME: locking and unlocking so often might cause a performance bottleneck while outgoing connections - // are being established (also applies to accept()) - usleep(ZT_CONNECT_RECHECK_DELAY * 1000); - //DEBUG_ERROR("waiting to connect...\n"); - tap->_tcpconns_m.lock(); - for(int i=0; i_Connections.size(); i++) - { - if(tap->_Connections[i]->state == PICO_ERR_ECONNRESET) { - errno = ECONNRESET; - DEBUG_ERROR("ECONNRESET"); - err = -1; - } - if(tap->_Connections[i]->state == ZT_SOCK_STATE_UNHANDLED_CONNECTED) { - tap->_Connections[i]->state = ZT_SOCK_STATE_CONNECTED; - errno = 0; - err = 0; // complete - complete = true; - } - } - tap->_tcpconns_m.unlock(); - if(complete) - break; - } - } - } - return err; + // non-blocking + if(err == 0 && !blocking) { + DEBUG_EXTRA("EINPROGRESS, not a real error, assuming non-blocking mode"); + errno = EINPROGRESS; + err = -1; + } + else // blocking + { + // FIXME: Double check that accept/connect queues in multithreaded apps don't get mixed up + if(err == 0 && blocking) { + bool complete = false; + while(true) + { + // FIXME: locking and unlocking so often might cause a performance bottleneck while outgoing connections + // are being established (also applies to accept()) + usleep(ZT_CONNECT_RECHECK_DELAY * 1000); + //DEBUG_ERROR("waiting to connect...\n"); + tap->_tcpconns_m.lock(); + for(int i=0; i_Connections.size(); i++) + { + if(tap->_Connections[i]->state == PICO_ERR_ECONNRESET) { + errno = ECONNRESET; + DEBUG_ERROR("ECONNRESET"); + err = -1; + } + if(tap->_Connections[i]->state == ZT_SOCK_STATE_UNHANDLED_CONNECTED) { + tap->_Connections[i]->state = ZT_SOCK_STATE_CONNECTED; + errno = 0; + err = 0; // complete + complete = true; + } + } + tap->_tcpconns_m.unlock(); + if(complete) + break; + } + } + } + return err; #endif - return 0; + return 0; } /* Darwin: - [--] [EBADF] S is not a valid descriptor. - [ ] [ENOTSOCK] S is not a socket. - [--] [EADDRNOTAVAIL] The specified address is not available from the local - machine. - [ ] [EADDRINUSE] The specified address is already in use. - [ ] [EINVAL] The socket is already bound to an address. - [ ] [EACCES] The requested address is protected, and the current - user has inadequate permission to access it. - [ ] [EFAULT] The name parameter is not in a valid part of the user - address space. + [--] [EBADF] S is not a valid descriptor. + [ ] [ENOTSOCK] S is not a socket. + [--] [EADDRNOTAVAIL] The specified address is not available from the local + machine. + [ ] [EADDRINUSE] The specified address is already in use. + [ ] [EINVAL] The socket is already bound to an address. + [ ] [EACCES] The requested address is protected, and the current + user has inadequate permission to access it. + [ ] [EFAULT] The name parameter is not in a valid part of the user + address space. */ int zts_bind(ZT_BIND_SIG) { - int err = 0; - if(fd < 0) { - errno = EBADF; - return -1; - } - if(!zt1Service) { - DEBUG_ERROR("Service not started. Call zts_start(path) first"); - errno = EBADF; - return -1; - } - ZeroTier::_multiplexer_lock.lock(); - ZeroTier::Connection *conn = ZeroTier::unmap[fd]; - ZeroTier::SocketTap *tap; - - if(conn) { - char ipstr[INET6_ADDRSTRLEN]; - memset(ipstr, 0, INET6_ADDRSTRLEN); - ZeroTier::InetAddress iaddr; - int port = 0; - if(conn->socket_family == AF_INET) { - inet_ntop(AF_INET, - (const void *)&((struct sockaddr_in *)addr)->sin_addr.s_addr, ipstr, INET_ADDRSTRLEN); - port = ((struct sockaddr_in*)addr)->sin_port; - } - if(conn->socket_family == AF_INET6) { - inet_ntop(AF_INET6, - (const void *)&((struct sockaddr_in6 *)addr)->sin6_addr.s6_addr, ipstr, INET6_ADDRSTRLEN); - port = ((struct sockaddr_in6*)addr)->sin6_port; - } - DEBUG_EXTRA("fd = %d, %s : %d", fd, ipstr, ntohs(port)); - iaddr.fromString(ipstr); - tap = getTapByAddr(iaddr); + int err = 0; + if(fd < 0) { + errno = EBADF; + return -1; + } + if(!zt1Service) { + DEBUG_ERROR("Service not started. Call zts_start(path) first"); + errno = EBADF; + return -1; + } + ZeroTier::_multiplexer_lock.lock(); + ZeroTier::Connection *conn = ZeroTier::unmap[fd]; + ZeroTier::SocketTap *tap; + + if(conn) { + char ipstr[INET6_ADDRSTRLEN]; + memset(ipstr, 0, INET6_ADDRSTRLEN); + ZeroTier::InetAddress iaddr; + int port = 0; + if(conn->socket_family == AF_INET) { + inet_ntop(AF_INET, + (const void *)&((struct sockaddr_in *)addr)->sin_addr.s_addr, ipstr, INET_ADDRSTRLEN); + port = ((struct sockaddr_in*)addr)->sin_port; + } + if(conn->socket_family == AF_INET6) { + inet_ntop(AF_INET6, + (const void *)&((struct sockaddr_in6 *)addr)->sin6_addr.s6_addr, ipstr, INET6_ADDRSTRLEN); + port = ((struct sockaddr_in6*)addr)->sin6_port; + } + DEBUG_EXTRA("fd = %d, %s : %d", fd, ipstr, ntohs(port)); + iaddr.fromString(ipstr); + tap = getTapByAddr(iaddr); - if(!tap) { - DEBUG_ERROR("no matching interface to bind to"); - errno = EADDRNOTAVAIL; - err = -1; - } + if(!tap) { + DEBUG_ERROR("no matching interface to bind to"); + errno = EADDRNOTAVAIL; + err = -1; + } #if defined(STACK_PICO) - else { - conn->picosock->priv = new ZeroTier::ConnectionPair(tap, conn); - tap->_Connections.push_back(conn); // Give this Connection to the tap we decided on - err = tap->Bind(conn, fd, addr, addrlen); - conn->tap = tap; - if(err == 0) { // success - ZeroTier::unmap.erase(fd); - ZeroTier::fdmap[fd] = new std::pair(conn, tap); - } - } + else { + conn->picosock->priv = new ZeroTier::ConnectionPair(tap, conn); + tap->_Connections.push_back(conn); // Give this Connection to the tap we decided on + err = tap->Bind(conn, fd, addr, addrlen); + conn->tap = tap; + if(err == 0) { // success + ZeroTier::unmap.erase(fd); + ZeroTier::fdmap[fd] = new std::pair(conn, tap); + } + } #endif #if defined(STACK_LWIP) - else { - tap->_Connections.push_back(conn); - err = tap->Bind(conn, fd, addr, addrlen); - if(err == 0) { // success - ZeroTier::unmap.erase(fd); - ZeroTier::fdmap[fd] = new std::pair(conn, tap); - } - } + else { + tap->_Connections.push_back(conn); + err = tap->Bind(conn, fd, addr, addrlen); + if(err == 0) { // success + ZeroTier::unmap.erase(fd); + ZeroTier::fdmap[fd] = new std::pair(conn, tap); + } + } #endif - } - else { - DEBUG_ERROR("unable to locate connection"); - errno = EBADF; - err = -1; - } - ZeroTier::_multiplexer_lock.unlock(); - return err; + } + else { + DEBUG_ERROR("unable to locate connection"); + errno = EBADF; + err = -1; + } + ZeroTier::_multiplexer_lock.unlock(); + return err; } /* Darwin: - [--] [EACCES] The current process has insufficient privileges. - [--] [EBADF] The argument socket is not a valid file descriptor. - [--] [EDESTADDRREQ] The socket is not bound to a local address and the protocol does not support listening on an unbound socket. - [ ] [EINVAL] socket is already connected. - [ ] [ENOTSOCK] The argument socket does not reference a socket. - [ ] [EOPNOTSUPP] The socket is not of a type that supports the operation listen(). + [--] [EACCES] The current process has insufficient privileges. + [--] [EBADF] The argument socket is not a valid file descriptor. + [--] [EDESTADDRREQ] The socket is not bound to a local address and the protocol does not support listening on an unbound socket. + [ ] [EINVAL] socket is already connected. + [ ] [ENOTSOCK] The argument socket does not reference a socket. + [ ] [EOPNOTSUPP] The socket is not of a type that supports the operation listen(). Linux: - [ ] [EADDRINUSE] Another socket is already listening on the same port. - [--] [EBADF] The argument sockfd is not a valid descriptor. - [ ] [ENOTSOCK] The argument sockfd is not a socket. - [ ] [EOPNOTSUPP] The socket is not of a type that supports the listen() operation. + [ ] [EADDRINUSE] Another socket is already listening on the same port. + [--] [EBADF] The argument sockfd is not a valid descriptor. + [ ] [ENOTSOCK] The argument sockfd is not a socket. + [ ] [EOPNOTSUPP] The socket is not of a type that supports the listen() operation. */ int zts_listen(ZT_LISTEN_SIG) { #if defined(STACK_PICO) - DEBUG_EXTRA("fd = %d", fd); - int err = 0; - if(fd < 0) { - errno = EBADF; - return -1; - } - if(!zt1Service) { - DEBUG_ERROR("service not started. call zts_start(path) first"); - errno = EACCES; - return -1; - } - ZeroTier::_multiplexer_lock.lock(); - std::pair *p = ZeroTier::fdmap[fd]; - if(!p) { - DEBUG_ERROR("unable to locate connection pair. did you bind?"); - errno = EDESTADDRREQ; - return -1; - } - ZeroTier::Connection *conn = p->first; - ZeroTier::SocketTap *tap = p->second; - if(!tap || !conn) { - DEBUG_ERROR("unable to locate tap interface for file descriptor"); - errno = EBADF; - return -1; - } - if(!err) { - backlog = backlog > 128 ? 128 : backlog; // See: /proc/sys/net/core/somaxconn - err = tap->Listen(conn, fd, backlog); - conn->state = ZT_SOCK_STATE_LISTENING; - ZeroTier::_multiplexer_lock.unlock(); - } - return err; + DEBUG_EXTRA("fd = %d", fd); + int err = 0; + if(fd < 0) { + errno = EBADF; + return -1; + } + if(!zt1Service) { + DEBUG_ERROR("service not started. call zts_start(path) first"); + errno = EACCES; + return -1; + } + ZeroTier::_multiplexer_lock.lock(); + std::pair *p = ZeroTier::fdmap[fd]; + if(!p) { + DEBUG_ERROR("unable to locate connection pair. did you bind?"); + errno = EDESTADDRREQ; + return -1; + } + ZeroTier::Connection *conn = p->first; + ZeroTier::SocketTap *tap = p->second; + if(!tap || !conn) { + DEBUG_ERROR("unable to locate tap interface for file descriptor"); + errno = EBADF; + return -1; + } + if(!err) { + backlog = backlog > 128 ? 128 : backlog; // See: /proc/sys/net/core/somaxconn + err = tap->Listen(conn, fd, backlog); + conn->state = ZT_SOCK_STATE_LISTENING; + ZeroTier::_multiplexer_lock.unlock(); + } + return err; #endif - return 0; + return 0; } /* Darwin: - [--] [EBADF] The descriptor is invalid. - [ ] [ENOTSOCK] The descriptor references a file, not a socket. - [ ] [EOPNOTSUPP] The referenced socket is not of type SOCK_STREAM. - [ ] [EFAULT] The addr parameter is not in a writable part of the - user address space. - [--] [EWOULDBLOCK] The socket is marked non-blocking and no connections - are present to be accepted. - [--] [EMFILE] The per-process descriptor table is full. - [ ] [ENFILE] The system file table is full. + [--] [EBADF] The descriptor is invalid. + [ ] [ENOTSOCK] The descriptor references a file, not a socket. + [ ] [EOPNOTSUPP] The referenced socket is not of type SOCK_STREAM. + [ ] [EFAULT] The addr parameter is not in a writable part of the + user address space. + [--] [EWOULDBLOCK] The socket is marked non-blocking and no connections + are present to be accepted. + [--] [EMFILE] The per-process descriptor table is full. + [ ] [ENFILE] The system file table is full. */ int zts_accept(ZT_ACCEPT_SIG) { #if defined(STACK_PICO) - DEBUG_EXTRA("fd = %d", fd); - int err = 0; - if(fd < 0) { - errno = EBADF; - return -1; - } - else - { - // +1 since we'll be creating a new pico_socket when we accept the connection - if(pico_ntimers()+1 >= PICO_MAX_TIMERS) { - DEBUG_ERROR("cannot provision additional socket due to limitation of PICO_MAX_TIMERS."); - errno = EMFILE; - err = -1; - } - ZeroTier::_multiplexer_lock.lock(); - std::pair *p = ZeroTier::fdmap[fd]; - if(!p) { - DEBUG_ERROR("unable to locate connection pair (did you zts_bind())?"); - errno = EBADF; - err = -1; - } - else { - ZeroTier::Connection *conn = p->first; - ZeroTier::SocketTap *tap = p->second; + DEBUG_EXTRA("fd = %d", fd); + int err = 0; + if(fd < 0) { + errno = EBADF; + return -1; + } + else + { + // +1 since we'll be creating a new pico_socket when we accept the connection + if(pico_ntimers()+1 >= PICO_MAX_TIMERS) { + DEBUG_ERROR("cannot provision additional socket due to limitation of PICO_MAX_TIMERS."); + errno = EMFILE; + err = -1; + } + ZeroTier::_multiplexer_lock.lock(); + std::pair *p = ZeroTier::fdmap[fd]; + if(!p) { + DEBUG_ERROR("unable to locate connection pair (did you zts_bind())?"); + errno = EBADF; + err = -1; + } + else { + ZeroTier::Connection *conn = p->first; + ZeroTier::SocketTap *tap = p->second; - // BLOCKING: loop and keep checking until we find a newly accepted connection - 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); - } - if(!err) { - ZeroTier::Connection *accepted_conn; - if(!blocking) { // non-blocking - DEBUG_EXTRA("EWOULDBLOCK, not a real error, assuming non-blocking mode"); - errno = EWOULDBLOCK; - err = -1; - accepted_conn = tap->Accept(conn); - } - else { // blocking - while(true) { - usleep(ZT_ACCEPT_RECHECK_DELAY * 1000); - accepted_conn = tap->Accept(conn); - if(accepted_conn) - break; // accepted fd = err - } - } - if(accepted_conn) { - ZeroTier::fdmap[accepted_conn->app_fd] = new std::pair(accepted_conn, tap); - err = accepted_conn->app_fd; - } - } - } - ZeroTier::_multiplexer_lock.unlock(); - } - return err; + // BLOCKING: loop and keep checking until we find a newly accepted connection + 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); + } + if(!err) { + ZeroTier::Connection *accepted_conn; + if(!blocking) { // non-blocking + DEBUG_EXTRA("EWOULDBLOCK, not a real error, assuming non-blocking mode"); + errno = EWOULDBLOCK; + err = -1; + accepted_conn = tap->Accept(conn); + } + else { // blocking + while(true) { + usleep(ZT_ACCEPT_RECHECK_DELAY * 1000); + accepted_conn = tap->Accept(conn); + if(accepted_conn) + break; // accepted fd = err + } + } + if(accepted_conn) { + ZeroTier::fdmap[accepted_conn->app_fd] = new std::pair(accepted_conn, tap); + err = accepted_conn->app_fd; + } + } + } + ZeroTier::_multiplexer_lock.unlock(); + } + return err; #endif - return 0; + return 0; } @@ -845,356 +845,356 @@ int zts_accept(ZT_ACCEPT_SIG) { Linux accept() (and accept4()) passes already-pending network errors on the new socket as an error code from accept(). This behavior differs from other BSD socket implementations. For reliable operation the application should detect the network errors defined for the protocol after accept() and treat them like EAGAIN by retrying. In the case of TCP/IP, these are ENETDOWN, EPROTO, ENOPROTOOPT, EHOSTDOWN, ENONET, EHOSTUNREACH, EOPNOTSUPP, and ENETUNREACH. Errors - [ ] [EAGAIN or EWOULDBLOCK] The socket is marked nonblocking and no connections are present to be accepted. POSIX.1-2001 allows either error to be returned for this case, and does not require these constants to have the same value, so a portable application should check for both possibilities. - [--] [EBADF] The descriptor is invalid. - [ ] [ECONNABORTED] A connection has been aborted. - [ ] [EFAULT] The addr argument is not in a writable part of the user address space. - [NA] [EINTR] The system call was interrupted by a signal that was caught before a valid connection arrived; see signal(7). - [ ] [EINVAL] Socket is not listening for connections, or addrlen is invalid (e.g., is negative). - [ ] [EINVAL] (accept4()) invalid value in flags. - [ ] [EMFILE] The per-process limit of open file descriptors has been reached. - [ ] [ENFILE] The system limit on the total number of open files has been reached. - [ ] [ENOBUFS, ENOMEM] Not enough free memory. This often means that the memory allocation is limited by the socket buffer limits, not by the system memory. - [ ] [ENOTSOCK] The descriptor references a file, not a socket. - [ ] [EOPNOTSUPP] The referenced socket is not of type SOCK_STREAM. - [ ] [EPROTO] Protocol error. + [ ] [EAGAIN or EWOULDBLOCK] The socket is marked nonblocking and no connections are present to be accepted. POSIX.1-2001 allows either error to be returned for this case, and does not require these constants to have the same value, so a portable application should check for both possibilities. + [--] [EBADF] The descriptor is invalid. + [ ] [ECONNABORTED] A connection has been aborted. + [ ] [EFAULT] The addr argument is not in a writable part of the user address space. + [NA] [EINTR] The system call was interrupted by a signal that was caught before a valid connection arrived; see signal(7). + [ ] [EINVAL] Socket is not listening for connections, or addrlen is invalid (e.g., is negative). + [ ] [EINVAL] (accept4()) invalid value in flags. + [ ] [EMFILE] The per-process limit of open file descriptors has been reached. + [ ] [ENFILE] The system limit on the total number of open files has been reached. + [ ] [ENOBUFS, ENOMEM] Not enough free memory. This often means that the memory allocation is limited by the socket buffer limits, not by the system memory. + [ ] [ENOTSOCK] The descriptor references a file, not a socket. + [ ] [EOPNOTSUPP] The referenced socket is not of type SOCK_STREAM. + [ ] [EPROTO] Protocol error. In addition, Linux accept() may fail if: EPERM Firewall rules forbid connection. */ #if defined(__linux__) - int zts_accept4(ZT_ACCEPT4_SIG) - { - DEBUG_INFO("fd = %d", fd); - int err = 0; - if(fd < 0) { - errno = EBADF; - err = -1; - } - return 0; - } + int zts_accept4(ZT_ACCEPT4_SIG) + { + DEBUG_INFO("fd = %d", fd); + int err = 0; + if(fd < 0) { + errno = EBADF; + err = -1; + } + return 0; + } #endif /* - [--] [EBADF] The argument s is not a valid descriptor. - [ ] [ENOTSOCK] The argument s is a file, not a socket. - [--] [ENOPROTOOPT] The option is unknown at the level indicated. - [ ] [EFAULT] The address pointed to by optval is not in a valid - part of the process address space. For getsockopt(), - this error may also be returned if optlen is not in a - valid part of the process address space. - [ ] [EDOM] The argument value is out of bounds. + [--] [EBADF] The argument s is not a valid descriptor. + [ ] [ENOTSOCK] The argument s is a file, not a socket. + [--] [ENOPROTOOPT] The option is unknown at the level indicated. + [ ] [EFAULT] The address pointed to by optval is not in a valid + part of the process address space. For getsockopt(), + this error may also be returned if optlen is not in a + valid part of the process address space. + [ ] [EDOM] The argument value is out of bounds. */ int zts_setsockopt(ZT_SETSOCKOPT_SIG) { #if defined(STACK_PICO) - DEBUG_INFO("fd = %d", fd); - int err = 0; - if(fd < 0) { - errno = EBADF; - err = -1; - } + DEBUG_INFO("fd = %d", fd); + int err = 0; + if(fd < 0) { + errno = EBADF; + err = -1; + } - // Disable Nagle's algorithm - struct pico_socket *p = NULL; - err = zts_get_pico_socket(fd, &p); - if(p) { - int value = 1; - if((err = pico_socket_setoption(p, PICO_TCP_NODELAY, &value)) < 0) { - if(err == PICO_ERR_EINVAL) { - DEBUG_ERROR("error while disabling Nagle's algorithm"); - errno = ENOPROTOOPT; - return -1; - } - } + // Disable Nagle's algorithm + struct pico_socket *p = NULL; + err = zts_get_pico_socket(fd, &p); + if(p) { + int value = 1; + if((err = pico_socket_setoption(p, PICO_TCP_NODELAY, &value)) < 0) { + if(err == PICO_ERR_EINVAL) { + DEBUG_ERROR("error while disabling Nagle's algorithm"); + errno = ENOPROTOOPT; + return -1; + } + } - } - err = setsockopt(fd, level, optname, optval, optlen); - return err; + } + err = setsockopt(fd, level, optname, optval, optlen); + return err; #endif - return 0; + return 0; } /* - [--] [EBADF] The argument s is not a valid descriptor. - [ ] [ENOTSOCK] The argument s is a file, not a socket. - [ ] [ENOPROTOOPT] The option is unknown at the level indicated. - [ ] [EFAULT] The address pointed to by optval is not in a valid - part of the process address space. For getsockopt(), - this error may also be returned if optlen is not in a - valid part of the process address space. - [ ] [EDOM] The argument value is out of bounds. + [--] [EBADF] The argument s is not a valid descriptor. + [ ] [ENOTSOCK] The argument s is a file, not a socket. + [ ] [ENOPROTOOPT] The option is unknown at the level indicated. + [ ] [EFAULT] The address pointed to by optval is not in a valid + part of the process address space. For getsockopt(), + this error may also be returned if optlen is not in a + valid part of the process address space. + [ ] [EDOM] The argument value is out of bounds. */ int zts_getsockopt(ZT_GETSOCKOPT_SIG) { - //DEBUG_INFO("fd = %d", fd); - int err = 0; - if(fd < 0) { - errno = EBADF; - err = -1; - } - err = getsockopt(fd, level, optname, optval, optlen); - return err; + //DEBUG_INFO("fd = %d", fd); + int err = 0; + if(fd < 0) { + errno = EBADF; + err = -1; + } + err = getsockopt(fd, level, optname, optval, optlen); + return err; } /* - [--] [EBADF] The argument s is not a valid descriptor. - [ ] [ENOTSOCK] The argument s is a file, not a socket. - [ ] [ENOBUFS] Insufficient resources were available in the system to - perform the operation. - [ ] [EFAULT] The name parameter points to memory not in a valid - part of the process address space. + [--] [EBADF] The argument s is not a valid descriptor. + [ ] [ENOTSOCK] The argument s is a file, not a socket. + [ ] [ENOBUFS] Insufficient resources were available in the system to + perform the operation. + [ ] [EFAULT] The name parameter points to memory not in a valid + part of the process address space. */ int zts_getsockname(ZT_GETSOCKNAME_SIG) { - DEBUG_INFO("fd = %d", fd); - int err = 0; - if(fd < 0) { - errno = EBADF; - err = -1; - } - // TODO - return err; + DEBUG_INFO("fd = %d", fd); + int err = 0; + if(fd < 0) { + errno = EBADF; + err = -1; + } + // TODO + return err; } /* - [--] [EBADF] The argument s is not a valid descriptor. - [ ] [ENOTSOCK] The argument s is a file, not a socket. - [ ] [ENOTCONN] The socket is not connected. - [ ] [ENOBUFS] Insufficient resources were available in the system to - perform the operation. - [ ] [EFAULT] The name parameter points to memory not in a valid - part of the process address space. + [--] [EBADF] The argument s is not a valid descriptor. + [ ] [ENOTSOCK] The argument s is a file, not a socket. + [ ] [ENOTCONN] The socket is not connected. + [ ] [ENOBUFS] Insufficient resources were available in the system to + perform the operation. + [ ] [EFAULT] The name parameter points to memory not in a valid + part of the process address space. */ int zts_getpeername(ZT_GETPEERNAME_SIG) { - DEBUG_INFO("fd = %d", fd); - int err = 0; - if(fd < 0) { - errno = EBADF; - err = -1; - } - // TODO - return err; + DEBUG_INFO("fd = %d", fd); + int err = 0; + if(fd < 0) { + errno = EBADF; + err = -1; + } + // TODO + return err; } /* Linux: - See: http://yarchive.net/comp/linux/close_return_value.html + See: http://yarchive.net/comp/linux/close_return_value.html Linux / Darwin: - [--] [EBADF] fildes is not a valid, active file descriptor. - [NA] [EINTR] Its execution was interrupted by a signal. - [ ] [EIO] A previously-uncommitted write(2) encountered an input/output error. + [--] [EBADF] fildes is not a valid, active file descriptor. + [NA] [EINTR] Its execution was interrupted by a signal. + [ ] [EIO] A previously-uncommitted write(2) encountered an input/output error. */ int zts_close(ZT_CLOSE_SIG) { #if defined(STACK_PICO) - DEBUG_EXTRA("fd = %d", fd); - int err = 0; - if(fd < 0) { - errno = EBADF; - err = -1; - } - else - { - if(!zt1Service) { - DEBUG_ERROR("cannot close socket. service not started. call zts_start(path) first"); - errno = EBADF; - err = -1; - } - else - { - ZeroTier::_multiplexer_lock.lock(); - //DEBUG_INFO("unmap=%d, fdmap=%d", ZeroTier::unmap.size(), ZeroTier::fdmap.size()); - // First, look for for unassigned connections - ZeroTier::Connection *conn = ZeroTier::unmap[fd]; + DEBUG_EXTRA("fd = %d", fd); + int err = 0; + if(fd < 0) { + errno = EBADF; + err = -1; + } + else + { + if(!zt1Service) { + DEBUG_ERROR("cannot close socket. service not started. call zts_start(path) first"); + errno = EBADF; + err = -1; + } + else + { + ZeroTier::_multiplexer_lock.lock(); + //DEBUG_INFO("unmap=%d, fdmap=%d", ZeroTier::unmap.size(), ZeroTier::fdmap.size()); + // First, look for for unassigned connections + ZeroTier::Connection *conn = ZeroTier::unmap[fd]; - // Since we found an unassigned connection, we don't need to consult the stack or tap - // during closure - it isn't yet stitched into the clockwork - if(conn) // unassigned - { - DEBUG_ERROR("unassigned closure"); - if((err = pico_socket_close(conn->picosock)) < 0) - DEBUG_ERROR("error calling pico_socket_close()"); - if((err = close(conn->app_fd)) < 0) - DEBUG_ERROR("error closing app_fd"); - if((err = close(conn->sdk_fd)) < 0) - DEBUG_ERROR("error closing sdk_fd"); - delete conn; - ZeroTier::unmap.erase(fd); - } - else // assigned - { - std::pair *p = ZeroTier::fdmap[fd]; - if(!p) - { - DEBUG_ERROR("unable to locate connection pair."); - errno = EBADF; - err = -1; - } - else // found everything, begin closure - { - conn = p->first; - ZeroTier::SocketTap *tap = p->second; + // Since we found an unassigned connection, we don't need to consult the stack or tap + // during closure - it isn't yet stitched into the clockwork + if(conn) // unassigned + { + DEBUG_ERROR("unassigned closure"); + if((err = pico_socket_close(conn->picosock)) < 0) + DEBUG_ERROR("error calling pico_socket_close()"); + if((err = close(conn->app_fd)) < 0) + DEBUG_ERROR("error closing app_fd"); + if((err = close(conn->sdk_fd)) < 0) + DEBUG_ERROR("error closing sdk_fd"); + delete conn; + ZeroTier::unmap.erase(fd); + } + else // assigned + { + std::pair *p = ZeroTier::fdmap[fd]; + if(!p) + { + DEBUG_ERROR("unable to locate connection pair."); + errno = EBADF; + err = -1; + } + else // found everything, begin closure + { + conn = p->first; + ZeroTier::SocketTap *tap = p->second; - // check if socket is blocking - 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); - } + // check if socket is blocking + 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); + } - if(blocking) { - DEBUG_INFO("blocking, waiting for write operations before closure..."); - for(int i=0; iTXbuf->count() == 0) - break; - usleep(ZT_API_CHECK_INTERVAL * 1000); - } - } + if(blocking) { + DEBUG_INFO("blocking, waiting for write operations before closure..."); + for(int i=0; iTXbuf->count() == 0) + break; + usleep(ZT_API_CHECK_INTERVAL * 1000); + } + } - // For cases where data might still need to pass through the library - // before socket closure - - /* - if(ZT_SOCK_BEHAVIOR_LINGER) { - socklen_t optlen; - struct linger so_linger; - so_linger.l_linger = 0; - zts_getsockopt(fd, SOL_SOCKET, SO_LINGER, &so_linger, &optlen); - //DEBUG_ERROR("fd = %d, value = %d", fd, so_linger.l_linger); - // if (so_linger.l_linger != 0) { - DEBUG_EXTRA("lingering before closure for (%d) seconds...", so_linger.l_linger); - sleep(3); // do the linger! - // } - } - else - { - DEBUG_ERROR("LINGER NOT enabled"); - } - */ + // For cases where data might still need to pass through the library + // before socket closure + + /* + if(ZT_SOCK_BEHAVIOR_LINGER) { + socklen_t optlen; + struct linger so_linger; + so_linger.l_linger = 0; + zts_getsockopt(fd, SOL_SOCKET, SO_LINGER, &so_linger, &optlen); + //DEBUG_ERROR("fd = %d, value = %d", fd, so_linger.l_linger); + // if (so_linger.l_linger != 0) { + DEBUG_EXTRA("lingering before closure for (%d) seconds...", so_linger.l_linger); + sleep(3); // do the linger! + // } + } + else + { + DEBUG_ERROR("LINGER NOT enabled"); + } + */ - //DEBUG_INFO("s->state = %s", ZeroTier::picoTCP::beautify_pico_state(conn->picosock->state)); - tap->Close(conn); - ZeroTier::fdmap.erase(fd); - err = 0; - } - } - //DEBUG_INFO(" unmap=%d, fdmap=%d", ZeroTier::unmap.size(), ZeroTier::fdmap.size()); - ZeroTier::_multiplexer_lock.unlock(); - } - } - return err; + //DEBUG_INFO("s->state = %s", ZeroTier::picoTCP::beautify_pico_state(conn->picosock->state)); + tap->Close(conn); + ZeroTier::fdmap.erase(fd); + err = 0; + } + } + //DEBUG_INFO(" unmap=%d, fdmap=%d", ZeroTier::unmap.size(), ZeroTier::fdmap.size()); + ZeroTier::_multiplexer_lock.unlock(); + } + } + return err; #endif - return 0; + return 0; } int zts_poll(ZT_POLL_SIG) { - return poll(fds, nfds, timeout); + return poll(fds, nfds, timeout); } int zts_select(ZT_SELECT_SIG) { - return select(nfds, readfds, writefds, exceptfds, timeout); + return select(nfds, readfds, writefds, exceptfds, timeout); } int zts_fcntl(ZT_FCNTL_SIG) { - int err = 0; - if(fd < 0) { - errno = EBADF; - err = -1; - } - else { - err = fcntl(fd, cmd, flags); - } - return err; + int err = 0; + if(fd < 0) { + errno = EBADF; + err = -1; + } + else { + err = fcntl(fd, cmd, flags); + } + return err; } /* - struct ifreq { - char ifr_name[IFNAMSIZ]; - union { - struct sockaddr ifr_addr; - struct sockaddr ifr_dstaddr; - struct sockaddr ifr_broadaddr; - struct sockaddr ifr_netmask; - struct sockaddr ifr_hwaddr; - short ifr_flags; - int ifr_ifindex; - int ifr_metric; - int ifr_mtu; - struct ifmap ifr_map; - char ifr_slave[IFNAMSIZ]; - char ifr_newname[IFNAMSIZ]; - char *ifr_data; - }; - }; + struct ifreq { + char ifr_name[IFNAMSIZ]; + union { + struct sockaddr ifr_addr; + struct sockaddr ifr_dstaddr; + struct sockaddr ifr_broadaddr; + struct sockaddr ifr_netmask; + struct sockaddr ifr_hwaddr; + short ifr_flags; + int ifr_ifindex; + int ifr_metric; + int ifr_mtu; + struct ifmap ifr_map; + char ifr_slave[IFNAMSIZ]; + char ifr_newname[IFNAMSIZ]; + char *ifr_data; + }; + }; */ /* - [ ] [BADF] fd is not a valid file descriptor. - [ ] [EFAULT] argp references an inaccessible memory area. - [ ] [EINVAL] request or argp is not valid. - [ ] [ENOTTY] The specified request does not apply to the kind of object that the file descriptor fd references. + [ ] [BADF] fd is not a valid file descriptor. + [ ] [EFAULT] argp references an inaccessible memory area. + [ ] [EINVAL] request or argp is not valid. + [ ] [ENOTTY] The specified request does not apply to the kind of object that the file descriptor fd references. */ int zts_ioctl(ZT_IOCTL_SIG) { - int err = 0; - if(fd < 0) { - errno = EBADF; - err = -1; - } - else { + int err = 0; + if(fd < 0) { + errno = EBADF; + err = -1; + } + else { #if defined(__linux__) - if(argp) - { - struct ifreq *ifr = (struct ifreq *)argp; - ZeroTier::SocketTap *tap = getTapByName(ifr->ifr_name); - if(!tap) { - DEBUG_ERROR("unable to locate tap interface with that name"); - err = -1; - errno = EINVAL; - } - // index of SocketTap interface - if(request == SIOCGIFINDEX) { - ifr->ifr_ifindex = tap->ifindex; - err = 0; - } - // MAC addres or SocketTap - if(request == SIOCGIFHWADDR) { - tap->_mac.copyTo(&(ifr->ifr_hwaddr.sa_data), sizeof(ifr->ifr_hwaddr.sa_data)); - err = 0; - } - // IP address of SocketTap - 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"); - } + if(argp) + { + struct ifreq *ifr = (struct ifreq *)argp; + ZeroTier::SocketTap *tap = getTapByName(ifr->ifr_name); + if(!tap) { + DEBUG_ERROR("unable to locate tap interface with that name"); + err = -1; + errno = EINVAL; + } + // index of SocketTap interface + if(request == SIOCGIFINDEX) { + ifr->ifr_ifindex = tap->ifindex; + err = 0; + } + // MAC addres or SocketTap + if(request == SIOCGIFHWADDR) { + tap->_mac.copyTo(&(ifr->ifr_hwaddr.sa_data), sizeof(ifr->ifr_hwaddr.sa_data)); + err = 0; + } + // IP address of SocketTap + 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 = ioctl(fd, request, argp); #endif - } - return err; + } + return err; } @@ -1202,195 +1202,195 @@ int zts_ioctl(ZT_IOCTL_SIG) Linux: - [ ] [EAGAIN or EWOULDBLOCK] The socket is marked nonblocking and the requested operation would block. POSIX.1-2001 allows either error to be returned for this case, and does not require these constants to have the same value, so a portable application should check for both possibilities. - [ ] [EBADF] An invalid descriptor was specified. - [ ] [ECONNRESET] Connection reset by peer. - [ ] [EDESTADDRREQ] The socket is not connection-mode, and no peer address is set. - [ ] [EFAULT] An invalid user space address was specified for an argument. - [ ] [EINTR] A signal occurred before any data was transmitted; see signal(7). - [ ] [EINVAL] Invalid argument passed. - [ ] [EISCONN] The connection-mode socket was connected already but a recipient was specified. (Now either this error is returned, or the recipient specification is ignored.) - [ ] [EMSGSIZE] The socket type requires that message be sent atomically, and the size of the message to be sent made this impossible. - [ ] [ENOBUFS] The output queue for a network interface was full. This generally indicates that the interface has stopped sending, but may be caused by transient congestion. (Normally, this does not occur in Linux. Packets are just silently dropped when a device queue overflows.) - [ ] [ENOMEM] No memory available. - [ ] [ENOTCONN] The socket is not connected, and no target has been given. - [ ] [ENOTSOCK] The argument sockfd is not a socket. - [ ] [EOPNOTSUPP] Some bit in the flags argument is inappropriate for the socket type. - [ ] [EPIPE] The local end has been shut down on a connection oriented socket. In this case the process will also receive a SIGPIPE unless MSG_NOSIGNAL is set. + [ ] [EAGAIN or EWOULDBLOCK] The socket is marked nonblocking and the requested operation would block. POSIX.1-2001 allows either error to be returned for this case, and does not require these constants to have the same value, so a portable application should check for both possibilities. + [ ] [EBADF] An invalid descriptor was specified. + [ ] [ECONNRESET] Connection reset by peer. + [ ] [EDESTADDRREQ] The socket is not connection-mode, and no peer address is set. + [ ] [EFAULT] An invalid user space address was specified for an argument. + [ ] [EINTR] A signal occurred before any data was transmitted; see signal(7). + [ ] [EINVAL] Invalid argument passed. + [ ] [EISCONN] The connection-mode socket was connected already but a recipient was specified. (Now either this error is returned, or the recipient specification is ignored.) + [ ] [EMSGSIZE] The socket type requires that message be sent atomically, and the size of the message to be sent made this impossible. + [ ] [ENOBUFS] The output queue for a network interface was full. This generally indicates that the interface has stopped sending, but may be caused by transient congestion. (Normally, this does not occur in Linux. Packets are just silently dropped when a device queue overflows.) + [ ] [ENOMEM] No memory available. + [ ] [ENOTCONN] The socket is not connected, and no target has been given. + [ ] [ENOTSOCK] The argument sockfd is not a socket. + [ ] [EOPNOTSUPP] Some bit in the flags argument is inappropriate for the socket type. + [ ] [EPIPE] The local end has been shut down on a connection oriented socket. In this case the process will also receive a SIGPIPE unless MSG_NOSIGNAL is set. */ ssize_t zts_sendto(ZT_SENDTO_SIG) { - DEBUG_INFO("fd = %d", fd); - int err = 0; - if(fd < 0) { - errno = EBADF; - err = -1; - } - else { - struct sockaddr_ll *socket_address = (struct sockaddr_ll *)addr; - ZeroTier::SocketTap *tap = getTapByIndex(socket_address->sll_ifindex); - if(tap) - { - DEBUG_INFO("found interface of ifindex=%d", tap->ifindex); - ZeroTier::Connection *conn = ZeroTier::unmap[fd]; - if(conn) { - DEBUG_INFO("located connection object for fd=%d", fd); - err = tap->Write(conn, (void*)buf, len); - } - else { - DEBUG_ERROR("unable to locate connection object for fd=%d", fd); - err = -1; - errno = EINVAL; - } - } - else - { - DEBUG_ERROR("unable to locate tap of ifindex=%d", socket_address->sll_ifindex); - err = -1; - errno = EINVAL; - } - //err = sendto(fd, buf, len, flags, addr, addrlen); - } - return err; + DEBUG_INFO("fd = %d", fd); + int err = 0; + if(fd < 0) { + errno = EBADF; + err = -1; + } + else { + struct sockaddr_ll *socket_address = (struct sockaddr_ll *)addr; + ZeroTier::SocketTap *tap = getTapByIndex(socket_address->sll_ifindex); + if(tap) + { + DEBUG_INFO("found interface of ifindex=%d", tap->ifindex); + ZeroTier::Connection *conn = ZeroTier::unmap[fd]; + if(conn) { + DEBUG_INFO("located connection object for fd=%d", fd); + err = tap->Write(conn, (void*)buf, len); + } + else { + DEBUG_ERROR("unable to locate connection object for fd=%d", fd); + err = -1; + errno = EINVAL; + } + } + else + { + DEBUG_ERROR("unable to locate tap of ifindex=%d", socket_address->sll_ifindex); + err = -1; + errno = EINVAL; + } + //err = sendto(fd, buf, len, flags, addr, addrlen); + } + return err; } // TODO ssize_t zts_sendmsg(ZT_SENDMSG_SIG) { - DEBUG_INFO("fd = %d", fd); - int err = 0; - if(fd < 0) { - errno = EBADF; - err = -1; - } - else { - err = sendmsg(fd, msg, flags); - } - return err; + DEBUG_INFO("fd = %d", fd); + int err = 0; + if(fd < 0) { + errno = EBADF; + err = -1; + } + else { + err = sendmsg(fd, msg, flags); + } + return err; } // TODO ssize_t zts_recvfrom(ZT_RECVFROM_SIG) { - DEBUG_INFO("fd = %d", fd); - int err = 0; - if(fd < 0) { - errno = EBADF; - err = -1; - } - else { - err = recvfrom(fd, buf, len, flags, addr, addrlen); - } - return err; + DEBUG_INFO("fd = %d", fd); + int err = 0; + if(fd < 0) { + errno = EBADF; + err = -1; + } + else { + err = recvfrom(fd, buf, len, flags, addr, addrlen); + } + return err; } // TODO ssize_t zts_recvmsg(ZT_RECVMSG_SIG) { - DEBUG_INFO("fd = %d", fd); - int err = 0; - if(fd < 0) { - errno = EBADF; - err = -1; - } - else { - err = recvmsg(fd, msg, flags); - } - return err; + DEBUG_INFO("fd = %d", fd); + int err = 0; + if(fd < 0) { + errno = EBADF; + err = -1; + } + else { + err = recvmsg(fd, msg, flags); + } + return err; } int zts_read(ZT_READ_SIG) { - //DEBUG_INFO("fd = %d", fd); - return read(fd, buf, len); + //DEBUG_INFO("fd = %d", fd); + return read(fd, buf, len); } int zts_write(ZT_WRITE_SIG) { - //DEBUG_INFO("fd = %d", fd); - return write(fd, buf, len); + //DEBUG_INFO("fd = %d", fd); + return write(fd, buf, len); } int zts_shutdown(ZT_SHUTDOWN_SIG) { #if defined(STACK_PICO) - DEBUG_INFO("fd = %d", fd); + DEBUG_INFO("fd = %d", fd); - 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; + 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(fd < 0) { - errno = EBADF; - err = -1; - } - else - { - if(!zt1Service) { - DEBUG_ERROR("cannot shutdown socket. service not started. call zts_start(path) first"); - errno = EBADF; - err = -1; - } - else - { - ZeroTier::_multiplexer_lock.lock(); - // First, look for for unassigned connections - ZeroTier::Connection *conn = ZeroTier::unmap[fd]; - // Since we found an unassigned connection, we don't need to consult the stack or tap - // during closure - it isn't yet stitched into the clockwork - if(conn) // unassigned - { - DEBUG_ERROR("unassigned shutdown"); - /* - PICO_SHUT_RD - PICO_SHUT_WR - PICO_SHUT_RDWR - */ - if((err = pico_socket_shutdown(conn->picosock, mode)) < 0) - DEBUG_ERROR("error calling pico_socket_shutdown()"); - delete conn; - ZeroTier::unmap.erase(fd); - // FIXME: Is deleting this correct behaviour? - } - else // assigned - { - std::pair *p = ZeroTier::fdmap[fd]; - if(!p) - { - DEBUG_ERROR("unable to locate connection pair."); - errno = EBADF; - err = -1; - } - else // found everything, begin closure - { - conn = p->first; - 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); - } - if(blocking) { - DEBUG_INFO("blocking, waiting for write operations before shutdown..."); - for(int i=0; iTXbuf->count() == 0) - break; - usleep(ZT_API_CHECK_INTERVAL * 1000); - } - } + if(fd < 0) { + errno = EBADF; + err = -1; + } + else + { + if(!zt1Service) { + DEBUG_ERROR("cannot shutdown socket. service not started. call zts_start(path) first"); + errno = EBADF; + err = -1; + } + else + { + ZeroTier::_multiplexer_lock.lock(); + // First, look for for unassigned connections + ZeroTier::Connection *conn = ZeroTier::unmap[fd]; + // Since we found an unassigned connection, we don't need to consult the stack or tap + // during closure - it isn't yet stitched into the clockwork + if(conn) // unassigned + { + DEBUG_ERROR("unassigned shutdown"); + /* + PICO_SHUT_RD + PICO_SHUT_WR + PICO_SHUT_RDWR + */ + if((err = pico_socket_shutdown(conn->picosock, mode)) < 0) + DEBUG_ERROR("error calling pico_socket_shutdown()"); + delete conn; + ZeroTier::unmap.erase(fd); + // FIXME: Is deleting this correct behaviour? + } + else // assigned + { + std::pair *p = ZeroTier::fdmap[fd]; + if(!p) + { + DEBUG_ERROR("unable to locate connection pair."); + errno = EBADF; + err = -1; + } + else // found everything, begin closure + { + conn = p->first; + 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); + } + if(blocking) { + DEBUG_INFO("blocking, waiting for write operations before shutdown..."); + for(int i=0; iTXbuf->count() == 0) + break; + usleep(ZT_API_CHECK_INTERVAL * 1000); + } + } - if((err = pico_socket_shutdown(conn->picosock, mode)) < 0) - DEBUG_ERROR("error calling pico_socket_shutdown()"); - } - } - ZeroTier::_multiplexer_lock.unlock(); - } - } - return err; + if((err = pico_socket_shutdown(conn->picosock, mode)) < 0) + DEBUG_ERROR("error calling pico_socket_shutdown()"); + } + } + ZeroTier::_multiplexer_lock.unlock(); + } + } + return err; #endif - return 0; + return 0; } /****************************************************************************/ @@ -1403,251 +1403,251 @@ int zts_shutdown(ZT_SHUTDOWN_SIG) namespace ZeroTier { - #include + #include - JNIEXPORT int JNICALL Java_zerotier_ZeroTier_ztjni_1start(JNIEnv *env, jobject thisObj, jstring path) { - if(path) { - homeDir = env->GetStringUTFChars(path, NULL); - zts_start(homeDir.c_str()); - } - } - // Shuts down ZeroTier service and SOCKS5 Proxy server - JNIEXPORT void JNICALL Java_zerotier_ZeroTier_ztjni_1stop(JNIEnv *env, jobject thisObj) { - if(zt1Service) - zts_stop(); - } + JNIEXPORT int JNICALL Java_zerotier_ZeroTier_ztjni_1start(JNIEnv *env, jobject thisObj, jstring path) { + if(path) { + homeDir = env->GetStringUTFChars(path, NULL); + zts_start(homeDir.c_str()); + } + } + // Shuts down ZeroTier service and SOCKS5 Proxy server + JNIEXPORT void JNICALL Java_zerotier_ZeroTier_ztjni_1stop(JNIEnv *env, jobject thisObj) { + if(zt1Service) + zts_stop(); + } - // Returns whether the ZeroTier service is running - JNIEXPORT jboolean JNICALL Java_zerotier_ZeroTier_ztjni_1running( - JNIEnv *env, jobject thisObj) - { - return zts_running(); - } - // Returns path for ZT config/data files - JNIEXPORT jstring JNICALL Java_zerotier_ZeroTier_ztjni_1homepath( - JNIEnv *env, jobject thisObj) - { - // TODO: fix, should copy into given arg - // return (*env).NewStringUTF(zts_get_homepath()); - return (*env).NewStringUTF(""); - } - // Join a network - JNIEXPORT void JNICALL Java_zerotier_ZeroTier_ztjni_1join( - JNIEnv *env, jobject thisObj, jstring nwid) - { - const char *nwidstr; - if(nwid) { - nwidstr = env->GetStringUTFChars(nwid, NULL); - zts_join(nwidstr); - } - } - // Leave a network - JNIEXPORT void JNICALL Java_zerotier_ZeroTier_ztjni_1leave( - JNIEnv *env, jobject thisObj, jstring nwid) - { - const char *nwidstr; - if(nwid) { - nwidstr = env->GetStringUTFChars(nwid, NULL); - zts_leave(nwidstr); - } - } - // FIXME: Re-implemented to make it play nicer with the C-linkage required for Xcode integrations - // Now only returns first assigned address per network. Shouldn't normally be a problem - JNIEXPORT jobject JNICALL Java_zerotier_ZeroTier_ztjni_1get_1ipv4_1address( - JNIEnv *env, jobject thisObj, jstring nwid) - { - const char *nwid_str = env->GetStringUTFChars(nwid, NULL); - char address_string[32]; - memset(address_string, 0, 32); - zts_get_ipv4_address(nwid_str, address_string, ZT_MAX_IPADDR_LEN); - jclass clazz = (*env).FindClass("java/util/ArrayList"); - jobject addresses = (*env).NewObject(clazz, (*env).GetMethodID(clazz, "", "()V")); - jstring _str = (*env).NewStringUTF(address_string); - env->CallBooleanMethod(addresses, env->GetMethodID(clazz, "add", "(Ljava/lang/Object;)Z"), _str); - return addresses; - } + // Returns whether the ZeroTier service is running + JNIEXPORT jboolean JNICALL Java_zerotier_ZeroTier_ztjni_1running( + JNIEnv *env, jobject thisObj) + { + return zts_running(); + } + // Returns path for ZT config/data files + JNIEXPORT jstring JNICALL Java_zerotier_ZeroTier_ztjni_1homepath( + JNIEnv *env, jobject thisObj) + { + // TODO: fix, should copy into given arg + // return (*env).NewStringUTF(zts_get_homepath()); + return (*env).NewStringUTF(""); + } + // Join a network + JNIEXPORT void JNICALL Java_zerotier_ZeroTier_ztjni_1join( + JNIEnv *env, jobject thisObj, jstring nwid) + { + const char *nwidstr; + if(nwid) { + nwidstr = env->GetStringUTFChars(nwid, NULL); + zts_join(nwidstr); + } + } + // Leave a network + JNIEXPORT void JNICALL Java_zerotier_ZeroTier_ztjni_1leave( + JNIEnv *env, jobject thisObj, jstring nwid) + { + const char *nwidstr; + if(nwid) { + nwidstr = env->GetStringUTFChars(nwid, NULL); + zts_leave(nwidstr); + } + } + // FIXME: Re-implemented to make it play nicer with the C-linkage required for Xcode integrations + // Now only returns first assigned address per network. Shouldn't normally be a problem + JNIEXPORT jobject JNICALL Java_zerotier_ZeroTier_ztjni_1get_1ipv4_1address( + JNIEnv *env, jobject thisObj, jstring nwid) + { + const char *nwid_str = env->GetStringUTFChars(nwid, NULL); + char address_string[32]; + memset(address_string, 0, 32); + zts_get_ipv4_address(nwid_str, address_string, ZT_MAX_IPADDR_LEN); + jclass clazz = (*env).FindClass("java/util/ArrayList"); + jobject addresses = (*env).NewObject(clazz, (*env).GetMethodID(clazz, "", "()V")); + jstring _str = (*env).NewStringUTF(address_string); + env->CallBooleanMethod(addresses, env->GetMethodID(clazz, "add", "(Ljava/lang/Object;)Z"), _str); + return addresses; + } - JNIEXPORT jobject JNICALL Java_zerotier_ZeroTier_ztjni_1get_1ipv6_1address( - JNIEnv *env, jobject thisObj, jstring nwid) - { - const char *nwid_str = env->GetStringUTFChars(nwid, NULL); - char address_string[32]; - memset(address_string, 0, 32); - zts_get_ipv6_address(nwid_str, address_string, ZT_MAX_IPADDR_LEN); - jclass clazz = (*env).FindClass("java/util/ArrayList"); - jobject addresses = (*env).NewObject(clazz, (*env).GetMethodID(clazz, "", "()V")); - jstring _str = (*env).NewStringUTF(address_string); - env->CallBooleanMethod(addresses, env->GetMethodID(clazz, "add", "(Ljava/lang/Object;)Z"), _str); - return addresses; - } + JNIEXPORT jobject JNICALL Java_zerotier_ZeroTier_ztjni_1get_1ipv6_1address( + JNIEnv *env, jobject thisObj, jstring nwid) + { + const char *nwid_str = env->GetStringUTFChars(nwid, NULL); + char address_string[32]; + memset(address_string, 0, 32); + zts_get_ipv6_address(nwid_str, address_string, ZT_MAX_IPADDR_LEN); + jclass clazz = (*env).FindClass("java/util/ArrayList"); + jobject addresses = (*env).NewObject(clazz, (*env).GetMethodID(clazz, "", "()V")); + jstring _str = (*env).NewStringUTF(address_string); + env->CallBooleanMethod(addresses, env->GetMethodID(clazz, "add", "(Ljava/lang/Object;)Z"), _str); + return addresses; + } - // Returns the device is in integer form - JNIEXPORT jint Java_zerotier_ZeroTier_ztjni_1get_1device_1id() - { - return zts_get_device_id(NULL); // TODO - } + // Returns the device is in integer form + JNIEXPORT jint Java_zerotier_ZeroTier_ztjni_1get_1device_1id() + { + return zts_get_device_id(NULL); // TODO + } - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1send(JNIEnv *env, jobject thisObj, jint fd, jarray buf, jint len, int flags) - { - jbyte *body = (*env).GetByteArrayElements((_jbyteArray *)buf, 0); - char * bufp = (char *)malloc(sizeof(char)*len); - memcpy(bufp, body, len); - (*env).ReleaseByteArrayElements((_jbyteArray *)buf, body, 0); - int written_bytes = zts_write(fd, body, len); - return written_bytes; - } + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1send(JNIEnv *env, jobject thisObj, jint fd, jarray buf, jint len, int flags) + { + jbyte *body = (*env).GetByteArrayElements((_jbyteArray *)buf, 0); + char * bufp = (char *)malloc(sizeof(char)*len); + memcpy(bufp, body, len); + (*env).ReleaseByteArrayElements((_jbyteArray *)buf, body, 0); + int written_bytes = zts_write(fd, body, len); + return written_bytes; + } - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1sendto( - JNIEnv *env, jobject thisObj, jint fd, jarray buf, jint len, jint flags, jobject ztaddr) - { - struct sockaddr_in addr; - jclass cls = (*env).GetObjectClass( ztaddr); - jfieldID f = (*env).GetFieldID( cls, "port", "I"); - addr.sin_port = htons((*env).GetIntField( ztaddr, f)); - f = (*env).GetFieldID( cls, "_rawAddr", "J"); - addr.sin_addr.s_addr = (*env).GetLongField( ztaddr, f); - addr.sin_family = AF_INET; - //LOGV("zt_sendto(): fd = %d\naddr = %s\nport=%d", fd, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); - // TODO: Optimize this - jbyte *body = (*env).GetByteArrayElements((_jbyteArray *)buf, 0); - char * bufp = (char *)malloc(sizeof(char)*len); - memcpy(bufp, body, len); - (*env).ReleaseByteArrayElements((_jbyteArray *)buf, body, 0); - // "connect" and send buffer contents - int sent_bytes = zts_sendto(fd, body, len, flags, (struct sockaddr *)&addr, sizeof(addr)); - return sent_bytes; - } + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1sendto( + JNIEnv *env, jobject thisObj, jint fd, jarray buf, jint len, jint flags, jobject ztaddr) + { + struct sockaddr_in addr; + jclass cls = (*env).GetObjectClass( ztaddr); + jfieldID f = (*env).GetFieldID( cls, "port", "I"); + addr.sin_port = htons((*env).GetIntField( ztaddr, f)); + f = (*env).GetFieldID( cls, "_rawAddr", "J"); + addr.sin_addr.s_addr = (*env).GetLongField( ztaddr, f); + addr.sin_family = AF_INET; + //LOGV("zt_sendto(): fd = %d\naddr = %s\nport=%d", fd, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); + // TODO: Optimize this + jbyte *body = (*env).GetByteArrayElements((_jbyteArray *)buf, 0); + char * bufp = (char *)malloc(sizeof(char)*len); + memcpy(bufp, body, len); + (*env).ReleaseByteArrayElements((_jbyteArray *)buf, body, 0); + // "connect" and send buffer contents + int sent_bytes = zts_sendto(fd, body, len, flags, (struct sockaddr *)&addr, sizeof(addr)); + return sent_bytes; + } - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1recvfrom( - JNIEnv *env, jobject thisObj, jint fd, jbyteArray buf, jint len, jint flags, jobject ztaddr) - { - struct sockaddr_in addr; - jbyte *body = (*env).GetByteArrayElements( buf, 0); - unsigned char buffer[ZT_SDK_MTU]; - int payload_offset = sizeof(int) + sizeof(struct sockaddr_storage); - int rxbytes = zts_recvfrom(fd, &buffer, len, flags, (struct sockaddr *)&addr, (socklen_t *)sizeof(struct sockaddr_storage)); - if(rxbytes > 0) - memcpy(body, (jbyte*)buffer + payload_offset, rxbytes); - (*env).ReleaseByteArrayElements( buf, body, 0); - // Update fields of Java ZTAddress object - jfieldID fid; - jclass cls = (*env).GetObjectClass( ztaddr); - fid = (*env).GetFieldID( cls, "port", "I"); - (*env).SetIntField( ztaddr, fid, addr.sin_port); - fid = (*env).GetFieldID( cls,"_rawAddr", "J"); - (*env).SetLongField( ztaddr, fid,addr.sin_addr.s_addr); - return rxbytes; - } + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1recvfrom( + JNIEnv *env, jobject thisObj, jint fd, jbyteArray buf, jint len, jint flags, jobject ztaddr) + { + struct sockaddr_in addr; + jbyte *body = (*env).GetByteArrayElements( buf, 0); + unsigned char buffer[ZT_SDK_MTU]; + int payload_offset = sizeof(int) + sizeof(struct sockaddr_storage); + int rxbytes = zts_recvfrom(fd, &buffer, len, flags, (struct sockaddr *)&addr, (socklen_t *)sizeof(struct sockaddr_storage)); + if(rxbytes > 0) + memcpy(body, (jbyte*)buffer + payload_offset, rxbytes); + (*env).ReleaseByteArrayElements( buf, body, 0); + // Update fields of Java ZTAddress object + jfieldID fid; + jclass cls = (*env).GetObjectClass( ztaddr); + fid = (*env).GetFieldID( cls, "port", "I"); + (*env).SetIntField( ztaddr, fid, addr.sin_port); + fid = (*env).GetFieldID( cls,"_rawAddr", "J"); + (*env).SetLongField( ztaddr, fid,addr.sin_addr.s_addr); + return rxbytes; + } - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1write(JNIEnv *env, jobject thisObj, jint fd, jarray buf, jint len) - { - jbyte *body = (*env).GetByteArrayElements((_jbyteArray *)buf, 0); - char * bufp = (char *)malloc(sizeof(char)*len); - memcpy(bufp, body, len); - (*env).ReleaseByteArrayElements((_jbyteArray *)buf, body, 0); - int written_bytes = zts_write(fd, body, len); - return written_bytes; - } + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1write(JNIEnv *env, jobject thisObj, jint fd, jarray buf, jint len) + { + jbyte *body = (*env).GetByteArrayElements((_jbyteArray *)buf, 0); + char * bufp = (char *)malloc(sizeof(char)*len); + memcpy(bufp, body, len); + (*env).ReleaseByteArrayElements((_jbyteArray *)buf, body, 0); + int written_bytes = zts_write(fd, body, len); + return written_bytes; + } - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1read(JNIEnv *env, jobject thisObj, jint fd, jarray buf, jint len) - { - jbyte *body = (*env).GetByteArrayElements((_jbyteArray *)buf, 0); - int read_bytes = read(fd, body, len); - (*env).ReleaseByteArrayElements((_jbyteArray *)buf, body, 0); - return read_bytes; - } + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1read(JNIEnv *env, jobject thisObj, jint fd, jarray buf, jint len) + { + jbyte *body = (*env).GetByteArrayElements((_jbyteArray *)buf, 0); + int read_bytes = read(fd, body, len); + (*env).ReleaseByteArrayElements((_jbyteArray *)buf, body, 0); + return read_bytes; + } - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1setsockopt( - JNIEnv *env, jobject thisObj, jint fd, jint level, jint optname, jint optval, jint optlen) { - return zts_setsockopt(fd, level, optname, (const void*)optval, optlen); - } + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1setsockopt( + JNIEnv *env, jobject thisObj, jint fd, jint level, jint optname, jint optval, jint optlen) { + return zts_setsockopt(fd, level, optname, (const void*)optval, optlen); + } - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1getsockopt(JNIEnv *env, jobject thisObj, jint fd, jint level, jint optname, jint optval, jint optlen) { - return zts_getsockopt(fd, level, optname, (void*)optval, (socklen_t *)optlen); - } + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1getsockopt(JNIEnv *env, jobject thisObj, jint fd, jint level, jint optname, jint optval, jint optlen) { + return zts_getsockopt(fd, level, optname, (void*)optval, (socklen_t *)optlen); + } - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1socket(JNIEnv *env, jobject thisObj, jint family, jint type, jint protocol) { - return zts_socket(family, type, protocol); - } - - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1connect(JNIEnv *env, jobject thisObj, jint fd, jstring addrstr, jint port) { - struct sockaddr_in addr; - const char *str = (*env).GetStringUTFChars( addrstr, 0); - addr.sin_addr.s_addr = inet_addr(str); - addr.sin_family = AF_INET; - addr.sin_port = htons( port ); - (*env).ReleaseStringUTFChars( addrstr, str); - return zts_connect(fd, (struct sockaddr *)&addr, sizeof(addr)); - } + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1socket(JNIEnv *env, jobject thisObj, jint family, jint type, jint protocol) { + return zts_socket(family, type, protocol); + } + + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1connect(JNIEnv *env, jobject thisObj, jint fd, jstring addrstr, jint port) { + struct sockaddr_in addr; + const char *str = (*env).GetStringUTFChars( addrstr, 0); + addr.sin_addr.s_addr = inet_addr(str); + addr.sin_family = AF_INET; + addr.sin_port = htons( port ); + (*env).ReleaseStringUTFChars( addrstr, str); + return zts_connect(fd, (struct sockaddr *)&addr, sizeof(addr)); + } - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1bind(JNIEnv *env, jobject thisObj, jint fd, jstring addrstr, jint port) { - struct sockaddr_in addr; - const char *str = (*env).GetStringUTFChars( addrstr, 0); - DEBUG_INFO("fd=%d, addr=%s, port=%d", fd, str, port); - addr.sin_addr.s_addr = inet_addr(str); - addr.sin_family = AF_INET; - addr.sin_port = htons( port ); - (*env).ReleaseStringUTFChars( addrstr, str); - return zts_bind(fd, (struct sockaddr *)&addr, sizeof(addr)); - } + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1bind(JNIEnv *env, jobject thisObj, jint fd, jstring addrstr, jint port) { + struct sockaddr_in addr; + const char *str = (*env).GetStringUTFChars( addrstr, 0); + DEBUG_INFO("fd=%d, addr=%s, port=%d", fd, str, port); + addr.sin_addr.s_addr = inet_addr(str); + addr.sin_family = AF_INET; + addr.sin_port = htons( port ); + (*env).ReleaseStringUTFChars( addrstr, str); + return zts_bind(fd, (struct sockaddr *)&addr, sizeof(addr)); + } #if defined(__linux__) - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1accept4(JNIEnv *env, jobject thisObj, jint fd, jstring addrstr, jint port, jint flags) { - struct sockaddr_in addr; - char *str; - // = env->GetStringUTFChars(addrstr, NULL); - (*env).ReleaseStringUTFChars( addrstr, str); - addr.sin_addr.s_addr = inet_addr(str); - addr.sin_family = AF_INET; - addr.sin_port = htons( port ); - return zts_accept4(fd, (struct sockaddr *)&addr, sizeof(addr), flags); - } + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1accept4(JNIEnv *env, jobject thisObj, jint fd, jstring addrstr, jint port, jint flags) { + struct sockaddr_in addr; + char *str; + // = env->GetStringUTFChars(addrstr, NULL); + (*env).ReleaseStringUTFChars( addrstr, str); + addr.sin_addr.s_addr = inet_addr(str); + addr.sin_family = AF_INET; + addr.sin_port = htons( port ); + return zts_accept4(fd, (struct sockaddr *)&addr, sizeof(addr), flags); + } #endif - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1accept(JNIEnv *env, jobject thisObj, jint fd, jstring addrstr, jint port) { - struct sockaddr_in addr; - // TODO: Send addr info back to Javaland - addr.sin_addr.s_addr = inet_addr(""); - addr.sin_family = AF_INET; - addr.sin_port = htons( port ); - return zts_accept(fd, (struct sockaddr *)&addr, (socklen_t *)sizeof(addr)); - } + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1accept(JNIEnv *env, jobject thisObj, jint fd, jstring addrstr, jint port) { + struct sockaddr_in addr; + // TODO: Send addr info back to Javaland + addr.sin_addr.s_addr = inet_addr(""); + addr.sin_family = AF_INET; + addr.sin_port = htons( port ); + return zts_accept(fd, (struct sockaddr *)&addr, (socklen_t *)sizeof(addr)); + } - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1listen(JNIEnv *env, jobject thisObj, jint fd, int backlog) { - return zts_listen(fd, backlog); - } + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1listen(JNIEnv *env, jobject thisObj, jint fd, int backlog) { + return zts_listen(fd, backlog); + } - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1close(JNIEnv *env, jobject thisObj, jint fd) { - return zts_close(fd); - } + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1close(JNIEnv *env, jobject thisObj, jint fd) { + return zts_close(fd); + } - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1getsockname(JNIEnv *env, jobject thisObj, jint fd, jobject ztaddr) { - struct sockaddr_in addr; - int err = zts_getsockname(fd, (struct sockaddr *)&addr, (socklen_t *)sizeof(struct sockaddr)); - jfieldID fid; - jclass cls = (*env).GetObjectClass(ztaddr); - fid = (*env).GetFieldID( cls, "port", "I"); - (*env).SetIntField( ztaddr, fid, addr.sin_port); - fid = (*env).GetFieldID( cls,"_rawAddr", "J"); - (*env).SetLongField( ztaddr, fid,addr.sin_addr.s_addr); - return err; - } + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1getsockname(JNIEnv *env, jobject thisObj, jint fd, jobject ztaddr) { + struct sockaddr_in addr; + int err = zts_getsockname(fd, (struct sockaddr *)&addr, (socklen_t *)sizeof(struct sockaddr)); + jfieldID fid; + jclass cls = (*env).GetObjectClass(ztaddr); + fid = (*env).GetFieldID( cls, "port", "I"); + (*env).SetIntField( ztaddr, fid, addr.sin_port); + fid = (*env).GetFieldID( cls,"_rawAddr", "J"); + (*env).SetLongField( ztaddr, fid,addr.sin_addr.s_addr); + return err; + } - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1getpeername(JNIEnv *env, jobject thisObj, jint fd, jobject ztaddr) { - struct sockaddr_in addr; - int err = zts_getpeername(fd, (struct sockaddr *)&addr, (socklen_t *)sizeof(struct sockaddr)); - jfieldID fid; - jclass cls = (*env).GetObjectClass( ztaddr); - fid = (*env).GetFieldID( cls, "port", "I"); - (*env).SetIntField( ztaddr, fid, addr.sin_port); - fid = (*env).GetFieldID( cls,"_rawAddr", "J"); - (*env).SetLongField( ztaddr, fid,addr.sin_addr.s_addr); - return err; - } + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1getpeername(JNIEnv *env, jobject thisObj, jint fd, jobject ztaddr) { + struct sockaddr_in addr; + int err = zts_getpeername(fd, (struct sockaddr *)&addr, (socklen_t *)sizeof(struct sockaddr)); + jfieldID fid; + jclass cls = (*env).GetObjectClass( ztaddr); + fid = (*env).GetFieldID( cls, "port", "I"); + (*env).SetIntField( ztaddr, fid, addr.sin_port); + fid = (*env).GetFieldID( cls,"_rawAddr", "J"); + (*env).SetLongField( ztaddr, fid,addr.sin_addr.s_addr); + return err; + } - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1fcntl(JNIEnv *env, jobject thisObj, jint fd, jint cmd, jint flags) { - return zts_fcntl(fd,cmd,flags); - } + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1fcntl(JNIEnv *env, jobject thisObj, jint fd, jint cmd, jint flags) { + return zts_fcntl(fd,cmd,flags); + } } #endif @@ -1658,58 +1658,58 @@ namespace ZeroTier { #if defined(STACK_PICO) int zts_get_pico_socket(int fd, struct pico_socket **s) { - int err = 0; - if(!zt1Service) { - DEBUG_ERROR("cannot locate socket. service not started. call zts_start(path) first"); - errno = EBADF; - err = -1; - } - else - { - ZeroTier::_multiplexer_lock.lock(); - // First, look for for unassigned connections - ZeroTier::Connection *conn = ZeroTier::unmap[fd]; - if(conn) - { - *s = conn->picosock; - err = 1; // unassigned - } - else - { - std::pair *p = ZeroTier::fdmap[fd]; - if(!p) - { - DEBUG_ERROR("unable to locate connection pair."); - errno = EBADF; - err = -1; - } - else - { - *s = p->first->picosock; - err = 0; // assigned - } - } - ZeroTier::_multiplexer_lock.unlock(); - } - return err; + int err = 0; + if(!zt1Service) { + DEBUG_ERROR("cannot locate socket. service not started. call zts_start(path) first"); + errno = EBADF; + err = -1; + } + else + { + ZeroTier::_multiplexer_lock.lock(); + // First, look for for unassigned connections + ZeroTier::Connection *conn = ZeroTier::unmap[fd]; + if(conn) + { + *s = conn->picosock; + err = 1; // unassigned + } + else + { + std::pair *p = ZeroTier::fdmap[fd]; + if(!p) + { + DEBUG_ERROR("unable to locate connection pair."); + errno = EBADF; + err = -1; + } + else + { + *s = p->first->picosock; + err = 0; // assigned + } + } + ZeroTier::_multiplexer_lock.unlock(); + } + return err; } #endif int zts_nsockets() { - ZeroTier::_multiplexer_lock.unlock(); - int num = ZeroTier::unmap.size() + ZeroTier::fdmap.size(); - ZeroTier::_multiplexer_lock.unlock(); - return num; + ZeroTier::_multiplexer_lock.unlock(); + int num = ZeroTier::unmap.size() + ZeroTier::fdmap.size(); + ZeroTier::_multiplexer_lock.unlock(); + return num; } int zts_maxsockets() { #if defined(STACK_PICO) - // TODO: This is only an approximation - return PICO_MAX_TIMERS - 10; + // TODO: This is only an approximation + return PICO_MAX_TIMERS - 10; #endif - return 32; + return 32; } /****************************************************************************/ @@ -1718,149 +1718,149 @@ int zts_maxsockets() ZeroTier::SocketTap *getTapByNWID(uint64_t nwid) { - ZeroTier::_vtaps_lock.lock(); - ZeroTier::SocketTap *s, *tap = nullptr; - for(int i=0; i_nwid == nwid) { tap = s; } - } - ZeroTier::_vtaps_lock.unlock(); - return tap; + ZeroTier::_vtaps_lock.lock(); + ZeroTier::SocketTap *s, *tap = nullptr; + for(int i=0; i_nwid == nwid) { tap = s; } + } + ZeroTier::_vtaps_lock.unlock(); + return tap; } ZeroTier::SocketTap *getTapByAddr(ZeroTier::InetAddress &addr) { - ZeroTier::_vtaps_lock.lock(); - ZeroTier::SocketTap *s, *tap = nullptr; - for(int i=0; i_ips.size(); j++) { - if(s->_ips[j].isEqualPrefix(addr) - || s->_ips[j].ipsEqual(addr) - || s->_ips[j].containsAddress(addr)) - { - tap = s; - } - } - } - ZeroTier::_vtaps_lock.unlock(); - return tap; + ZeroTier::_vtaps_lock.lock(); + ZeroTier::SocketTap *s, *tap = nullptr; + for(int i=0; i_ips.size(); j++) { + if(s->_ips[j].isEqualPrefix(addr) + || s->_ips[j].ipsEqual(addr) + || s->_ips[j].containsAddress(addr)) + { + tap = s; + } + } + } + ZeroTier::_vtaps_lock.unlock(); + return tap; } ZeroTier::SocketTap *getTapByName(char *ifname) { - ZeroTier::_vtaps_lock.lock(); - ZeroTier::SocketTap *s, *tap = nullptr; - for(int i=0; i_dev.c_str(), ifname)) { - tap = s; - } - } - ZeroTier::_vtaps_lock.unlock(); - return tap; + ZeroTier::_vtaps_lock.lock(); + ZeroTier::SocketTap *s, *tap = nullptr; + for(int i=0; i_dev.c_str(), ifname)) { + tap = s; + } + } + ZeroTier::_vtaps_lock.unlock(); + return tap; } ZeroTier::SocketTap *getTapByIndex(int index) { - ZeroTier::_vtaps_lock.lock(); - ZeroTier::SocketTap *s, *tap = nullptr; - for(int i=0; iifindex == index) { - tap = s; - } - } - ZeroTier::_vtaps_lock.unlock(); - return tap; + ZeroTier::_vtaps_lock.lock(); + ZeroTier::SocketTap *s, *tap = nullptr; + for(int i=0; iifindex == index) { + tap = s; + } + } + ZeroTier::_vtaps_lock.unlock(); + return tap; } void dismantleTaps() { - ZeroTier::_vtaps_lock.lock(); - for(int i=0; i hpsp(ZeroTier::OSUtils::split(ZeroTier::homeDir.c_str(), - ZT_PATH_SEPARATOR_S,"","")); - std::string ptmp; - if (ZeroTier::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)) { - DEBUG_ERROR("home path does not exist, and could not create"); - handle_general_failure(); - perror("error\n"); - } - } - } - } - else { - DEBUG_ERROR("homeDir is empty, could not construct path"); - handle_general_failure(); - return NULL; - } + DEBUG_INFO("homeDir=%s", ZeroTier::homeDir.c_str()); + // Where network .conf files will be stored + ZeroTier::netDir = ZeroTier::homeDir + "/networks.d"; + zt1Service = (ZeroTier::OneService *)0; + + // Construct path for network config and supporting service files + if (ZeroTier::homeDir.length()) { + std::vector hpsp(ZeroTier::OSUtils::split(ZeroTier::homeDir.c_str(), + ZT_PATH_SEPARATOR_S,"","")); + std::string ptmp; + if (ZeroTier::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)) { + DEBUG_ERROR("home path does not exist, and could not create"); + handle_general_failure(); + perror("error\n"); + } + } + } + } + else { + DEBUG_ERROR("homeDir is empty, could not construct path"); + handle_general_failure(); + return NULL; + } - // Generate random port for new service instance - unsigned int randp = 0; - ZeroTier::Utils::getSecureRandom(&randp,sizeof(randp)); - // TODO: Better port random range selection - int servicePort = 9000 + (randp % 1000); + // Generate random port for new service instance + unsigned int randp = 0; + ZeroTier::Utils::getSecureRandom(&randp,sizeof(randp)); + // TODO: Better port random range selection + int servicePort = 9000 + (randp % 1000); - for(;;) { - zt1Service = ZeroTier::OneService::newInstance(ZeroTier::homeDir.c_str(),servicePort); - switch(zt1Service->run()) { - case ZeroTier::OneService::ONE_STILL_RUNNING: - case ZeroTier::OneService::ONE_NORMAL_TERMINATION: - break; - case ZeroTier::OneService::ONE_UNRECOVERABLE_ERROR: - DEBUG_ERROR("fatal error: %s",zt1Service->fatalErrorMessage().c_str()); - break; - case ZeroTier::OneService::ONE_IDENTITY_COLLISION: { - delete zt1Service; - zt1Service = (ZeroTier::OneService *)0; - std::string oldid; - ZeroTier::OSUtils::readFile((ZeroTier::homeDir + ZT_PATH_SEPARATOR_S - + "identity.secret").c_str(),oldid); - if (oldid.length()) { - ZeroTier::OSUtils::writeFile((ZeroTier::homeDir + ZT_PATH_SEPARATOR_S - + "identity.secret.saved_after_collision").c_str(),oldid); - ZeroTier::OSUtils::rm((ZeroTier::homeDir + ZT_PATH_SEPARATOR_S - + "identity.secret").c_str()); - ZeroTier::OSUtils::rm((ZeroTier::homeDir + ZT_PATH_SEPARATOR_S - + "identity.public").c_str()); - } - } - continue; // restart! - } - break; // terminate loop -- normally we don't keep restarting - } - delete zt1Service; - zt1Service = (ZeroTier::OneService *)0; - return NULL; + for(;;) { + zt1Service = ZeroTier::OneService::newInstance(ZeroTier::homeDir.c_str(),servicePort); + switch(zt1Service->run()) { + case ZeroTier::OneService::ONE_STILL_RUNNING: + case ZeroTier::OneService::ONE_NORMAL_TERMINATION: + break; + case ZeroTier::OneService::ONE_UNRECOVERABLE_ERROR: + DEBUG_ERROR("fatal error: %s",zt1Service->fatalErrorMessage().c_str()); + break; + case ZeroTier::OneService::ONE_IDENTITY_COLLISION: { + delete zt1Service; + zt1Service = (ZeroTier::OneService *)0; + std::string oldid; + ZeroTier::OSUtils::readFile((ZeroTier::homeDir + ZT_PATH_SEPARATOR_S + + "identity.secret").c_str(),oldid); + if (oldid.length()) { + ZeroTier::OSUtils::writeFile((ZeroTier::homeDir + ZT_PATH_SEPARATOR_S + + "identity.secret.saved_after_collision").c_str(),oldid); + ZeroTier::OSUtils::rm((ZeroTier::homeDir + ZT_PATH_SEPARATOR_S + + "identity.secret").c_str()); + ZeroTier::OSUtils::rm((ZeroTier::homeDir + ZT_PATH_SEPARATOR_S + + "identity.public").c_str()); + } + } + continue; // restart! + } + break; // terminate loop -- normally we don't keep restarting + } + delete zt1Service; + zt1Service = (ZeroTier::OneService *)0; + return NULL; } void handle_general_failure() { #ifdef ZT_EXIT_ON_GENERAL_FAIL - DEBUG_ERROR("exiting (ZT_EXIT_ON_GENERAL_FAIL==1)"); - //exit(-1); + DEBUG_ERROR("exiting (ZT_EXIT_ON_GENERAL_FAIL==1)"); + //exit(-1); #endif } diff --git a/src/lwIP.cpp b/src/lwIP.cpp index 8e107ac..72df2fe 100644 --- a/src/lwIP.cpp +++ b/src/lwIP.cpp @@ -42,352 +42,352 @@ err_t tapif_init(struct netif *netif) err_t low_level_output(struct netif *netif, struct pbuf *p) { - DEBUG_INFO(); - struct pbuf *q; - char buf[ZT_MAX_MTU+32]; - char *bufptr; - int totalLength = 0; + DEBUG_INFO(); + struct pbuf *q; + char buf[ZT_MAX_MTU+32]; + char *bufptr; + int totalLength = 0; - ZeroTier::SocketTap *tap = (ZeroTier::SocketTap*)netif->state; - bufptr = buf; - // Copy data from each pbuf, one at a time - for(q = p; q != NULL; q = q->next) { - memcpy(bufptr, q->payload, q->len); - bufptr += q->len; - totalLength += q->len; - } - // Split ethernet header and feed into handler - struct eth_hdr *ethhdr; - ethhdr = (struct eth_hdr *)buf; + ZeroTier::SocketTap *tap = (ZeroTier::SocketTap*)netif->state; + bufptr = buf; + // Copy data from each pbuf, one at a time + for(q = p; q != NULL; q = q->next) { + memcpy(bufptr, q->payload, q->len); + bufptr += q->len; + totalLength += q->len; + } + // Split ethernet header and feed into handler + struct eth_hdr *ethhdr; + ethhdr = (struct eth_hdr *)buf; - ZeroTier::MAC src_mac; - ZeroTier::MAC dest_mac; - src_mac.setTo(ethhdr->src.addr, 6); - dest_mac.setTo(ethhdr->dest.addr, 6); + ZeroTier::MAC src_mac; + ZeroTier::MAC dest_mac; + src_mac.setTo(ethhdr->src.addr, 6); + dest_mac.setTo(ethhdr->dest.addr, 6); - tap->_handler(tap->_arg,NULL,tap->_nwid,src_mac,dest_mac, - ZeroTier::Utils::ntoh((uint16_t)ethhdr->type),0,buf + sizeof(struct eth_hdr),totalLength - sizeof(struct eth_hdr)); - return ERR_OK; + tap->_handler(tap->_arg,NULL,tap->_nwid,src_mac,dest_mac, + ZeroTier::Utils::ntoh((uint16_t)ethhdr->type),0,buf + sizeof(struct eth_hdr),totalLength - sizeof(struct eth_hdr)); + return ERR_OK; } namespace ZeroTier { - void lwIP::lwip_init_interface(SocketTap *tap, const InetAddress &ip) - { - DEBUG_INFO(); - Mutex::Lock _l(tap->_ips_m); + void lwIP::lwip_init_interface(SocketTap *tap, const InetAddress &ip) + { + DEBUG_INFO(); + Mutex::Lock _l(tap->_ips_m); - if (std::find(tap->_ips.begin(),tap->_ips.end(),ip) == tap->_ips.end()) { - tap->_ips.push_back(ip); - std::sort(tap->_ips.begin(),tap->_ips.end()); + if (std::find(tap->_ips.begin(),tap->_ips.end(),ip) == tap->_ips.end()) { + tap->_ips.push_back(ip); + std::sort(tap->_ips.begin(),tap->_ips.end()); #if defined(LIBZT_IPV4) - if (ip.isV4()) { - // Set IP - static ip_addr_t ipaddr, netmask, gw; - IP4_ADDR(&gw,127,0,0,1); - ipaddr.addr = *((u32_t *)ip.rawIpData()); - netmask.addr = *((u32_t *)ip.netmask().rawIpData()); - netif_add(&(tap->lwipdev),&ipaddr, &netmask, &gw, NULL, tapif_init, ethernet_input); - tap->lwipdev.state = tap; - tap->lwipdev.output = etharp_output; - tap->_mac.copyTo(tap->lwipdev.hwaddr, 6); - tap->lwipdev.mtu = tap->_mtu; - tap->lwipdev.name[0] = 'l'; - tap->lwipdev.name[1] = '4'; - tap->lwipdev.linkoutput = low_level_output; - tap->lwipdev.hwaddr_len = 6; - tap->lwipdev.flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_IGMP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP; - netif_set_default(&(tap->lwipdev)); - netif_set_up(&(tap->lwipdev)); - DEBUG_INFO("addr=%s, netmask=%s", ip.toString().c_str(), ip.netmask().toString().c_str()); - } + if (ip.isV4()) { + // Set IP + static ip_addr_t ipaddr, netmask, gw; + IP4_ADDR(&gw,127,0,0,1); + ipaddr.addr = *((u32_t *)ip.rawIpData()); + netmask.addr = *((u32_t *)ip.netmask().rawIpData()); + netif_add(&(tap->lwipdev),&ipaddr, &netmask, &gw, NULL, tapif_init, ethernet_input); + tap->lwipdev.state = tap; + tap->lwipdev.output = etharp_output; + tap->_mac.copyTo(tap->lwipdev.hwaddr, 6); + tap->lwipdev.mtu = tap->_mtu; + tap->lwipdev.name[0] = 'l'; + tap->lwipdev.name[1] = '4'; + tap->lwipdev.linkoutput = low_level_output; + tap->lwipdev.hwaddr_len = 6; + tap->lwipdev.flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_IGMP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP; + netif_set_default(&(tap->lwipdev)); + netif_set_up(&(tap->lwipdev)); + DEBUG_INFO("addr=%s, netmask=%s", ip.toString().c_str(), ip.netmask().toString().c_str()); + } #endif #if defined(LIBZT_IPV6) - if(ip.isV6()) { - DEBUG_INFO("local_addr=%s", ip.toString().c_str()); - static ip6_addr_t addr6; - struct sockaddr_in6 in6; - memcpy(in6.sin6_addr.s6_addr,ip.rawIpData(),16); - in6_to_ip6((ip6_addr *)&addr6, &in6); - tap->lwipdev6.mtu = tap->_mtu; - tap->lwipdev6.name[0] = 'l'; - tap->lwipdev6.name[1] = '6'; - tap->lwipdev6.hwaddr_len = 6; - tap->lwipdev6.linkoutput = low_level_output; - tap->lwipdev6.ip6_autoconfig_enabled = 1; - tap->_mac.copyTo(tap->lwipdev6.hwaddr, tap->lwipdev6.hwaddr_len); - netif_create_ip6_linklocal_address(&(tap->lwipdev6), 1); - netif_add(&(tap->lwipdev6), NULL, tapif_init, ethernet_input); - netif_set_default(&(tap->lwipdev6)); - netif_set_up(&(tap->lwipdev6)); - netif_ip6_addr_set_state(&(tap->lwipdev6), 1, IP6_ADDR_TENTATIVE); - ip6_addr_copy(ip_2_ip6(tap->lwipdev6.ip6_addr[1]), addr6); - tap->lwipdev6.output_ip6 = ethip6_output; - tap->lwipdev6.state = tap; - tap->lwipdev6.flags = NETIF_FLAG_LINK_UP | NETIF_FLAG_UP; - DEBUG_INFO("addr=%s, netmask=%s", ip.toString().c_str(), ip.netmask().toString().c_str()); - } + if(ip.isV6()) { + DEBUG_INFO("local_addr=%s", ip.toString().c_str()); + static ip6_addr_t addr6; + struct sockaddr_in6 in6; + memcpy(in6.sin6_addr.s6_addr,ip.rawIpData(),16); + in6_to_ip6((ip6_addr *)&addr6, &in6); + tap->lwipdev6.mtu = tap->_mtu; + tap->lwipdev6.name[0] = 'l'; + tap->lwipdev6.name[1] = '6'; + tap->lwipdev6.hwaddr_len = 6; + tap->lwipdev6.linkoutput = low_level_output; + tap->lwipdev6.ip6_autoconfig_enabled = 1; + tap->_mac.copyTo(tap->lwipdev6.hwaddr, tap->lwipdev6.hwaddr_len); + netif_create_ip6_linklocal_address(&(tap->lwipdev6), 1); + netif_add(&(tap->lwipdev6), NULL, tapif_init, ethernet_input); + netif_set_default(&(tap->lwipdev6)); + netif_set_up(&(tap->lwipdev6)); + netif_ip6_addr_set_state(&(tap->lwipdev6), 1, IP6_ADDR_TENTATIVE); + ip6_addr_copy(ip_2_ip6(tap->lwipdev6.ip6_addr[1]), addr6); + tap->lwipdev6.output_ip6 = ethip6_output; + tap->lwipdev6.state = tap; + tap->lwipdev6.flags = NETIF_FLAG_LINK_UP | NETIF_FLAG_UP; + DEBUG_INFO("addr=%s, netmask=%s", ip.toString().c_str(), ip.netmask().toString().c_str()); + } #endif - } - } + } + } - void lwIP::lwip_loop(SocketTap *tap) - { - DEBUG_INFO(); - uint64_t prev_tcp_time = 0, prev_status_time = 0, prev_discovery_time = 0; - while(tap->_run) - { - uint64_t now = OSUtils::now(); - uint64_t since_tcp = now - prev_tcp_time; - uint64_t since_discovery = now - prev_discovery_time; - uint64_t since_status = now - prev_status_time; - uint64_t tcp_remaining = LWIP_TCP_TIMER_INTERVAL; - uint64_t discovery_remaining = 5000; + void lwIP::lwip_loop(SocketTap *tap) + { + DEBUG_INFO(); + uint64_t prev_tcp_time = 0, prev_status_time = 0, prev_discovery_time = 0; + while(tap->_run) + { + uint64_t now = OSUtils::now(); + uint64_t since_tcp = now - prev_tcp_time; + uint64_t since_discovery = now - prev_discovery_time; + uint64_t since_status = now - prev_status_time; + uint64_t tcp_remaining = LWIP_TCP_TIMER_INTERVAL; + uint64_t discovery_remaining = 5000; #if defined(LIBZT_IPV6) - #define DISCOVERY_INTERVAL 1000 + #define DISCOVERY_INTERVAL 1000 #elif defined(LIBZT_IPV4) - #define DISCOVERY_INTERVAL ARP_TMR_INTERVAL + #define DISCOVERY_INTERVAL ARP_TMR_INTERVAL #endif - // Main TCP/ETHARP timer section - if (since_tcp >= LWIP_TCP_TIMER_INTERVAL) { - prev_tcp_time = now; - tcp_tmr(); - } - else { - tcp_remaining = LWIP_TCP_TIMER_INTERVAL - since_tcp; - } - if (since_discovery >= DISCOVERY_INTERVAL) { - prev_discovery_time = now; + // Main TCP/ETHARP timer section + if (since_tcp >= LWIP_TCP_TIMER_INTERVAL) { + prev_tcp_time = now; + tcp_tmr(); + } + else { + tcp_remaining = LWIP_TCP_TIMER_INTERVAL - since_tcp; + } + if (since_discovery >= DISCOVERY_INTERVAL) { + prev_discovery_time = now; #if defined(LIBZT_IPV4) - etharp_tmr(); + etharp_tmr(); #endif #if defined(LIBZT_IPV6) - nd6_tmr(); + nd6_tmr(); #endif - } else { - discovery_remaining = DISCOVERY_INTERVAL - since_discovery; - } - tap->_phy.poll((unsigned long)std::min(tcp_remaining,discovery_remaining)); - } - } + } else { + discovery_remaining = DISCOVERY_INTERVAL - since_discovery; + } + tap->_phy.poll((unsigned long)std::min(tcp_remaining,discovery_remaining)); + } + } - void lwIP::lwip_rx(SocketTap *tap, const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len) - { - DEBUG_INFO(); - struct pbuf *p,*q; - if (!tap->_enabled) - return; - struct eth_hdr ethhdr; - from.copyTo(ethhdr.src.addr, 6); - to.copyTo(ethhdr.dest.addr, 6); - ethhdr.type = ZeroTier::Utils::hton((uint16_t)etherType); + void lwIP::lwip_rx(SocketTap *tap, const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len) + { + DEBUG_INFO(); + struct pbuf *p,*q; + if (!tap->_enabled) + return; + struct eth_hdr ethhdr; + from.copyTo(ethhdr.src.addr, 6); + to.copyTo(ethhdr.dest.addr, 6); + ethhdr.type = ZeroTier::Utils::hton((uint16_t)etherType); - p = pbuf_alloc(PBUF_RAW, len+sizeof(struct eth_hdr), PBUF_POOL); - if (p != NULL) { - const char *dataptr = reinterpret_cast(data); - // First pbuf gets ethernet header at start - q = p; - if (q->len < sizeof(ethhdr)) { - DEBUG_ERROR("dropped packet: first pbuf smaller than ethernet header"); - return; - } - memcpy(q->payload,ðhdr,sizeof(ethhdr)); - memcpy((char*)q->payload + sizeof(ethhdr),dataptr,q->len - sizeof(ethhdr)); - dataptr += q->len - sizeof(ethhdr); + p = pbuf_alloc(PBUF_RAW, len+sizeof(struct eth_hdr), PBUF_POOL); + if (p != NULL) { + const char *dataptr = reinterpret_cast(data); + // First pbuf gets ethernet header at start + q = p; + if (q->len < sizeof(ethhdr)) { + DEBUG_ERROR("dropped packet: first pbuf smaller than ethernet header"); + return; + } + memcpy(q->payload,ðhdr,sizeof(ethhdr)); + memcpy((char*)q->payload + sizeof(ethhdr),dataptr,q->len - sizeof(ethhdr)); + dataptr += q->len - sizeof(ethhdr); - // Remaining pbufs (if any) get rest of data - while ((q = q->next)) { - memcpy(q->payload,dataptr,q->len); - dataptr += q->len; - } - } - else { - DEBUG_ERROR("dropped packet: no pbufs available"); - return; - } - { + // Remaining pbufs (if any) get rest of data + while ((q = q->next)) { + memcpy(q->payload,dataptr,q->len); + dataptr += q->len; + } + } + else { + DEBUG_ERROR("dropped packet: no pbufs available"); + return; + } + { #if defined(LIBZT_IPV6) - if(tap->lwipdev6.input(p, &(tap->lwipdev6)) != ERR_OK) { - DEBUG_ERROR("error while feeding frame into stack lwipdev6"); - } + if(tap->lwipdev6.input(p, &(tap->lwipdev6)) != ERR_OK) { + DEBUG_ERROR("error while feeding frame into stack lwipdev6"); + } #endif #if defined(LIBZT_IPV4) - if(tap->lwipdev.input(p, &(tap->lwipdev)) != ERR_OK) { - DEBUG_ERROR("error while feeding frame into stack lwipdev"); - } + if(tap->lwipdev.input(p, &(tap->lwipdev)) != ERR_OK) { + DEBUG_ERROR("error while feeding frame into stack lwipdev"); + } #endif - } - } + } + } - int lwIP::lwip_Socket(void **pcb, int socket_family, int socket_type, int protocol) - { - // TODO: check lwIP timers, and max sockets - DEBUG_INFO(); - if(socket_type == SOCK_STREAM) { - struct tcp_pcb *new_tcp_PCB = tcp_new(); - *pcb = new_tcp_PCB; - return ERR_OK; - } - if(socket_type == SOCK_DGRAM) { - struct udp_pcb *new_udp_PCB = udp_new(); - *pcb = new_udp_PCB; - return ERR_OK; - } - if(socket_type == SOCK_RAW) { - DEBUG_ERROR("SOCK_RAW, not currently supported."); - return -1; - } - return -1; - } + int lwIP::lwip_Socket(void **pcb, int socket_family, int socket_type, int protocol) + { + // TODO: check lwIP timers, and max sockets + DEBUG_INFO(); + if(socket_type == SOCK_STREAM) { + struct tcp_pcb *new_tcp_PCB = tcp_new(); + *pcb = new_tcp_PCB; + return ERR_OK; + } + if(socket_type == SOCK_DGRAM) { + struct udp_pcb *new_udp_PCB = udp_new(); + *pcb = new_udp_PCB; + return ERR_OK; + } + if(socket_type == SOCK_RAW) { + DEBUG_ERROR("SOCK_RAW, not currently supported."); + return -1; + } + return -1; + } - int lwIP::lwip_Connect(Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen) - { - DEBUG_INFO(); - } + int lwIP::lwip_Connect(Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen) + { + DEBUG_INFO(); + } - int lwIP::lwip_Bind(SocketTap *tap, Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen) - { - DEBUG_INFO(); - ip_addr_t ba; - char addrstr[INET6_ADDRSTRLEN]; - int port = 0, err = 0; + int lwIP::lwip_Bind(SocketTap *tap, Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen) + { + DEBUG_INFO(); + ip_addr_t ba; + char addrstr[INET6_ADDRSTRLEN]; + int port = 0, err = 0; #if defined(LIBZT_IPV4) - DEBUG_ERROR("A"); - struct sockaddr_in *in4; - if(addr->sa_family == AF_INET) { - DEBUG_ERROR("A"); - in4 = (struct sockaddr_in *)addr; - DEBUG_ERROR("A"); - inet_ntop(AF_INET, &(in4->sin_addr), addrstr, INET_ADDRSTRLEN); - DEBUG_ERROR("A"); - DEBUG_INFO("%s:%d", addrstr, lwip_ntohs(in4->sin_port)); - } - ba = convert_ip(in4); - port = lwip_ntohs(in4->sin_port); - DEBUG_INFO("port=%d", port); - DEBUG_INFO("port=%d", lwip_ntohs(port)); + DEBUG_ERROR("A"); + struct sockaddr_in *in4; + if(addr->sa_family == AF_INET) { + DEBUG_ERROR("A"); + in4 = (struct sockaddr_in *)addr; + DEBUG_ERROR("A"); + inet_ntop(AF_INET, &(in4->sin_addr), addrstr, INET_ADDRSTRLEN); + DEBUG_ERROR("A"); + DEBUG_INFO("%s:%d", addrstr, lwip_ntohs(in4->sin_port)); + } + ba = convert_ip(in4); + port = lwip_ntohs(in4->sin_port); + DEBUG_INFO("port=%d", port); + DEBUG_INFO("port=%d", lwip_ntohs(port)); #endif #if defined(LIBZT_IPV6) - struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&addr; - in6_to_ip6((ip6_addr *)&ba, in6); - if(addr->sa_family == AF_INET6) { - struct sockaddr_in6 *connaddr6 = (struct sockaddr_in6 *)addr; - inet_ntop(AF_INET6, &(connaddr6->sin6_addr), addrstr, INET6_ADDRSTRLEN); - DEBUG_INFO("%s:%d", addrstr, lwip_ntohs(connaddr6->sin6_port)); - } + struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&addr; + in6_to_ip6((ip6_addr *)&ba, in6); + if(addr->sa_family == AF_INET6) { + struct sockaddr_in6 *connaddr6 = (struct sockaddr_in6 *)addr; + inet_ntop(AF_INET6, &(connaddr6->sin6_addr), addrstr, INET6_ADDRSTRLEN); + DEBUG_INFO("%s:%d", addrstr, lwip_ntohs(connaddr6->sin6_port)); + } #endif - if(conn->socket_type == SOCK_DGRAM) { - err = udp_bind((struct udp_pcb*)conn->pcb, (const ip_addr_t *)&ba, port); - if(err == ERR_USE) { - err = -1; - errno = EADDRINUSE; // port in use - } - else { - // set the recv callback - udp_recv((struct udp_pcb*)conn->pcb, nc_udp_recved, new ConnectionPair(tap, conn)); - err = ERR_OK; - errno = ERR_OK; // success - } - } - else if (conn->socket_type == SOCK_STREAM) { - err = tcp_bind((struct tcp_pcb*)conn->pcb, (const ip_addr_t *)&ba, port); - if(err != ERR_OK) { - DEBUG_ERROR("err=%d", err); - if(err == ERR_USE){ - err = -1; - errno = EADDRINUSE; - } - if(err == ERR_MEM){ - err = -1; - errno = ENOMEM; - } - if(err == ERR_BUF){ - err = -1; - errno = ENOMEM; - } - } - else { - err = ERR_OK; - errno = ERR_OK; // success - } - } - return err; - } + if(conn->socket_type == SOCK_DGRAM) { + err = udp_bind((struct udp_pcb*)conn->pcb, (const ip_addr_t *)&ba, port); + if(err == ERR_USE) { + err = -1; + errno = EADDRINUSE; // port in use + } + else { + // set the recv callback + udp_recv((struct udp_pcb*)conn->pcb, nc_udp_recved, new ConnectionPair(tap, conn)); + err = ERR_OK; + errno = ERR_OK; // success + } + } + else if (conn->socket_type == SOCK_STREAM) { + err = tcp_bind((struct tcp_pcb*)conn->pcb, (const ip_addr_t *)&ba, port); + if(err != ERR_OK) { + DEBUG_ERROR("err=%d", err); + if(err == ERR_USE){ + err = -1; + errno = EADDRINUSE; + } + if(err == ERR_MEM){ + err = -1; + errno = ENOMEM; + } + if(err == ERR_BUF){ + err = -1; + errno = ENOMEM; + } + } + else { + err = ERR_OK; + errno = ERR_OK; // success + } + } + return err; + } - int lwIP::lwip_Listen(SocketTap *tap, PhySocket *sock, PhySocket *rpcSock, void **uptr, struct listen_st *listen_rpc) - { - DEBUG_INFO(); - // to be implemented - } + int lwIP::lwip_Listen(SocketTap *tap, PhySocket *sock, PhySocket *rpcSock, void **uptr, struct listen_st *listen_rpc) + { + DEBUG_INFO(); + // to be implemented + } - int lwIP::lwip_Read(SocketTap *tap, PhySocket *sock, void **uptr, bool lwip_invoked) - { - DEBUG_EXTRA(); - // to be implemented - } + int lwIP::lwip_Read(SocketTap *tap, PhySocket *sock, void **uptr, bool lwip_invoked) + { + DEBUG_EXTRA(); + // to be implemented + } - int lwIP::lwip_Write(SocketTap *tap, Connection *conn) - { - DEBUG_EXTRA("conn=%p", (void*)&conn); - // to be implemented - } + int lwIP::lwip_Write(SocketTap *tap, Connection *conn) + { + DEBUG_EXTRA("conn=%p", (void*)&conn); + // to be implemented + } - int lwIP::lwip_Close(SocketTap *tap, PhySocket *sock, Connection *conn) - { - DEBUG_INFO(); - // to be implemented - } + int lwIP::lwip_Close(SocketTap *tap, PhySocket *sock, Connection *conn) + { + DEBUG_INFO(); + // to be implemented + } - /****************************************************************************/ - /* Callbacks from lwIP stack */ - /****************************************************************************/ + /****************************************************************************/ + /* Callbacks from lwIP stack */ + /****************************************************************************/ - err_t lwIP::nc_recved(void *arg, struct tcp_pcb *PCB, struct pbuf *p, err_t err) - { - DEBUG_INFO(); - // to be implemented - return ERR_OK; - } + err_t lwIP::nc_recved(void *arg, struct tcp_pcb *PCB, struct pbuf *p, err_t err) + { + DEBUG_INFO(); + // to be implemented + return ERR_OK; + } - err_t lwIP::nc_accept(void *arg, struct tcp_pcb *newPCB, err_t err) - { - DEBUG_INFO(); - // to be implemented - return -1; - } - - void lwIP::nc_udp_recved(void * arg, struct udp_pcb * upcb, struct pbuf * p, const ip_addr_t * addr, u16_t port) - { - DEBUG_INFO(); - // to be implemented - } - - err_t lwIP::nc_sent(void* arg, struct tcp_pcb *PCB, u16_t len) - { - DEBUG_EXTRA("pcb=%p", (void*)&PCB); - // to be implemented - return ERR_OK; - } - - err_t lwIP::nc_connected(void *arg, struct tcp_pcb *PCB, err_t err) - { - DEBUG_ATTN("pcb=%p", (void*)&PCB); - // to be implemented - return ERR_OK; - } + err_t lwIP::nc_accept(void *arg, struct tcp_pcb *newPCB, err_t err) + { + DEBUG_INFO(); + // to be implemented + return -1; + } + + void lwIP::nc_udp_recved(void * arg, struct udp_pcb * upcb, struct pbuf * p, const ip_addr_t * addr, u16_t port) + { + DEBUG_INFO(); + // to be implemented + } + + err_t lwIP::nc_sent(void* arg, struct tcp_pcb *PCB, u16_t len) + { + DEBUG_EXTRA("pcb=%p", (void*)&PCB); + // to be implemented + return ERR_OK; + } + + err_t lwIP::nc_connected(void *arg, struct tcp_pcb *PCB, err_t err) + { + DEBUG_ATTN("pcb=%p", (void*)&PCB); + // to be implemented + return ERR_OK; + } - err_t lwIP::nc_poll(void* arg, struct tcp_pcb *PCB) - { - DEBUG_INFO(); - // to be implemented - return ERR_OK; - } + err_t lwIP::nc_poll(void* arg, struct tcp_pcb *PCB) + { + DEBUG_INFO(); + // to be implemented + return ERR_OK; + } - void lwIP::nc_err(void *arg, err_t err) - { - DEBUG_INFO(); - // to be implemented - } + void lwIP::nc_err(void *arg, err_t err) + { + DEBUG_INFO(); + // to be implemented + } } diff --git a/src/lwIP.hpp b/src/lwIP.hpp index 42430a0..9cbf556 100644 --- a/src/lwIP.hpp +++ b/src/lwIP.hpp @@ -51,16 +51,16 @@ struct tcp_pcb; struct netif; #if defined(LIBZT_IPV4) - #define LWIP_NETIF_ADD_SIG struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask, ip_addr_t *gw, void *state, netif_init_fn init, netif_input_fn input - #define LWIP_ETHARP_OUTPUT_SIG struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr + #define LWIP_NETIF_ADD_SIG struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask, ip_addr_t *gw, void *state, netif_init_fn init, netif_input_fn input + #define LWIP_ETHARP_OUTPUT_SIG struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr #endif #if defined(LIBZT_IPV6) #include "lwip/ip6_addr.h" - #define LWIP_NETIF_ADD_SIG struct netif *netif, void *state, netif_init_fn init, netif_input_fn input - #define LWIP_ETHIP6_OUTPUT_SIG struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr - #define LWIP_ETHARP_OUTPUT_SIG struct netif *netif, struct pbuf *q, const ip6_addr_t *ipaddr - #define LWIP_NETIF_IP6_ADDR_SET_STATE_SIG struct netif* netif, s8_t addr_idx, u8_t state - #define LWIP_NETIF_CREATE_IP6_LINKLOCAL_ADDRESS_SIG struct netif *netif, u8_t from_mac_48bit + #define LWIP_NETIF_ADD_SIG struct netif *netif, void *state, netif_init_fn init, netif_input_fn input + #define LWIP_ETHIP6_OUTPUT_SIG struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr + #define LWIP_ETHARP_OUTPUT_SIG struct netif *netif, struct pbuf *q, const ip6_addr_t *ipaddr + #define LWIP_NETIF_IP6_ADDR_SET_STATE_SIG struct netif* netif, s8_t addr_idx, u8_t state + #define LWIP_NETIF_CREATE_IP6_LINKLOCAL_ADDRESS_SIG struct netif *netif, u8_t from_mac_48bit #endif #define LWIP_PBUF_FREE_SIG struct pbuf *p @@ -105,13 +105,13 @@ struct netif; #if defined(LIBZT_IPV4) - extern "C" err_t etharp_output(LWIP_ETHARP_OUTPUT_SIG); + extern "C" err_t etharp_output(LWIP_ETHARP_OUTPUT_SIG); #endif #if defined(LIBZT_IPV6) - extern "C" void nd6_tmr(void); - extern "C" void netif_ip6_addr_set_state(LWIP_NETIF_IP6_ADDR_SET_STATE_SIG); - extern "C" void netif_create_ip6_linklocal_address(LWIP_NETIF_CREATE_IP6_LINKLOCAL_ADDRESS_SIG); - extern "C" err_t _ethip6_output(LWIP_ETHIP6_OUTPUT_SIG); + extern "C" void nd6_tmr(void); + extern "C" void netif_ip6_addr_set_state(LWIP_NETIF_IP6_ADDR_SET_STATE_SIG); + extern "C" void netif_create_ip6_linklocal_address(LWIP_NETIF_CREATE_IP6_LINKLOCAL_ADDRESS_SIG); + extern "C" err_t _ethip6_output(LWIP_ETHIP6_OUTPUT_SIG); #endif extern "C" void lwip_init(); @@ -161,45 +161,45 @@ extern "C" err_t ip_input(LWIP_IP_INPUT_SIG); namespace ZeroTier { - - class SocketTap; - struct Connection; + + class SocketTap; + struct Connection; - class lwIP - { - public: + class lwIP + { + public: - /* - * Set up an interface in the network stack for the SocketTap - */ - void lwip_init_interface(SocketTap *tap, const InetAddress &ip); + /* + * Set up an interface in the network stack for the SocketTap + */ + void lwip_init_interface(SocketTap *tap, const InetAddress &ip); - /* - * Main stack loop - */ - void lwip_loop(SocketTap *tap); + /* + * Main stack loop + */ + void lwip_loop(SocketTap *tap); - /* - * Packets from the ZeroTier virtual wire enter the stack here - */ - void lwip_rx(SocketTap *tap, const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len); - - int lwip_Socket(void **pcb, int socket_family, int socket_type, int protocol); - int lwip_Connect(Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen); - int lwip_Bind(SocketTap *tap, Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen); - int lwip_Listen(SocketTap *tap, PhySocket *sock, PhySocket *rpcSock, void **uptr, struct listen_st *listen_rpc); - int lwip_Read(SocketTap *tap, PhySocket *sock, void **uptr, bool lwip_invoked); - int lwip_Write(SocketTap *tap, Connection *conn); - int lwip_Close(SocketTap *tap, PhySocket *sock, Connection *conn); + /* + * Packets from the ZeroTier virtual wire enter the stack here + */ + void lwip_rx(SocketTap *tap, const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len); + + int lwip_Socket(void **pcb, int socket_family, int socket_type, int protocol); + int lwip_Connect(Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen); + int lwip_Bind(SocketTap *tap, Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen); + int lwip_Listen(SocketTap *tap, PhySocket *sock, PhySocket *rpcSock, void **uptr, struct listen_st *listen_rpc); + int lwip_Read(SocketTap *tap, PhySocket *sock, void **uptr, bool lwip_invoked); + int lwip_Write(SocketTap *tap, Connection *conn); + int lwip_Close(SocketTap *tap, PhySocket *sock, Connection *conn); - static err_t nc_recved(void *arg, struct tcp_pcb *PCB, struct pbuf *p, err_t err); - static err_t nc_accept(void *arg, struct tcp_pcb *newPCB, err_t err); - static void nc_udp_recved(void * arg, struct udp_pcb * upcb, struct pbuf * p, const ip_addr_t * addr, u16_t port); - static void nc_err(void *arg, err_t err); - static err_t nc_poll(void* arg, struct tcp_pcb *PCB); - static err_t nc_sent(void *arg, struct tcp_pcb *PCB, u16_t len); - static err_t nc_connected(void *arg, struct tcp_pcb *PCB, err_t err); - }; + static err_t nc_recved(void *arg, struct tcp_pcb *PCB, struct pbuf *p, err_t err); + static err_t nc_accept(void *arg, struct tcp_pcb *newPCB, err_t err); + static void nc_udp_recved(void * arg, struct udp_pcb * upcb, struct pbuf * p, const ip_addr_t * addr, u16_t port); + static void nc_err(void *arg, err_t err); + static err_t nc_poll(void* arg, struct tcp_pcb *PCB); + static err_t nc_sent(void *arg, struct tcp_pcb *PCB, u16_t len); + static err_t nc_connected(void *arg, struct tcp_pcb *PCB, err_t err); + }; } #endif diff --git a/src/picoTCP.cpp b/src/picoTCP.cpp index 65893de..2594c81 100644 --- a/src/picoTCP.cpp +++ b/src/picoTCP.cpp @@ -93,27 +93,27 @@ namespace ZeroTier { if(!tap->picodev_initialized) { picodev.send = pico_eth_send; // tx - picodev.poll = pico_eth_poll; // 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->_dev.c_str(), mac) != 0) { - DEBUG_ERROR("dev init failed"); - handle_general_failure(); - return false; - } + picodev.poll = pico_eth_poll; // 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->_dev.c_str(), mac) != 0) { + DEBUG_ERROR("dev init failed"); + handle_general_failure(); + return false; + } tap->picodev_initialized = true; } 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)); - //DEBUG_INFO("mac = %s", tap->_mac.toString(ipbuf)); - return true; + 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)); + //DEBUG_INFO("mac = %s", tap->_mac.toString(ipbuf)); + return true; } if(ip.isV6()) { @@ -121,12 +121,12 @@ namespace ZeroTier { 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("addr6 = %s", ipv6_str); - //DEBUG_INFO("mac = %s", tap->_mac.toString(ipbuf)); - return true; + 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("addr6 = %s", ipv6_str); + //DEBUG_INFO("mac = %s", tap->_mac.toString(ipbuf)); + return true; } } return false; @@ -137,8 +137,8 @@ namespace ZeroTier { while(tap->_run) { tap->_phy.poll(ZT_PHY_POLL_INTERVAL); - pico_stack_tick(); - //tap->Housekeeping(); + pico_stack_tick(); + //tap->Housekeeping(); } } @@ -149,17 +149,17 @@ namespace ZeroTier { Mutex::Lock _l(conn->_rx_m); if(!conn || !tap) { - DEBUG_ERROR("invalid tap or conn"); - handle_general_failure(); - return; - } + DEBUG_ERROR("invalid tap or conn"); + handle_general_failure(); + return; + } int r, n; uint16_t port = 0; union { - struct pico_ip4 ip4; - struct pico_ip6 ip6; - } peer; + struct pico_ip4 ip4; + struct pico_ip6 ip6; + } peer; do { n = 0; @@ -167,38 +167,38 @@ namespace ZeroTier { int avail = ZT_TCP_RX_BUF_SZ - conn->RXbuf->count(); if(avail) { - r = pico_socket_recvfrom(s, conn->RXbuf->get_buf(), ZT_STACK_SOCKET_RD_MAX, - (void *)&peer.ip4.addr, &port); - - conn->tot += r; + r = pico_socket_recvfrom(s, conn->RXbuf->get_buf(), ZT_STACK_SOCKET_RD_MAX, + (void *)&peer.ip4.addr, &port); + + conn->tot += r; - if (r > 0) - { - conn->RXbuf->produce(r); - //DEBUG_INFO("RXbuf->count() = %d", conn->RXbuf->count()); - n = tap->_phy.streamSend(conn->sock, conn->RXbuf->get_buf(), r); + if (r > 0) + { + conn->RXbuf->produce(r); + //DEBUG_INFO("RXbuf->count() = %d", conn->RXbuf->count()); + n = tap->_phy.streamSend(conn->sock, conn->RXbuf->get_buf(), r); - if(n>0) - conn->RXbuf->consume(n); - //DEBUG_INFO("pico_recv = %d, streamSend = %d, rxsz = %d, tot = %d", r, n, conn->RXbuf->count(), conn->tot); + if(n>0) + conn->RXbuf->consume(n); + //DEBUG_INFO("pico_recv = %d, streamSend = %d, rxsz = %d, tot = %d", r, n, conn->RXbuf->count(), conn->tot); - //DEBUG_TRANS("[ TCP RX <- STACK] :: conn = %p, len = %d", conn, n); - } + //DEBUG_TRANS("[ TCP RX <- STACK] :: conn = %p, len = %d", conn, n); + } - if(conn->RXbuf->count() == 0) { + if(conn->RXbuf->count() == 0) { tap->_phy.setNotifyWritable(conn->sock, false); } else { - tap->_phy.setNotifyWritable(conn->sock, true); + tap->_phy.setNotifyWritable(conn->sock, true); } - } - else { - //tap->_phy.setNotifyWritable(conn->sock, false); - DEBUG_ERROR("not enough space left on I/O RX buffer for pico_socket(%p)", s); - handle_general_failure(); - } - } - while(r > 0); + } + else { + //tap->_phy.setNotifyWritable(conn->sock, false); + DEBUG_ERROR("not enough space left on I/O RX buffer for pico_socket(%p)", s); + handle_general_failure(); + } + } + while(r > 0); } // from stack socket to app socket @@ -212,50 +212,50 @@ namespace ZeroTier { uint16_t port = 0; union { - struct pico_ip4 ip4; - struct pico_ip6 ip6; - } peer; + struct pico_ip4 ip4; + struct pico_ip6 ip6; + } peer; - char tmpbuf[ZT_SDK_MTU]; - unsigned char *addr_pos, *sz_pos, *payload_pos; + char tmpbuf[ZT_SDK_MTU]; + unsigned char *addr_pos, *sz_pos, *payload_pos; struct sockaddr_in addr_in; addr_in.sin_addr.s_addr = peer.ip4.addr; - addr_in.sin_port = port; + addr_in.sin_port = port; - // RX - int r = pico_socket_recvfrom(s, tmpbuf, ZT_SDK_MTU, (void *)&peer.ip4.addr, &port); - //DEBUG_FLOW(" [ RXBUF <- STACK] Receiving (%d) from stack, copying to receving buffer", r); + // RX + int r = pico_socket_recvfrom(s, tmpbuf, ZT_SDK_MTU, (void *)&peer.ip4.addr, &port); + //DEBUG_FLOW(" [ RXBUF <- STACK] Receiving (%d) from stack, copying to receving buffer", r); if(conn->rxsz == ZT_UDP_RX_BUF_SZ) { // if UDP buffer full - //DEBUG_FLOW(" [ RXBUF <- STACK] UDP RX buffer full. Discarding oldest payload segment"); - memmove(conn->rxbuf, conn->rxbuf + ZT_SDK_MTU, ZT_UDP_RX_BUF_SZ - ZT_SDK_MTU); - addr_pos = conn->rxbuf + (ZT_UDP_RX_BUF_SZ - ZT_SDK_MTU); // TODO: - sz_pos = addr_pos + sizeof(struct sockaddr_storage); - conn->rxsz -= ZT_SDK_MTU; - } - else { - addr_pos = conn->rxbuf + conn->rxsz; // where we'll prepend the size of the address - sz_pos = addr_pos + sizeof(struct sockaddr_storage); - } - payload_pos = addr_pos + sizeof(struct sockaddr_storage) + sizeof(r); - memcpy(addr_pos, &addr_in, sizeof(struct sockaddr_storage)); - memcpy(payload_pos, tmpbuf, r); // write payload to app's socket + //DEBUG_FLOW(" [ RXBUF <- STACK] UDP RX buffer full. Discarding oldest payload segment"); + memmove(conn->rxbuf, conn->rxbuf + ZT_SDK_MTU, ZT_UDP_RX_BUF_SZ - ZT_SDK_MTU); + addr_pos = conn->rxbuf + (ZT_UDP_RX_BUF_SZ - ZT_SDK_MTU); // TODO: + sz_pos = addr_pos + sizeof(struct sockaddr_storage); + conn->rxsz -= ZT_SDK_MTU; + } + else { + addr_pos = conn->rxbuf + conn->rxsz; // where we'll prepend the size of the address + sz_pos = addr_pos + sizeof(struct sockaddr_storage); + } + payload_pos = addr_pos + sizeof(struct sockaddr_storage) + sizeof(r); + memcpy(addr_pos, &addr_in, sizeof(struct sockaddr_storage)); + memcpy(payload_pos, tmpbuf, r); // write payload to app's socket - // Adjust buffer size + // Adjust buffer size if(r) { - conn->rxsz += ZT_SDK_MTU; - memcpy(sz_pos, &r, sizeof(r)); - } - if (r < 0) { - DEBUG_ERROR("unable to read from picosock=%p", s); - handle_general_failure(); - } - tap->_rx_buf_m.unlock(); + conn->rxsz += ZT_SDK_MTU; + memcpy(sz_pos, &r, sizeof(r)); + } + if (r < 0) { + DEBUG_ERROR("unable to read from picosock=%p", s); + handle_general_failure(); + } + tap->_rx_buf_m.unlock(); - if(r) - tap->phyOnUnixWritable(conn->sock, NULL, true); - //DEBUG_EXTRA(" Copied onto rxbuf (%d) from stack socket", r); - return; + if(r) + tap->phyOnUnixWritable(conn->sock, NULL, true); + //DEBUG_EXTRA(" Copied onto rxbuf (%d) from stack socket", r); + return; } */ } @@ -263,70 +263,70 @@ namespace ZeroTier { void picoTCP::pico_cb_tcp_write(SocketTap *tap, struct pico_socket *s) { Connection *conn = (Connection*)((ConnectionPair*)(s->priv))->conn; - Mutex::Lock _l(conn->_tx_m); - if(!conn) { + Mutex::Lock _l(conn->_tx_m); + if(!conn) { DEBUG_ERROR("invalid connection"); handle_general_failure(); return; } - int txsz = conn->TXbuf->count(); - if(txsz <= 0) - return; - //DEBUG_INFO("TXbuf->count() = %d", conn->TXbuf->count()); + int txsz = conn->TXbuf->count(); + if(txsz <= 0) + return; + //DEBUG_INFO("TXbuf->count() = %d", conn->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(conn->picosock, conn->TXbuf->get_buf(), max_write_len)) < 0) { - DEBUG_ERROR("unable to write to picosock=%p, r=%d", conn->picosock, r); - handle_general_failure(); - return; - } - if(conn->socket_type == SOCK_STREAM) { - //DEBUG_TRANS("[ TCP TX -> STACK] :: conn = %p, len = %d", conn, r); - } - if(conn->socket_type == SOCK_DGRAM) { - //DEBUG_TRANS("[ UDP TX -> STACK] :: conn = %p, len = %d", conn, r); - } - if(r == 0) { - // This is a peciliarity of the picoTCP network stack, if we receive no error code, and the size of - // the byte stream written is 0, this is an indication that the buffer for this pico_socket is too small - // DEBUG_ERROR("pico_socket buffer is too small (adjust ZT_STACK_SOCKET_TX_SZ, ZT_STACK_SOCKET_RX_SZ)"); - // handle_general_failure(); - } - if(r>0) - conn->TXbuf->consume(r); + if((r = pico_socket_write(conn->picosock, conn->TXbuf->get_buf(), max_write_len)) < 0) { + DEBUG_ERROR("unable to write to picosock=%p, r=%d", conn->picosock, r); + handle_general_failure(); + return; + } + if(conn->socket_type == SOCK_STREAM) { + //DEBUG_TRANS("[ TCP TX -> STACK] :: conn = %p, len = %d", conn, r); + } + if(conn->socket_type == SOCK_DGRAM) { + //DEBUG_TRANS("[ UDP TX -> STACK] :: conn = %p, len = %d", conn, r); + } + if(r == 0) { + // This is a peciliarity of the picoTCP network stack, if we receive no error code, and the size of + // the byte stream written is 0, this is an indication that the buffer for this pico_socket is too small + // DEBUG_ERROR("pico_socket buffer is too small (adjust ZT_STACK_SOCKET_TX_SZ, ZT_STACK_SOCKET_RX_SZ)"); + // handle_general_failure(); + } + if(r>0) + conn->TXbuf->consume(r); } void picoTCP::pico_cb_socket_activity(uint16_t ev, struct pico_socket *s) - { - if(!(SocketTap*)((ConnectionPair*)(s->priv))) - return; - SocketTap *tap = (SocketTap*)((ConnectionPair*)(s->priv))->tap; - Connection *conn = (Connection*)((ConnectionPair*)(s->priv))->conn; - if(!tap || !conn) { - DEBUG_ERROR("invalid tap or conn"); - handle_general_failure(); - return; - } - int err = 0; - if(!conn) { - DEBUG_ERROR("invalid connection"); - handle_general_failure(); - return; - } - // PICO_SOCK_EV_CONN - triggered when connection is established (TCP only). This event is + { + if(!(SocketTap*)((ConnectionPair*)(s->priv))) + return; + SocketTap *tap = (SocketTap*)((ConnectionPair*)(s->priv))->tap; + Connection *conn = (Connection*)((ConnectionPair*)(s->priv))->conn; + if(!tap || !conn) { + DEBUG_ERROR("invalid tap or conn"); + handle_general_failure(); + return; + } + int err = 0; + if(!conn) { + DEBUG_ERROR("invalid connection"); + handle_general_failure(); + return; + } + // PICO_SOCK_EV_CONN - triggered when connection is established (TCP only). This event is // received either after a successful call to pico socket connect to indicate that the connection // 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 connection from a remote host. - if (ev & PICO_SOCK_EV_CONN) { - if(conn->state == ZT_SOCK_STATE_LISTENING) - { - Mutex::Lock _l(tap->_tcpconns_m); - uint32_t peer; + if (ev & PICO_SOCK_EV_CONN) { + if(conn->state == ZT_SOCK_STATE_LISTENING) + { + Mutex::Lock _l(tap->_tcpconns_m); + uint32_t peer; uint16_t port; - struct pico_socket *client_psock = pico_socket_accept(s, &peer, &port); - if(!client_psock) { - DEBUG_ERROR("pico_err=%s, picosock=%p", beautify_pico_error(pico_err), s); - return; + struct pico_socket *client_psock = pico_socket_accept(s, &peer, &port); + if(!client_psock) { + DEBUG_ERROR("pico_err=%s, picosock=%p", beautify_pico_error(pico_err), s); + return; } // Create a new Connection and add it to the queue, @@ -343,19 +343,19 @@ namespace ZeroTier { conn->_AcceptedConnections.push(newConn); - int value = 1; - pico_socket_setoption(newConn->picosock, PICO_TCP_NODELAY, &value); - + int value = 1; + pico_socket_setoption(newConn->picosock, PICO_TCP_NODELAY, &value); + if(ZT_SOCK_BEHAVIOR_LINGER) { - int linger_time_ms = ZT_SOCK_BEHAVIOR_LINGER_TIME; - int t_err = 0; - if((t_err = pico_socket_setoption(newConn->picosock, PICO_SOCKET_OPT_LINGER, &linger_time_ms)) < 0) - DEBUG_ERROR("unable to set LINGER size, err = %d, pico_err = %d, app_fd=%d, sdk_fd=%d", t_err, pico_err, conn->app_fd, conn->sdk_fd); - } + int linger_time_ms = ZT_SOCK_BEHAVIOR_LINGER_TIME; + int t_err = 0; + if((t_err = pico_socket_setoption(newConn->picosock, PICO_SOCKET_OPT_LINGER, &linger_time_ms)) < 0) + DEBUG_ERROR("unable to set LINGER size, err = %d, pico_err = %d, app_fd=%d, sdk_fd=%d", t_err, pico_err, conn->app_fd, conn->sdk_fd); + } /* - linger_time_ms = 0; - if((t_err = pico_socket_getoption(newConn->picosock, PICO_SOCKET_OPT_LINGER, &linger_time_ms)) < 0) - DEBUG_ERROR("unable to set LINGER size, err = %d, pico_err = %d", t_err, pico_err); + linger_time_ms = 0; + if((t_err = pico_socket_getoption(newConn->picosock, PICO_SOCKET_OPT_LINGER, &linger_time_ms)) < 0) + DEBUG_ERROR("unable to set LINGER size, err = %d, pico_err = %d", t_err, pico_err); DEBUG_TEST("getting linger = %d", linger_time_ms); */ // For I/O loop participation and referencing the PhySocket's parent Connection in callbacks @@ -367,79 +367,79 @@ namespace ZeroTier { // set state so socket multiplexer logic will pick this up conn->state = ZT_SOCK_STATE_UNHANDLED_CONNECTED; } - } + } - // PICO_SOCK_EV_FIN - triggered when the socket is closed. No further communication is + // 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, conn=%p, app_fd=%d, sdk_fd=%d", s, conn, conn->app_fd, conn->sdk_fd); - conn->closure_ts = std::time(nullptr); - } + if (ev & PICO_SOCK_EV_FIN) { + //DEBUG_EXTRA("PICO_SOCK_EV_FIN (socket closed), picosock=%p, conn=%p, app_fd=%d, sdk_fd=%d", s, conn, conn->app_fd, conn->sdk_fd); + conn->closure_ts = std::time(nullptr); + } - // 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"); - conn->state = 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, conn->app_fd, conn->sdk_fd); - } - // PICO_SOCK_EV_CLOSE - triggered when a FIN segment is received (TCP only). This event + // 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"); + conn->state = 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, conn->app_fd, conn->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 connection, 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 connection half-open (only for sending) after the FIN packet has been received, // allowing new data to be sent in the TCP CLOSE WAIT state. - if (ev & PICO_SOCK_EV_CLOSE) { - err = pico_socket_close(s); - //DEBUG_INFO("PICO_SOCK_EV_CLOSE (socket closure) err = %d, picosock=%p, conn=%p, app_fd=%d, sdk_fd=%d", err, s, conn, conn->app_fd, conn->sdk_fd); - conn->closure_ts = std::time(nullptr); - return; - } - // PICO_SOCK_EV_RD - triggered when new data arrives on the socket. A new receive action + if (ev & PICO_SOCK_EV_CLOSE) { + err = pico_socket_close(s); + //DEBUG_INFO("PICO_SOCK_EV_CLOSE (socket closure) err = %d, picosock=%p, conn=%p, app_fd=%d, sdk_fd=%d", err, s, conn, conn->app_fd, conn->sdk_fd); + conn->closure_ts = std::time(nullptr); + return; + } + // 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(conn->socket_type==SOCK_STREAM) - pico_cb_tcp_read(tap, s); - if(conn->socket_type==SOCK_DGRAM) - pico_cb_udp_read(tap, s); - } - // PICO_SOCK_EV_WR - triggered when ready to write to the socket. Issuing a write/send call + if (ev & PICO_SOCK_EV_RD) { + if(conn->socket_type==SOCK_STREAM) + pico_cb_tcp_read(tap, s); + if(conn->socket_type==SOCK_DGRAM) + 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) { - pico_cb_tcp_write(tap, s); - } - } + if (ev & PICO_SOCK_EV_WR) { + pico_cb_tcp_write(tap, s); + } + } - int pico_eth_send(struct pico_device *dev, void *buf, int len) - { - //DEBUG_INFO("len = %d", len); - SocketTap *tap = (SocketTap*)(dev->tap); - if(!tap) { - DEBUG_ERROR("invalid dev->tap"); - handle_general_failure(); - 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); - 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)); - return len; - } + int pico_eth_send(struct pico_device *dev, void *buf, int len) + { + //DEBUG_INFO("len = %d", len); + SocketTap *tap = (SocketTap*)(dev->tap); + if(!tap) { + DEBUG_ERROR("invalid dev->tap"); + handle_general_failure(); + 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); + 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)); + return len; + } - // receive frames from zerotier virtual wire and copy them to a guarded buffer awaiting placement into network stack - void picoTCP::pico_rx(SocketTap *tap, const MAC &from,const MAC &to,unsigned int etherType, - const void *data,unsigned int len) + // receive frames from zerotier virtual wire and copy them to a guarded buffer awaiting placement into network stack + void picoTCP::pico_rx(SocketTap *tap, const MAC &from,const MAC &to,unsigned int etherType, + const void *data,unsigned int len) { DEBUG_INFO("len = %d", len); if(!tap) { - DEBUG_ERROR("invalid tap"); - handle_general_failure(); - return; - } + DEBUG_ERROR("invalid tap"); + handle_general_failure(); + 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); @@ -467,101 +467,101 @@ namespace ZeroTier { } // feed frames on the guarded RX buffer (from zerotier virtual wire) into the network stack - int pico_eth_poll(struct pico_device *dev, int loop_score) - { - SocketTap *tap = (SocketTap*)(dev->tap); - if(!tap) { - DEBUG_ERROR("invalid dev->tap"); - handle_general_failure(); - return ZT_ERR_GENERAL_FAILURE; - } - // FIXME: The copy logic and/or buffer structure should be reworked for better performance after the BETA - // SocketTap *tap = (SocketTap*)netif->state; - Mutex::Lock _l(tap->_pico_frame_rxbuf_m); - unsigned char frame[ZT_SDK_MTU]; - int len; - int err = 0; - while (tap->pico_frame_rxbuf_tot > 0 && loop_score > 0) { - //DEBUG_FLOW(" [ FBUF -> STACK] Frame buffer SZ=%d", tap->pico_frame_rxbuf_tot); - memset(frame, 0, sizeof(frame)); - len = 0; - memcpy(&len, tap->pico_frame_rxbuf, sizeof(len)); // get frame len - if(len >= 0) { - //DEBUG_FLOW(" [ FBUF -> STACK] Moving FRAME of size (%d) from FBUF(sz=%d) into stack",len, tap->pico_frame_rxbuf_tot-len); - memcpy(frame, tap->pico_frame_rxbuf + sizeof(len), len-(sizeof(len)) ); // get frame data - memmove(tap->pico_frame_rxbuf, tap->pico_frame_rxbuf + len, MAX_PICO_FRAME_RX_BUF_SZ-len); // shift buffer - err = pico_stack_recv(dev, (uint8_t*)frame, (len-sizeof(len))); - //DEBUG_INFO("recv = %d", err); - tap->pico_frame_rxbuf_tot-=len; - } - else { - DEBUG_ERROR("Invalid frame size (%d). Exiting.",len); - handle_general_failure(); - } - loop_score--; - } - return loop_score; - } - - int picoTCP::pico_Socket(struct pico_socket **p, int socket_family, int socket_type, int protocol) - { - int err = 0; + int pico_eth_poll(struct pico_device *dev, int loop_score) + { + SocketTap *tap = (SocketTap*)(dev->tap); + if(!tap) { + DEBUG_ERROR("invalid dev->tap"); + handle_general_failure(); + return ZT_ERR_GENERAL_FAILURE; + } + // FIXME: The copy logic and/or buffer structure should be reworked for better performance after the BETA + // SocketTap *tap = (SocketTap*)netif->state; + Mutex::Lock _l(tap->_pico_frame_rxbuf_m); + unsigned char frame[ZT_SDK_MTU]; + int len; + int err = 0; + while (tap->pico_frame_rxbuf_tot > 0 && loop_score > 0) { + //DEBUG_FLOW(" [ FBUF -> STACK] Frame buffer SZ=%d", tap->pico_frame_rxbuf_tot); + memset(frame, 0, sizeof(frame)); + len = 0; + memcpy(&len, tap->pico_frame_rxbuf, sizeof(len)); // get frame len + if(len >= 0) { + //DEBUG_FLOW(" [ FBUF -> STACK] Moving FRAME of size (%d) from FBUF(sz=%d) into stack",len, tap->pico_frame_rxbuf_tot-len); + memcpy(frame, tap->pico_frame_rxbuf + sizeof(len), len-(sizeof(len)) ); // get frame data + memmove(tap->pico_frame_rxbuf, tap->pico_frame_rxbuf + len, MAX_PICO_FRAME_RX_BUF_SZ-len); // shift buffer + err = pico_stack_recv(dev, (uint8_t*)frame, (len-sizeof(len))); + //DEBUG_INFO("recv = %d", err); + tap->pico_frame_rxbuf_tot-=len; + } + else { + DEBUG_ERROR("Invalid frame size (%d). Exiting.",len); + handle_general_failure(); + } + loop_score--; + } + return loop_score; + } + + int picoTCP::pico_Socket(struct pico_socket **p, int socket_family, int socket_type, int protocol) + { + int err = 0; if(pico_ntimers() >= PICO_MAX_TIMERS) { - DEBUG_ERROR("cannot create additional socket, see PICO_MAX_TIMERS. current = %d", pico_ntimers()); - errno = EMFILE; - err = -1; + 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) { - DEBUG_ERROR("SOCK_DGRAM"); - psock = pico_socket_open( - protocol_version, PICO_PROTO_UDP, &ZeroTier::picoTCP::pico_cb_socket_activity); - if(psock) { // configure size of UDP SND/RCV buffers - // TODO - } - } - if(socket_type == SOCK_STREAM) { - psock = pico_socket_open( - protocol_version, PICO_PROTO_TCP, &ZeroTier::picoTCP::pico_cb_socket_activity); - 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; - int value = 1; - pico_socket_setoption(psock, PICO_TCP_NODELAY, &value); + 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) { + DEBUG_ERROR("SOCK_DGRAM"); + psock = pico_socket_open( + protocol_version, PICO_PROTO_UDP, &ZeroTier::picoTCP::pico_cb_socket_activity); + if(psock) { // configure size of UDP SND/RCV buffers + // TODO + } + } + if(socket_type == SOCK_STREAM) { + psock = pico_socket_open( + protocol_version, PICO_PROTO_TCP, &ZeroTier::picoTCP::pico_cb_socket_activity); + 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; + int value = 1; + pico_socket_setoption(psock, PICO_TCP_NODELAY, &value); - 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", t_err, 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", t_err, pico_err); - - if(ZT_SOCK_BEHAVIOR_LINGER) { - int linger_time_ms = ZT_SOCK_BEHAVIOR_LINGER_TIME; - if((t_err = pico_socket_setoption(psock, PICO_SOCKET_OPT_LINGER, &linger_time_ms)) < 0) - DEBUG_ERROR("unable to set LINGER, err = %d, pico_err = %d", t_err, pico_err); - } - } - } - *p = psock; + 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", t_err, 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", t_err, pico_err); + + if(ZT_SOCK_BEHAVIOR_LINGER) { + int linger_time_ms = ZT_SOCK_BEHAVIOR_LINGER_TIME; + if((t_err = pico_socket_setoption(psock, PICO_SOCKET_OPT_LINGER, &linger_time_ms)) < 0) + DEBUG_ERROR("unable to set LINGER, err = %d, pico_err = %d", t_err, pico_err); + } + } + } + *p = psock; } return err; - } + } - int picoTCP::pico_Connect(Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen) - { - if(!conn || !conn->picosock) { - DEBUG_ERROR("invalid conn or conn->picosock"); - handle_general_failure(); - return ZT_ERR_GENERAL_FAILURE; - } + int picoTCP::pico_Connect(Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen) + { + if(!conn || !conn->picosock) { + DEBUG_ERROR("invalid conn or conn->picosock"); + handle_general_failure(); + return ZT_ERR_GENERAL_FAILURE; + } int err = 0; if(conn->socket_family == AF_INET) { struct pico_ip4 zaddr; @@ -579,7 +579,7 @@ namespace ZeroTier { 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); + pico_string_to_ipv6(ipv6_str, zaddr.addr); err = pico_socket_connect(conn->picosock, &zaddr, in6->sin6_port); } memcpy(&(conn->peer_addr), &addr, sizeof(struct sockaddr_storage)); @@ -591,17 +591,17 @@ namespace ZeroTier { if(err == PICO_ERR_EHOSTUNREACH) DEBUG_ERROR("PICO_ERR_EHOSTUNREACH"); return err; - } + } - int picoTCP::pico_Bind(Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen) - { - //DEBUG_INFO(); - if(!conn || !conn->picosock) { - DEBUG_ERROR("invalid conn or conn->picosock"); - handle_general_failure(); - return ZT_ERR_GENERAL_FAILURE; - } - int err = 0; + int picoTCP::pico_Bind(Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen) + { + //DEBUG_INFO(); + if(!conn || !conn->picosock) { + DEBUG_ERROR("invalid conn or conn->picosock"); + handle_general_failure(); + return ZT_ERR_GENERAL_FAILURE; + } + int err = 0; if(conn->socket_family == AF_INET) { struct pico_ip4 zaddr; uint32_t tempaddr; @@ -620,8 +620,8 @@ namespace ZeroTier { 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("addr=%s:%d", ipv6_str, Utils::ntoh(in6->sin6_port)); + pico_string_to_ipv6("::", pip6.addr); + //DEBUG_EXTRA("addr=%s:%d", ipv6_str, Utils::ntoh(in6->sin6_port)); err = pico_socket_bind(conn->picosock, &pip6, (uint16_t *)&(in6->sin6_port)); } if(err < 0) { @@ -645,67 +645,67 @@ namespace ZeroTier { } } return err; - } + } - int picoTCP::pico_Listen(Connection *conn, int fd, int backlog) - { - //DEBUG_INFO(); - if(!conn || !conn->picosock) { - DEBUG_ERROR("invalid conn or conn->picosock"); - handle_general_failure(); - return ZT_ERR_GENERAL_FAILURE; - } - int err = 0; - if((err = pico_socket_listen(conn->picosock, backlog)) < 0) - { - if(err == PICO_ERR_EINVAL) { - DEBUG_ERROR("PICO_ERR_EINVAL"); - errno = EINVAL; - return -1; - } + int picoTCP::pico_Listen(Connection *conn, int fd, int backlog) + { + //DEBUG_INFO(); + if(!conn || !conn->picosock) { + DEBUG_ERROR("invalid conn or conn->picosock"); + handle_general_failure(); + return ZT_ERR_GENERAL_FAILURE; + } + int err = 0; + if((err = pico_socket_listen(conn->picosock, backlog)) < 0) + { + if(err == PICO_ERR_EINVAL) { + DEBUG_ERROR("PICO_ERR_EINVAL"); + errno = EINVAL; + return -1; + } if(err == PICO_ERR_EISCONN) { DEBUG_ERROR("PICO_ERR_EISCONN"); errno = EISCONN; return -1; } - } - conn->state = ZT_SOCK_STATE_LISTENING; - return ZT_ERR_OK; - } + } + conn->state = ZT_SOCK_STATE_LISTENING; + return ZT_ERR_OK; + } - Connection* picoTCP::pico_Accept(Connection *conn) - { - if(!conn) { - DEBUG_ERROR("invalid conn"); - handle_general_failure(); - return NULL; - } - // Retreive first of queued Connections from parent connection - Connection *new_conn = NULL; - if(conn->_AcceptedConnections.size()) { + Connection* picoTCP::pico_Accept(Connection *conn) + { + if(!conn) { + DEBUG_ERROR("invalid conn"); + handle_general_failure(); + return NULL; + } + // Retreive first of queued Connections from parent connection + Connection *new_conn = NULL; + if(conn->_AcceptedConnections.size()) { new_conn = conn->_AcceptedConnections.front(); conn->_AcceptedConnections.pop(); } - return new_conn; - } + return new_conn; + } - int picoTCP::pico_Read(SocketTap *tap, PhySocket *sock, Connection* conn, bool stack_invoked) - { - DEBUG_INFO(); - //exit(0); - /* - if(!conn || !tap || !conn) { - DEBUG_ERROR("invalid tap, sock, or conn"); - handle_general_failure(); - return; - } - //DEBUG_INFO(); - if(!stack_invoked) { - // The stack thread writes to RXBUF as well - tap->_tcpconns_m.lock(); - tap->_rx_buf_m.lock(); - } - int tot = 0, n = -1, write_attempts = 0; + int picoTCP::pico_Read(SocketTap *tap, PhySocket *sock, Connection* conn, bool stack_invoked) + { + DEBUG_INFO(); + //exit(0); + /* + if(!conn || !tap || !conn) { + DEBUG_ERROR("invalid tap, sock, or conn"); + handle_general_failure(); + return; + } + //DEBUG_INFO(); + if(!stack_invoked) { + // The stack thread writes to RXBUF as well + tap->_tcpconns_m.lock(); + tap->_rx_buf_m.lock(); + } + int tot = 0, n = -1, write_attempts = 0; if(conn && conn->rxsz) { //DEBUG_INFO("conn = %p", conn); @@ -733,7 +733,7 @@ namespace ZeroTier { if(conn->rxsz-n > 0) { // If more remains on buffer memcpy(conn->rxbuf, conn->rxbuf+ZT_SDK_MTU, conn->rxsz - ZT_SDK_MTU); } - conn->rxsz -= ZT_SDK_MTU; + conn->rxsz -= ZT_SDK_MTU; } // if(conn->socket_type==SOCK_STREAM) { @@ -743,20 +743,20 @@ namespace ZeroTier { // n = write(conn->sdk_fd, conn->rxbuf, conn->rxsz); if(conn->rxsz-n > 0) // If more remains on buffer memcpy(conn->rxbuf, conn->rxbuf+n, conn->rxsz - n); - conn->rxsz -= n; + conn->rxsz -= n; } // Notify ZT I/O loop that it has new buffer contents if(n) { if(conn->socket_type==SOCK_STREAM) { //#if DEBUG_LEVEL >= MSG_TRANSFER - // DEBUG_TRANS("[ TCP RX <- STACK] :: conn = %p, len = %d", conn, n); + // DEBUG_TRANS("[ TCP RX <- STACK] :: conn = %p, len = %d", conn, n); //#endif - } - if(conn->rxsz == 0) { + } + if(conn->rxsz == 0) { tap->_phy.setNotifyWritable(sock, false); } else { - tap->_phy.setNotifyWritable(sock, true); + tap->_phy.setNotifyWritable(sock, true); } } else { @@ -764,92 +764,92 @@ namespace ZeroTier { } } if(!stack_invoked) { - tap->_tcpconns_m.unlock(); - tap->_rx_buf_m.unlock(); - } - // DEBUG_FLOW("[ ZTSOCK <- RXBUF] Emitted (%d) from RXBUF(%d) to socket", tot, conn->rxsz); - */ - return 0; - } + tap->_tcpconns_m.unlock(); + tap->_rx_buf_m.unlock(); + } + // DEBUG_FLOW("[ ZTSOCK <- RXBUF] Emitted (%d) from RXBUF(%d) to socket", tot, conn->rxsz); + */ + return 0; + } - int picoTCP::pico_Write(Connection *conn, void *data, ssize_t len) - { - int err = 0; - // TODO: Add RingBuffer overflow checks - //DEBUG_INFO("conn=%p, len = %d", conn, len); - Mutex::Lock _l(conn->_tx_m); + int picoTCP::pico_Write(Connection *conn, void *data, ssize_t len) + { + int err = 0; + // TODO: Add RingBuffer overflow checks + //DEBUG_INFO("conn=%p, len = %d", conn, len); + Mutex::Lock _l(conn->_tx_m); if(len <= 0) { - DEBUG_ERROR("invalid write length (len=%d)", len); - handle_general_failure(); - return -1; - } - if(conn->picosock->state & PICO_SOCKET_STATE_CLOSED){ - DEBUG_ERROR("socket is CLOSED, this write() will fail"); - return -1; - } - if(!conn) { - DEBUG_ERROR("invalid connection (len=%d)", len); - handle_general_failure(); - return -1; - } + DEBUG_ERROR("invalid write length (len=%d)", len); + handle_general_failure(); + return -1; + } + if(conn->picosock->state & PICO_SOCKET_STATE_CLOSED){ + DEBUG_ERROR("socket is CLOSED, this write() will fail"); + return -1; + } + if(!conn) { + DEBUG_ERROR("invalid connection (len=%d)", len); + handle_general_failure(); + return -1; + } - int original_txsz = conn->TXbuf->count(); + int original_txsz = conn->TXbuf->count(); - if(original_txsz + len >= ZT_TCP_TX_BUF_SZ) { - DEBUG_ERROR("txsz = %d, len = %d", original_txsz, len); - DEBUG_ERROR("TX buffer is too small, try increasing ZT_TCP_TX_BUF_SZ in libzt.h"); - exit(0); - } + 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"); + exit(0); + } - int buf_w = conn->TXbuf->write((const unsigned char*)data, len); - if (buf_w != len) { - // because we checked ZT_TCP_TX_BUF_SZ above, this should not happen - DEBUG_ERROR("TX wrote only %d but expected to write %d", buf_w, len); - exit(0); - } - //DEBUG_INFO("TXbuf->count() = %d", conn->TXbuf->count()); - int txsz = conn->TXbuf->count(); + int buf_w = conn->TXbuf->write((const unsigned char*)data, len); + if (buf_w != len) { + // because we checked ZT_TCP_TX_BUF_SZ above, this should not happen + DEBUG_ERROR("TX wrote only %d but expected to write %d", buf_w, len); + exit(0); + } + //DEBUG_INFO("TXbuf->count() = %d", conn->TXbuf->count()); + int txsz = conn->TXbuf->count(); - //if(original_txsz > 0) - // return; // don't write here, we already have stuff in the queue, a callback will handle it - + //if(original_txsz > 0) + // return; // don't write here, we already have stuff in the queue, a callback will handle it + int r, max_write_len = std::min(std::min(txsz, ZT_SDK_MTU),ZT_STACK_SOCKET_WR_MAX); //int buf_r = conn->TXbuf->read(conn->tmptxbuf, max_write_len); - - if((r = pico_socket_write(conn->picosock, conn->TXbuf->get_buf(), max_write_len)) < 0) { - DEBUG_ERROR("unable to write to picosock=%p, r=%d", conn->picosock, r); - err = -1; - } - else { - err = r; // successful write - } - if(conn->socket_type == SOCK_STREAM) { - //DEBUG_TRANS("[ TCP TX -> STACK] :: conn = %p, len = %d", conn, r); - } - if(conn->socket_type == SOCK_DGRAM) { - //DEBUG_TRANS("[ UDP TX -> STACK] :: conn = %p, len = %d", conn, r); - } - if(r>0) - conn->TXbuf->consume(r); + + if((r = pico_socket_write(conn->picosock, conn->TXbuf->get_buf(), max_write_len)) < 0) { + DEBUG_ERROR("unable to write to picosock=%p, r=%d", conn->picosock, r); + err = -1; + } + else { + err = r; // successful write + } + if(conn->socket_type == SOCK_STREAM) { + //DEBUG_TRANS("[ TCP TX -> STACK] :: conn = %p, len = %d", conn, r); + } + if(conn->socket_type == SOCK_DGRAM) { + //DEBUG_TRANS("[ UDP TX -> STACK] :: conn = %p, len = %d", conn, r); + } + if(r>0) + conn->TXbuf->consume(r); - return err; - } + return err; + } - int picoTCP::pico_Close(Connection *conn) - { - DEBUG_INFO("conn = %p, picosock=%p, fd = %d", conn, conn->picosock, conn->app_fd); - if(!conn || !conn->picosock) - return ZT_ERR_GENERAL_FAILURE; - int err = 0; - Mutex::Lock _l(conn->tap->_tcpconns_m); - if(conn->closure_ts != -1) // it was closed at some point in the past, it'll work itself out - return ZT_ERR_OK; - if((err = pico_socket_close(conn->picosock)) < 0) { - errno = pico_err; - DEBUG_ERROR("error closing pico_socket(%p)", (void*)(conn->picosock)); - } - return err; - } + int picoTCP::pico_Close(Connection *conn) + { + DEBUG_INFO("conn = %p, picosock=%p, fd = %d", conn, conn->picosock, conn->app_fd); + if(!conn || !conn->picosock) + return ZT_ERR_GENERAL_FAILURE; + int err = 0; + Mutex::Lock _l(conn->tap->_tcpconns_m); + if(conn->closure_ts != -1) // it was closed at some point in the past, it'll work itself out + return ZT_ERR_OK; + if((err = pico_socket_close(conn->picosock)) < 0) { + errno = pico_err; + DEBUG_ERROR("error closing pico_socket(%p)", (void*)(conn->picosock)); + } + return err; + } char *picoTCP::beautify_pico_error(int err) { diff --git a/src/picoTCP.hpp b/src/picoTCP.hpp index 3337b5c..1f98126 100644 --- a/src/picoTCP.hpp +++ b/src/picoTCP.hpp @@ -73,12 +73,12 @@ namespace ZeroTier /* * Send raw frames from the stack to the ZeroTier virtual wire */ - int pico_eth_send(struct pico_device *dev, void *buf, int len); + int pico_eth_send(struct pico_device *dev, void *buf, int len); - /* + /* * Read raw frames from RX frame buffer into the stack */ - int pico_eth_poll(struct pico_device *dev, int loop_score); + int pico_eth_poll(struct pico_device *dev, int loop_score); class SocketTap; struct Connection; @@ -88,38 +88,38 @@ namespace ZeroTier public: /* - * Set up an interface in the network stack for the SocketTap - */ + * Set up an interface in the network stack for the SocketTap + */ bool pico_init_interface(ZeroTier::SocketTap *tap, const ZeroTier::InetAddress &ip); /* - * Main stack loop - */ + * Main stack loop + */ void pico_loop(SocketTap *tap); /* - * Read bytes from the stack to the RX buffer (prepare to be read by app) - */ + * Read bytes from the stack to the RX buffer (prepare to be read by app) + */ static void pico_cb_tcp_read(SocketTap *tap, struct pico_socket *s); /* - * Read bytes from the stack to the RX buffer (prepare to be read by app) - */ - static void pico_cb_udp_read(SocketTap *tap, struct pico_socket *s); + * Read bytes from the stack to the RX buffer (prepare to be read by app) + */ + static void pico_cb_udp_read(SocketTap *tap, struct pico_socket *s); - /* - * Write bytes from TX buffer to stack (prepare to be sent to ZT virtual wire) - */ + /* + * Write bytes from TX buffer to stack (prepare to be sent to ZT virtual wire) + */ static void pico_cb_tcp_write(SocketTap *tap, struct pico_socket *s); /* - * Write bytes from TX buffer to stack (prepare to be sent to ZT virtual wire) - */ - static void pico_cb_socket_activity(uint16_t ev, struct pico_socket *s); + * Write bytes from TX buffer to stack (prepare to be sent to ZT virtual wire) + */ + static void pico_cb_socket_activity(uint16_t ev, struct pico_socket *s); /* - * Packets from the ZeroTier virtual wire enter the stack here - */ + * Packets from the ZeroTier virtual wire enter the stack here + */ void pico_rx(SocketTap *tap, const ZeroTier::MAC &from,const ZeroTier::MAC &to,unsigned int etherType,const void *data,unsigned int len); /* @@ -130,39 +130,39 @@ namespace ZeroTier /* * Connect to remote host via userspace network stack interface - Called from SocketTap */ - int pico_Connect(Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen); - - /* + int pico_Connect(Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen); + + /* * Bind to a userspace network stack interface - Called from SocketTap */ - int pico_Bind(Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen); - - /* + int pico_Bind(Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen); + + /* * Listen for incoming connections - Called from SocketTap */ - int pico_Listen(Connection *conn, int fd, int backlog); + int pico_Listen(Connection *conn, int fd, int backlog); - /* + /* * Accept an incoming connection - Called from SocketTap */ - Connection* pico_Accept(Connection *conn); + Connection* pico_Accept(Connection *conn); - /* + /* * Read from RX buffer to application - Called from SocketTap */ - int pico_Read(SocketTap *tap, ZeroTier::PhySocket *sock,Connection *conn,bool stack_invoked); + int pico_Read(SocketTap *tap, ZeroTier::PhySocket *sock,Connection *conn,bool stack_invoked); - /* + /* * Write to userspace network stack - Called from SocketTap */ - int pico_Write(Connection *conn, void *data, ssize_t len); + int pico_Write(Connection *conn, void *data, ssize_t len); - /* + /* * Close a Connection - Called from SocketTap */ int pico_Close(Connection *conn); - /* + /* * Converts picoTCP error codes to pretty string */ static char *beautify_pico_error(int err); diff --git a/test/echotest.cpp b/test/echotest.cpp index 42a30a9..c75ec26 100644 --- a/test/echotest.cpp +++ b/test/echotest.cpp @@ -68,9 +68,9 @@ void loadTestConfigFile(std::string filepath) prefix = value; } if(key[0] != '#' && key[0] != ';') { - testConf[prefix + "." + key] = value; // format: alice.ipv4 172.30.30.1 - //fprintf(stderr, "%s.%s = %s\n", prefix.c_str(), key.c_str(), testConf[prefix + "." + key].c_str()); - } + testConf[prefix + "." + key] = value; // format: alice.ipv4 172.30.30.1 + //fprintf(stderr, "%s.%s = %s\n", prefix.c_str(), key.c_str(), testConf[prefix + "." + key].c_str()); + } } testFile.close(); @@ -225,18 +225,18 @@ void start_echo_mode(std::string ipstr, int listen_port) int main(int argc , char *argv[]) { - if(argc < 5) { - fprintf(stderr, "usage: echotest to \n"); - fprintf(stderr, "e.g. : echotest test/selftest.conf bob to alice\n"); - return 1; - } + if(argc < 5) { + fprintf(stderr, "usage: echotest to \n"); + fprintf(stderr, "e.g. : echotest test/selftest.conf bob to alice\n"); + return 1; + } std::string from = argv[2]; std::string to = argv[4]; std::string me = from; - int start_port = 0; - int port_offset = 0; + int start_port = 0; + int port_offset = 0; int echo_listen_port = 0; std::string local_echo_ipv4; diff --git a/test/layer2.cpp b/test/layer2.cpp index daec62d..76d28f8 100644 --- a/test/layer2.cpp +++ b/test/layer2.cpp @@ -27,22 +27,22 @@ unsigned short csum(unsigned short *buf, int nwords) { - unsigned long sum; - for(sum=0; nwords>0; nwords--) - sum += *buf++; - sum = (sum >> 16) + (sum &0xffff); - sum += (sum >> 16); - return (unsigned short)(~sum); + unsigned long sum; + for(sum=0; nwords>0; nwords--) + sum += *buf++; + sum = (sum >> 16) + (sum &0xffff); + sum += (sum >> 16); + return (unsigned short)(~sum); } int main(int argc , char *argv[]) { if(argc < 3) { - fprintf(stderr, "usage: layer2 \n"); - return 1; - } + fprintf(stderr, "usage: layer2 \n"); + return 1; + } - // initialize library + // initialize library printf("Starting libzt...\n"); zts_simple_start(argv[1], argv[2]); char device_id[11]; @@ -181,7 +181,7 @@ int main(int argc , char *argv[]) usleep(10000); // Send packet if (zts_sendto(fd, sendbuf, tx_len, 0, (struct sockaddr*)&socket_address, sizeof(struct sockaddr_ll)) < 0) - fprintf(stderr, "Send failed\n"); + fprintf(stderr, "Send failed\n"); } // dismantle all zt virtual taps (SocketTaps) diff --git a/test/selftest.cpp b/test/selftest.cpp index 5c3b6c0..0387fa9 100644 --- a/test/selftest.cpp +++ b/test/selftest.cpp @@ -116,7 +116,7 @@ std::map testConf; [OK] comprehensive server ipv6 - test all ipv4/6 server simple/sustained modes Performance: - (See libzt.h, compile libzt with appropriate ZT_TCP_TX_BUF_SZ, ZT_TCP_RX_BUF_SZ, ZT_UDP_TX_BUF_SZ, and ZT_UDO_RX_BUF_SZ for your test) + (See libzt.h, compile libzt with appropriate ZT_TCP_TX_BUF_SZ, ZT_TCP_RX_BUF_SZ, ZT_UDP_TX_BUF_SZ, and ZT_UDO_RX_BUF_SZ for your test) [OK] Throughput - Test maximum RX/TX speeds [ ] Memory Usage - Test memory consumption profile @@ -164,9 +164,9 @@ void loadTestConfigFile(std::string filepath) prefix = value; } if(key[0] != '#' && key[0] != ';') { - testConf[prefix + "." + key] = value; - fprintf(stderr, "%s.%s = %s\n", prefix.c_str(), key.c_str(), testConf[prefix + "." + key].c_str()); - } + testConf[prefix + "." + key] = value; + fprintf(stderr, "%s.%s = %s\n", prefix.c_str(), key.c_str(), testConf[prefix + "." + key].c_str()); + } } testFile.close(); @@ -870,7 +870,7 @@ int slam_api_test() int results[SLAM_NUMBER*SLAM_REPEAT]; struct hostent *server; - struct sockaddr_in6 addr6; + struct sockaddr_in6 addr6; struct sockaddr_in addr; // int start_stack_timer_count = pico_ntimers(); // number of picoTCP timers allocated @@ -946,17 +946,17 @@ int slam_api_test() int port; while(!(std::find(used_ports.begin(),used_ports.end(),port) == used_ports.end())) { - port = MIN_PORT + (rand() % (int)(MAX_PORT - MIN_PORT + 1)); - } - used_ports.push_back(port); - std::cout << "port = " << port << std::endl; + port = MIN_PORT + (rand() % (int)(MAX_PORT - MIN_PORT + 1)); + } + used_ports.push_back(port); + std::cout << "port = " << port << std::endl; if(false) { server = gethostbyname2("::",AF_INET6); - memset((char *) &addr6, 0, sizeof(addr6)); - addr6.sin6_flowinfo = 0; - addr6.sin6_family = AF_INET6; - addr6.sin6_port = htons(port); + memset((char *) &addr6, 0, sizeof(addr6)); + addr6.sin6_flowinfo = 0; + addr6.sin6_family = AF_INET6; + addr6.sin6_port = htons(port); addr6.sin6_addr = in6addr_any; err = zts_bind(sock, (struct sockaddr *)&addr6, (socklen_t)(sizeof addr6)); } @@ -1020,10 +1020,10 @@ int slam_api_test() // connect() if(false) { server = gethostbyname2("::",AF_INET6); - memset((char *) &addr6, 0, sizeof(addr6)); - addr6.sin6_flowinfo = 0; - addr6.sin6_family = AF_INET6; - addr6.sin6_port = htons(port); + memset((char *) &addr6, 0, sizeof(addr6)); + addr6.sin6_flowinfo = 0; + addr6.sin6_family = AF_INET6; + addr6.sin6_port = htons(port); addr6.sin6_addr = in6addr_any; err = zts_connect(sock, (struct sockaddr *)&addr6, (socklen_t)(sizeof addr6)); } @@ -1086,7 +1086,7 @@ int random_api_test() int calls_made = 0; // how many calls we'll make - int num_of_api_calls = 10; + int num_of_api_calls = 10; zts_socket() @@ -1241,24 +1241,24 @@ void test_bad_args() int main(int argc , char *argv[]) { - if(argc < 5) { - fprintf(stderr, "usage: selftest to \n"); - fprintf(stderr, "e.g. : selftest test/selftest.conf alice to bob\n"); - return 1; - } + if(argc < 5) { + fprintf(stderr, "usage: selftest to \n"); + fprintf(stderr, "e.g. : selftest test/selftest.conf alice to bob\n"); + return 1; + } std::string from = argv[2]; std::string to = argv[4]; std::string me = from; - std::vector results; + std::vector results; - int err = 0; - int mode = 0; - int port = 0; - int operation = 0; - int start_port = 0; - int port_offset = 0; + int err = 0; + int mode = 0; + int port = 0; + int operation = 0; + int start_port = 0; + int port_offset = 0; int count = 0; int delay = 0; diff --git a/test/ztproxy.cpp b/test/ztproxy.cpp index c7e56f9..8ca6d66 100644 --- a/test/ztproxy.cpp +++ b/test/ztproxy.cpp @@ -191,9 +191,9 @@ namespace ZeroTier { struct sockaddr_in6 in6; memset(&in6,0,sizeof(in6)); in6.sin6_family = AF_INET; - struct hostent *server; - server = gethostbyname2((char*)host.c_str(),AF_INET6); - memmove((char *) &in6.sin6_addr.s6_addr, (char *) server->h_addr, server->h_length); + struct hostent *server; + server = gethostbyname2((char*)host.c_str(),AF_INET6); + memmove((char *) &in6.sin6_addr.s6_addr, (char *) server->h_addr, server->h_length); in6.sin6_port = Utils::hton(dest_port); conn->destination_sock = _phy.tcpConnect((const struct sockaddr *)&in6, connected, this); } diff --git a/test/ztproxy.hpp b/test/ztproxy.hpp index 213b674..d1dd545 100644 --- a/test/ztproxy.hpp +++ b/test/ztproxy.hpp @@ -84,7 +84,7 @@ namespace ZeroTier { void threadMain() throw(); - TcpConnection *getConnection(PhySocket *sock); + TcpConnection *getConnection(PhySocket *sock); private: volatile bool _enabled;