summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--attic/Socket.hpp (renamed from node/Socket.hpp)0
-rw-r--r--attic/SocketManager.hpp (renamed from node/SocketManager.hpp)0
-rw-r--r--include/ZeroTierOne.h66
-rw-r--r--node/Constants.hpp40
-rw-r--r--node/InetAddress.cpp320
-rw-r--r--node/InetAddress.hpp270
-rw-r--r--node/MAC.hpp7
-rw-r--r--node/Node.cpp30
-rw-r--r--node/Node.hpp206
-rw-r--r--node/NodeConfig.cpp137
-rw-r--r--node/NodeConfig.hpp181
-rw-r--r--node/RuntimeEnvironment.hpp37
-rw-r--r--objects.mk1
-rw-r--r--osdep/SoftwareUpdater.hpp22
14 files changed, 561 insertions, 756 deletions
diff --git a/node/Socket.hpp b/attic/Socket.hpp
index 79f393fb..79f393fb 100644
--- a/node/Socket.hpp
+++ b/attic/Socket.hpp
diff --git a/node/SocketManager.hpp b/attic/SocketManager.hpp
index 21a49ea4..21a49ea4 100644
--- a/node/SocketManager.hpp
+++ b/attic/SocketManager.hpp
diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h
index 2c875a4f..61cee72e 100644
--- a/include/ZeroTierOne.h
+++ b/include/ZeroTierOne.h
@@ -35,22 +35,34 @@
#include <stdint.h>
-#ifndef ZT_SOCKADDR_STORAGE
#if defined(_WIN32) || defined(_WIN64)
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <Windows.h>
#else /* not Windows */
+#include <arpa/inet.h>
#include <netinet/in.h>
#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 35efd0f8..ff91417c 100644
--- a/node/Constants.hpp
+++ b/node/Constants.hpp
@@ -300,14 +300,19 @@
#define ZT_STARTUP_AGGRO (ZT_PING_UNANSWERED_AFTER * 2)
/**
- * Maximum delay between runs of the main loop in Node.cpp
+ * How long since last message from an authoritative upstream peer before we increment our desperation level?
*/
-#define ZT_MAX_SERVICE_LOOP_INTERVAL ZT_STARTUP_AGGRO
+#define ZT_DESPERATION_INCREMENT (ZT_STARTUP_AGGRO * 2)
+
+/**
+ * "Spam" packets to lower desperation links every Nth packet
+ */
+#define ZT_DESPERATION_SPAM_EVERY 10
/**
- * Try TCP tunnels if nothing received for this long
+ * Maximum delay between runs of the main loop in Node.cpp
*/
-#define ZT_TCP_TUNNEL_FAILOVER_TIMEOUT (ZT_STARTUP_AGGRO * 5)
+#define ZT_MAX_SERVICE_LOOP_INTERVAL ZT_STARTUP_AGGRO
/**
* Timeout for overall peer activity (measured from last receive)
@@ -320,11 +325,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
*
* When we send something (including frames), we generally expect a response.
@@ -375,28 +375,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
*
* If the number of bridge routes exceeds this, we cull routes from the
diff --git a/node/InetAddress.cpp b/node/InetAddress.cpp
index 45781f42..9452086a 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<const struct sockaddr_in *>(this)->sin_addr.s_addr) & 0xffff0000) == 0xa9fe0000);
+ case AF_INET6:
+ return (memcmp(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr,v6llPrefix,8) == 0);
}
return false;
}
-bool InetAddress::isDefaultRoute() const
- throw()
+std::string InetAddress::toString() const
{
- 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;
+ char buf[128];
+ switch(ss_family) {
+ case AF_INET:
+ Utils::snprintf(buf,sizeof(buf),"%d.%d.%d.%d/%d",
+ (int)(reinterpret_cast<const unsigned char *>(&(reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr)))[0],
+ (int)(reinterpret_cast<const unsigned char *>(&(reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr)))[1],
+ (int)(reinterpret_cast<const unsigned char *>(&(reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr)))[2],
+ (int)(reinterpret_cast<const unsigned char *>(&(reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr)))[3],
+ (int)Utils::ntoh((uint16_t)(reinterpret_cast<const struct sockaddr_in *>(this)->sin_port))
+ );
+ 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/%d",
+ (int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[0]),
+ (int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[1]),
+ (int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[2]),
+ (int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[3]),
+ (int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[4]),
+ (int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[5]),
+ (int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[6]),
+ (int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[7]),
+ (int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[8]),
+ (int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[9]),
+ (int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[10]),
+ (int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[11]),
+ (int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[12]),
+ (int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[13]),
+ (int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[14]),
+ (int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[15]),
+ (int)Utils::ntoh((uint16_t)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_port))
+ );
+ return std::string(buf);
+ }
+ return std::string();
}
-std::string InetAddress::toString() const
+std::string InetAddress::toIpString() 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",
+ (int)(reinterpret_cast<const unsigned char *>(&(reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr)))[0],
+ (int)(reinterpret_cast<const unsigned char *>(&(reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr)))[1],
+ (int)(reinterpret_cast<const unsigned char *>(&(reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr)))[2],
+ (int)(reinterpret_cast<const unsigned char *>(&(reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr)))[3]
+ );
+ 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",
+ (int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[0]),
+ (int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[1]),
+ (int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[2]),
+ (int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[3]),
+ (int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[4]),
+ (int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[5]),
+ (int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[6]),
+ (int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[7]),
+ (int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[8]),
+ (int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[9]),
+ (int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[10]),
+ (int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[11]),
+ (int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[12]),
+ (int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[13]),
+ (int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[14]),
+ (int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[15])
+ );
+ return std::string(buf);
}
-
return std::string();
}
@@ -148,48 +181,22 @@ 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<struct sockaddr_in *>(&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;
+ unsigned char *bf = reinterpret_cast<unsigned char *>(reinterpret_cast<struct sockaddr_in6 *>(&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) ? 0xff : (0xff << (8 - bitsLeft)));
+ bf[i] |= (unsigned char)((bitsLeft >= 8) ? 0x00 : (0xff >> bitsLeft));
bitsLeft -= 8;
- } else bf[i] = (unsigned char)0;
+ }
}
} break;
}
@@ -200,12 +207,12 @@ InetAddress InetAddress::broadcast() 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 >> netmaskBits()));
+ reinterpret_cast<struct sockaddr_in *>(&r)->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<unsigned char *>(reinterpret_cast<struct sockaddr_in6 *>(&r)->sin6_addr.s6_addr);
signed int bitsLeft = (signed int)netmaskBits();
for(unsigned int i=0;i<16;++i) {
if (bitsLeft > 0) {
@@ -218,130 +225,29 @@ InetAddress InetAddress::broadcast() const
return r;
}
-bool InetAddress::sameNetworkAs(const InetAddress &ipnet) 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) {
- case AF_INET:
- if (bits >= 32) bits = 32;
- break;
- case AF_INET6:
- if (bits >= 128) bits = 128;
- 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;
- }
- 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;
-}
-
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 c041ffdf..381c6ba2 100644
--- a/node/InetAddress.hpp
+++ b/node/InetAddress.hpp
@@ -35,39 +35,20 @@
#include <string>
#include "Constants.hpp"
+#include "../include/ZeroTierOne.h"
#include "Utils.hpp"
#include "MAC.hpp"
-#ifdef __WINDOWS__
-#include <WinSock2.h>
-#include <WS2tcpip.h>
-#include <Windows.h>
-#else
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <sys/socket.h>
-#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()
+ {
+ 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(&_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;
+ 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<struct sockaddr_in *>(this)->sin_port = Utils::hton((uint16_t)port);
+ break;
+ case AF_INET6:
+ reinterpret_cast<struct sockaddr_in6 *>(this)->sin6_port = Utils::hton((uint16_t)port);
+ break;
+ }
}
/**
@@ -159,19 +212,9 @@ public:
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
@@ -179,14 +222,14 @@ public:
std::string toString() const;
/**
- * @param ipSlashPort ASCII IP/port format notation
+ * @return IP portion only, in ASCII string format
*/
- void fromString(const std::string &ipSlashPort);
+ std::string toIpString() const;
/**
- * @return IP portion only, in ASCII string format
+ * @param ipSlashPort ASCII IP/port format notation
*/
- std::string toIpString() const;
+ void fromString(const std::string &ipSlashPort);
/**
* @return Port or 0 if no port component defined
@@ -194,9 +237,9 @@ public:
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<const struct sockaddr_in *>(this)->sin_port));
+ case AF_INET6: return Utils::ntoh((uint16_t)(reinterpret_cast<const struct sockaddr_in6 *>(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,7 +295,7 @@ 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;
@@ -271,91 +303,54 @@ public:
}
/**
- * @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<const struct sockaddr_in *>(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<const struct sockaddr_in6 *>(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<const struct sockaddr_in *>(this)->sin_addr.s_addr);
+ case AF_INET6: return (const void *)(reinterpret_cast<const struct sockaddr_in6 *>(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<struct sockaddr_in *>(this)->sin_addr.s_addr);
+ case AF_INET6: return (void *)(reinterpret_cast<struct sockaddr_in6 *>(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 a01a5f3b..3981c77d 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 00000000..dcf1d657
--- /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 <http://www.gnu.org/licenses/>.
+ *
+ * --
+ *
+ * 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 00000000..fc78fd80
--- /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 <http://www.gnu.org/licenses/>.
+ *
+ * --
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <map>
+
+#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> network(uint64_t nwid)
+ {
+ Mutex::Lock _l(_networks_m);
+ std::map< uint64_t,Network >::iterator nw(_networks.find(nwid));
+ return ((nw == _networks.end()) ? SharedPtr<Network>() : 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<Network> > _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 b8783b58..00000000
--- 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 <http://www.gnu.org/licenses/>.
- *
- * --
- *
- * 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 <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdint.h>
-
-#include <memory>
-#include <string>
-#include <map>
-#include <set>
-
-#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<std::string,bool> networksDotD(Utils::listDirectory(networksFolder.c_str()));
- std::vector<uint64_t> configuredNets;
- for(std::map<std::string,bool>::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<uint64_t>::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<Network> >::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 7d574c7d..00000000
--- 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 <http://www.gnu.org/licenses/>.
- *
- * --
- *
- * 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 <stdint.h>
-
-#include <map>
-#include <set>
-#include <string>
-#include <vector>
-#include <stdexcept>
-
-#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> network(uint64_t nwid) const
- {
- Mutex::Lock _l(_networks_m);
- std::map< uint64_t,SharedPtr<Network> >::const_iterator n(_networks.find(nwid));
- return ((n == _networks.end()) ? SharedPtr<Network>() : n->second);
- }
-
- /**
- * @return Vector containing all networks
- */
- inline std::vector< SharedPtr<Network> > networks() const
- {
- std::vector< SharedPtr<Network> > nwlist;
- Mutex::Lock _l(_networks_m);
- for(std::map< uint64_t,SharedPtr<Network> >::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<Network> join(uint64_t nwid)
- {
- Mutex::Lock _l(_networks_m);
- SharedPtr<Network> &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<Network> >::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<std::string> networkTapDeviceNames() const
- {
- std::vector<std::string> tapDevs;
- Mutex::Lock _l(_networks_m);
- for(std::map< uint64_t,SharedPtr<Network> >::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<Network> > _networks; // persisted in networks.d/
- Mutex _networks_m;
-};
-
-} // namespace ZeroTier
-
-#endif
diff --git a/node/RuntimeEnvironment.hpp b/node/RuntimeEnvironment.hpp
index 425c6d84..4e3a75c3 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 408ef1ce..20e5ae49 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 6c1e573a..3c0181c6 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;