diff --git a/ext/ZeroTierOne.patch b/ext/ZeroTierOne.patch index 5a766ab..4094e39 100644 --- a/ext/ZeroTierOne.patch +++ b/ext/ZeroTierOne.patch @@ -37,10 +37,19 @@ index 74c22d33..58979e26 100644 if (nqcb->oldQueues[i]->byteLength > maxQueueLength) { maxQueueLength = nqcb->oldQueues[i]->byteLength; diff --git a/service/OneService.cpp b/service/OneService.cpp -index a1c53764..757863a8 100644 +index a1c53764..e3034059 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp -@@ -2244,6 +2244,12 @@ public: +@@ -625,6 +625,8 @@ public: + break; + if (!pkt) + break; ++ if (!_run) ++ break; + + const ZT_ResultCode rc = _node->processWirePacket(nullptr,pkt->now,pkt->sock,&(pkt->from),pkt->data,pkt->size,&_nextBackgroundTaskDeadline); + { +@@ -2244,6 +2246,12 @@ public: #endif syncManagedStuff(n,true,true); n.tap->setMtu(nwc->mtu); diff --git a/include/Constants.hpp b/include/Constants.hpp index b25aa43..f511004 100644 --- a/include/Constants.hpp +++ b/include/Constants.hpp @@ -33,6 +33,18 @@ #ifndef LIBZT_CONSTANTS_HPP #define LIBZT_CONSTANTS_HPP +////////////////////////////////////////////////////////////////////////////// +// Callbacks // +////////////////////////////////////////////////////////////////////////////// + +#define ZTS_NODE_CALLBACKS 1 +#define ZTS_NETWORK_CALLBACKS 1 +#define ZTS_NETIF_CALLBACKS 1 +#define ZTS_PEER_CALLBACKS 1 + +#define ZTS_CALLBACK_PROCESSING_INTERVAL ZTS_WRAPPER_CHECK_INTERVAL // 100 // ms +#define ZTS_CALLBACK_MSG_QUEUE_LEN 256 + ////////////////////////////////////////////////////////////////////////////// // Error codes returned by ZeroTier and the libzt API // // See ext/ZeroTierOne/include/ZeroTierOne.h // @@ -40,25 +52,45 @@ typedef int zts_err_t; -#define ZTS_ERR_OK 0 // Everything is ok -#define ZTS_ERR_INVALID_ARG -1 // A parameter provided by the user application is invalid (e.g. our of range, NULL, etc) -#define ZTS_ERR_SERVICE -2 // The service isn't initialized or is for some other reason currently unavailable -#define ZTS_ERR_INVALID_OP -3 // For some reason this API operation is not permitted (perhaps the service is still starting?) +#define ZTS_ERR_OK 0 // Everything is ok +#define ZTS_ERR_INVALID_ARG -1 // A parameter provided by the user application is invalid (e.g. our of range, NULL, etc) +#define ZTS_ERR_SERVICE -2 // The service isn't initialized or is for some other reason currently unavailable +#define ZTS_ERR_INVALID_OP -3 // For some reason this API operation is not permitted (perhaps the service is still starting?) -#define ZTS_EVENT_NODE_ONLINE 0x01 // Node is online -#define ZTS_EVENT_NODE_OFFLINE 0x02 // Node is offline -#define ZTS_EVENT_NODE_DOWN 0x03 // Node is shutting down -#define ZTS_EVENT_NODE_IDENTITY_COLLISION 0x04 // Identity collision - check for duplicate instances -#define ZTS_EVENT_NODE_UNRECOVERABLE_ERROR 0x05 // Something is seriously wrong -#define ZTS_EVENT_NODE_NORMAL_TERMINATION 0x06 // Service thread has stopped - -#define ZTS_EVENT_NETWORK_NOT_FOUND 0x07 -#define ZTS_EVENT_NETWORK_CLIENT_TOO_OLD 0x08 -#define ZTS_EVENT_NETWORK_REQUESTING_CONFIG 0x09 -#define ZTS_EVENT_NETWORK_OK 0x0a -#define ZTS_EVENT_NETWORK_ACCESS_DENIED 0x0b -#define ZTS_EVENT_NETWORK_READY 0x0c -#define ZTS_EVENT_NETWORK_DOWN 0x0d +#define ZTS_EVENT_NONE 0x00000000 +// Node-specific events +#define ZTS_EVENT_NODE_ONLINE 0x00000001 // Node is online +#define ZTS_EVENT_NODE_OFFLINE 0x00000002 // Node is offline +#define ZTS_EVENT_NODE_DOWN 0x00000004 // Node is shutting down +#define ZTS_EVENT_NODE_IDENTITY_COLLISION 0x00000008 // Identity collision - check for duplicate instances +#define ZTS_EVENT_NODE_UNRECOVERABLE_ERROR 0x00000010 // Something is seriously wrong +#define ZTS_EVENT_NODE_NORMAL_TERMINATION 0x00000020 // Service thread has stopped +// Network-specific events +#define ZTS_EVENT_NETWORK_NOT_FOUND 0x00000080 +#define ZTS_EVENT_NETWORK_CLIENT_TOO_OLD 0x00000100 +#define ZTS_EVENT_NETWORK_REQUESTING_CONFIG 0x00000200 +#define ZTS_EVENT_NETWORK_OK 0x00000400 +#define ZTS_EVENT_NETWORK_ACCESS_DENIED 0x00000800 +#define ZTS_EVENT_NETWORK_READY_IP4 0x00001000 +#define ZTS_EVENT_NETWORK_READY_IP6 0x00002000 +#define ZTS_EVENT_NETWORK_DOWN 0x00004000 +#define ZTS_EVENT_NETWORK_STATUS_CHANGE ZTS_EVENT_NETWORK_NOT_FOUND | ZTS_EVENT_NETWORK_CLIENT_TOO_OLD | ZTS_EVENT_NETWORK_REQUESTING_CONFIG | ZTS_EVENT_NETWORK_OK | ZTS_EVENT_NETWORK_ACCESS_DENIED +// lwIP netif events +#define ZTS_EVENT_NETIF_UP_IP4 0x00100000 +#define ZTS_EVENT_NETIF_UP_IP6 0x00200000 +#define ZTS_EVENT_NETIF_DOWN_IP4 0x00400000 +#define ZTS_EVENT_NETIF_DOWN_IP6 0x00800000 +#define ZTS_EVENT_NETIF_REMOVED 0x01000000 +#define ZTS_EVENT_NETIF_LINK_UP 0x02000000 +#define ZTS_EVENT_NETIF_LINK_DOWN 0x04000000 +#define ZTS_EVENT_NETIF_NEW_ADDRESS 0x08000000 +#define ZTS_EVENT_NETIF_STATUS_CHANGE ZTS_EVENT_NETIF_UP_IP4 | ZTS_EVENT_NETIF_UP_IP6 | ZTS_EVENT_NETIF_DOWN_IP4 | ZTS_EVENT_NETIF_DOWN_IP6 | ZTS_EVENT_NETIF_LINK_UP | ZTS_EVENT_NETIF_LINK_DOWN +// +#define ZTS_EVENT_GENERIC_DOWN ZTS_EVENT_NETWORK_DOWN | ZTS_EVENT_NETIF_DOWN_IP4 | ZTS_EVENT_NETIF_DOWN_IP6 | ZTS_EVENT_NETIF_LINK_DOWN +// Peer events +#define ZTS_EVENT_PEER_P2P 0x20000000 +#define ZTS_EVENT_PEER_RELAY 0x40000000 +#define ZTS_EVENT_PEER_UNREACHABLE 0x80000000 // Not yet supported ////////////////////////////////////////////////////////////////////////////// // libzt config // diff --git a/include/Defs.hpp b/include/Defs.hpp index 3ce43bd..39a8162 100644 --- a/include/Defs.hpp +++ b/include/Defs.hpp @@ -39,6 +39,8 @@ #include #endif +namespace ZeroTier { + ////////////////////////////////////////////////////////////////////////////// // Subset of: ZeroTierOne.h // // We redefine a few ZT structures here so that we don't need to drag the // @@ -208,4 +210,6 @@ struct zts_peer_list unsigned long peerCount; }; +} // namespace ZeroTier + #endif // _H \ No newline at end of file diff --git a/include/ServiceControls.hpp b/include/ServiceControls.hpp index 1501afa..9ceca6c 100644 --- a/include/ServiceControls.hpp +++ b/include/ServiceControls.hpp @@ -33,6 +33,10 @@ #ifndef LIBZT_SERVICE_CONTROLS_HPP #define LIBZT_SERVICE_CONTROLS_HPP +#include "Constants.hpp" + +namespace ZeroTier { + #ifdef _WIN32 #ifdef ADD_EXPORTS #define ZT_SOCKET_API __declspec(dllexport) @@ -45,8 +49,6 @@ #define ZTCALL #endif -void api_sleep(int interval_ms); - ////////////////////////////////////////////////////////////////////////////// // ZeroTier Service Controls // ////////////////////////////////////////////////////////////////////////////// @@ -386,4 +388,6 @@ void _hibernate_if_needed(); } #endif +} // namespace ZeroTier + #endif // _H \ No newline at end of file diff --git a/include/VirtualTap.hpp b/include/VirtualTap.hpp index 22cd1af..6fe509e 100644 --- a/include/VirtualTap.hpp +++ b/include/VirtualTap.hpp @@ -78,33 +78,9 @@ public: ~VirtualTap(); - /** - * A state will only be reported via callback if it differs from this value. Subsequently this - * value will be updated. - */ - int _lastReportedStatus; - - /** - * The last time that this virtual tap received a network config update from the core - */ - uint64_t _lastConfigUpdateTime = 0; - - /** - * The last time that a callback notification was sent to the user application signalling - * that this interface is ready to process traffic. - */ - uint64_t _lastReadyReportTime = 0; - - void lastConfigUpdate(uint64_t lastConfigUpdateTime); - void setEnabled(bool en); bool enabled() const; - /** - * Registers a device with the given address - */ - void registerIpWithStack(const InetAddress &ip); - /** * Adds an address to the userspace stack interface associated with this VirtualTap * - Starts VirtualTap main thread ONLY if successful @@ -178,6 +154,48 @@ public: void phyOnUnixData(PhySocket *sock, void **uptr, void *data, ssize_t len); void phyOnUnixWritable(PhySocket *sock, void **uptr, bool stack_invoked); + ////////////////////////////////////////////////////////////////////////////// + // Lower-level lwIP netif handling and traffic handling readiness // + ////////////////////////////////////////////////////////////////////////////// + + void *netif4 = NULL; + void *netif6 = NULL; + + bool netif4WasUpLastCheck = false; + bool netif6WasUpLastCheck = false; + + /** + * Notes the current state of the lower level lwIP netif and reports if a state change + * has happened since the last check. This method is likely temporary. + */ + uint64_t recognizeLowerLevelInterfaceStateChange(void *n); + + /** + * A state will only be reported via callback if it differs from this value. Subsequently this + * value will be updated. + */ + //int _lastReportedStatus; + + /** + * The last time that this virtual tap received a network config update from the core + */ + uint64_t _lastConfigUpdateTime = 0; + + /** + * The last time that a callback notification was sent to the user application signalling + * that this interface is ready to process traffic. + */ + uint64_t _lastReadyReportTime = 0; + + void lastConfigUpdate(uint64_t lastConfigUpdateTime); + + int _networkStatus = 0; + int _netifStatus = 0; + /** + * Returns whether or not this interface is ready for traffic. + */ + bool isReady(); + ////////////////////////////////////////////////////////////////////////////// // Vars // ////////////////////////////////////////////////////////////////////////////// diff --git a/include/VirtualTapManager.hpp b/include/VirtualTapManager.hpp deleted file mode 100644 index ab2958b..0000000 --- a/include/VirtualTapManager.hpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -/** - * @file - * - * Management of virtual tap interfaces - */ - -#ifndef LIBZT_VIRTUAL_TAP_MANAGER_H -#define LIBZT_VIRTUAL_TAP_MANAGER_H - -#include "VirtualTap.hpp" -#include "OneService.hpp" - -namespace ZeroTier { - -class VirtualTap; - -/** - * @brief Static utility class for safely handling VirtualTap(s) - */ -class VirtualTapManager -{ -public: - - static void add_tap(VirtualTap *tap); - static VirtualTap *getTapByNWID(uint64_t nwid); - static size_t get_vtaps_size(); - static void remove_by_nwid(uint64_t nwid); - static void clear(); - static void get_network_details_helper(void *zt1ServiceRef, uint64_t nwid, struct zts_network_details *nd); - static void get_network_details(void *zt1ServiceRef, uint64_t nwid, struct zts_network_details *nd); - static void get_all_network_details(void *zt1ServiceRef, struct zts_network_details *nds, int *num); -}; - -} // namespace ZeroTier - -#endif // _H \ No newline at end of file diff --git a/include/lwIP.h b/include/lwIP.h index 22c40e3..c4d146d 100644 --- a/include/lwIP.h +++ b/include/lwIP.h @@ -37,11 +37,31 @@ #include "lwip/err.h" namespace ZeroTier { - class MAC; - class Mutex; - class VirtualTap; - struct InetAddress; -} + +class MAC; +class Mutex; +class VirtualTap; +struct InetAddress; + +/** + * @brief Structure used to associate packets with interfaces. + */ +struct zts_sorted_packet +{ + // lwIP pbuf containing packet (originally encapsulated by ZT packet) + struct pbuf *p; + // ZT VirtualTap from which this packet originates + ZeroTier::VirtualTap *vtap; + // lwIP netif we should accept this packet on + struct netif *n; +}; + +/** + * @brief Return whether a given netif's NETIF_FLAG_UP flag is set + * + * @usage This is a convenience function to encapsulate a macro + */ +bool lwip_is_netif_up(void *netif); /** * @brief Increase the delay multiplier for the main driver loop @@ -76,15 +96,14 @@ void lwip_driver_init(); void lwip_driver_shutdown(); /** - * @brief Bring all interfaces down belonging to the given virtual tap interface + * @brief Bring down and delete all interfaces belonging to the given virtual tap * * @usage This is to be called when the application desires to stop all traffic processing in the * stack. Unlike lwip_driver_shutdown(), the application can easily resume traffic processing * by re-adding a virtual tap (and associated lwip netifs) * @return */ -void lwip_driver_set_tap_interfaces_down(void *tapref); -void lwip_driver_set_all_interfaces_down(); +void lwip_dispose_of_netifs(void *tapref); /** * @brief Initialize and start the DNS client @@ -128,7 +147,7 @@ static void netif_link_callback(struct netif *netif); * @param ip Virtual IP address for this ZeroTier VirtualTap interface * @return */ -void lwip_init_interface(void *tapref, const ZeroTier::MAC &mac, const ZeroTier::InetAddress &ip); +void lwip_init_interface(void *tapref, const MAC &mac, const InetAddress &ip); /** * @brief Called from the stack, outbound ethernet frames from the network stack enter the ZeroTier virtual wire here. @@ -152,7 +171,9 @@ err_t lwip_eth_tx(struct netif *netif, struct pbuf *p); * @param len Length of Ethernet frame * @return */ -void lwip_eth_rx(ZeroTier::VirtualTap *tap, const ZeroTier::MAC &from, const ZeroTier::MAC &to, unsigned int etherType, +void lwip_eth_rx(VirtualTap *tap, const MAC &from, const MAC &to, unsigned int etherType, const void *data, unsigned int len); +} // namespace ZeroTier + #endif // _H diff --git a/include/lwipopts.h b/include/lwipopts.h index e72350d..8847ccb 100644 --- a/include/lwipopts.h +++ b/include/lwipopts.h @@ -53,7 +53,7 @@ */ #if __ANDROID__ #define LWIP_PROVIDE_ERRNO 1 -//#define SOCKLEN_T_DEFINED +#define SOCKLEN_T_DEFINED #elif !defined(_MSC_VER) #define LWIP_PROVIDE_ERRNO 1 #endif @@ -61,7 +61,7 @@ /** * Disable assertions */ -#define LWIP_NOASSERT 0 +#define LWIP_NOASSERT 1 /** * Don't redefine byte-order functions if they're already available @@ -103,6 +103,33 @@ */ #define LWIP_DBG_HALT 0x08U +/*------------------------------------------------------------------------------ +---------------------------------- Timers -------------------------------------- +------------------------------------------------------------------------------*/ +/* +Be careful about setting this too small. lwIP just counts the number +of times its timer is called and uses this to control time sensitive +operations (such as TCP retransmissions), rather than actually +measuring time using something more accurate. If you call the timer +functions very frequently you may see things (such as retransmissions) +happening sooner than they should. +*/ +/* these are originally defined in tcp_impl.h */ +#ifndef TCP_TMR_INTERVAL +/* The TCP timer interval in milliseconds. */ +#define TCP_TMR_INTERVAL 250 +#endif /* TCP_TMR_INTERVAL */ + +#ifndef TCP_FAST_INTERVAL +/* the fine grained timeout in milliseconds */ +#define TCP_FAST_INTERVAL TCP_TMR_INTERVAL +#endif /* TCP_FAST_INTERVAL */ + +#ifndef TCP_SLOW_INTERVALs +/* the coarse grained timeout in milliseconds */ +#define TCP_SLOW_INTERVAL (2*TCP_TMR_INTERVAL) +#endif /* TCP_SLOW_INTERVAL */ + /*------------------------------------------------------------------------------ ----------------------- Below: Modified contents of opt.h ---------------------- ------------------------------------------------------------------------------*/ @@ -243,7 +270,7 @@ * Your system should provide mutexes supporting priority inversion to use this. */ #if !defined LWIP_TCPIP_CORE_LOCKING || defined __DOXYGEN__ -#define LWIP_TCPIP_CORE_LOCKING 0 +#define LWIP_TCPIP_CORE_LOCKING 1 #endif /** @@ -350,7 +377,7 @@ * a lot of data that needs to be copied, this should be set high. */ #if !defined MEM_SIZE || defined __DOXYGEN__ -#define MEM_SIZE 1600 +#define MEM_SIZE 1024 * 1024 #endif /** @@ -464,7 +491,7 @@ * this should be set high. */ #if !defined MEMP_NUM_PBUF || defined __DOXYGEN__ -#define MEMP_NUM_PBUF 16 +#define MEMP_NUM_PBUF 1024 #endif /** @@ -472,7 +499,7 @@ * (requires the LWIP_RAW option) */ #if !defined MEMP_NUM_RAW_PCB || defined __DOXYGEN__ -#define MEMP_NUM_RAW_PCB 4 +#define MEMP_NUM_RAW_PCB 1024 #endif /** @@ -481,7 +508,7 @@ * (requires the LWIP_UDP option) */ #if !defined MEMP_NUM_UDP_PCB || defined __DOXYGEN__ -#define MEMP_NUM_UDP_PCB 4 +#define MEMP_NUM_UDP_PCB 1024 #endif /** @@ -489,7 +516,7 @@ * (requires the LWIP_TCP option) */ #if !defined MEMP_NUM_TCP_PCB || defined __DOXYGEN__ -#define MEMP_NUM_TCP_PCB 5 +#define MEMP_NUM_TCP_PCB 1024 #endif /** @@ -497,7 +524,7 @@ * (requires the LWIP_TCP option) */ #if !defined MEMP_NUM_TCP_PCB_LISTEN || defined __DOXYGEN__ -#define MEMP_NUM_TCP_PCB_LISTEN 8 +#define MEMP_NUM_TCP_PCB_LISTEN 1024 #endif /** @@ -505,7 +532,7 @@ * (requires the LWIP_TCP option) */ #if !defined MEMP_NUM_TCP_SEG || defined __DOXYGEN__ -#define MEMP_NUM_TCP_SEG 16 +#define MEMP_NUM_TCP_SEG 1024 #endif /** @@ -523,7 +550,7 @@ * reassembly (whole packets, not fragments!) */ #if !defined MEMP_NUM_REASSDATA || defined __DOXYGEN__ -#define MEMP_NUM_REASSDATA 5 +#define MEMP_NUM_REASSDATA 16 #endif /** @@ -585,7 +612,7 @@ * (only needed if you use the sequential API, like api_lib.c) */ #if !defined MEMP_NUM_NETCONN || defined __DOXYGEN__ -#define MEMP_NUM_NETCONN 4 +#define MEMP_NUM_NETCONN 256 #endif /** @@ -603,7 +630,7 @@ * (only needed if you use tcpip.c) */ #if !defined MEMP_NUM_TCPIP_MSG_API || defined __DOXYGEN__ -#define MEMP_NUM_TCPIP_MSG_API 8 +#define MEMP_NUM_TCPIP_MSG_API 64 #endif /** @@ -612,7 +639,7 @@ * (only needed if you use tcpip.c) */ #if !defined MEMP_NUM_TCPIP_MSG_INPKT || defined __DOXYGEN__ -#define MEMP_NUM_TCPIP_MSG_INPKT 8 +#define MEMP_NUM_TCPIP_MSG_INPKT 64 #endif /** @@ -635,7 +662,7 @@ * PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */ #if !defined PBUF_POOL_SIZE || defined __DOXYGEN__ -#define PBUF_POOL_SIZE 16 +#define PBUF_POOL_SIZE 128 #endif /** MEMP_NUM_API_MSG: the number of concurrently active calls to various @@ -689,7 +716,7 @@ * ARP_TABLE_SIZE: Number of active MAC-IP address pairs cached. */ #if !defined ARP_TABLE_SIZE || defined __DOXYGEN__ -#define ARP_TABLE_SIZE 10 +#define ARP_TABLE_SIZE 64 #endif /** the time an ARP entry stays valid after its last update, @@ -847,7 +874,7 @@ * (PBUF_POOL_SIZE > 2 * IP_REASS_MAX_PBUFS)! */ #if !defined IP_REASS_MAX_PBUFS || defined __DOXYGEN__ -#define IP_REASS_MAX_PBUFS 10 +#define IP_REASS_MAX_PBUFS 32 #endif /** @@ -1292,7 +1319,7 @@ * will be TCP_WND >> TCP_RCV_SCALE */ #if !defined TCP_WND || defined __DOXYGEN__ -#define TCP_WND (4 * TCP_MSS) +#define TCP_WND 0xffff // (4 * TCP_MSS) #endif /** @@ -1306,7 +1333,7 @@ * TCP_SYNMAXRTX: Maximum number of retransmissions of SYN segments. */ #if !defined TCP_SYNMAXRTX || defined __DOXYGEN__ -#define TCP_SYNMAXRTX 6 +#define TCP_SYNMAXRTX 12 // 6 #endif /** @@ -1367,7 +1394,7 @@ * To achieve good performance, this should be at least 2 * TCP_MSS. */ #if !defined TCP_SND_BUF || defined __DOXYGEN__ -#define TCP_SND_BUF (2 * TCP_MSS) +#define TCP_SND_BUF 1024 * 32 // (2 * TCP_MSS) #endif /** @@ -1375,7 +1402,7 @@ * as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. */ #if !defined TCP_SND_QUEUELEN || defined __DOXYGEN__ -#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1))/(TCP_MSS)) +#define TCP_SND_QUEUELEN 1024 // ((4 * (TCP_SND_BUF) + (TCP_MSS - 1))/(TCP_MSS)) #endif /** @@ -1689,7 +1716,7 @@ * if you have a tiny ARP table or if there never are concurrent connections. */ #if !defined LWIP_NETIF_HWADDRHINT || defined __DOXYGEN__ -#define LWIP_NETIF_HWADDRHINT 0 +#define LWIP_NETIF_HWADDRHINT 1 #endif /** @@ -2005,7 +2032,7 @@ * (only used if you use sockets.c) */ #if !defined LWIP_COMPAT_SOCKETS || defined __DOXYGEN__ -#define LWIP_COMPAT_SOCKETS 1 +#define LWIP_COMPAT_SOCKETS 0 #endif /** @@ -2014,7 +2041,7 @@ * names (read, write & close). (only used if you use sockets.c) */ #if !defined LWIP_POSIX_SOCKETS_IO_NAMES || defined __DOXYGEN__ -#define LWIP_POSIX_SOCKETS_IO_NAMES 1 +#define LWIP_POSIX_SOCKETS_IO_NAMES 0 #endif /** @@ -2152,7 +2179,7 @@ * LWIP_STATS==1: Enable statistics collection in lwip_stats. */ #if !defined LWIP_STATS || defined __DOXYGEN__ -#define LWIP_STATS 1 +#define LWIP_STATS 0 #endif #if LWIP_STATS @@ -2161,7 +2188,7 @@ * LWIP_STATS_DISPLAY==1: Compile in the statistics output functions. */ #if !defined LWIP_STATS_DISPLAY || defined __DOXYGEN__ -#define LWIP_STATS_DISPLAY 1 +#define LWIP_STATS_DISPLAY 0 #endif /** @@ -3572,4 +3599,4 @@ * @} */ -#endif /* LWIP_HDR_OPT_H */ +#endif /* LWIP_HDR_OPT_H */ \ No newline at end of file diff --git a/src/ServiceControls.cpp b/src/ServiceControls.cpp index 0467187..faf1e30 100644 --- a/src/ServiceControls.cpp +++ b/src/ServiceControls.cpp @@ -37,10 +37,11 @@ #include "ZeroTierOne.h" #include "Constants.hpp" -#include "VirtualTapManager.hpp" #include "lwIP.h" #include "OSUtils.hpp" #include "ServiceControls.hpp" +#include "VirtualTap.hpp" +#include "Defs.hpp" #include "lwip/stats.h" @@ -53,8 +54,14 @@ WSADATA wsaData; #include #endif +struct zts_network_details; +struct zts_peer_details; +struct zts_network_details; + namespace ZeroTier { +class VirtualTap; + /* * A lock used to protect any call which relies on the presence of a valid pointer * to the ZeroTier service. @@ -91,6 +98,7 @@ Mutex _vtaps_lock; // Global reference to ZeroTier service OneService *zt1Service; + // User-provided callback for ZeroTier events void (*_userCallbackFunc)(uint64_t, int); #ifdef SDK_JNI @@ -99,9 +107,8 @@ static JavaVM *jvm = NULL; jobject objRef = NULL; jmethodID _userCallbackMethodRef = NULL; #endif -} -using namespace ZeroTier; +std::map peerCache; ////////////////////////////////////////////////////////////////////////////// // Internal ZeroTier Service Controls (user application shall not use these)// @@ -112,8 +119,8 @@ std::queue*> _callbackMsgQueue; void _push_callback_event(uint64_t nwid, int eventCode) { _callback_lock.lock(); - if (_callbackMsgQueue.size() >= 128) { - DEBUG_ERROR("too many callback messages in queue"); + if (_callbackMsgQueue.size() >= ZTS_CALLBACK_MSG_QUEUE_LEN) { + DEBUG_ERROR("too many callback messages in queue (see: ZTS_CALLBACK_MSG_QUEUE_LEN)"); _callback_lock.unlock(); return; } @@ -132,7 +139,7 @@ void _process_callback_event_helper(uint64_t nwid, int eventCode) } #else if (_userCallbackFunc) { - _userCallbackFunc((uint64_t)0, ZTS_EVENT_NODE_OFFLINE); + _userCallbackFunc(nwid, eventCode); } #endif } @@ -192,11 +199,13 @@ int _zts_can_perform_service_operation() void _hibernate_if_needed() { - if (VirtualTapManager::get_vtaps_size()) { + _vtaps_lock.lock(); + if (vtapMap.size()) { lwip_wake_driver(); } else { lwip_hibernate_driver(); } + _vtaps_lock.unlock(); } #ifdef SDK_JNI #endif @@ -204,7 +213,7 @@ void _hibernate_if_needed() /* * Monitors the conditions required for triggering callbacks into user code. This was made * into its own thread to prevent user application abuse of callbacks from affecting - * the timing of more sensitive aspects of the library such as polling and RX/TX of packets + * the timing of more sensitive aspects of the library such as polling and packet processing */ #if defined(_WIN32) DWORD WINAPI _zts_monitor_callback_conditions(LPVOID thread_id) @@ -215,74 +224,188 @@ void *_zts_monitor_callback_conditions(void *thread_id) #if defined(__APPLE__) pthread_setname_np(ZTS_EVENT_CALLBACK_THREAD_NAME); #endif - while (!_serviceIsShuttingDown) + + while (true) { + if (_serviceIsShuttingDown) { + break; + } + _service_lock.lock(); + _callback_lock.lock(); + +#if ZTS_NODE_CALLBACKS + // ZT Node states if (!_zts_node_online()) { if (_nodeIsOnlineToggle) { _nodeIsOnlineToggle = false; - _process_callback_event((uint64_t)0, ZTS_EVENT_NODE_OFFLINE); + _process_callback_event_helper((uint64_t)0, ZTS_EVENT_NODE_OFFLINE); + } + _service_lock.unlock(); + _callback_lock.unlock(); + _api_sleep(ZTS_CALLBACK_PROCESSING_INTERVAL); + // Only process pending network callbacks if the node is online + continue; + } + if (_zts_node_online()) { + uint64_t nodeId = 0; + if (_zts_can_perform_service_operation()) { + nodeId = zt1Service->getNode()->address(); } - } if (_zts_node_online()) { // Only process pending network callbacks if the node is online if (!_nodeIsOnlineToggle) { _nodeIsOnlineToggle = true; - _process_callback_event((uint64_t)0, ZTS_EVENT_NODE_ONLINE); + _process_callback_event_helper(nodeId, ZTS_EVENT_NODE_ONLINE); } + } +#endif - // First, handle queued messages from other threads - _callback_lock.lock(); - while (_callbackMsgQueue.size()) { - std::pair *msg = _callbackMsgQueue.front(); - _callbackMsgQueue.pop(); - _process_callback_event_helper(msg->first, msg->second); - delete msg; - } - _callback_lock.unlock(); - - // Second, inspect network states for changes we should report - _vtaps_lock.lock(); - ZT_VirtualNetworkList *nl = zt1Service->getNode()->networks(); - for(unsigned long i=0;inetworkCount;++i) { - OneService::NetworkSettings localSettings; - zt1Service->getNetworkSettings(nl->networks[i].nwid,localSettings); - if (vtapMap[nl->networks[i].nwid]->_lastReportedStatus != nl->networks[i].status) { - switch (nl->networks[i].status) { - case ZT_NETWORK_STATUS_NOT_FOUND: - _process_callback_event(nl->networks[i].nwid, ZTS_EVENT_NETWORK_NOT_FOUND); - break; - case ZT_NETWORK_STATUS_CLIENT_TOO_OLD: - _process_callback_event(nl->networks[i].nwid, ZTS_EVENT_NETWORK_CLIENT_TOO_OLD); - break; - case ZT_NETWORK_STATUS_REQUESTING_CONFIGURATION: - _process_callback_event(nl->networks[i].nwid, ZTS_EVENT_NETWORK_REQUESTING_CONFIG); - break; - case ZT_NETWORK_STATUS_OK: - _process_callback_event(nl->networks[i].nwid, ZTS_EVENT_NETWORK_OK); - break; - case ZT_NETWORK_STATUS_ACCESS_DENIED: - _process_callback_event(nl->networks[i].nwid, ZTS_EVENT_NETWORK_ACCESS_DENIED); - break; - default: - break; + // Handle messages placed in the message queue + while (_callbackMsgQueue.size()) { + std::pair *msg = _callbackMsgQueue.front(); + _callbackMsgQueue.pop(); +#if ZTS_NETIF_CALLBACKS + // lwIP netif + if (msg->second & (ZTS_EVENT_NETIF_STATUS_CHANGE)) { + _vtaps_lock.lock(); + if (!vtapMap.count(msg->first)) { + if (msg->second & (ZTS_EVENT_GENERIC_DOWN)) { + _process_callback_event_helper(msg->first, msg->second); } - vtapMap[nl->networks[i].nwid]->_lastReportedStatus = nl->networks[i].status; + delete msg; + msg = NULL; + _vtaps_lock.unlock(); + continue; } + if (msg->second == ZTS_EVENT_NETIF_UP_IP4 && vtapMap[msg->first]->_networkStatus == ZTS_EVENT_NETWORK_OK) { + _process_callback_event_helper(msg->first, ZTS_EVENT_NETWORK_READY_IP4); + } + if (msg->second == ZTS_EVENT_NETIF_UP_IP6 && vtapMap[msg->first]->_networkStatus == ZTS_EVENT_NETWORK_OK) { + _process_callback_event_helper(msg->first, ZTS_EVENT_NETWORK_READY_IP6); + } + if (msg->second & (ZTS_EVENT_NETIF_STATUS_CHANGE)) { + vtapMap[msg->first]->_netifStatus = msg->second; + } + _vtaps_lock.unlock(); + _process_callback_event_helper(msg->first, msg->second); } - zt1Service->getNode()->freeQueryResult((void *)nl); - // Finally, check for a more useful definition of "readiness" +#endif // ZTS_NETIF_CALLBACKS + delete msg; + msg = NULL; + } + +#if ZTS_NETIF_CALLBACKS // Section for non-queued lwIP netif messages + // lwIP netif states + _vtaps_lock.lock(); + if (vtapMap.size()) { std::map::iterator it; for (it = vtapMap.begin(); it != vtapMap.end(); it++) { - VirtualTap *tap = it->second; - if (tap->_lastConfigUpdateTime > 0 && !tap->_lastReadyReportTime && tap->_ips.size() > 0) { - tap->_lastReadyReportTime = tap->_lastConfigUpdateTime; - _process_callback_event(tap->_nwid, ZTS_EVENT_NETWORK_READY); + VirtualTap *vtap = (VirtualTap*)it->second; + uint64_t eventCode = vtap->recognizeLowerLevelInterfaceStateChange(vtap->netif4); + if (eventCode != ZTS_EVENT_NONE) { + _process_callback_event_helper(vtap->_nwid, eventCode); + } + eventCode = vtap->recognizeLowerLevelInterfaceStateChange(vtap->netif6); + if (eventCode != ZTS_EVENT_NONE) { + _process_callback_event_helper(vtap->_nwid, eventCode); } } - _vtaps_lock.unlock(); } - // Doesn't need to happen as often as other API operations - _api_sleep(ZTS_WRAPPER_CHECK_INTERVAL); + _vtaps_lock.unlock(); +#endif // ZTS_NETIF_CALLBACKS + +#if ZTS_PEER_CALLBACKS + // TODO: Add peerCache clearning mechanism + // TODO: Add ZTS_EVENT_PEER_NEW message? + ZT_PeerList *pl = zt1Service->getNode()->peers(); + if (pl) { + for(unsigned long i=0;ipeerCount;++i) { + if (!peerCache.count(pl->peers[i].address)) { // Add first entry + if (pl->peers[i].pathCount > 0) { + _process_callback_event_helper(pl->peers[i].address, ZTS_EVENT_PEER_P2P); + } + if (pl->peers[i].pathCount == 0) { + _process_callback_event_helper(pl->peers[i].address, ZTS_EVENT_PEER_RELAY); + } + } + else { + if (peerCache[pl->peers[i].address] == 0 && pl->peers[i].pathCount > 0) { + _process_callback_event_helper(pl->peers[i].address, ZTS_EVENT_PEER_P2P); + } + if (peerCache[pl->peers[i].address] > 0 && pl->peers[i].pathCount == 0) { + _process_callback_event_helper(pl->peers[i].address, ZTS_EVENT_PEER_RELAY); + } + } + peerCache[pl->peers[i].address] = pl->peers[i].pathCount; + } + } + zt1Service->getNode()->freeQueryResult((void *)pl); +#endif // ZTS_PEER_CALLBACKS + +#if ZTS_NETWORK_CALLBACKS + + _vtaps_lock.lock(); + // Second, inspect network states for changes we should report + // TODO: Use proper ZT callback mechanism + // TODO: _push_callback_event(_nwid, ZTS_EVENT_NETWORK_DOWN); + ZT_VirtualNetworkList *nl = zt1Service->getNode()->networks(); + for(unsigned long i=0;inetworkCount;++i) { + OneService::NetworkSettings localSettings; + zt1Service->getNetworkSettings(nl->networks[i].nwid,localSettings); + if (!vtapMap.count(nl->networks[i].nwid)) { + continue; + } + if (vtapMap[nl->networks[i].nwid]->_networkStatus == nl->networks[i].status) { + continue; // no state change + } + VirtualTap *vtap = vtapMap[nl->networks[i].nwid]; + uint64_t nwid = nl->networks[i].nwid; + switch (nl->networks[i].status) { + case ZT_NETWORK_STATUS_NOT_FOUND: + _process_callback_event_helper(nwid, ZTS_EVENT_NETWORK_NOT_FOUND); + break; + case ZT_NETWORK_STATUS_CLIENT_TOO_OLD: + _process_callback_event_helper(nwid, ZTS_EVENT_NETWORK_CLIENT_TOO_OLD); + break; + case ZT_NETWORK_STATUS_REQUESTING_CONFIGURATION: + _process_callback_event_helper(nwid, ZTS_EVENT_NETWORK_REQUESTING_CONFIG); + break; + case ZT_NETWORK_STATUS_OK: + if (vtap->netif4 && lwip_is_netif_up(vtap->netif4)) { + _process_callback_event_helper(nwid, ZTS_EVENT_NETWORK_READY_IP4); + } + if (vtap->netif6 && lwip_is_netif_up(vtap->netif6)) { + _process_callback_event_helper(nwid, ZTS_EVENT_NETWORK_READY_IP6); + } + _process_callback_event_helper(nwid, ZTS_EVENT_NETWORK_OK); + break; + case ZT_NETWORK_STATUS_ACCESS_DENIED: + _process_callback_event_helper(nwid, ZTS_EVENT_NETWORK_ACCESS_DENIED); + break; + default: + break; + } + vtapMap[nwid]->_networkStatus = nl->networks[i].status; + } + _vtaps_lock.unlock(); + zt1Service->getNode()->freeQueryResult((void *)nl); + +#endif // ZTS_NETWORK_CALLBACKS + + // Finally, check for a more useful definition of "readiness" + /* + std::map::iterator it; + for (it = vtapMap.begin(); it != vtapMap.end(); it++) { + VirtualTap *tap = it->second; + if (tap->_lastConfigUpdateTime > 0 && !tap->_lastReadyReportTime && tap->_ips.size() > 0) { + tap->_lastReadyReportTime = tap->_lastConfigUpdateTime; + _process_callback_event(tap->_nwid, ZTS_EVENT_NETWORK_READY); + } + }*/ + _service_lock.unlock(); + _callback_lock.unlock(); + _api_sleep(ZTS_CALLBACK_PROCESSING_INTERVAL); } - DEBUG_ERROR("exiting from monitor loop"); + DEBUG_INFO("exited from callback processing loop"); + pthread_exit(0); } // Starts a ZeroTier service in the background @@ -306,7 +429,6 @@ void *_zts_start_service(void *thread_id) DEBUG_INFO("service already started, doing nothing"); retval = NULL; } - try { std::vector hpsp(OSUtils::split(homeDir.c_str(), ZT_PATH_SEPARATOR_S,"","")); std::string ptmp; @@ -367,10 +489,11 @@ void *_zts_start_service(void *thread_id) _service_lock.unlock(); _serviceIsShuttingDown = false; _process_callback_event((uint64_t)0, ZTS_EVENT_NODE_DOWN); + DEBUG_INFO("exiting zt service thread"); } catch ( ... ) { DEBUG_ERROR("unexpected exception starting ZeroTier instance"); } - pthread_exit(NULL); + pthread_exit(0); } #ifdef __cplusplus @@ -434,7 +557,11 @@ JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_get_1service_1port( zts_err_t zts_join(const uint64_t nwid, int blocking) { zts_err_t retval = ZTS_ERR_OK; - retval = VirtualTapManager::get_vtaps_size() >= ZTS_MAX_JOINED_NETWORKS ? ZTS_ERR_INVALID_OP : ZTS_ERR_OK; + + _vtaps_lock.lock(); + retval = vtapMap.size() >= ZTS_MAX_JOINED_NETWORKS ? ZTS_ERR_INVALID_OP : ZTS_ERR_OK; + _vtaps_lock.unlock(); + if (retval == ZTS_ERR_OK) { _service_lock.lock(); if (blocking) { @@ -463,7 +590,6 @@ zts_err_t zts_join(const uint64_t nwid, int blocking) } } _service_lock.unlock(); - _hibernate_if_needed(); } return retval; } @@ -504,8 +630,9 @@ zts_err_t zts_leave(const uint64_t nwid, int blocking) zt1Service->getNode()->leave(nwid, NULL, NULL); } } - VirtualTapManager::remove_by_nwid(nwid); - _hibernate_if_needed(); + _vtaps_lock.lock(); + vtapMap.erase(nwid); + _vtaps_lock.unlock(); _service_lock.unlock(); return retval; } @@ -520,6 +647,7 @@ JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_leave( zts_err_t zts_leave_all(int blocking) { zts_err_t retval = ZTS_ERR_OK; + /* if (!zt1Service || _freeHasBeenCalled || _serviceIsShuttingDown) { retval = ZTS_ERR_SERVICE; } @@ -531,6 +659,8 @@ zts_err_t zts_leave_all(int blocking) zts_leave(nds[i].nwid); } } + */ + return retval; } #ifdef SDK_JNI @@ -588,7 +718,9 @@ JNIEXPORT jboolean JNICALL Java_com_zerotier_libzt_ZeroTier_core_1running( int zts_ready() { _service_lock.lock(); - bool stackRunning = VirtualTapManager::get_vtaps_size() > 0 ? true : false; + _vtaps_lock.lock(); + bool stackRunning = vtapMap.size() > 0 ? true : false; + _vtaps_lock.unlock(); _service_lock.unlock(); return zts_core_running() && stackRunning; } @@ -693,8 +825,6 @@ zts_err_t zts_start_with_callback(const char *path, void (*callback)(uint64_t, i } } _startup_lock.unlock(); - // if (blocking && retval == ZTS_ERR_OK) { DEBUG_INFO("node=%llx online", (unsigned long long)zts_get_node_id());} - _hibernate_if_needed(); return retval; } @@ -754,7 +884,6 @@ zts_err_t zts_startjoin(const char *path, const uint64_t nwid) retval = ZTS_ERR_SERVICE; } } - _hibernate_if_needed(); return retval; } #ifdef SDK_JNI @@ -773,11 +902,26 @@ zts_err_t zts_stop(int blocking) { zts_err_t retval = ZTS_ERR_OK; _service_lock.lock(); + // leave all networks + /* + _vtaps_lock.lock(); + if (vtapMap.size()) { + std::map::iterator it; + for (it = vtapMap.begin(); it != vtapMap.end(); it++) { + VirtualTap *vtap = (VirtualTap*)it->second; + zt1Service->getNode()->leave(vtap->_nwid, NULL, NULL); + } + vtapMap.clear(); + } + _vtaps_lock.unlock(); + */ + // begin shutdown + peerCache.clear(); // TODO: Ensure this is locked correctly bool didStop = false; if (_zts_can_perform_service_operation()) { - didStop = true; + _serviceIsShuttingDown = true; zt1Service->terminate(); - VirtualTapManager::clear(); + didStop = true; } else { // Nothing to do @@ -791,7 +935,6 @@ zts_err_t zts_stop(int blocking) // Block until ZT service thread successfully exits pthread_join(service_thread, NULL); } - _hibernate_if_needed(); _clear_registered_callback(); return retval; } @@ -898,7 +1041,9 @@ zts_err_t zts_get_num_joined_networks() retval = ZTS_ERR_SERVICE; } else { - retval = VirtualTapManager::get_vtaps_size(); + _vtaps_lock.lock(); + retval = vtapMap.size(); + _vtaps_lock.unlock(); } return retval; } @@ -910,8 +1055,50 @@ JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_get_1num_1joined_1networ } #endif +////////////////////////////////////////////////////////////////////////////// +// Network Details // +////////////////////////////////////////////////////////////////////////////// + +void __get_network_details_helper(uint64_t nwid, struct zts_network_details *nd) +{ + socklen_t addrlen; + VirtualTap *tap = vtapMap[nwid]; + nd->nwid = tap->_nwid; + nd->mtu = tap->_mtu; + // assigned addresses + nd->num_addresses = tap->_ips.size() < ZTS_MAX_ASSIGNED_ADDRESSES ? tap->_ips.size() : ZTS_MAX_ASSIGNED_ADDRESSES; + for (int j=0; jnum_addresses; j++) { + addrlen = tap->_ips[j].isV4() ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6); + memcpy(&(nd->addr[j]), &(tap->_ips[j]), addrlen); + } + // routes + nd->num_routes = ZTS_MAX_NETWORK_ROUTES;; + zt1Service->getRoutes(nwid, (ZT_VirtualNetworkRoute*)&(nd->routes)[0], &(nd->num_routes)); +} + +void _get_network_details(uint64_t nwid, struct zts_network_details *nd) +{ + _vtaps_lock.lock(); + __get_network_details_helper(nwid, nd); + _vtaps_lock.unlock(); +} + +void _get_all_network_details(struct zts_network_details *nds, int *num) +{ + _vtaps_lock.lock(); + *num = vtapMap.size(); + int idx = 0; + std::map::iterator it; + for (it = vtapMap.begin(); it != vtapMap.end(); it++) { + _get_network_details(it->first, &nds[idx]); + idx++; + } + _vtaps_lock.unlock(); +} + zts_err_t zts_get_network_details(uint64_t nwid, struct zts_network_details *nd) { + _service_lock.lock(); zts_err_t retval = ZTS_ERR_OK; if (!nd || nwid == 0) { retval = ZTS_ERR_INVALID_ARG; @@ -920,8 +1107,9 @@ zts_err_t zts_get_network_details(uint64_t nwid, struct zts_network_details *nd) retval = ZTS_ERR_SERVICE; } if (retval == ZTS_ERR_OK) { - VirtualTapManager::get_network_details(zt1Service, nwid, nd); + _get_network_details(nwid, nd); } + _service_lock.unlock(); return retval; } #ifdef SDK_JNI @@ -929,6 +1117,7 @@ zts_err_t zts_get_network_details(uint64_t nwid, struct zts_network_details *nd) zts_err_t zts_get_all_network_details(struct zts_network_details *nds, int *num) { + _service_lock.lock(); zts_err_t retval = ZTS_ERR_OK; if (!nds || !num) { retval = ZTS_ERR_INVALID_ARG; @@ -937,13 +1126,18 @@ zts_err_t zts_get_all_network_details(struct zts_network_details *nds, int *num) retval = ZTS_ERR_SERVICE; } if (retval == ZTS_ERR_OK) { - VirtualTapManager::get_all_network_details(zt1Service, nds, num); + _get_all_network_details(nds, num); } + _service_lock.unlock(); return retval; } #ifdef SDK_JNI #endif +////////////////////////////////////////////////////////////////////////////// +// HTTP Backplane // +////////////////////////////////////////////////////////////////////////////// + zts_err_t zts_enable_http_backplane_mgmt() { zts_err_t retval = ZTS_ERR_OK; @@ -979,3 +1173,5 @@ zts_err_t zts_disable_http_backplane_mgmt() #ifdef __cplusplus } #endif + +} // namespace ZeroTier \ No newline at end of file diff --git a/src/VirtualTap.cpp b/src/VirtualTap.cpp index aedcb9a..76a287d 100644 --- a/src/VirtualTap.cpp +++ b/src/VirtualTap.cpp @@ -36,10 +36,11 @@ #include "OSUtils.hpp" #include "Constants.hpp" // libzt +#include "ServiceControls.hpp" +#include "OneService.hpp" extern void _push_callback_event(uint64_t nwid, int eventCode); #include "Mutex.hpp" -#include "VirtualTapManager.hpp" #include "lwIP.h" #ifdef _MSC_VER @@ -48,8 +49,12 @@ extern void _push_callback_event(uint64_t nwid, int eventCode); namespace ZeroTier { +class VirtualTap; + extern OneService *zt1Service; extern void (*_userCallbackFunc)(uint64_t, int); +extern std::map vtapMap; +extern Mutex _vtaps_lock; /** * A virtual tap device. The ZeroTier core service creates one of these for each @@ -77,28 +82,59 @@ VirtualTap::VirtualTap( _unixListenSocket((PhySocket *)0), _phy(this,false,true) { - VirtualTapManager::add_tap(this); memset(vtap_full_name, 0, sizeof(vtap_full_name)); snprintf(vtap_full_name, sizeof(vtap_full_name), "libzt%llx", (unsigned long long)_nwid); _dev = vtap_full_name; ::pipe(_shutdownSignalPipe); + + _vtaps_lock.lock(); + vtapMap[_nwid] = this; + _vtaps_lock.unlock(); + lwip_driver_init(); - // start virtual tap thread and stack I/O loops + // Start virtual tap thread and stack I/O loops _thread = Thread::start(this); } VirtualTap::~VirtualTap() { - _push_callback_event(_nwid, ZTS_EVENT_NETWORK_DOWN); - lwip_driver_set_tap_interfaces_down(this); _run = false; ::write(_shutdownSignalPipe[1],"\0",1); _phy.whack(); + lwip_dispose_of_netifs(this); Thread::join(_thread); ::close(_shutdownSignalPipe[0]); ::close(_shutdownSignalPipe[1]); } +uint64_t VirtualTap::recognizeLowerLevelInterfaceStateChange(void *n) +{ + if (!n) { + return ZTS_EVENT_NONE; + } + if (n == netif4) { + if (netif4WasUpLastCheck && !lwip_is_netif_up(netif4)) { + netif4WasUpLastCheck = false; + return ZTS_EVENT_NETIF_DOWN_IP4; + } + if (!netif4WasUpLastCheck && lwip_is_netif_up(netif4)) { + netif4WasUpLastCheck = true; + return ZTS_EVENT_NETIF_UP_IP4; + } + } + if (n == netif6) { + if (netif6WasUpLastCheck && !lwip_is_netif_up(netif6)) { + netif6WasUpLastCheck = false; + return ZTS_EVENT_NETIF_DOWN_IP6; + } + if (!netif6WasUpLastCheck && lwip_is_netif_up(netif6)) { + netif6WasUpLastCheck = true; + return ZTS_EVENT_NETIF_UP_IP6; + } + } + return ZTS_EVENT_NONE; +} + void VirtualTap::lastConfigUpdate(uint64_t lastConfigUpdateTime) { _lastConfigUpdateTime = lastConfigUpdateTime; @@ -114,20 +150,15 @@ bool VirtualTap::enabled() const return _enabled; } -void VirtualTap::registerIpWithStack(const InetAddress &ip) -{ - lwip_init_interface((void*)this, this->_mac, ip); -} - bool VirtualTap::addIp(const InetAddress &ip) { char ipbuf[INET6_ADDRSTRLEN]; Mutex::Lock _l(_ips_m); - registerIpWithStack(ip); if (std::find(_ips.begin(),_ips.end(),ip) == _ips.end()) { _ips.push_back(ip); std::sort(_ips.begin(),_ips.end()); } + lwip_init_interface((void*)this, this->_mac, ip); return true; } @@ -231,7 +262,8 @@ void VirtualTap::threadMain() while (true) { FD_SET(_shutdownSignalPipe[0],&readfds); select(nfds,&readfds,&nullfds,&nullfds,&tv); - if (FD_ISSET(_shutdownSignalPipe[0],&readfds)) { // writes to shutdown pipe terminate thread + // writes to shutdown pipe terminate thread + if (FD_ISSET(_shutdownSignalPipe[0],&readfds)) { break; } #ifdef _MSC_VER diff --git a/src/VirtualTapManager.cpp b/src/VirtualTapManager.cpp deleted file mode 100644 index fedb38c..0000000 --- a/src/VirtualTapManager.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -/** - * @file - * - * Management of virtual tap interfaces - */ - -#include "VirtualTap.hpp" -#include "VirtualTapManager.hpp" -#include "ServiceControls.hpp" -#include "OneService.hpp" - -namespace ZeroTier { - -extern std::map vtapMap; -extern Mutex _vtaps_lock; -extern void (*_userCallbackFunc)(uint64_t, int); - -class VirtualTap; - -void VirtualTapManager::add_tap(VirtualTap *tap) { - _vtaps_lock.lock(); - vtapMap[tap->_nwid] = tap; - _vtaps_lock.unlock(); -} - -VirtualTap *VirtualTapManager::getTapByNWID(uint64_t nwid) { - _vtaps_lock.lock(); - VirtualTap *s, *tap = vtapMap[nwid]; - _vtaps_lock.unlock(); - return tap; -} - -size_t VirtualTapManager::get_vtaps_size() { - size_t sz; - _vtaps_lock.lock(); - sz = vtapMap.size(); - _vtaps_lock.unlock(); - return sz; -} - -void VirtualTapManager::remove_by_nwid(uint64_t nwid) { - _vtaps_lock.lock(); - vtapMap.erase(nwid); - _vtaps_lock.unlock(); -} - -void VirtualTapManager::clear() { - _vtaps_lock.lock(); - vtapMap.clear(); - _vtaps_lock.unlock(); -} - -void VirtualTapManager::get_network_details_helper(void *zt1ServiceRef, uint64_t nwid, struct zts_network_details *nd) -{ - socklen_t addrlen; - VirtualTap *tap = vtapMap[nwid]; - nd->nwid = tap->_nwid; - nd->mtu = tap->_mtu; - // assigned addresses - nd->num_addresses = tap->_ips.size() < ZTS_MAX_ASSIGNED_ADDRESSES ? tap->_ips.size() : ZTS_MAX_ASSIGNED_ADDRESSES; - for (int j=0; jnum_addresses; j++) { - addrlen = tap->_ips[j].isV4() ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6); - memcpy(&(nd->addr[j]), &(tap->_ips[j]), addrlen); - } - // routes - nd->num_routes = ZTS_MAX_NETWORK_ROUTES; - OneService *zt1Service = (OneService*)zt1ServiceRef; - zt1Service->getRoutes(nwid, (ZT_VirtualNetworkRoute*)&(nd->routes)[0], &(nd->num_routes)); -} - -void VirtualTapManager::get_network_details(void *zt1ServiceRef, uint64_t nwid, struct zts_network_details *nd) { - _vtaps_lock.lock(); - get_network_details_helper(zt1ServiceRef, nwid, nd); - _vtaps_lock.unlock(); -} - -void VirtualTapManager::get_all_network_details(void *zt1ServiceRef, struct zts_network_details *nds, int *num) { - - _vtaps_lock.lock(); - *num = vtapMap.size(); - int idx = 0; - std::map::iterator it; - for (it = vtapMap.begin(); it != vtapMap.end(); it++) { - get_network_details(zt1ServiceRef, it->first, &nds[idx]); - idx++; - } - _vtaps_lock.unlock(); -} - -} // namespace ZeroTier \ No newline at end of file diff --git a/src/lwIP.cpp b/src/lwIP.cpp index 4aa4a0a..9a776cc 100644 --- a/src/lwIP.cpp +++ b/src/lwIP.cpp @@ -60,28 +60,22 @@ #if defined(_WIN32) #include -void ms_sleep(unsigned long ms) -{ - Sleep(ms); -} #endif -std::queue rx_queue; - -ZeroTier::Mutex _rx_input_lock_m; +namespace ZeroTier { bool main_loop_exited = false; bool lwip_driver_initialized = false; bool has_already_been_initialized = false; int hibernationDelayMultiplier = 1; -ZeroTier::Mutex driver_m; +Mutex driver_m; -ZeroTier::MAC _mac; // TODO: Should remove this - -std::vector lwip_netifs; +std::queue rx_queue; +ZeroTier::Mutex _rx_input_lock_m; extern void _push_callback_event(uint64_t nwid, int eventCode); +extern void _process_callback_event_helper(uint64_t nwid, int eventCode); void lwip_hibernate_driver() { @@ -108,10 +102,8 @@ void my_tcpip_callback(void *arg) if (main_loop_exited) { return; } - // stats_display(); err_t err = ERR_OK; int loop_score = LWIP_FRAMES_HANDLED_PER_CORE_CALL; // max num of packets to read per polling call - // TODO: Optimize (use Ringbuffer) while (loop_score > 0) { // TODO: Swap this block out for a thread-safe container _rx_input_lock_m.lock(); @@ -119,75 +111,32 @@ void my_tcpip_callback(void *arg) _rx_input_lock_m.unlock(); return; } - struct pbuf *p = rx_queue.front(); + struct zts_sorted_packet *sp = rx_queue.front(); + struct pbuf *p = sp->p; rx_queue.pop(); _rx_input_lock_m.unlock(); - - // Packet routing logic. Inputs packet into correct lwip netif interface depending on protocol type - struct ip_hdr *iphdr; - switch (((struct eth_hdr *)p->payload)->type) - { - case PP_HTONS(ETHTYPE_IPV6): { - iphdr = (struct ip_hdr *)((char *)p->payload + SIZEOF_ETH_HDR); - for (size_t i=0; ioutput_ip6 && - lwip_netifs[i]->output_ip6 == ethip6_output) { - // TODO: Check prefix match? - if ((err = lwip_netifs[i]->input(p, lwip_netifs[i])) != ERR_OK) { - DEBUG_ERROR("packet input error (ipv6, p=%p, netif=%p)=%d", p, &lwip_netifs[i], err); - pbuf_free(p); - } - break; - } - } - } break; - case PP_HTONS(ETHTYPE_IP): { - iphdr = (struct ip_hdr *)((char *)p->payload + SIZEOF_ETH_HDR); - for (size_t i=0; ioutput && - lwip_netifs[i]->output == etharp_output) { - if (lwip_netifs[i]->ip_addr.u_addr.ip4.addr == iphdr->dest.addr || - ip4_addr_isbroadcast_u32(iphdr->dest.addr, lwip_netifs[i])) { - if ((err = lwip_netifs[i]->input(p, lwip_netifs[i])) != ERR_OK) { - DEBUG_ERROR("packet input error (ipv4, p=%p, netif=%p)=%d", p, &lwip_netifs[i], err); - pbuf_free(p); - } - break; - } - } - } - } break; - case PP_HTONS(ETHTYPE_ARP): { - for (size_t i=0; istate) { - //pbuf_ref(p); - if ((err = lwip_netifs[i]->input(p, lwip_netifs[i])) != ERR_OK) { - DEBUG_ERROR("packet input error (arp, p=%p, netif=%p)=%d", p, &lwip_netifs[i], err); - pbuf_free(p); - } - break; - } - } - break; - } break; - default: - DEBUG_INFO("unhandled packet type (p=%p)", p); - break; + // Feed packet into appropriate lwIP netif + if (sp->p && sp->n) { + if ((err = sp->n->input(sp->p, sp->n)) != ERR_OK) { + DEBUG_ERROR("packet input error (p=%p, n=%p)=%d", p, sp->n, err); + pbuf_free(p); + } + sp->p = NULL; } - // - p = NULL; + delete sp; + sp = NULL; loop_score--; } } -// main thread which starts the initialization process +// Main thread which starts the initialization process static void main_lwip_driver_loop(void *arg) { #if defined(__linux__) - pthread_setname_np(pthread_self(), "lwip_driver_loop"); + pthread_setname_np(pthread_self(), "lwipDriver"); #endif #if defined(__APPLE__) - pthread_setname_np("lwip_driver_loop"); + pthread_setname_np("lwipDriver"); #endif sys_sem_t sem; LWIP_UNUSED_ARG(arg); @@ -199,7 +148,7 @@ static void main_lwip_driver_loop(void *arg) sys_sem_wait(&sem); while(lwip_driver_initialized) { #if defined(_WIN32) - ms_sleep(LWIP_GUARDED_BUF_CHECK_INTERVAL*hibernationDelayMultiplier); + Sleep(LWIP_GUARDED_BUF_CHECK_INTERVAL*hibernationDelayMultiplier); #else usleep(LWIP_GUARDED_BUF_CHECK_INTERVAL*1000*hibernationDelayMultiplier); #endif @@ -247,34 +196,22 @@ void lwip_driver_shutdown() } } -void lwip_driver_set_all_interfaces_down() +void lwip_dispose_of_netifs(void *tapref) { - for (size_t i=0; inetif4) { + netif_remove((struct netif*)(vtap->netif4)); + netif_set_down((struct netif*)(vtap->netif4)); + netif_set_link_down((struct netif*)(vtap->netif4)); + delete vtap->netif4; + vtap->netif4 = NULL; } - lwip_netifs.clear(); -} - -void lwip_driver_set_tap_interfaces_down(void *tapref) -{ - int sz_i = lwip_netifs.size(); - std::vector::iterator iter; - for (iter = lwip_netifs.begin(); iter != lwip_netifs.end(); ) { - struct netif *lp = *(iter); - if (lp->state == tapref) { - netif_remove(lp); - netif_set_down(lp); - netif_set_link_down(lp); - iter = lwip_netifs.erase(iter); - } - else { - ++iter; - } + if (vtap->netif6) { + netif_remove((struct netif*)(vtap->netif6)); + netif_set_down((struct netif*)(vtap->netif6)); + netif_set_link_down((struct netif*)(vtap->netif6)); + delete vtap->netif6; + vtap->netif6 = NULL; } } @@ -304,7 +241,7 @@ err_t lwip_eth_tx(struct netif *netif, struct pbuf *p) int len = totalLength - sizeof(struct eth_hdr); int proto = ZeroTier::Utils::ntoh((uint16_t)ethhdr->type); tap->_handler(tap->_arg, NULL, tap->_nwid, src_mac, dest_mac, proto, 0, data, len); - +/* if (ZT_MSG_TRANSFER == true) { char flagbuf[32]; memset(&flagbuf, 0, 32); @@ -318,6 +255,7 @@ err_t lwip_eth_tx(struct netif *netif, struct pbuf *p) DEBUG_TRANS("len=%5d dst=%s [%s TX <-- %s] proto=0x%04x %s", totalLength, macBuf, nodeBuf, tap->nodeId().c_str(), ZeroTier::Utils::ntoh(ethhdr->type), flagbuf); } +*/ return ERR_OK; @@ -326,23 +264,18 @@ err_t lwip_eth_tx(struct netif *netif, struct pbuf *p) void lwip_eth_rx(ZeroTier::VirtualTap *tap, const ZeroTier::MAC &from, const ZeroTier::MAC &to, unsigned int etherType, const void *data, unsigned int len) { - if (!lwip_netifs.size()) { - DEBUG_ERROR("there are no netifs set up to handle this packet. ignoring."); - return; - } - struct pbuf *p,*q; struct eth_hdr ethhdr; from.copyTo(ethhdr.src.addr, 6); to.copyTo(ethhdr.dest.addr, 6); ethhdr.type = ZeroTier::Utils::hton((uint16_t)etherType); - +/* if (ZT_MSG_TRANSFER == true) { char flagbuf[32]; memset(&flagbuf, 0, 32); char macBuf[ZTS_MAC_ADDRSTRLEN], nodeBuf[ZTS_ID_LEN]; snprintf(macBuf, ZTS_MAC_ADDRSTRLEN, "%02x:%02x:%02x:%02x:%02x:%02x", - ethhdr.dest.addr[0], ethhdr.dest.addr[1], ethhdr.dest.addr[2], + ethhdr.dest.addr[0], ethhdr.dest.addr[1], ethhdr.dest.addr[2], ethhdr.dest.addr[3], ethhdr.dest.addr[4], ethhdr.dest.addr[5]); ZeroTier::MAC mac; mac.setTo(ethhdr.src.addr, 6); @@ -350,7 +283,20 @@ void lwip_eth_rx(ZeroTier::VirtualTap *tap, const ZeroTier::MAC &from, const Zer DEBUG_TRANS("len=%5d dst=%s [%s RX --> %s] proto=0x%04x %s", len, macBuf, nodeBuf, tap->nodeId().c_str(), ZeroTier::Utils::ntoh(ethhdr.type), flagbuf); } - +*/ + if (etherType == 0x0800 || etherType == 0x0806) { // ip4 or ARP + if (!tap->netif4) { + DEBUG_ERROR("dropped packet: no netif to accept this packet (etherType=%x) on this vtap (%p)", etherType, tap); + return; + } + } + if (etherType == 0x86DD) { // ip6 + if (!tap->netif6) { + DEBUG_ERROR("dropped packet: no netif to accept this packet (etherType=%x) on this vtap (%p)", etherType, tap); + return; + } + } + p = pbuf_alloc(PBUF_RAW, len+sizeof(struct eth_hdr), PBUF_RAM); if (!p) { DEBUG_ERROR("dropped packet: unable to allocate memory for pbuf"); @@ -374,6 +320,7 @@ void lwip_eth_rx(ZeroTier::VirtualTap *tap, const ZeroTier::MAC &from, const Zer memcpy(q->payload,dataptr,q->len); dataptr += q->len; } + _rx_input_lock_m.lock(); if (rx_queue.size() >= LWIP_MAX_GUARDED_RX_BUF_SZ) { DEBUG_INFO("dropped packet: rx_queue is full (>= %d)", LWIP_MAX_GUARDED_RX_BUF_SZ); @@ -382,7 +329,26 @@ void lwip_eth_rx(ZeroTier::VirtualTap *tap, const ZeroTier::MAC &from, const Zer p = NULL; return; } - rx_queue.push(p); + + // Construct a pre-sorted packet for lwIP packet feeder timeout + struct zts_sorted_packet *sp = new struct zts_sorted_packet; + sp->p = p; + sp->vtap=tap; + + switch (etherType) + { + case 0x0800: // ip4 + case 0x0806: // ARP + sp->n = (struct netif *)tap->netif4; + break; + case 0x86DD: // ip6 + sp->n = (struct netif *)tap->netif6; + break; + default: + DEBUG_ERROR("dropped packet: unhandled (etherType=%x)", etherType); + break; + } + rx_queue.push(sp); _rx_input_lock_m.unlock(); } @@ -406,6 +372,11 @@ static void print_netif_info(struct netif *netif) { ); } +bool lwip_is_netif_up(void *netif) +{ + return netif_is_up((struct netif*)netif); +} + /** * Called when the status of a netif changes: * - Interface is up/down (ZTS_EVENT_NETIF_UP, ZTS_EVENT_NETIF_DOWN) @@ -413,21 +384,33 @@ static void print_netif_info(struct netif *netif) { */ static void netif_status_callback(struct netif *netif) { + // TODO: It appears that there may be a bug in lwIP's handling of callbacks for netifs + // configured to handle ipv4 traffic. For this reason a temporary measure of checking + // the status of the interfaces ourselves from the service is used. if (!netif->state) { return; } ZeroTier::VirtualTap *tap = (ZeroTier::VirtualTap *)netif->state; - // TODO: The following events may be triggered when there's simply a new - // address assignment, state will be kept in the virtual tap instead of - // at this lower level. This will allow us to filter out redundant events if (netif->flags & NETIF_FLAG_UP) { - _push_callback_event(tap->_nwid, ZTS_EVENT_NETIF_UP); + ZeroTier::VirtualTap *vtap = (ZeroTier::VirtualTap*)netif->state; + if (netif == vtap->netif6) { + // DEBUG_INFO("netif=%p, vtap->netif6=%p", netif, vtap->netif6); + _push_callback_event(tap->_nwid, ZTS_EVENT_NETIF_UP_IP6); + } + if (netif == vtap->netif4) { + // DEBUG_INFO("netif=%p, vtap->netif4=%p", netif, vtap->netif4); + _push_callback_event(tap->_nwid, ZTS_EVENT_NETIF_UP_IP4); + } } if (!(netif->flags & NETIF_FLAG_UP)) { - _push_callback_event(tap->_nwid, ZTS_EVENT_NETIF_DOWN); + if (netif->flags & NETIF_FLAG_MLD6) { + _push_callback_event(tap->_nwid, ZTS_EVENT_NETIF_DOWN_IP6); + } else { + _push_callback_event(tap->_nwid, ZTS_EVENT_NETIF_DOWN_IP4); + } } // TODO: ZTS_EVENT_NETIF_NEW_ADDRESS - print_netif_info(netif); + //print_netif_info(netif); } /** @@ -440,7 +423,7 @@ static void netif_remove_callback(struct netif *netif) } ZeroTier::VirtualTap *tap = (ZeroTier::VirtualTap *)netif->state; _push_callback_event(tap->_nwid, ZTS_EVENT_NETIF_REMOVED); - print_netif_info(netif); + //print_netif_info(netif); } /** @@ -458,14 +441,14 @@ static void netif_link_callback(struct netif *netif) if (netif->flags & NETIF_FLAG_LINK_UP) { _push_callback_event(tap->_nwid, ZTS_EVENT_NETIF_LINK_DOWN); } - print_netif_info(netif); + //print_netif_info(netif); } static err_t netif_init_4(struct netif *netif) { netif->hwaddr_len = 6; - netif->name[0] = 'e'; - netif->name[1] = '0'+lwip_netifs.size(); + netif->name[0] = 'z'; + netif->name[1] = '4'; netif->linkoutput = lwip_eth_tx; netif->output = etharp_output; netif->mtu = ZT_MAX_MTU; @@ -475,7 +458,6 @@ static err_t netif_init_4(struct netif *netif) | NETIF_FLAG_IGMP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP; - _mac.copyTo(netif->hwaddr, netif->hwaddr_len); netif->hwaddr_len = sizeof(netif->hwaddr); return ERR_OK; } @@ -483,8 +465,8 @@ static err_t netif_init_4(struct netif *netif) static err_t netif_init_6(struct netif *netif) { netif->hwaddr_len = 6; - netif->name[0] = 'e'; - netif->name[1] = '0'+(char)lwip_netifs.size(); + netif->name[0] = 'z'; + netif->name[1] = '6'; netif->linkoutput = lwip_eth_tx; netif->output = etharp_output; netif->output_ip6 = ethip6_output; @@ -494,7 +476,6 @@ static err_t netif_init_6(struct netif *netif) | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP | NETIF_FLAG_MLD6; - _mac.copyTo(netif->hwaddr, netif->hwaddr_len); netif->hwaddr_len = sizeof(netif->hwaddr); return ERR_OK; } @@ -503,10 +484,7 @@ void lwip_init_interface(void *tapref, const ZeroTier::MAC &mac, const ZeroTier: { char ipbuf[INET6_ADDRSTRLEN]; char macbuf[ZTS_MAC_ADDRSTRLEN]; - struct netif *lwipdev = new struct netif; - lwip_netifs.push_back(lwipdev); - - _mac = mac; + struct netif *n = new struct netif; if (ip.isV4()) { char nmbuf[INET6_ADDRSTRLEN]; @@ -514,37 +492,47 @@ void lwip_init_interface(void *tapref, const ZeroTier::MAC &mac, const ZeroTier: IP4_ADDR(&gw,127,0,0,1); ipaddr.addr = *((u32_t *)ip.rawIpData()); netmask.addr = *((u32_t *)ip.netmask().rawIpData()); - netif_add(lwipdev, &ipaddr, &netmask, &gw, NULL, netif_init_4, tcpip_input); - lwipdev->state = tapref; + netif_add(n, &ipaddr, &netmask, &gw, NULL, netif_init_4, tcpip_input); + n->state = tapref; + mac.copyTo(n->hwaddr, n->hwaddr_len); snprintf(macbuf, ZTS_MAC_ADDRSTRLEN, "%02x:%02x:%02x:%02x:%02x:%02x", - lwipdev->hwaddr[0], lwipdev->hwaddr[1], lwipdev->hwaddr[2], - lwipdev->hwaddr[3], lwipdev->hwaddr[4], lwipdev->hwaddr[5]); + n->hwaddr[0], n->hwaddr[1], n->hwaddr[2], + n->hwaddr[3], n->hwaddr[4], n->hwaddr[5]); DEBUG_INFO("initialized netif as [mac=%s, addr=%s, nm=%s]", macbuf, ip.toString(ipbuf), ip.netmask().toString(nmbuf)); + netif_set_up(n); + netif_set_link_up(n); + ZeroTier::VirtualTap *vtap = (ZeroTier::VirtualTap*)tapref; + vtap->netif4 = (void*)n; } if (ip.isV6()) { static ip6_addr_t ipaddr; memcpy(&(ipaddr.addr), ip.rawIpData(), sizeof(ipaddr.addr)); - lwipdev->ip6_autoconfig_enabled = 1; - netif_add(lwipdev, NULL, NULL, NULL, NULL, netif_init_6, tcpip_input); - netif_ip6_addr_set(lwipdev, 1, &ipaddr); - lwipdev->state = tapref; - netif_create_ip6_linklocal_address(lwipdev, 1); - netif_ip6_addr_set_state(lwipdev, 0, IP6_ADDR_TENTATIVE); - netif_ip6_addr_set_state(lwipdev, 1, IP6_ADDR_TENTATIVE); - netif_set_default(lwipdev); - netif_set_up(lwipdev); - netif_set_link_up(lwipdev); + n->ip6_autoconfig_enabled = 1; + netif_add(n, NULL, NULL, NULL, NULL, netif_init_6, tcpip_input); + netif_ip6_addr_set(n, 1, &ipaddr); + n->state = tapref; + mac.copyTo(n->hwaddr, n->hwaddr_len); + netif_create_ip6_linklocal_address(n, 1); + netif_ip6_addr_set_state(n, 0, IP6_ADDR_TENTATIVE); + netif_ip6_addr_set_state(n, 1, IP6_ADDR_TENTATIVE); + netif_set_default(n); + netif_set_up(n); + netif_set_link_up(n); snprintf(macbuf, ZTS_MAC_ADDRSTRLEN, "%02x:%02x:%02x:%02x:%02x:%02x", - lwipdev->hwaddr[0], lwipdev->hwaddr[1], lwipdev->hwaddr[2], - lwipdev->hwaddr[3], lwipdev->hwaddr[4], lwipdev->hwaddr[5]); + n->hwaddr[0], n->hwaddr[1], n->hwaddr[2], + n->hwaddr[3], n->hwaddr[4], n->hwaddr[5]); DEBUG_INFO("initialized netif as [mac=%s, addr=%s]", macbuf, ip.toString(ipbuf)); + ZeroTier::VirtualTap *vtap = (ZeroTier::VirtualTap*)tapref; + vtap->netif6 = (void*)n; } // Set netif callbacks, these will be used to inform decisions made // by the higher level callback monitor thread - netif_set_status_callback(lwipdev, netif_status_callback); - netif_set_remove_callback(lwipdev, netif_remove_callback); - netif_set_link_callback(lwipdev, netif_link_callback); + netif_set_status_callback(n, netif_status_callback); + netif_set_remove_callback(n, netif_remove_callback); + netif_set_link_callback(n, netif_link_callback); } + +} // namespace ZeroTier \ No newline at end of file