diff --git a/node/Socket.hpp b/attic/Socket.hpp similarity index 100% rename from node/Socket.hpp rename to attic/Socket.hpp diff --git a/node/SocketManager.hpp b/attic/SocketManager.hpp similarity index 100% rename from node/SocketManager.hpp rename to attic/SocketManager.hpp diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index 2c875a4f5..61cee72e7 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -35,21 +35,33 @@ #include -#ifndef ZT_SOCKADDR_STORAGE #if defined(_WIN32) || defined(_WIN64) #include #include #include #else /* not Windows */ +#include #include #endif /* Windows or not */ -#define ZT_SOCKADDR_STORAGE struct sockaddr_storage -#endif /* !ZT_SOCKADDR_STORAGE */ #ifdef __cplusplus extern "C" { #endif +/****************************************************************************/ +/* Core constants */ +/****************************************************************************/ + +/** + * Maximum frame MTU + */ +#define ZT1_MAX_MTU 2800 + +/** + * Maximum length of a wire message packet in bytes + */ +#define ZT1_MAX_WIRE_MESSAGE_LENGTH 1500 + /****************************************************************************/ /* Structures and other types */ /****************************************************************************/ @@ -149,9 +161,9 @@ typedef struct typedef struct { /** - * Remote socket address + * Socket address */ - ZT_SOCKADDR_STORAGE remoteAddress; + struct sockaddr_storage address; /** * Link desperation -- higher equals "worse" or "slower" @@ -191,7 +203,7 @@ typedef struct /** * Packet data */ - const void *packetData; + const char packetData[ZT1_MAX_WIRE_MESSAGE_LENGTH]; /** * Length of packet @@ -207,7 +219,7 @@ typedef struct /** * ZeroTier network ID of virtual LAN port */ - uint64_t networkId; + uint64_t nwid; /** * Source MAC address @@ -232,7 +244,7 @@ typedef struct /** * Ethernet frame data */ - const void *frameData; + const char frameData[ZT1_MAX_MTU]; /** * Ethernet frame length @@ -290,7 +302,7 @@ typedef struct /** * 64-bit ZeroTier network ID */ - uint64_t networkId; + uint64_t nwid; /** * Ethernet MAC (40 bits) that should be assigned to port @@ -346,7 +358,7 @@ typedef struct * This is only used for ZeroTier-managed address assignments sent by the * virtual network's configuration master. */ - const ZT_SOCKADDR_STORAGE *assignedAddresses; + const struct sockaddr_storage *assignedAddresses; /** * Number of assigned addresses @@ -376,7 +388,7 @@ typedef struct /** * Address of endpoint */ - ZT_SOCKADDR_STORAGE address; + struct sockaddr_storage address; /** * Time since last send in milliseconds or -1 for never @@ -466,7 +478,7 @@ typedef struct /** * Array of network paths to peer */ - struct ZT1_PeerPhysicalPath *paths; + ZT1_PeerPhysicalPath *paths; /** * Number of paths (size of paths[]) @@ -561,7 +573,7 @@ typedef int (*ZT1_DataStorePutFunction)(ZT1_Node *,const char *,const void *,uns * @param node Result: pointer is set to new node instance on success * @param dataStoreGetFunction Function called to get objects from persistent storage * @param dataStorePutFunction Function called to put objects in persistent storage - * @param portConfigCallback Function to be called when virtual LANs are created, deleted, or their config parameters change + * @param networkConfigCallback Function to be called when virtual LANs are created, deleted, or their config parameters change * @param statusCallback Function to receive status updates and non-fatal error notices * @return OK (0) or error code if a fatal error condition has occurred */ @@ -569,7 +581,7 @@ enum ZT1_ResultCode ZT1_Node_new( ZT1_Node **node, ZT1_DataStoreGetFunction *dataStoreGetFunction, ZT1_DataStorePutFunction *dataStorePutFunction, - ZT1_VirtualPortConfigCallback *portConfigCallback, + ZT1_VirtualNetworkConfigCallback *networkConfigCallback, ZT1_StatusCallback *statusCallback); /** @@ -609,11 +621,11 @@ enum ZT1_ResultCode ZT1_Node_run( uint64_t now, const ZT1_WireMessage *inputWireMessages, unsigned int inputWireMessageCount, - const ZT1_VirtualLanFrame *inputLanFrames, - unsigned int inputLanFrameCount, + const ZT1_VirtualNetworkFrame *inputFrames, + unsigned int inputFrameCount, const ZT1_WireMessage **outputWireMessages, unsigned int *outputWireMessageCount, - const ZT1_VirtualLanFrame **outputLanFrames, + const ZT1_VirtualNetworkFrame **outputFrames, unsigned int *outputLanFrameCount, unsigned long *maxNextInterval); @@ -624,10 +636,10 @@ enum ZT1_ResultCode ZT1_Node_run( * or these may be deffered if a netconf is not available yet. * * @param node Node instance - * @param networkId 64-bit ZeroTIer network ID + * @param nwid 64-bit ZeroTIer network ID * @return OK (0) or error code if a fatal error condition has occurred */ -enum ZT1_ResultCode ZT1_Node_join(ZT1_Node *node,uint64_t networkId); +enum ZT1_ResultCode ZT1_Node_join(ZT1_Node *node,uint64_t nwid); /** * Leave a network @@ -637,19 +649,18 @@ enum ZT1_ResultCode ZT1_Node_join(ZT1_Node *node,uint64_t networkId); * the port is now deleted. * * @param node Node instance - * @param networkId 64-bit network ID + * @param nwid 64-bit network ID * @return OK (0) or error code if a fatal error condition has occurred */ -enum ZT1_ResultCode ZT1_Node_leave(ZT1_Node *node,uint64_t networkId); +enum ZT1_ResultCode ZT1_Node_leave(ZT1_Node *node,uint64_t nwid); /** * Get the status of this node * * @param node Node instance * @param status Buffer to fill with current node status - * @return OK (0) or error code if a fatal error condition has occurred */ -enum ZT1_ResultCode ZT1_Node_status(ZT1_Node *node,ZT1_NodeStatus *status); +void ZT1_Node_status(ZT1_Node *node,ZT1_NodeStatus *status); /** * Get a list of known peer nodes @@ -710,6 +721,15 @@ enum ZT1_ResultCode ZT1_Node_setNetconfMaster( ZT1_Node *node, void *networkConfigMasterInstance); +/** + * Get ZeroTier One version + * + * @param major Result: major version + * @param minor Result: minor version + * @param revision Result: revision + */ +void ZT1_version(int *major,int *minor,int *revision); + #ifdef __cplusplus } #endif diff --git a/node/Constants.hpp b/node/Constants.hpp index 35efd0f8f..ff91417cf 100644 --- a/node/Constants.hpp +++ b/node/Constants.hpp @@ -299,16 +299,21 @@ */ #define ZT_STARTUP_AGGRO (ZT_PING_UNANSWERED_AFTER * 2) +/** + * How long since last message from an authoritative upstream peer before we increment our desperation level? + */ +#define ZT_DESPERATION_INCREMENT (ZT_STARTUP_AGGRO * 2) + +/** + * "Spam" packets to lower desperation links every Nth packet + */ +#define ZT_DESPERATION_SPAM_EVERY 10 + /** * Maximum delay between runs of the main loop in Node.cpp */ #define ZT_MAX_SERVICE_LOOP_INTERVAL ZT_STARTUP_AGGRO -/** - * Try TCP tunnels if nothing received for this long - */ -#define ZT_TCP_TUNNEL_FAILOVER_TIMEOUT (ZT_STARTUP_AGGRO * 5) - /** * Timeout for overall peer activity (measured from last receive) */ @@ -319,11 +324,6 @@ */ #define ZT_PEER_PATH_ACTIVITY_TIMEOUT ZT_PEER_ACTIVITY_TIMEOUT -/** - * Close TCP sockets if unused for this long (SocketManager) - */ -#define ZT_TCP_TUNNEL_ACTIVITY_TIMEOUT ZT_PEER_ACTIVITY_TIMEOUT - /** * Stop relaying via peers that have not responded to direct sends * @@ -374,28 +374,6 @@ */ #define ZT_MIN_BEACON_RESPONSE_INTERVAL (ZT_BEACON_INTERVAL / 32) -/** - * Minimum interval between attempts to do a software update - */ -#define ZT_UPDATE_MIN_INTERVAL 120000 - -/** - * Maximum interval between checks for new versions - */ -#define ZT_UPDATE_MAX_INTERVAL 7200000 - -/** - * Software update HTTP timeout in seconds - */ -#define ZT_UPDATE_HTTP_TIMEOUT 120 - -/** - * Delay between fetches of the root topology update URL - * - * 86400000 = check once every 24 hours (this doesn't change often) - */ -#define ZT_UPDATE_ROOT_TOPOLOGY_CHECK_INTERVAL 86400000 - /** * Sanity limit on maximum bridge routes * diff --git a/node/InetAddress.cpp b/node/InetAddress.cpp index 45781f42d..9452086a7 100644 --- a/node/InetAddress.cpp +++ b/node/InetAddress.cpp @@ -45,24 +45,29 @@ const InetAddress InetAddress::DEFAULT6((const void *)0,16,0); void InetAddress::set(const std::string &ip,unsigned int port) throw() { - memset(&_sa,0,sizeof(_sa)); if (ip.find(':') != std::string::npos) { - _sa.sin6.sin6_family = AF_INET6; - _sa.sin6.sin6_port = Utils::hton((uint16_t)port); - if (inet_pton(AF_INET6,ip.c_str(),(void *)&(_sa.sin6.sin6_addr.s6_addr)) <= 0) - _sa.saddr.sa_family = 0; + struct sockaddr_in6 sin6; + memset(&sin6,0,sizeof(sin6)); + sin6.sin6_family = AF_INET6; + sin6.sin6_port = Utils::hton((uint16_t)port); + if (inet_pton(AF_INET6,ip.c_str(),(void *)&(sin6.sin6_addr.s6_addr)) <= 0) + memset(this,0,sizeof(InetAddress)); + else *this = sin6; } else { - _sa.sin.sin_family = AF_INET; - _sa.sin.sin_port = Utils::hton((uint16_t)port); - if (inet_pton(AF_INET,ip.c_str(),(void *)&(_sa.sin.sin_addr.s_addr)) <= 0) - _sa.saddr.sa_family = 0; + struct sockaddr_in sin; + memset(&sin,0,sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_port = Utils::hton((uint16_t)port); + if (inet_pton(AF_INET,ip.c_str(),(void *)&(sin.sin_addr.s_addr)) <= 0) + memset(this,0,sizeof(InetAddress)); + else *this = sin; } } void InetAddress::set(const void *ipBytes,unsigned int ipLen,unsigned int port) throw() { - memset(&_sa,0,sizeof(_sa)); + memset(this,0,sizeof(InetAddress)); if (ipLen == 4) { setV4(); if (ipBytes) @@ -79,59 +84,87 @@ void InetAddress::set(const void *ipBytes,unsigned int ipLen,unsigned int port) bool InetAddress::isLinkLocal() const throw() { - if (_sa.saddr.sa_family == AF_INET) - return ((Utils::ntoh((uint32_t)_sa.sin.sin_addr.s_addr) & 0xffff0000) == 0xa9fe0000); - else if (_sa.saddr.sa_family == AF_INET6) { - if (_sa.sin6.sin6_addr.s6_addr[0] != 0xfe) return false; - if (_sa.sin6.sin6_addr.s6_addr[1] != 0x80) return false; - if (_sa.sin6.sin6_addr.s6_addr[2] != 0x00) return false; - if (_sa.sin6.sin6_addr.s6_addr[3] != 0x00) return false; - if (_sa.sin6.sin6_addr.s6_addr[4] != 0x00) return false; - if (_sa.sin6.sin6_addr.s6_addr[5] != 0x00) return false; - if (_sa.sin6.sin6_addr.s6_addr[6] != 0x00) return false; - if (_sa.sin6.sin6_addr.s6_addr[7] != 0x00) return false; - return true; + static const unsigned char v6llPrefix[8] = { 0xfe,0x80,0x00,0x00,0x00,0x00,0x00,0x00 }; + switch(ss_family) { + case AF_INET: + return ((Utils::ntoh((uint32_t)reinterpret_cast(this)->sin_addr.s_addr) & 0xffff0000) == 0xa9fe0000); + case AF_INET6: + return (memcmp(reinterpret_cast(this)->sin6_addr.s6_addr,v6llPrefix,8) == 0); } return false; } -bool InetAddress::isDefaultRoute() const - throw() -{ - if (_sa.saddr.sa_family == AF_INET) - return ((_sa.sin.sin_addr.s_addr == 0)&&(_sa.sin.sin_port == 0)); - else if (_sa.saddr.sa_family == AF_INET6) - return ((Utils::isZero(_sa.sin6.sin6_addr.s6_addr,16))&&(_sa.sin6.sin6_port == 0)); - return false; -} - std::string InetAddress::toString() const { - char buf[128],buf2[128]; - - switch(_sa.saddr.sa_family) { + char buf[128]; + switch(ss_family) { case AF_INET: -#ifdef __WINDOWS__ - if (inet_ntop(AF_INET,(PVOID)&(_sa.sin.sin_addr.s_addr),buf,sizeof(buf))) { -#else - if (inet_ntop(AF_INET,(const void *)&(_sa.sin.sin_addr.s_addr),buf,sizeof(buf))) { -#endif - Utils::snprintf(buf2,sizeof(buf2),"%s/%u",buf,(unsigned int)ntohs(_sa.sin.sin_port)); - return std::string(buf2); - } - break; + Utils::snprintf(buf,sizeof(buf),"%d.%d.%d.%d/%d", + (int)(reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr)))[0], + (int)(reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr)))[1], + (int)(reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr)))[2], + (int)(reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr)))[3], + (int)Utils::ntoh((uint16_t)(reinterpret_cast(this)->sin_port)) + ); + return std::string(buf); case AF_INET6: -#ifdef __WINDOWS__ - if (inet_ntop(AF_INET6,(PVOID)&(_sa.sin6.sin6_addr.s6_addr),buf,sizeof(buf))) { -#else - if (inet_ntop(AF_INET6,(const void *)&(_sa.sin6.sin6_addr.s6_addr),buf,sizeof(buf))) { -#endif - Utils::snprintf(buf2,sizeof(buf2),"%s/%u",buf,(unsigned int)ntohs(_sa.sin6.sin6_port)); - return std::string(buf2); - } - break; + Utils::snprintf(buf,sizeof(buf),"%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x/%d", + (int)(reinterpret_cast(this)->sin6_addr.s6_addr[0]), + (int)(reinterpret_cast(this)->sin6_addr.s6_addr[1]), + (int)(reinterpret_cast(this)->sin6_addr.s6_addr[2]), + (int)(reinterpret_cast(this)->sin6_addr.s6_addr[3]), + (int)(reinterpret_cast(this)->sin6_addr.s6_addr[4]), + (int)(reinterpret_cast(this)->sin6_addr.s6_addr[5]), + (int)(reinterpret_cast(this)->sin6_addr.s6_addr[6]), + (int)(reinterpret_cast(this)->sin6_addr.s6_addr[7]), + (int)(reinterpret_cast(this)->sin6_addr.s6_addr[8]), + (int)(reinterpret_cast(this)->sin6_addr.s6_addr[9]), + (int)(reinterpret_cast(this)->sin6_addr.s6_addr[10]), + (int)(reinterpret_cast(this)->sin6_addr.s6_addr[11]), + (int)(reinterpret_cast(this)->sin6_addr.s6_addr[12]), + (int)(reinterpret_cast(this)->sin6_addr.s6_addr[13]), + (int)(reinterpret_cast(this)->sin6_addr.s6_addr[14]), + (int)(reinterpret_cast(this)->sin6_addr.s6_addr[15]), + (int)Utils::ntoh((uint16_t)(reinterpret_cast(this)->sin6_port)) + ); + return std::string(buf); } + return std::string(); +} +std::string InetAddress::toIpString() const +{ + char buf[128]; + switch(ss_family) { + case AF_INET: + Utils::snprintf(buf,sizeof(buf),"%d.%d.%d.%d", + (int)(reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr)))[0], + (int)(reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr)))[1], + (int)(reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr)))[2], + (int)(reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr)))[3] + ); + return std::string(buf); + case AF_INET6: + Utils::snprintf(buf,sizeof(buf),"%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x", + (int)(reinterpret_cast(this)->sin6_addr.s6_addr[0]), + (int)(reinterpret_cast(this)->sin6_addr.s6_addr[1]), + (int)(reinterpret_cast(this)->sin6_addr.s6_addr[2]), + (int)(reinterpret_cast(this)->sin6_addr.s6_addr[3]), + (int)(reinterpret_cast(this)->sin6_addr.s6_addr[4]), + (int)(reinterpret_cast(this)->sin6_addr.s6_addr[5]), + (int)(reinterpret_cast(this)->sin6_addr.s6_addr[6]), + (int)(reinterpret_cast(this)->sin6_addr.s6_addr[7]), + (int)(reinterpret_cast(this)->sin6_addr.s6_addr[8]), + (int)(reinterpret_cast(this)->sin6_addr.s6_addr[9]), + (int)(reinterpret_cast(this)->sin6_addr.s6_addr[10]), + (int)(reinterpret_cast(this)->sin6_addr.s6_addr[11]), + (int)(reinterpret_cast(this)->sin6_addr.s6_addr[12]), + (int)(reinterpret_cast(this)->sin6_addr.s6_addr[13]), + (int)(reinterpret_cast(this)->sin6_addr.s6_addr[14]), + (int)(reinterpret_cast(this)->sin6_addr.s6_addr[15]) + ); + return std::string(buf); + } return std::string(); } @@ -148,64 +181,16 @@ void InetAddress::fromString(const std::string &ipSlashPort) } } -std::string InetAddress::toIpString() const -{ - char buf[128]; - switch(_sa.saddr.sa_family) { - case AF_INET: -#ifdef __WINDOWS__ - if (inet_ntop(AF_INET,(PVOID)&(_sa.sin.sin_addr.s_addr),buf,sizeof(buf))) - return std::string(buf); -#else - if (inet_ntop(AF_INET,(const void *)&(_sa.sin.sin_addr.s_addr),buf,sizeof(buf))) - return std::string(buf); -#endif - break; - case AF_INET6: -#ifdef __WINDOWS__ - if (inet_ntop(AF_INET6,(PVOID)&(_sa.sin6.sin6_addr.s6_addr),buf,sizeof(buf))) - return std::string(buf); -#else - if (inet_ntop(AF_INET6,(const void *)&(_sa.sin6.sin6_addr.s6_addr),buf,sizeof(buf))) - return std::string(buf); -#endif - break; - } - return std::string(); -} - InetAddress InetAddress::netmask() const throw() { InetAddress r(*this); - switch(_sa.saddr.sa_family) { + switch(r.ss_family) { case AF_INET: - r._sa.sin.sin_addr.s_addr = Utils::hton((uint32_t)(0xffffffff << (32 - netmaskBits()))); + reinterpret_cast(&r)->sin_addr.s_addr = Utils::hton((uint32_t)(0xffffffff << (32 - netmaskBits()))); break; case AF_INET6: { - unsigned char *bf = (unsigned char *)r._sa.sin6.sin6_addr.s6_addr; - signed int bitsLeft = (signed int)netmaskBits(); - for(unsigned int i=0;i<16;++i) { - if (bitsLeft > 0) { - bf[i] = (unsigned char)((bitsLeft >= 8) ? 0xff : (0xff << (8 - bitsLeft))); - bitsLeft -= 8; - } else bf[i] = (unsigned char)0; - } - } break; - } - return r; -} - -InetAddress InetAddress::broadcast() const - throw() -{ - InetAddress r(*this); - switch(_sa.saddr.sa_family) { - case AF_INET: - r._sa.sin.sin_addr.s_addr |= Utils::hton((uint32_t)(0xffffffff >> netmaskBits())); - break; - case AF_INET6: { - unsigned char *bf = (unsigned char *)r._sa.sin6.sin6_addr.s6_addr; + unsigned char *bf = reinterpret_cast(reinterpret_cast(&r)->sin6_addr.s6_addr); signed int bitsLeft = (signed int)netmaskBits(); for(unsigned int i=0;i<16;++i) { if (bitsLeft > 0) { @@ -218,130 +203,51 @@ InetAddress InetAddress::broadcast() const return r; } -bool InetAddress::sameNetworkAs(const InetAddress &ipnet) const +InetAddress InetAddress::broadcast() const throw() { - if (_sa.saddr.sa_family != ipnet._sa.saddr.sa_family) - return false; - - unsigned int bits = netmaskBits(); - if (bits != ipnet.netmaskBits()) - return false; - if (!bits) - return true; - switch(_sa.saddr.sa_family) { + InetAddress r(*this); + switch(r.ss_family) { case AF_INET: - if (bits >= 32) bits = 32; + reinterpret_cast(&r)->sin_addr.s_addr |= Utils::hton((uint32_t)(0xffffffff >> netmaskBits())); break; - case AF_INET6: - if (bits >= 128) bits = 128; - break; - default: - return false; + case AF_INET6: { + unsigned char *bf = reinterpret_cast(reinterpret_cast(&r)->sin6_addr.s6_addr); + signed int bitsLeft = (signed int)netmaskBits(); + for(unsigned int i=0;i<16;++i) { + if (bitsLeft > 0) { + bf[i] |= (unsigned char)((bitsLeft >= 8) ? 0x00 : (0xff >> bitsLeft)); + bitsLeft -= 8; + } + } + } break; } - - const uint8_t *a = (const uint8_t *)rawIpData(); - const uint8_t *b = (const uint8_t *)ipnet.rawIpData(); - while (bits >= 8) { - if (*(a++) != *(b++)) - return false; - bits -= 8; - } - bits = 8 - bits; - return ((*a >> bits) == (*b >> bits)); -} - -bool InetAddress::within(const InetAddress &ipnet) const - throw() -{ - if (_sa.saddr.sa_family != ipnet._sa.saddr.sa_family) - return false; - - unsigned int bits = ipnet.netmaskBits(); - switch(_sa.saddr.sa_family) { - case AF_INET: - if (bits > 32) return false; - break; - case AF_INET6: - if (bits > 128) return false; - break; - default: return false; - } - - const uint8_t *a = (const uint8_t *)rawIpData(); - const uint8_t *b = (const uint8_t *)ipnet.rawIpData(); - while (bits >= 8) { - if (*(a++) != *(b++)) - return false; - bits -= 8; - } - if (bits) { - uint8_t mask = ((0xff << (8 - bits)) & 0xff); - return ((*a & mask) == (*b & mask)); - } else return true; -} - -bool InetAddress::operator==(const InetAddress &a) const - throw() -{ - if (_sa.saddr.sa_family == AF_INET) { - if (a._sa.saddr.sa_family == AF_INET) - return ((_sa.sin.sin_addr.s_addr == a._sa.sin.sin_addr.s_addr)&&(_sa.sin.sin_port == a._sa.sin.sin_port)); - return false; - } else if (_sa.saddr.sa_family == AF_INET6) { - if (a._sa.saddr.sa_family == AF_INET6) { - if (_sa.sin6.sin6_port == a._sa.sin6.sin6_port) - return (!memcmp(_sa.sin6.sin6_addr.s6_addr,a._sa.sin6.sin6_addr.s6_addr,sizeof(_sa.sin6.sin6_addr.s6_addr))); - } - return false; - } else return (memcmp(&_sa,&a._sa,sizeof(_sa)) == 0); -} - -bool InetAddress::operator<(const InetAddress &a) const - throw() -{ - if (_sa.saddr.sa_family < a._sa.saddr.sa_family) - return true; - else if (_sa.saddr.sa_family == a._sa.saddr.sa_family) { - if (_sa.saddr.sa_family == AF_INET) { - unsigned long x = Utils::ntoh((uint32_t)_sa.sin.sin_addr.s_addr); - unsigned long y = Utils::ntoh((uint32_t)a._sa.sin.sin_addr.s_addr); - if (x == y) - return (Utils::ntoh((uint16_t)_sa.sin.sin_port) < Utils::ntoh((uint16_t)a._sa.sin.sin_port)); - else return (x < y); - } else if (_sa.saddr.sa_family == AF_INET6) { - int cmp = (int)memcmp(_sa.sin6.sin6_addr.s6_addr,a._sa.sin6.sin6_addr.s6_addr,16); - if (cmp == 0) - return (Utils::ntoh((uint16_t)_sa.sin6.sin6_port) < Utils::ntoh((uint16_t)a._sa.sin6.sin6_port)); - else return (cmp < 0); - } else return (memcmp(&_sa,&a._sa,sizeof(_sa)) < 0); - } - return false; + return r; } InetAddress InetAddress::makeIpv6LinkLocal(const MAC &mac) throw() { - InetAddress ip; - ip._sa.saddr.sa_family = AF_INET6; - ip._sa.sin6.sin6_addr.s6_addr[0] = 0xfe; - ip._sa.sin6.sin6_addr.s6_addr[1] = 0x80; - ip._sa.sin6.sin6_addr.s6_addr[2] = 0x00; - ip._sa.sin6.sin6_addr.s6_addr[3] = 0x00; - ip._sa.sin6.sin6_addr.s6_addr[4] = 0x00; - ip._sa.sin6.sin6_addr.s6_addr[5] = 0x00; - ip._sa.sin6.sin6_addr.s6_addr[6] = 0x00; - ip._sa.sin6.sin6_addr.s6_addr[7] = 0x00; - ip._sa.sin6.sin6_addr.s6_addr[8] = mac[0] & 0xfd; - ip._sa.sin6.sin6_addr.s6_addr[9] = mac[1]; - ip._sa.sin6.sin6_addr.s6_addr[10] = mac[2]; - ip._sa.sin6.sin6_addr.s6_addr[11] = 0xff; - ip._sa.sin6.sin6_addr.s6_addr[12] = 0xfe; - ip._sa.sin6.sin6_addr.s6_addr[13] = mac[3]; - ip._sa.sin6.sin6_addr.s6_addr[14] = mac[4]; - ip._sa.sin6.sin6_addr.s6_addr[15] = mac[5]; - ip._sa.sin6.sin6_port = Utils::hton((uint16_t)64); - return ip; + struct sockaddr_in6 sin6; + sin6.sin6_family = AF_INET6; + sin6.sin6_addr.s6_addr[0] = 0xfe; + sin6.sin6_addr.s6_addr[1] = 0x80; + sin6.sin6_addr.s6_addr[2] = 0x00; + sin6.sin6_addr.s6_addr[3] = 0x00; + sin6.sin6_addr.s6_addr[4] = 0x00; + sin6.sin6_addr.s6_addr[5] = 0x00; + sin6.sin6_addr.s6_addr[6] = 0x00; + sin6.sin6_addr.s6_addr[7] = 0x00; + sin6.sin6_addr.s6_addr[8] = mac[0] & 0xfd; + sin6.sin6_addr.s6_addr[9] = mac[1]; + sin6.sin6_addr.s6_addr[10] = mac[2]; + sin6.sin6_addr.s6_addr[11] = 0xff; + sin6.sin6_addr.s6_addr[12] = 0xfe; + sin6.sin6_addr.s6_addr[13] = mac[3]; + sin6.sin6_addr.s6_addr[14] = mac[4]; + sin6.sin6_addr.s6_addr[15] = mac[5]; + sin6.sin6_port = Utils::hton((uint16_t)64); + return InetAddress(sin6); } } // namespace ZeroTier diff --git a/node/InetAddress.hpp b/node/InetAddress.hpp index c041ffdf7..381c6ba2b 100644 --- a/node/InetAddress.hpp +++ b/node/InetAddress.hpp @@ -35,39 +35,20 @@ #include #include "Constants.hpp" +#include "../include/ZeroTierOne.h" #include "Utils.hpp" #include "MAC.hpp" -#ifdef __WINDOWS__ -#include -#include -#include -#else -#include -#include -#include -#endif - namespace ZeroTier { /** - * Wrapper for sockaddr structures for IPV4 and IPV6 + * Extends sockaddr_storage with friendly C++ methods * - * Note: this class is raw memcpy'able, which is used in a couple places. + * This adds no new fields, so it can be memcpy'd and assigned to/from + * raw sockaddr_storage structures. This is used in a few places. */ -class InetAddress +struct InetAddress : public sockaddr_storage { -public: - /** - * Address type - */ - enum AddressType - { - TYPE_NULL = 0, - TYPE_IPV4 = AF_INET, - TYPE_IPV6 = AF_INET6 - }; - /** * Loopback IPv4 address (no port) */ @@ -88,9 +69,16 @@ public: */ static const InetAddress DEFAULT6; - InetAddress() throw() { memset(&_sa,0,sizeof(_sa)); } - InetAddress(const InetAddress &a) throw() { memcpy(&_sa,&a._sa,sizeof(_sa)); } - InetAddress(const struct sockaddr *sa) throw() { this->set(sa); } + InetAddress() throw() { memset(this,0,sizeof(InetAddress)); } + InetAddress(const InetAddress &a) throw() { memcpy(this,&a,sizeof(InetAddress)); } + InetAddress(const struct sockaddr_storage &ss) throw() { *this = ss; } + InetAddress(const struct sockaddr_storage *ss) throw() { *this = ss; } + InetAddress(const struct sockaddr &sa) throw() { *this = sa; } + InetAddress(const struct sockaddr *sa) throw() { *this = sa; } + InetAddress(const struct sockaddr_in &sa) throw() { *this = sa; } + InetAddress(const struct sockaddr_in *sa) throw() { *this = sa; } + InetAddress(const struct sockaddr_in6 &sa) throw() { *this = sa; } + InetAddress(const struct sockaddr_in6 *sa) throw() { *this = sa; } InetAddress(const void *ipBytes,unsigned int ipLen,unsigned int port) throw() { this->set(ipBytes,ipLen,port); } InetAddress(const uint32_t ipv4,unsigned int port) throw() { this->set(&ipv4,4,port); } InetAddress(const std::string &ip,unsigned int port) throw() { this->set(ip,port); } @@ -100,23 +88,84 @@ public: inline InetAddress &operator=(const InetAddress &a) throw() { - memcpy(&_sa,&a._sa,sizeof(_sa)); + memcpy(this,&a,sizeof(InetAddress)); return *this; } - /** - * Set from an OS-level sockaddr structure - * - * @param sa Socket address (V4 or V6) - */ - inline void set(const struct sockaddr *sa) + inline InetAddress &operator=(const struct sockaddr_storage &ss) throw() { - switch(sa->sa_family) { - case AF_INET: memcpy(&_sa.sin,sa,sizeof(struct sockaddr_in)); break; - case AF_INET6: memcpy(&_sa.sin6,sa,sizeof(struct sockaddr_in6)); break; - default: memset(&_sa,0,sizeof(_sa)); break; + memcpy(this,&ss,sizeof(InetAddress)); + return *this; + } + + inline InetAddress &operator=(const struct sockaddr_storage *ss) + throw() + { + memcpy(this,ss,sizeof(InetAddress)); + return *this; + } + + inline InetAddress &operator=(const struct sockaddr_in &sa) + throw() + { + memset(this,0,sizeof(InetAddress)); + memcpy(this,&sa,sizeof(struct sockaddr_in)); + return *this; + } + + inline InetAddress &operator=(const struct sockaddr_in *sa) + throw() + { + memset(this,0,sizeof(InetAddress)); + memcpy(this,sa,sizeof(struct sockaddr_in)); + return *this; + } + + inline InetAddress &operator=(const struct sockaddr_in6 &sa) + throw() + { + memset(this,0,sizeof(InetAddress)); + memcpy(this,&sa,sizeof(struct sockaddr_in6)); + return *this; + } + + inline InetAddress &operator=(const struct sockaddr_in6 *sa) + throw() + { + memset(this,0,sizeof(InetAddress)); + memcpy(this,sa,sizeof(struct sockaddr_in6)); + return *this; + } + + inline InetAddress &operator=(const struct sockaddr &sa) + throw() + { + memset(this,0,sizeof(InetAddress)); + switch(sa.sa_family) { + case AF_INET: + memcpy(this,&sa,sizeof(struct sockaddr_in)); + break; + case AF_INET6: + memcpy(this,&sa,sizeof(struct sockaddr_in6)); + break; } + return *this; + } + + inline InetAddress &operator=(const struct sockaddr *sa) + throw() + { + memset(this,0,sizeof(InetAddress)); + switch(sa->sa_family) { + case AF_INET: + memcpy(this,sa,sizeof(struct sockaddr_in)); + break; + case AF_INET6: + memcpy(this,sa,sizeof(struct sockaddr_in6)); + break; + } + return *this; } /** @@ -146,10 +195,14 @@ public: inline void setPort(unsigned int port) throw() { - if (_sa.saddr.sa_family == AF_INET) - _sa.sin.sin_port = Utils::hton((uint16_t)port); - else if (_sa.saddr.sa_family == AF_INET6) - _sa.sin6.sin6_port = Utils::hton((uint16_t)port); + switch(ss_family) { + case AF_INET: + reinterpret_cast(this)->sin_port = Utils::hton((uint16_t)port); + break; + case AF_INET6: + reinterpret_cast(this)->sin6_port = Utils::hton((uint16_t)port); + break; + } } /** @@ -158,45 +211,35 @@ public: bool isLinkLocal() const throw(); - /** - * @return True if this ip/netmask would represent a default route (e.g. 0.0.0.0/0) - */ - bool isDefaultRoute() const - throw(); - /** * @return True if this is a loopback address */ - inline bool isLoopback() const - throw() - { - return ((*this == LO4)||(*this == LO6)); - } + inline bool isLoopback() const throw() { return ((*this == LO4)||(*this == LO6)); } /** * @return ASCII IP/port format representation */ std::string toString() const; - /** - * @param ipSlashPort ASCII IP/port format notation - */ - void fromString(const std::string &ipSlashPort); - /** * @return IP portion only, in ASCII string format */ std::string toIpString() const; + /** + * @param ipSlashPort ASCII IP/port format notation + */ + void fromString(const std::string &ipSlashPort); + /** * @return Port or 0 if no port component defined */ inline unsigned int port() const throw() { - switch(_sa.saddr.sa_family) { - case AF_INET: return Utils::ntoh((uint16_t)_sa.sin.sin_port); - case AF_INET6: return Utils::ntoh((uint16_t)_sa.sin6.sin6_port); + switch(ss_family) { + case AF_INET: return Utils::ntoh((uint16_t)(reinterpret_cast(this)->sin_port)); + case AF_INET6: return Utils::ntoh((uint16_t)(reinterpret_cast(this)->sin6_port)); default: return 0; } } @@ -229,33 +272,22 @@ public: /** * @return True if this is an IPv4 address */ - inline bool isV4() const throw() { return (_sa.saddr.sa_family == AF_INET); } + inline bool isV4() const throw() { return (ss_family == AF_INET); } /** * @return True if this is an IPv6 address */ - inline bool isV6() const throw() { return (_sa.saddr.sa_family == AF_INET6); } - - /** - * @return Address type or TYPE_NULL if not defined - */ - inline AddressType type() const throw() { return (AddressType)_sa.saddr.sa_family; } + inline bool isV6() const throw() { return (ss_family == AF_INET6); } /** * Force type to IPv4 */ - inline void setV4() throw() { _sa.saddr.sa_family = AF_INET; } + inline void setV4() throw() { ss_family = AF_INET; } /** * Force type to IPv6 */ - inline void setV6() throw() { _sa.saddr.sa_family = AF_INET6; } - - /** - * @return Raw sockaddr structure - */ - inline struct sockaddr *saddr() throw() { return &(_sa.saddr); } - inline const struct sockaddr *saddr() const throw() { return &(_sa.saddr); } + inline void setV6() throw() { ss_family = AF_INET6; } /** * @return Length of sockaddr_in if IPv4, sockaddr_in6 if IPv6 @@ -263,99 +295,62 @@ public: inline unsigned int saddrLen() const throw() { - switch(_sa.saddr.sa_family) { + switch(ss_family) { case AF_INET: return sizeof(struct sockaddr_in); case AF_INET6: return sizeof(struct sockaddr_in6); default: return 0; } } - /** - * @return Checksum of this address (not portable, so don't use for long-term storage purposes) - */ - inline uint64_t hashCode() const - { - switch(_sa.saddr.sa_family) { - case AF_INET: - return ((uint64_t)_sa.sin.sin_port + (uint64_t)(_sa.sin.sin_addr.s_addr)); - case AF_INET6: - return ((uint64_t)_sa.sin6.sin6_port + ( ((const uint64_t *)_sa.sin6.sin6_addr.s6_addr)[0] ^ ((const uint64_t *)_sa.sin6.sin6_addr.s6_addr)[1] )); - } - return 0; - } - - /** - * @return Combined length of internal structure, room for either V4 or V6 - */ - inline unsigned int saddrSpaceLen() const throw() { return sizeof(_sa); } - /** * @return Raw sockaddr_in structure (valid if IPv4) */ - inline const struct sockaddr_in *saddr4() const throw() { return &(_sa.sin); } + inline const struct sockaddr_in *saddr4() const throw() { return reinterpret_cast(this); } /** * @return Raw sockaddr_in6 structure (valid if IPv6) */ - inline const struct sockaddr_in6 *saddr6() const throw() { return &(_sa.sin6); } + inline const struct sockaddr_in6 *saddr6() const throw() { return reinterpret_cast(this); } /** - * @return Raw IP address (4 bytes for IPv4, 16 bytes for IPv6) + * @return pointer to raw IP address bytes */ - inline void *rawIpData() throw() { return ((_sa.saddr.sa_family == AF_INET) ? (void *)(&(_sa.sin.sin_addr.s_addr)) : (void *)_sa.sin6.sin6_addr.s6_addr); } - inline const void *rawIpData() const throw() { return ((_sa.saddr.sa_family == AF_INET) ? (void *)(&(_sa.sin.sin_addr.s_addr)) : (void *)_sa.sin6.sin6_addr.s6_addr); } - - /** - * Compare only the IP portions of addresses, ignoring port/netmask - * - * @param a Address to compare - * @return True if both addresses are of the same (valid) type and their IPs match - */ - inline bool ipsEqual(const InetAddress &a) const + inline const void *rawIpData() const throw() { - if (_sa.saddr.sa_family == a._sa.saddr.sa_family) { - switch(_sa.saddr.sa_family) { - case AF_INET: - return (_sa.sin.sin_addr.s_addr == a._sa.sin.sin_addr.s_addr); - case AF_INET6: - return (!memcmp(_sa.sin6.sin6_addr.s6_addr,a._sa.sin6.sin6_addr.s6_addr,16)); - } + switch(ss_family) { + case AF_INET: return (const void *)&(reinterpret_cast(this)->sin_addr.s_addr); + case AF_INET6: return (const void *)(reinterpret_cast(this)->sin6_addr.s6_addr); + default: return 0; } - return false; } /** - * Compare IP/netmask with another IP/netmask - * - * @param ipnet IP/netmask to compare with - * @return True if [netmask] bits match + * @return pointer to raw IP address bytes */ - bool sameNetworkAs(const InetAddress &ipnet) const - throw(); - - /** - * Determine whether this address is within an ip/netmask - * - * @param ipnet IP/netmask - * @return True if this address is within this network - */ - bool within(const InetAddress &ipnet) const - throw(); + inline void *rawIpData() + throw() + { + switch(ss_family) { + case AF_INET: return (void *)&(reinterpret_cast(this)->sin_addr.s_addr); + case AF_INET6: return (void *)(reinterpret_cast(this)->sin6_addr.s6_addr); + default: return 0; + } + } /** * Set to null/zero */ - inline void zero() throw() { memset(&_sa,0,sizeof(_sa)); } + inline void zero() throw() { memset(this,0,sizeof(InetAddress)); } /** * @return True if address family is non-zero */ - inline operator bool() const throw() { return ((_sa.saddr.sa_family == AF_INET)||(_sa.saddr.sa_family == AF_INET6)); } + inline operator bool() const throw() { return (ss_family != 0); } - bool operator==(const InetAddress &a) const throw(); + inline bool operator==(const InetAddress &a) const throw() { return (memcmp(this,&a,sizeof(InetAddress)) == 0); } inline bool operator!=(const InetAddress &a) const throw() { return !(*this == a); } - bool operator<(const InetAddress &a) const throw(); + inline bool operator<(const InetAddress &a) const throw() { return (memcmp(this,&a,sizeof(InetAddress)) < 0); } inline bool operator>(const InetAddress &a) const throw() { return (a < *this); } inline bool operator<=(const InetAddress &a) const throw() { return !(a < *this); } inline bool operator>=(const InetAddress &a) const throw() { return !(*this < a); } @@ -366,13 +361,6 @@ public: */ static InetAddress makeIpv6LinkLocal(const MAC &mac) throw(); - -private: - union { - struct sockaddr saddr; - struct sockaddr_in sin; - struct sockaddr_in6 sin6; - } _sa; }; } // namespace ZeroTier diff --git a/node/MAC.hpp b/node/MAC.hpp index a01a5f3ba..3981c77d8 100644 --- a/node/MAC.hpp +++ b/node/MAC.hpp @@ -71,6 +71,13 @@ public: MAC(const Address &ztaddr,uint64_t nwid) throw() { fromAddress(ztaddr,nwid); } + MAC(const uint64_t m) throw() : _m(m & 0xffffffffffffULL) {} + + /** + * @return MAC in 64-bit integer + */ + inline uint64_t toInt() const throw() { return _m; } + /** * Set MAC to zero */ diff --git a/node/Node.cpp b/node/Node.cpp new file mode 100644 index 000000000..dcf1d6577 --- /dev/null +++ b/node/Node.cpp @@ -0,0 +1,30 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2015 ZeroTier, Inc. + * + * 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 . + * + * -- + * + * ZeroTier may be used and distributed under the terms of the GPLv3, which + * are available at: http://www.gnu.org/licenses/gpl-3.0.html + * + * If you would like to embed ZeroTier into a commercial application or + * redistribute it in a modified binary form, please contact ZeroTier Networks + * LLC. Start here: http://www.zerotier.com/ + */ + +#include "Node.hpp" +#include "RuntimeEnvironment.hpp" + diff --git a/node/Node.hpp b/node/Node.hpp new file mode 100644 index 000000000..fc78fd80e --- /dev/null +++ b/node/Node.hpp @@ -0,0 +1,206 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2015 ZeroTier, Inc. + * + * 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 . + * + * -- + * + * ZeroTier may be used and distributed under the terms of the GPLv3, which + * are available at: http://www.gnu.org/licenses/gpl-3.0.html + * + * If you would like to embed ZeroTier into a commercial application or + * redistribute it in a modified binary form, please contact ZeroTier Networks + * LLC. Start here: http://www.zerotier.com/ + */ + +#ifndef ZT_NODE_HPP +#define ZT_NODE_HPP + +#include +#include +#include + +#include + +#include "Constants.hpp" + +#include "../include/ZeroTierOne.h" + +#include "InetAddress.hpp" +#include "Mutex.hpp" +#include "MAC.hpp" + +namespace ZeroTier { + +class RuntimeEnvironment; + +/** + * Implementation of Node object as defined in CAPI + * + * The pointer returned by ZT1_Node_new() is an instance of this class. + */ +class Node +{ +public: + Node( + ZT1_DataStoreGetFunction *dataStoreGetFunction, + ZT1_DataStorePutFunction *dataStorePutFunction, + ZT1_VirtualNetworkConfigCallback *networkConfigCallback, + ZT1_StatusCallback *statusCallback); + + ~Node(); + + // Public API Functions ---------------------------------------------------- + + ZT1_ResultCode run( + uint64_t now, + const ZT1_WireMessage *inputWireMessages, + unsigned int inputWireMessageCount, + const ZT1_VirtualLanFrame *inputLanFrames, + unsigned int inputLanFrameCount, + const ZT1_WireMessage **outputWireMessages, + unsigned int *outputWireMessageCount, + const ZT1_VirtualNetworkFrame **outputFrames, + unsigned int *outputLanFrameCount, + unsigned long *maxNextInterval); + + ZT1_ResultCode join(uint64_t nwid); + + ZT1_ResultCode leave(uint64_t nwid); + + void status(ZT1_NodeStatus *status); + + ZT1_PeerList *peers(); + + ZT1_VirtualNetworkConfig *networkConfig(uint64_t nwid); + + ZT1_VirtualNetworkList *listNetworks(); + + void freeQueryResult(void *qr); + + ZT1_ResultCode setNetconfMaster( + ZT1_Node *node, + void *networkConfigMasterInstance); + + // Internal functions ------------------------------------------------------ + + /** + * @return Time as of last call to run() + */ + inline uint64_t now() const throw() { return _now; } + + /** + * @return Current level of desperation + */ + inline int desperation() const throw() { return (int)((_now - _timeOfLastPrivilgedPacket) / ZT_DESPERATION_INCREMENT); } + + /** + * Enqueue a ZeroTier message to be sent + * + * @param addr Destination address + * @param data Packet data + * @param len Packet length + */ + inline void putPacket(const InetAddress &addr,const void *data,unsigned int len) + { + Mutex::Lock _l(_outputWireMessages_m); + if (_outputWireMessageCount >= _outputWireMessageCapacity) { + ZT1_WireMessage *old = _outputWireMessages; + _outputWireMessages = new ZT1_WireMessage[_outputWireMessageCapacity *= 2]; + memcpy(_outputWireMessages,old,sizeof(ZT1_WireMessage) * _outputWireMessageCount); + delete [] old; + } + ZT1_WireMessage &wm = _outputWireMessages[_outputWireMessageCount++]; + memcpy(&(wm.address),&addr,sizeof(ZT_SOCKADDR_STORAGE)); + wm.desperation = this->desperation(); + wm.spam = (int)((++_spamCounter % ZT_DESPERATION_SPAM_EVERY) == 0); + memcpy(wm.packetData,data,len); + wm.packetLength = len; + } + + /** + * Enqueue a frame to be injected into a tap device (port) + * + * @param nwid Network ID + * @param source Source MAC + * @param dest Destination MAC + * @param etherType 16-bit ethernet type + * @param vlanId VLAN ID or 0 if none + * @param data Frame data + * @param len Frame length + */ + inline void putFrame(uint64_t nwid,const MAC &source,const MAC &dest,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len) + { + Mutex::Lock _l(_outputFrames_m); + if (_outputFrameCount >= _outputFrameCapacity) { + ZT1_VirtualNetworkFrame *old = _outputFrames; + _outputFrames = new ZT1_VirtualNetworkFrame[_outputFrameCapacity *= 2]; + memcpy(_outputFrames,old,sizeof(ZT1_VirtualNetworkFrame) * _outputFrameCount); + delete [] old; + } + ZT1_VirtualNetworkFrame &f = _outputFrames[_outputFrameCount++]; + f.nwid = nwid; + f.sourceMac = source.toInt(); + f.destMac = dest.toInt(); + f.etherType = etherType; + f.vlanId = vlanId; + memcpy(f.frameData,data,len); + f.frameLength = len; + } + + /** + * @param nwid Network ID + * @return Network instance + */ + inline SharedPtr network(uint64_t nwid) + { + Mutex::Lock _l(_networks_m); + std::map< uint64_t,Network >::iterator nw(_networks.find(nwid)); + return ((nw == _networks.end()) ? SharedPtr() : nw->second); + } + +private: + RuntimeEnvironment *RR; + + ZT1_WireMessage *_outputWireMessages; + unsigned long _outputWireMessageCount; + unsigned long _outputWireMessageCapacity; + Mutex _outputWireMessages_m; + + ZT1_VirtualNetworkFrame *_outputFrames; + unsigned long _outputFrameCount; + unsigned long _outputFrameCapacity; + Mutex _outputFrames_m; + + ZT1_DataStoreGetFunction *_dataStoreGetFunction, + ZT1_DataStorePutFunction *_dataStorePutFunction, + ZT1_VirtualPortConfigCallback *_portConfigCallback, + ZT1_StatusCallback *_statusCallback); + + //Dictionary _localConfig; // persisted as local.conf + //Mutex _localConfig_m; + + std::map< uint64_t,SharedPtr > _networks; + Mutex _networks_m; + + uint64_t _now; // time of last run() + uint64_t _timeOfLastPacketReceived; + uint64_t _timeOfLastPrivilgedPacket; + unsigned int _spamCounter; // used to "spam" every Nth packet +}; + +} // namespace ZeroTier + +#endif diff --git a/node/NodeConfig.cpp b/node/NodeConfig.cpp deleted file mode 100644 index b8783b58f..000000000 --- a/node/NodeConfig.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2015 ZeroTier, Inc. - * - * 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 . - * - * -- - * - * ZeroTier may be used and distributed under the terms of the GPLv3, which - * are available at: http://www.gnu.org/licenses/gpl-3.0.html - * - * If you would like to embed ZeroTier into a commercial application or - * redistribute it in a modified binary form, please contact ZeroTier Networks - * LLC. Start here: http://www.zerotier.com/ - */ - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "Constants.hpp" - -#include "NodeConfig.hpp" -#include "RuntimeEnvironment.hpp" -#include "Defaults.hpp" -#include "Utils.hpp" -#include "Logger.hpp" -#include "Topology.hpp" -#include "Packet.hpp" -#include "InetAddress.hpp" -#include "Peer.hpp" -#include "Node.hpp" -#include "SoftwareUpdater.hpp" - -namespace ZeroTier { - -NodeConfig::NodeConfig(const RuntimeEnvironment *renv) : - RR(renv) -{ - { - Mutex::Lock _l(_localConfig_m); - _readLocalConfig(); - } - - std::string networksFolder(RR->homePath + ZT_PATH_SEPARATOR_S + "networks.d"); - std::map networksDotD(Utils::listDirectory(networksFolder.c_str())); - std::vector configuredNets; - for(std::map::iterator d(networksDotD.begin());d!=networksDotD.end();++d) { - if (!d->second) { - std::string::size_type dot = d->first.rfind(".conf"); - if (dot != std::string::npos) { - uint64_t nwid = Utils::hexStrToU64(d->first.substr(0,dot).c_str()); - if ((nwid > 0)&&(std::find(configuredNets.begin(),configuredNets.end(),nwid) == configuredNets.end())) - configuredNets.push_back(nwid); - } - } - } - - for(std::vector::iterator n(configuredNets.begin());n!=configuredNets.end();++n) { - try { - _networks[*n] = Network::newInstance(RR,this,*n); - } catch (std::exception &exc) { - LOG("unable to create network %.16llx: %s",(unsigned long long)*n,exc.what()); - } catch ( ... ) { - LOG("unable to create network %.16llx: (unknown exception)",(unsigned long long)*n); - } - } -} - -NodeConfig::~NodeConfig() -{ - _writeLocalConfig(); -} - -void NodeConfig::putLocalConfig(const std::string &key,const char *value) -{ - Mutex::Lock _l(_localConfig_m); - _localConfig[key] = value; - _writeLocalConfig(); -} - -void NodeConfig::putLocalConfig(const std::string &key,const std::string &value) -{ - Mutex::Lock _l(_localConfig_m); - _localConfig[key] = value; - _writeLocalConfig(); -} - -std::string NodeConfig::getLocalConfig(const std::string &key) const -{ - Mutex::Lock _l(_localConfig_m); - Dictionary::const_iterator i(_localConfig.find(key)); - if (i == _localConfig.end()) - return std::string(); - return i->second; -} - -void NodeConfig::clean() -{ - Mutex::Lock _l(_networks_m); - for(std::map< uint64_t,SharedPtr >::const_iterator n(_networks.begin());n!=_networks.end();++n) - n->second->clean(); -} - -void NodeConfig::_readLocalConfig() -{ - // assumes _localConfig_m is locked - std::string localDotConf(RR->homePath + ZT_PATH_SEPARATOR_S + "local.conf"); - std::string buf; - if (Utils::readFile(localDotConf.c_str(),buf)) - _localConfig.fromString(buf.c_str()); -} - -void NodeConfig::_writeLocalConfig() -{ - // assumes _localConfig_m is locked - Utils::writeFile(((RR->homePath + ZT_PATH_SEPARATOR_S + "local.conf")).c_str(),_localConfig.toString()); -} - -} // namespace ZeroTier diff --git a/node/NodeConfig.hpp b/node/NodeConfig.hpp deleted file mode 100644 index 7d574c7d1..000000000 --- a/node/NodeConfig.hpp +++ /dev/null @@ -1,181 +0,0 @@ -/* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2015 ZeroTier, Inc. - * - * 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 . - * - * -- - * - * ZeroTier may be used and distributed under the terms of the GPLv3, which - * are available at: http://www.gnu.org/licenses/gpl-3.0.html - * - * If you would like to embed ZeroTier into a commercial application or - * redistribute it in a modified binary form, please contact ZeroTier Networks - * LLC. Start here: http://www.zerotier.com/ - */ - -#ifndef ZT_NODECONFIG_HPP -#define ZT_NODECONFIG_HPP - -#include - -#include -#include -#include -#include -#include - -#include "SharedPtr.hpp" -#include "Network.hpp" -#include "Utils.hpp" -#include "Buffer.hpp" -#include "Dictionary.hpp" - -namespace ZeroTier { - -class RuntimeEnvironment; - -/** - * Node configuration endpoint - */ -class NodeConfig -{ -public: - /** - * @param renv Runtime environment - * @throws std::runtime_error Unable to initialize or listen for IPC connections - */ - NodeConfig(const RuntimeEnvironment *renv); - - ~NodeConfig(); - - /** - * Store something in local configuration cache - * - * By convention, keys starting with _ will not be shown in the command bus - * local config functions. - * - * @param key Configuration key - * @param value Configuration value - */ - void putLocalConfig(const std::string &key,const char *value); - void putLocalConfig(const std::string &key,const std::string &value); - - /** - * @param key Configuration key - * @return Value or empty string if not found - */ - std::string getLocalConfig(const std::string &key) const; - - /** - * @param nwid Network ID - * @return Network or NULL if no network for that ID - */ - inline SharedPtr network(uint64_t nwid) const - { - Mutex::Lock _l(_networks_m); - std::map< uint64_t,SharedPtr >::const_iterator n(_networks.find(nwid)); - return ((n == _networks.end()) ? SharedPtr() : n->second); - } - - /** - * @return Vector containing all networks - */ - inline std::vector< SharedPtr > networks() const - { - std::vector< SharedPtr > nwlist; - Mutex::Lock _l(_networks_m); - for(std::map< uint64_t,SharedPtr >::const_iterator n(_networks.begin());n!=_networks.end();++n) - nwlist.push_back(n->second); - return nwlist; - } - - /** - * Join a network or return existing network if already joined - * - * @param nwid Network ID to join - * @return New network instance - */ - inline SharedPtr join(uint64_t nwid) - { - Mutex::Lock _l(_networks_m); - SharedPtr &nw = _networks[nwid]; - if (nw) - return nw; - else return (nw = Network::newInstance(RR,this,nwid)); - } - - /** - * Leave a network - * - * @param nwid Network ID - * @return True if network was left, false if we were not a member of this network - */ - inline bool leave(uint64_t nwid) - { - Mutex::Lock _l(_networks_m); - std::map< uint64_t,SharedPtr >::iterator n(_networks.find(nwid)); - if (n != _networks.end()) { - n->second->destroy(); - _networks.erase(n); - return true; - } else return false; - } - - /** - * Perform cleanup and possibly persist saved state - */ - void clean(); - - /** - * @param nwid Network ID - * @return True if this network exists - */ - inline bool hasNetwork(uint64_t nwid) - { - Mutex::Lock _l(_networks_m); - return (_networks.find(nwid) != _networks.end()); - } - - /** - * @return Sorted vector of network tap device names from our virtual networks (not other taps on system) - */ - inline std::vector networkTapDeviceNames() const - { - std::vector tapDevs; - Mutex::Lock _l(_networks_m); - for(std::map< uint64_t,SharedPtr >::const_iterator n(_networks.begin());n!=_networks.end();++n) { - std::string dn(n->second->tapDeviceName()); - if (dn.length()) - tapDevs.push_back(dn); - } - return tapDevs; - } - -private: - void _readLocalConfig(); - void _writeLocalConfig(); - - const RuntimeEnvironment *RR; - - Dictionary _localConfig; // persisted as local.conf - Mutex _localConfig_m; - - std::map< uint64_t,SharedPtr > _networks; // persisted in networks.d/ - Mutex _networks_m; -}; - -} // namespace ZeroTier - -#endif diff --git a/node/RuntimeEnvironment.hpp b/node/RuntimeEnvironment.hpp index 425c6d84a..4e3a75c31 100644 --- a/node/RuntimeEnvironment.hpp +++ b/node/RuntimeEnvironment.hpp @@ -41,12 +41,8 @@ class Switch; class Topology; class CMWC4096; class Node; -class SoftwareUpdater; -class SocketManager; class Multicaster; class AntiRecursion; -class EthernetTapFactory; -class HttpClient; class NetworkConfigMaster; /** @@ -65,50 +61,23 @@ class RuntimeEnvironment { public: RuntimeEnvironment() : - homePath(), identity(), - initialized(false), - tcpTunnelingEnabled(false), - timeOfLastResynchronize(0), - timeOfLastPacketReceived(0), - tapFactory((EthernetTapFactory *)0), - sm((SocketManager *)0), netconfMaster((NetworkConfigMaster *)0), log((Logger *)0), prng((CMWC4096 *)0), - http((HttpClient *)0), sw((Switch *)0), mc((Multicaster *)0), antiRec((AntiRecursion *)0), topology((Topology *)0), nc((NodeConfig *)0), - node((Node *)0), - updater((SoftwareUpdater *)0) + node((Node *)0) { } - // Full path to home folder - std::string homePath; - // This node's identity Identity identity; - // Are we initialized? - volatile bool initialized; - - // Are we in outgoing TCP failover mode? - volatile bool tcpTunnelingEnabled; - - // Time network environment (e.g. fingerprint) last changed -- used to determine online-ness - volatile uint64_t timeOfLastResynchronize; - - // Time last packet was received -- from anywhere. This is updated in Peer::receive() - // via an ugly const_cast<>. - volatile uint64_t timeOfLastPacketReceived; - - // These are passed in from outside and are not created or deleted by the ZeroTier node core - EthernetTapFactory *tapFactory; - SocketManager *sm; + // This is set externally to an instance of this base class if netconf functionality is enabled NetworkConfigMaster *netconfMaster; /* @@ -121,14 +90,12 @@ public: Logger *log; // null if logging is disabled CMWC4096 *prng; - HttpClient *http; Switch *sw; Multicaster *mc; AntiRecursion *antiRec; Topology *topology; NodeConfig *nc; Node *node; - SoftwareUpdater *updater; // null if software updates are not enabled }; } // namespace ZeroTier diff --git a/objects.mk b/objects.mk index 408ef1ce0..20e5ae492 100644 --- a/objects.mk +++ b/objects.mk @@ -15,7 +15,6 @@ OBJS=\ node/Network.o \ node/NetworkConfig.o \ node/Node.o \ - node/NodeConfig.o \ node/OutboundMulticast.o \ node/Packet.o \ node/Peer.o \ diff --git a/osdep/SoftwareUpdater.hpp b/osdep/SoftwareUpdater.hpp index 6c1e573ab..3c0181c69 100644 --- a/osdep/SoftwareUpdater.hpp +++ b/osdep/SoftwareUpdater.hpp @@ -38,6 +38,28 @@ #include "Defaults.hpp" #include "Address.hpp" +/** + * Delay between fetches of the root topology update URL + * + * 86400000 = check once every 24 hours (this doesn't change often) + */ +#define ZT_UPDATE_ROOT_TOPOLOGY_CHECK_INTERVAL 86400000 + +/** + * Minimum interval between attempts to do a software update + */ +#define ZT_UPDATE_MIN_INTERVAL 120000 + +/** + * Maximum interval between checks for new versions + */ +#define ZT_UPDATE_MAX_INTERVAL 7200000 + +/** + * Software update HTTP timeout in seconds + */ +#define ZT_UPDATE_HTTP_TIMEOUT 120 + namespace ZeroTier { class RuntimeEnvironment;