Whole heap more cleanup and refactoring...

This commit is contained in:
Adam Ierymenko 2015-03-31 17:53:34 -07:00
parent 647ce82b86
commit 36eab4f1a9
14 changed files with 575 additions and 770 deletions

View File

@ -35,21 +35,33 @@
#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

View File

@ -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
*

View File

@ -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()
{
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<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:
#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<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::toIpString() const
{
char buf[128];
switch(ss_family) {
case AF_INET:
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:
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,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<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;
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<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 +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<struct sockaddr_in *>(&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<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) ? 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

View File

@ -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()
{
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<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;
}
}
/**
@ -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<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,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<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

View File

@ -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
*/

30
node/Node.cpp Normal file
View File

@ -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"

206
node/Node.hpp Normal file
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 \

View File

@ -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;