mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-05 20:13:44 +02:00
.
This commit is contained in:
parent
263798d1c3
commit
9642ff5fb9
21 changed files with 502 additions and 760 deletions
|
@ -19,7 +19,11 @@
|
|||
#ifndef ZT_ZEROTIER_API_H
|
||||
#define ZT_ZEROTIER_API_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <cstdint>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
/* For struct sockaddr_storage, which is referenced here. */
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
|
@ -513,45 +517,6 @@ enum ZT_Event
|
|||
ZT_EVENT_REMOTE_TRACE = 7
|
||||
};
|
||||
|
||||
/**
|
||||
* A root server
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* Name of root
|
||||
*
|
||||
* This will be a DNS name for dynamic roots. For static roots
|
||||
* it will be the ZeroTier address. The presence or absence
|
||||
* of a dot is used internally as a distinguisher.
|
||||
*/
|
||||
const char *name;
|
||||
|
||||
/**
|
||||
* Serialized locator
|
||||
*/
|
||||
const void *locator;
|
||||
|
||||
/**
|
||||
* The size of locator in bytes
|
||||
*/
|
||||
unsigned int locatorSize;
|
||||
} ZT_Root;
|
||||
|
||||
/**
|
||||
* List of root servers
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* Number of root servers
|
||||
*/
|
||||
unsigned int count;
|
||||
|
||||
/**
|
||||
* Array of root servers
|
||||
*/
|
||||
ZT_Root roots[];
|
||||
} ZT_RootList;
|
||||
|
||||
/**
|
||||
* Payload of REMOTE_TRACE event
|
||||
*/
|
||||
|
@ -1010,29 +975,6 @@ enum ZT_PeerRole
|
|||
ZT_PEER_ROLE_PLANET = 2 // planetary root
|
||||
};
|
||||
|
||||
/**
|
||||
* DNS record types for reporting DNS results
|
||||
*
|
||||
* These integer IDs (other than end of results) are the same as the DNS protocol's
|
||||
* internal IDs. Not all of these are used by ZeroTier, and not all DNS record types
|
||||
* are listed here. These are just common ones that are used now or may be used in
|
||||
* the future for some purpose.
|
||||
*/
|
||||
enum ZT_DNSRecordType
|
||||
{
|
||||
ZT_DNS_RECORD__END_OF_RESULTS = 0,
|
||||
ZT_DNS_RECORD_A = 1,
|
||||
ZT_DNS_RECORD_NS = 2,
|
||||
ZT_DNS_RECORD_CNAME = 5,
|
||||
ZT_DNS_RECORD_PTR = 12,
|
||||
ZT_DNS_RECORD_MX = 15,
|
||||
ZT_DNS_RECORD_TXT = 16,
|
||||
ZT_DNS_RECORD_AAAA = 28,
|
||||
ZT_DNS_RECORD_LOC = 29,
|
||||
ZT_DNS_RECORD_SRV = 33,
|
||||
ZT_DNS_RECORD_DNAME = 39
|
||||
};
|
||||
|
||||
/**
|
||||
* Virtual network configuration
|
||||
*/
|
||||
|
@ -1541,8 +1483,9 @@ typedef int (*ZT_PathCheckFunction)(
|
|||
* (1) Node
|
||||
* (2) User pointer
|
||||
* (3) ZeroTier address (least significant 40 bits)
|
||||
* (4) Desired address family or -1 for any
|
||||
* (5) Buffer to fill with result
|
||||
* (4) Identity in string form
|
||||
* (5) Desired address family or -1 for any
|
||||
* (6) Buffer to fill with result
|
||||
*
|
||||
* If provided this function will be occasionally called to get physical
|
||||
* addresses that might be tried to reach a ZeroTier address. It must
|
||||
|
@ -1554,53 +1497,10 @@ typedef int (*ZT_PathLookupFunction)(
|
|||
void *, /* User ptr */
|
||||
void *, /* Thread ptr */
|
||||
uint64_t, /* ZeroTier address (40 bits) */
|
||||
const char *, /* Identity in string form */
|
||||
int, /* Desired ss_family or -1 for any */
|
||||
struct sockaddr_storage *); /* Result buffer */
|
||||
|
||||
/**
|
||||
* Function to request an asynchronous DNS TXT lookup
|
||||
*
|
||||
* Parameters:
|
||||
* (1) Node
|
||||
* (2) User pointer
|
||||
* (3) Thread pointer
|
||||
* (4) Array of DNS record types we want
|
||||
* (5) Number of DNS record types in array
|
||||
* (6) DNS name to fetch
|
||||
* (7) DNS request ID to supply to ZT_Node_processDNSResult()
|
||||
*
|
||||
* DNS is not handled in the core because every platform and runtime
|
||||
* typically has its own DNS functions or libraries and these may need
|
||||
* to interface with OS or network services in your local environment.
|
||||
* Instead this function and its result submission counterpart are
|
||||
* provided so you can provide a DNS implementation.
|
||||
*
|
||||
* If this callback is set in your callback struct to a NULL value,
|
||||
* DNS will not be available. The ZeroTier protocol is designed to
|
||||
* work in the absence of DNS but you may not get optimal results. For
|
||||
* example you may default to root servers that are not geographically
|
||||
* optimal or your node may cease to function if a root server's IP
|
||||
* changes and there's no way to signal this.
|
||||
*
|
||||
* This function requests resolution of a DNS record. The result
|
||||
* submission method ZT_Node_processDNSResult() must be called at
|
||||
* least once in response. See its documentation.
|
||||
*
|
||||
* Right now ZeroTier only requests resolution of TXT records, but
|
||||
* it's possible that this will change in the future.
|
||||
*
|
||||
* It's safe to call processDNSResult() from within your handler
|
||||
* for this function.
|
||||
*/
|
||||
typedef void (*ZT_DNSResolver)(
|
||||
ZT_Node *, /* Node */
|
||||
void *, /* User ptr */
|
||||
void *, /* Thread ptr */
|
||||
const enum ZT_DNSRecordType *, /* DNS record type(s) to fetch */
|
||||
unsigned int, /* Number of DNS record type(s) */
|
||||
const char *, /* DNS name to fetch */
|
||||
uintptr_t); /* Request ID for returning results */
|
||||
|
||||
/****************************************************************************/
|
||||
/* C Node API */
|
||||
/****************************************************************************/
|
||||
|
@ -1640,11 +1540,6 @@ struct ZT_Node_Callbacks
|
|||
*/
|
||||
ZT_EventCallback eventCallback;
|
||||
|
||||
/**
|
||||
* STRONGLY RECOMMENDED: Function to request a DNS lookup
|
||||
*/
|
||||
ZT_DNSResolver dnsResolver;
|
||||
|
||||
/**
|
||||
* OPTIONAL: Function to check whether a given physical path should be used
|
||||
*/
|
||||
|
@ -1750,60 +1645,6 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_processBackgroundTasks(
|
|||
int64_t now,
|
||||
volatile int64_t *nextBackgroundTaskDeadline);
|
||||
|
||||
/**
|
||||
* Submit the result(s) of a requested DNS query
|
||||
*
|
||||
* This MUST be called at least once after the node requsts DNS resolution.
|
||||
* If there are no results or DNS is not implemented or available, just
|
||||
* send one ZT_DNS_RECORD__END_OF_RESULTS to signal that no results were
|
||||
* obtained.
|
||||
*
|
||||
* If result is non-NULL but resultLength is zero then result is assumed to
|
||||
* be a C string terminated by a zero. Passing an unterminated string with a
|
||||
* zero resultLength will result in a crash.
|
||||
*
|
||||
* The results of A and AAAA records can be returned as either strings or
|
||||
* binary IP address bytes (network byte order). If the result is a string,
|
||||
* resultLength must be 0 to signal that result is a C string. Otherwise for
|
||||
* A resultLength must be 4 and for AAAA it must be 16 if the result is
|
||||
* in binary format.
|
||||
*
|
||||
* The Node implementation makes an effort to ignore obviously invalid
|
||||
* submissions like an AAAA record in bianry form with length 25, but this
|
||||
* is not guaranteed. It's possible to crash your program by calling this
|
||||
* with garbage inputs.
|
||||
*
|
||||
* Results may be submitted in any order and order should not be assumed
|
||||
* to have any meaning.
|
||||
*
|
||||
* The ZT_DNS_RECORD__END_OF_RESULTS pseudo-response must be sent after all
|
||||
* results have been submitted. The result and resultLength paramters are
|
||||
* ignored for this type ID.
|
||||
*
|
||||
* It is safe to call this function from inside the DNS request callback,
|
||||
* such as to return a locally cached result or a result from some kind
|
||||
* of local database. It's also safe to call this function from threads
|
||||
* other than the one that received the DNS request.
|
||||
*
|
||||
* @param node Node instance that requested DNS resolution
|
||||
* @param tptr Thread pointer to pass to functions/callbacks resulting from this call
|
||||
* @param dnsRequestID Request ID supplied to DNS request callback
|
||||
* @param name DNS name
|
||||
* @param recordType Record type of this result
|
||||
* @param result Result (content depends on record type)
|
||||
* @param resultLength Length of result
|
||||
* @param resultIsString If non-zero, IP results for A and AAAA records are being given as C strings not binary IPs
|
||||
*/
|
||||
ZT_SDK_API void ZT_Node_processDNSResult(
|
||||
ZT_Node *node,
|
||||
void *tptr,
|
||||
uintptr_t dnsRequestID,
|
||||
const char *name,
|
||||
enum ZT_DNSRecordType recordType,
|
||||
const void *result,
|
||||
unsigned int resultLength,
|
||||
int resultIsString);
|
||||
|
||||
/**
|
||||
* Join a network
|
||||
*
|
||||
|
@ -1884,36 +1725,25 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_multicastSubscribe(ZT_Node *node,void *tpt
|
|||
ZT_SDK_API enum ZT_ResultCode ZT_Node_multicastUnsubscribe(ZT_Node *node,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi);
|
||||
|
||||
/**
|
||||
* List roots for this node
|
||||
* Add a root server (has no effect if already added)
|
||||
*
|
||||
* @param node Node instance
|
||||
* @param now Current time
|
||||
* @return List of roots, use ZT_Node_freeQueryResult to free this when done
|
||||
* @param identity Identity of this root server in string format
|
||||
* @return OK (0) or error code if a fatal error condition has occurred
|
||||
*/
|
||||
ZT_SDK_API ZT_RootList *ZT_Node_listRoots(ZT_Node *node,int64_t now);
|
||||
ZT_SDK_API enum ZT_ResultCode ZT_Node_addRoot(ZT_Node *node,const char *identity);
|
||||
|
||||
/**
|
||||
* Add or update a root
|
||||
* Remove a root server
|
||||
*
|
||||
* The node will begin trying to resolve the DNS TXT record for
|
||||
* this root and possibly obtain it from other peers.
|
||||
* This removes this node's root designation but does not prevent this node
|
||||
* from communicating with it or close active paths to it.
|
||||
*
|
||||
* @param node Node instance
|
||||
* @param name DNS name or simply the address in hex form for static roots
|
||||
* @param locator Binary-serialized locator of NULL if none
|
||||
* @param locatorSize Size of locator or 0 if none
|
||||
* @return OK (0) or error code
|
||||
* @param identity Identity in string format
|
||||
* @return OK (0) or error code if a fatal error condition has occurred
|
||||
*/
|
||||
ZT_SDK_API enum ZT_ResultCode ZT_Node_setRoot(ZT_Node *node,const char *name,const void *locator,unsigned int locatorSize);
|
||||
|
||||
/**
|
||||
* Remove a dynamic root
|
||||
*
|
||||
* @param node Node instance
|
||||
* @param name DNS name of this dynamic root or the address in hex form for static roots
|
||||
* @return OK (0) or error code
|
||||
*/
|
||||
ZT_SDK_API enum ZT_ResultCode ZT_Node_removeRoot(ZT_Node *node,const char *name);
|
||||
ZT_SDK_API enum ZT_ResultCode ZT_Node_removeRoot(ZT_Node *node,const char *identity);
|
||||
|
||||
/**
|
||||
* Get this node's 40-bit ZeroTier address
|
||||
|
|
|
@ -37,9 +37,9 @@
|
|||
#define ZT_ADDRESS_RESERVED_PREFIX 0xff
|
||||
|
||||
/**
|
||||
* Maximum DNS or URL name size for an Endpoint (set so that max marshaled endpoint size is 128 bytes)
|
||||
* Maximum DNS or URL name size for an Endpoint (set so that max marshaled endpoint size is 64 bytes)
|
||||
*/
|
||||
#define ZT_ENDPOINT_MAX_NAME_SIZE 124
|
||||
#define ZT_ENDPOINT_MAX_NAME_SIZE 61
|
||||
|
||||
/**
|
||||
* Size of an identity hash (SHA384)
|
||||
|
|
|
@ -60,13 +60,13 @@ static EccPoint curve_G = CONCAT(Curve_G_, ECC_CURVE);
|
|||
static uint64_t curve_n[NUM_ECC_DIGITS] = CONCAT(Curve_N_, ECC_CURVE);
|
||||
|
||||
// Use ZeroTier's secure PRNG
|
||||
static inline int getRandomNumber(uint64_t *p_vli)
|
||||
static ZT_ALWAYS_INLINE int getRandomNumber(uint64_t *p_vli)
|
||||
{
|
||||
Utils::getSecureRandom(p_vli,ECC_BYTES);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline void vli_clear(uint64_t *p_vli)
|
||||
static ZT_ALWAYS_INLINE void vli_clear(uint64_t *p_vli)
|
||||
{
|
||||
uint i;
|
||||
for(i=0; i<NUM_ECC_DIGITS; ++i)
|
||||
|
@ -76,7 +76,7 @@ static inline void vli_clear(uint64_t *p_vli)
|
|||
}
|
||||
|
||||
/* Returns 1 if p_vli == 0, 0 otherwise. */
|
||||
static inline int vli_isZero(uint64_t *p_vli)
|
||||
static ZT_ALWAYS_INLINE int vli_isZero(uint64_t *p_vli)
|
||||
{
|
||||
uint i;
|
||||
for(i = 0; i < NUM_ECC_DIGITS; ++i)
|
||||
|
@ -90,13 +90,13 @@ static inline int vli_isZero(uint64_t *p_vli)
|
|||
}
|
||||
|
||||
/* Returns nonzero if bit p_bit of p_vli is set. */
|
||||
static inline uint64_t vli_testBit(uint64_t *p_vli, uint p_bit)
|
||||
static ZT_ALWAYS_INLINE uint64_t vli_testBit(uint64_t *p_vli, uint p_bit)
|
||||
{
|
||||
return (p_vli[p_bit/64] & ((uint64_t)1 << (p_bit % 64)));
|
||||
}
|
||||
|
||||
/* Counts the number of 64-bit "digits" in p_vli. */
|
||||
static inline uint vli_numDigits(uint64_t *p_vli)
|
||||
static ZT_ALWAYS_INLINE uint vli_numDigits(uint64_t *p_vli)
|
||||
{
|
||||
int i;
|
||||
/* Search from the end until we find a non-zero digit.
|
||||
|
@ -109,7 +109,7 @@ static inline uint vli_numDigits(uint64_t *p_vli)
|
|||
}
|
||||
|
||||
/* Counts the number of bits required for p_vli. */
|
||||
static inline uint vli_numBits(uint64_t *p_vli)
|
||||
static ZT_ALWAYS_INLINE uint vli_numBits(uint64_t *p_vli)
|
||||
{
|
||||
uint i;
|
||||
uint64_t l_digit;
|
||||
|
@ -130,7 +130,7 @@ static inline uint vli_numBits(uint64_t *p_vli)
|
|||
}
|
||||
|
||||
/* Sets p_dest = p_src. */
|
||||
static inline void vli_set(uint64_t *p_dest, uint64_t *p_src)
|
||||
static ZT_ALWAYS_INLINE void vli_set(uint64_t *p_dest, uint64_t *p_src)
|
||||
{
|
||||
uint i;
|
||||
for(i=0; i<NUM_ECC_DIGITS; ++i)
|
||||
|
@ -464,7 +464,7 @@ static inline void vli_mmod_fast(uint64_t *p_result, uint64_t *p_product)
|
|||
//#endif
|
||||
|
||||
/* Computes p_result = (p_left * p_right) % curve_p. */
|
||||
static inline void vli_modMult_fast(uint64_t *p_result, uint64_t *p_left, uint64_t *p_right)
|
||||
static ZT_ALWAYS_INLINE void vli_modMult_fast(uint64_t *p_result, uint64_t *p_left, uint64_t *p_right)
|
||||
{
|
||||
uint64_t l_product[2 * NUM_ECC_DIGITS];
|
||||
vli_mult(l_product, p_left, p_right);
|
||||
|
@ -472,7 +472,7 @@ static inline void vli_modMult_fast(uint64_t *p_result, uint64_t *p_left, uint64
|
|||
}
|
||||
|
||||
/* Computes p_result = p_left^2 % curve_p. */
|
||||
static inline void vli_modSquare_fast(uint64_t *p_result, uint64_t *p_left)
|
||||
static ZT_ALWAYS_INLINE void vli_modSquare_fast(uint64_t *p_result, uint64_t *p_left)
|
||||
{
|
||||
uint64_t l_product[2 * NUM_ECC_DIGITS];
|
||||
vli_square(l_product, p_left);
|
||||
|
@ -576,7 +576,7 @@ static inline void vli_modInv(uint64_t *p_result, uint64_t *p_input, uint64_t *p
|
|||
/* ------ Point operations ------ */
|
||||
|
||||
/* Returns 1 if p_point is the point at infinity, 0 otherwise. */
|
||||
static inline int EccPoint_isZero(EccPoint *p_point)
|
||||
static ZT_ALWAYS_INLINE int EccPoint_isZero(EccPoint *p_point)
|
||||
{
|
||||
return (vli_isZero(p_point->x) && vli_isZero(p_point->y));
|
||||
}
|
||||
|
@ -635,7 +635,7 @@ static inline void EccPoint_double_jacobian(uint64_t *X1, uint64_t *Y1, uint64_t
|
|||
}
|
||||
|
||||
/* Modify (x1, y1) => (x1 * z^2, y1 * z^3) */
|
||||
static inline void apply_z(uint64_t *X1, uint64_t *Y1, uint64_t *Z)
|
||||
static ZT_ALWAYS_INLINE void apply_z(uint64_t *X1, uint64_t *Y1, uint64_t *Z)
|
||||
{
|
||||
uint64_t t1[NUM_ECC_DIGITS];
|
||||
|
||||
|
@ -772,7 +772,7 @@ static inline void EccPoint_mult(EccPoint *p_result, EccPoint *p_point, uint64_t
|
|||
vli_set(p_result->y, Ry[0]);
|
||||
}
|
||||
|
||||
static inline void ecc_bytes2native(uint64_t p_native[NUM_ECC_DIGITS], const uint8_t p_bytes[ECC_BYTES])
|
||||
static ZT_ALWAYS_INLINE void ecc_bytes2native(uint64_t p_native[NUM_ECC_DIGITS], const uint8_t p_bytes[ECC_BYTES])
|
||||
{
|
||||
unsigned i;
|
||||
for(i=0; i<NUM_ECC_DIGITS; ++i)
|
||||
|
@ -783,7 +783,7 @@ static inline void ecc_bytes2native(uint64_t p_native[NUM_ECC_DIGITS], const uin
|
|||
}
|
||||
}
|
||||
|
||||
static inline void ecc_native2bytes(uint8_t p_bytes[ECC_BYTES], const uint64_t p_native[NUM_ECC_DIGITS])
|
||||
static ZT_ALWAYS_INLINE void ecc_native2bytes(uint8_t p_bytes[ECC_BYTES], const uint64_t p_native[NUM_ECC_DIGITS])
|
||||
{
|
||||
unsigned i;
|
||||
for(i=0; i<NUM_ECC_DIGITS; ++i)
|
||||
|
@ -961,7 +961,7 @@ static inline void vli_modMult(uint64_t *p_result, uint64_t *p_left, uint64_t *p
|
|||
vli_set(p_result, l_product);
|
||||
}
|
||||
|
||||
static inline uint umax(uint a, uint b)
|
||||
static ZT_ALWAYS_INLINE uint umax(uint a, uint b)
|
||||
{
|
||||
return (a > b ? a : b);
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include "Address.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
#define ZT_ENDPOINT_MARSHAL_SIZE_MAX (ZT_ENDPOINT_MAX_NAME_SIZE+4)
|
||||
#define ZT_ENDPOINT_MARSHAL_SIZE_MAX (ZT_ENDPOINT_MAX_NAME_SIZE+3)
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -46,10 +46,10 @@ public:
|
|||
|
||||
ZT_ALWAYS_INLINE Endpoint() { memset(reinterpret_cast<void *>(this),0,sizeof(Endpoint)); }
|
||||
|
||||
ZT_ALWAYS_INLINE Endpoint(const InetAddress &sa) : _t(INETADDR) { _v.sa = sa; }
|
||||
explicit ZT_ALWAYS_INLINE Endpoint(const InetAddress &sa) : _t(INETADDR) { _v.sa = sa; }
|
||||
ZT_ALWAYS_INLINE Endpoint(const Address &zt,const uint8_t identityHash[ZT_IDENTITY_HASH_SIZE]) : _t(ZEROTIER) { _v.zt.a = zt.toInt(); memcpy(_v.zt.idh,identityHash,ZT_IDENTITY_HASH_SIZE); }
|
||||
ZT_ALWAYS_INLINE Endpoint(const char *name,const int port) : _t(DNSNAME) { Utils::scopy(_v.dns.name,sizeof(_v.dns.name),name); _v.dns.port = port; }
|
||||
ZT_ALWAYS_INLINE Endpoint(const char *url) : _t(URL) { Utils::scopy(_v.url,sizeof(_v.url),url); }
|
||||
explicit ZT_ALWAYS_INLINE Endpoint(const char *url) : _t(URL) { Utils::scopy(_v.url,sizeof(_v.url),url); }
|
||||
|
||||
ZT_ALWAYS_INLINE const InetAddress *sockaddr() const { return (_t == INETADDR) ? reinterpret_cast<const InetAddress *>(&_v.sa) : nullptr; }
|
||||
ZT_ALWAYS_INLINE const char *dnsName() const { return (_t == DNSNAME) ? _v.dns.name : nullptr; }
|
||||
|
@ -61,6 +61,45 @@ public:
|
|||
|
||||
ZT_ALWAYS_INLINE Type type() const { return _t; }
|
||||
|
||||
ZT_ALWAYS_INLINE bool operator==(const Endpoint &ep) const
|
||||
{
|
||||
if (_t == ep._t) {
|
||||
switch(_t) {
|
||||
case INETADDR: return (*sockaddr() == *ep.sockaddr());
|
||||
case DNSNAME: return ((_v.dns.port == ep._v.dns.port)&&(strcmp(_v.dns.name,ep._v.dns.name) == 0));
|
||||
case ZEROTIER: return ((_v.zt.a == ep._v.zt.a)&&(memcmp(_v.zt.idh,ep._v.zt.idh,sizeof(_v.zt.idh)) == 0));
|
||||
case URL: return (strcmp(_v.url,ep._v.url) == 0);
|
||||
case ETHERNET: return (_v.eth == ep._v.eth);
|
||||
default: return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
ZT_ALWAYS_INLINE bool operator!=(const Endpoint &ep) const { return (!(*this == ep)); }
|
||||
ZT_ALWAYS_INLINE bool operator<(const Endpoint &ep) const
|
||||
{
|
||||
if ((int)_t < (int)ep._t) {
|
||||
return true;
|
||||
} else if (_t == ep._t) {
|
||||
int ncmp;
|
||||
switch(_t) {
|
||||
case INETADDR: return (*sockaddr() < *ep.sockaddr());
|
||||
case DNSNAME:
|
||||
ncmp = strcmp(_v.dns.name,ep._v.dns.name);
|
||||
return ((ncmp < 0) ? true : (ncmp == 0)&&(_v.dns.port < ep._v.dns.port));
|
||||
case ZEROTIER: return (_v.zt.a < ep._v.zt.a) ? true : ((_v.zt.a == ep._v.zt.a)&&(memcmp(_v.zt.idh,ep._v.zt.idh,sizeof(_v.zt.idh)) < 0));
|
||||
case URL: return (strcmp(_v.url,ep._v.url) < 0);
|
||||
case ETHERNET: return (_v.eth < ep._v.eth);
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
ZT_ALWAYS_INLINE bool operator>(const Endpoint &ep) const { return (ep < *this); }
|
||||
ZT_ALWAYS_INLINE bool operator<=(const Endpoint &ep) const { return !(ep < *this); }
|
||||
ZT_ALWAYS_INLINE bool operator>=(const Endpoint &ep) const { return !(*this < ep); }
|
||||
|
||||
// Marshal interface ///////////////////////////////////////////////////////
|
||||
static ZT_ALWAYS_INLINE int marshalSizeMax() { return ZT_ENDPOINT_MARSHAL_SIZE_MAX; }
|
||||
inline int marshal(uint8_t data[ZT_ENDPOINT_MARSHAL_SIZE_MAX]) const
|
||||
{
|
||||
|
@ -79,16 +118,16 @@ public:
|
|||
if (p == (ZT_ENDPOINT_MAX_NAME_SIZE+1))
|
||||
return -1;
|
||||
}
|
||||
data[p++] = (uint8_t)((_v.dns.port >> 8) & 0xff);
|
||||
data[p++] = (uint8_t)(_v.dns.port & 0xff);
|
||||
data[p++] = (uint8_t)(_v.dns.port >> 8U);
|
||||
data[p++] = (uint8_t)_v.dns.port;
|
||||
return p;
|
||||
case ZEROTIER:
|
||||
data[0] = (uint8_t)ZEROTIER;
|
||||
data[1] = (uint8_t)((_v.zt.a >> 32) & 0xff);
|
||||
data[2] = (uint8_t)((_v.zt.a >> 24) & 0xff);
|
||||
data[3] = (uint8_t)((_v.zt.a >> 16) & 0xff);
|
||||
data[4] = (uint8_t)((_v.zt.a >> 8) & 0xff);
|
||||
data[5] = (uint8_t)(_v.zt.a & 0xff);
|
||||
data[1] = (uint8_t)(_v.zt.a >> 32U);
|
||||
data[2] = (uint8_t)(_v.zt.a >> 24U);
|
||||
data[3] = (uint8_t)(_v.zt.a >> 16U);
|
||||
data[4] = (uint8_t)(_v.zt.a >> 8U);
|
||||
data[5] = (uint8_t)_v.zt.a;
|
||||
memcpy(data + 6,_v.zt.idh,ZT_IDENTITY_HASH_SIZE);
|
||||
return (ZT_IDENTITY_HASH_SIZE + 6);
|
||||
case URL:
|
||||
|
@ -104,12 +143,12 @@ public:
|
|||
return p;
|
||||
case ETHERNET:
|
||||
data[0] = (uint8_t)ETHERNET;
|
||||
data[1] = (uint8_t)((_v.eth >> 40) & 0xff);
|
||||
data[2] = (uint8_t)((_v.eth >> 32) & 0xff);
|
||||
data[3] = (uint8_t)((_v.eth >> 24) & 0xff);
|
||||
data[4] = (uint8_t)((_v.eth >> 16) & 0xff);
|
||||
data[5] = (uint8_t)((_v.eth >> 8) & 0xff);
|
||||
data[6] = (uint8_t)(_v.eth & 0xff);
|
||||
data[1] = (uint8_t)(_v.eth >> 40U);
|
||||
data[2] = (uint8_t)(_v.eth >> 32U);
|
||||
data[3] = (uint8_t)(_v.eth >> 24U);
|
||||
data[4] = (uint8_t)(_v.eth >> 16U);
|
||||
data[5] = (uint8_t)(_v.eth >> 8U);
|
||||
data[6] = (uint8_t)_v.eth;
|
||||
return 7;
|
||||
default:
|
||||
data[0] = (uint8_t)NIL;
|
||||
|
@ -142,17 +181,17 @@ public:
|
|||
if ((p >= (ZT_ENDPOINT_MAX_NAME_SIZE+1))||(p >= (len-2)))
|
||||
return -1;
|
||||
}
|
||||
_v.dns.port = ((int)data[p++]) << 8;
|
||||
_v.dns.port |= (int)data[p++];
|
||||
_v.dns.port = (uint16_t)(((unsigned int)data[p++]) << 8U);
|
||||
_v.dns.port |= (uint16_t)data[p++];
|
||||
return p;
|
||||
case ZEROTIER:
|
||||
if (len < (ZT_IDENTITY_HASH_SIZE + 6))
|
||||
return -1;
|
||||
_t = ZEROTIER;
|
||||
_v.zt.a = ((uint64_t)data[1]) << 32;
|
||||
_v.zt.a |= ((uint64_t)data[2]) << 24;
|
||||
_v.zt.a |= ((uint64_t)data[3]) << 16;
|
||||
_v.zt.a |= ((uint64_t)data[4]) << 8;
|
||||
_v.zt.a = ((uint64_t)data[1]) << 32U;
|
||||
_v.zt.a |= ((uint64_t)data[2]) << 24U;
|
||||
_v.zt.a |= ((uint64_t)data[3]) << 16U;
|
||||
_v.zt.a |= ((uint64_t)data[4]) << 8U;
|
||||
_v.zt.a |= (uint64_t)data[5];
|
||||
memcpy(_v.zt.idh,data + 6,ZT_IDENTITY_HASH_SIZE);
|
||||
return (ZT_IDENTITY_HASH_SIZE + 6);
|
||||
|
@ -175,16 +214,17 @@ public:
|
|||
if (len < 7)
|
||||
return -1;
|
||||
_t = ZEROTIER;
|
||||
_v.eth = ((uint64_t)data[1]) << 40;
|
||||
_v.eth |= ((uint64_t)data[2]) << 32;
|
||||
_v.eth |= ((uint64_t)data[3]) << 24;
|
||||
_v.eth |= ((uint64_t)data[4]) << 16;
|
||||
_v.eth |= ((uint64_t)data[5]) << 8;
|
||||
_v.eth = ((uint64_t)data[1]) << 40U;
|
||||
_v.eth |= ((uint64_t)data[2]) << 32U;
|
||||
_v.eth |= ((uint64_t)data[3]) << 24U;
|
||||
_v.eth |= ((uint64_t)data[4]) << 16U;
|
||||
_v.eth |= ((uint64_t)data[5]) << 8U;
|
||||
_v.eth |= (uint64_t)data[6];
|
||||
return 7;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private:
|
||||
Type _t;
|
||||
|
@ -192,7 +232,7 @@ private:
|
|||
struct sockaddr_storage sa;
|
||||
struct {
|
||||
char name[ZT_ENDPOINT_MAX_NAME_SIZE];
|
||||
int port;
|
||||
uint16_t port;
|
||||
} dns;
|
||||
struct {
|
||||
uint64_t a;
|
||||
|
|
|
@ -368,7 +368,7 @@ public:
|
|||
/**
|
||||
* @return True if this identity contains something
|
||||
*/
|
||||
ZT_ALWAYS_INLINE operator bool() const { return (_address); }
|
||||
explicit ZT_ALWAYS_INLINE operator bool() const { return (_address); }
|
||||
|
||||
ZT_ALWAYS_INLINE bool operator==(const Identity &id) const
|
||||
{
|
||||
|
@ -407,7 +407,7 @@ public:
|
|||
|
||||
// Marshal interface ///////////////////////////////////////////////////////
|
||||
static ZT_ALWAYS_INLINE int marshalSizeMax() { return ZT_IDENTITY_MARSHAL_SIZE_MAX; }
|
||||
inline int marshal(uint8_t restrict data[ZT_IDENTITY_MARSHAL_SIZE_MAX],const bool includePrivate = false) const
|
||||
inline int marshal(uint8_t data[ZT_IDENTITY_MARSHAL_SIZE_MAX],const bool includePrivate = false) const
|
||||
{
|
||||
_address.copyTo(data,ZT_ADDRESS_LENGTH);
|
||||
switch(_type) {
|
||||
|
|
|
@ -11,11 +11,8 @@
|
|||
*/
|
||||
/****/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <cstdint>
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
|
@ -33,20 +30,20 @@ InetAddress::IpScope InetAddress::ipScope() const
|
|||
|
||||
case AF_INET: {
|
||||
const uint32_t ip = Utils::ntoh((uint32_t)reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr);
|
||||
switch(ip >> 24) {
|
||||
switch(ip >> 24U) {
|
||||
case 0x00: return IP_SCOPE_NONE; // 0.0.0.0/8 (reserved, never used)
|
||||
case 0x06: return IP_SCOPE_PSEUDOPRIVATE; // 6.0.0.0/8 (US Army)
|
||||
case 0x0a: return IP_SCOPE_PRIVATE; // 10.0.0.0/8
|
||||
case 0x0b: return IP_SCOPE_PSEUDOPRIVATE; // 11.0.0.0/8 (US DoD)
|
||||
case 0x15: return IP_SCOPE_PSEUDOPRIVATE; // 21.0.0.0/8 (US DDN-RVN)
|
||||
case 0x16: return IP_SCOPE_PSEUDOPRIVATE; // 22.0.0.0/8 (US DISA)
|
||||
case 0x19: return IP_SCOPE_PSEUDOPRIVATE; // 25.0.0.0/8 (UK Ministry of Defense)
|
||||
case 0x1a: return IP_SCOPE_PSEUDOPRIVATE; // 26.0.0.0/8 (US DISA)
|
||||
case 0x1c: return IP_SCOPE_PSEUDOPRIVATE; // 28.0.0.0/8 (US DSI-North)
|
||||
case 0x1d: return IP_SCOPE_PSEUDOPRIVATE; // 29.0.0.0/8 (US DISA)
|
||||
case 0x1e: return IP_SCOPE_PSEUDOPRIVATE; // 30.0.0.0/8 (US DISA)
|
||||
case 0x33: return IP_SCOPE_PSEUDOPRIVATE; // 51.0.0.0/8 (UK Department of Social Security)
|
||||
case 0x37: return IP_SCOPE_PSEUDOPRIVATE; // 55.0.0.0/8 (US DoD)
|
||||
case 0x0b: //return IP_SCOPE_PSEUDOPRIVATE; // 11.0.0.0/8 (US DoD)
|
||||
case 0x15: //return IP_SCOPE_PSEUDOPRIVATE; // 21.0.0.0/8 (US DDN-RVN)
|
||||
case 0x16: //return IP_SCOPE_PSEUDOPRIVATE; // 22.0.0.0/8 (US DISA)
|
||||
case 0x19: //return IP_SCOPE_PSEUDOPRIVATE; // 25.0.0.0/8 (UK Ministry of Defense)
|
||||
case 0x1a: //return IP_SCOPE_PSEUDOPRIVATE; // 26.0.0.0/8 (US DISA)
|
||||
case 0x1c: //return IP_SCOPE_PSEUDOPRIVATE; // 28.0.0.0/8 (US DSI-North)
|
||||
case 0x1d: //return IP_SCOPE_PSEUDOPRIVATE; // 29.0.0.0/8 (US DISA)
|
||||
case 0x1e: //return IP_SCOPE_PSEUDOPRIVATE; // 30.0.0.0/8 (US DISA)
|
||||
case 0x33: //return IP_SCOPE_PSEUDOPRIVATE; // 51.0.0.0/8 (UK Department of Social Security)
|
||||
case 0x37: //return IP_SCOPE_PSEUDOPRIVATE; // 55.0.0.0/8 (US DoD)
|
||||
case 0x38: return IP_SCOPE_PSEUDOPRIVATE; // 56.0.0.0/8 (US Postal Service)
|
||||
case 0x64:
|
||||
if ((ip & 0xffc00000) == 0x64400000) return IP_SCOPE_PRIVATE; // 100.64.0.0/10
|
||||
|
@ -164,7 +161,7 @@ bool InetAddress::fromString(const char *ipSlashPort)
|
|||
unsigned int port = 0;
|
||||
if (*portAt) {
|
||||
*(portAt++) = (char)0;
|
||||
port = Utils::strToUInt(portAt) & 0xffff;
|
||||
port = Utils::strToUInt(portAt) & 0xffffU;
|
||||
}
|
||||
|
||||
if (strchr(buf,':')) {
|
||||
|
@ -189,7 +186,7 @@ InetAddress InetAddress::netmask() const
|
|||
InetAddress r(*this);
|
||||
switch(r.ss_family) {
|
||||
case AF_INET:
|
||||
reinterpret_cast<struct sockaddr_in *>(&r)->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)(0xffffffffU << (32 - netmaskBits())));
|
||||
break;
|
||||
case AF_INET6: {
|
||||
uint64_t nm[2];
|
||||
|
@ -211,7 +208,7 @@ InetAddress InetAddress::broadcast() const
|
|||
{
|
||||
if (ss_family == AF_INET) {
|
||||
InetAddress r(*this);
|
||||
reinterpret_cast<struct sockaddr_in *>(&r)->sin_addr.s_addr |= Utils::hton((uint32_t)(0xffffffff >> netmaskBits()));
|
||||
reinterpret_cast<struct sockaddr_in *>(&r)->sin_addr.s_addr |= Utils::hton((uint32_t)(0xffffffffU >> netmaskBits()));
|
||||
return r;
|
||||
}
|
||||
return InetAddress();
|
||||
|
@ -222,7 +219,7 @@ InetAddress InetAddress::network() const
|
|||
InetAddress r(*this);
|
||||
switch(r.ss_family) {
|
||||
case AF_INET:
|
||||
reinterpret_cast<struct sockaddr_in *>(&r)->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)(0xffffffffU << (32 - netmaskBits())));
|
||||
break;
|
||||
case AF_INET6: {
|
||||
uint64_t nm[2];
|
||||
|
@ -294,7 +291,7 @@ bool InetAddress::isNetwork() const
|
|||
if (bits >= 32)
|
||||
return false;
|
||||
uint32_t ip = Utils::ntoh((uint32_t)reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr);
|
||||
return ((ip & (0xffffffff >> bits)) == 0);
|
||||
return ((ip & (0xffffffffU >> bits)) == 0);
|
||||
}
|
||||
case AF_INET6: {
|
||||
unsigned int bits = netmaskBits();
|
||||
|
@ -304,7 +301,7 @@ bool InetAddress::isNetwork() const
|
|||
return false;
|
||||
const unsigned char *ip = reinterpret_cast<const unsigned char *>(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr);
|
||||
unsigned int p = bits / 8;
|
||||
if ((ip[p++] & (0xff >> (bits % 8))) != 0)
|
||||
if ((ip[p++] & (0xffU >> (bits % 8))) != 0)
|
||||
return false;
|
||||
while (p < 16) {
|
||||
if (ip[p++])
|
||||
|
@ -378,48 +375,49 @@ bool InetAddress::operator<(const InetAddress &a) const
|
|||
|
||||
InetAddress InetAddress::makeIpv6LinkLocal(const MAC &mac)
|
||||
{
|
||||
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);
|
||||
InetAddress r;
|
||||
sockaddr_in6 *const sin6 = reinterpret_cast<struct sockaddr_in6 *>(&r);
|
||||
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] & 0xfdU;
|
||||
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 r;
|
||||
}
|
||||
|
||||
InetAddress InetAddress::makeIpv6rfc4193(uint64_t nwid,uint64_t zeroTierAddress)
|
||||
{
|
||||
InetAddress r;
|
||||
struct sockaddr_in6 *const sin6 = reinterpret_cast<struct sockaddr_in6 *>(&r);
|
||||
sockaddr_in6 *const sin6 = reinterpret_cast<struct sockaddr_in6 *>(&r);
|
||||
sin6->sin6_family = AF_INET6;
|
||||
sin6->sin6_addr.s6_addr[0] = 0xfd;
|
||||
sin6->sin6_addr.s6_addr[1] = (uint8_t)(nwid >> 56);
|
||||
sin6->sin6_addr.s6_addr[2] = (uint8_t)(nwid >> 48);
|
||||
sin6->sin6_addr.s6_addr[3] = (uint8_t)(nwid >> 40);
|
||||
sin6->sin6_addr.s6_addr[4] = (uint8_t)(nwid >> 32);
|
||||
sin6->sin6_addr.s6_addr[5] = (uint8_t)(nwid >> 24);
|
||||
sin6->sin6_addr.s6_addr[6] = (uint8_t)(nwid >> 16);
|
||||
sin6->sin6_addr.s6_addr[7] = (uint8_t)(nwid >> 8);
|
||||
sin6->sin6_addr.s6_addr[1] = (uint8_t)(nwid >> 56U);
|
||||
sin6->sin6_addr.s6_addr[2] = (uint8_t)(nwid >> 48U);
|
||||
sin6->sin6_addr.s6_addr[3] = (uint8_t)(nwid >> 40U);
|
||||
sin6->sin6_addr.s6_addr[4] = (uint8_t)(nwid >> 32U);
|
||||
sin6->sin6_addr.s6_addr[5] = (uint8_t)(nwid >> 24U);
|
||||
sin6->sin6_addr.s6_addr[6] = (uint8_t)(nwid >> 16U);
|
||||
sin6->sin6_addr.s6_addr[7] = (uint8_t)(nwid >> 8U);
|
||||
sin6->sin6_addr.s6_addr[8] = (uint8_t)nwid;
|
||||
sin6->sin6_addr.s6_addr[9] = 0x99;
|
||||
sin6->sin6_addr.s6_addr[10] = 0x93;
|
||||
sin6->sin6_addr.s6_addr[11] = (uint8_t)(zeroTierAddress >> 32);
|
||||
sin6->sin6_addr.s6_addr[12] = (uint8_t)(zeroTierAddress >> 24);
|
||||
sin6->sin6_addr.s6_addr[13] = (uint8_t)(zeroTierAddress >> 16);
|
||||
sin6->sin6_addr.s6_addr[14] = (uint8_t)(zeroTierAddress >> 8);
|
||||
sin6->sin6_addr.s6_addr[11] = (uint8_t)(zeroTierAddress >> 32U);
|
||||
sin6->sin6_addr.s6_addr[12] = (uint8_t)(zeroTierAddress >> 24U);
|
||||
sin6->sin6_addr.s6_addr[13] = (uint8_t)(zeroTierAddress >> 16U);
|
||||
sin6->sin6_addr.s6_addr[14] = (uint8_t)(zeroTierAddress >> 8U);
|
||||
sin6->sin6_addr.s6_addr[15] = (uint8_t)zeroTierAddress;
|
||||
sin6->sin6_port = Utils::hton((uint16_t)88); // /88 includes 0xfd + network ID, discriminating by device ID below that
|
||||
return r;
|
||||
|
@ -427,19 +425,19 @@ InetAddress InetAddress::makeIpv6rfc4193(uint64_t nwid,uint64_t zeroTierAddress)
|
|||
|
||||
InetAddress InetAddress::makeIpv66plane(uint64_t nwid,uint64_t zeroTierAddress)
|
||||
{
|
||||
nwid ^= (nwid >> 32);
|
||||
nwid ^= (nwid >> 32U);
|
||||
InetAddress r;
|
||||
struct sockaddr_in6 *const sin6 = reinterpret_cast<struct sockaddr_in6 *>(&r);
|
||||
sockaddr_in6 *const sin6 = reinterpret_cast<struct sockaddr_in6 *>(&r);
|
||||
sin6->sin6_family = AF_INET6;
|
||||
sin6->sin6_addr.s6_addr[0] = 0xfc;
|
||||
sin6->sin6_addr.s6_addr[1] = (uint8_t)(nwid >> 24);
|
||||
sin6->sin6_addr.s6_addr[2] = (uint8_t)(nwid >> 16);
|
||||
sin6->sin6_addr.s6_addr[3] = (uint8_t)(nwid >> 8);
|
||||
sin6->sin6_addr.s6_addr[1] = (uint8_t)(nwid >> 24U);
|
||||
sin6->sin6_addr.s6_addr[2] = (uint8_t)(nwid >> 16U);
|
||||
sin6->sin6_addr.s6_addr[3] = (uint8_t)(nwid >> 8U);
|
||||
sin6->sin6_addr.s6_addr[4] = (uint8_t)nwid;
|
||||
sin6->sin6_addr.s6_addr[5] = (uint8_t)(zeroTierAddress >> 32);
|
||||
sin6->sin6_addr.s6_addr[6] = (uint8_t)(zeroTierAddress >> 24);
|
||||
sin6->sin6_addr.s6_addr[7] = (uint8_t)(zeroTierAddress >> 16);
|
||||
sin6->sin6_addr.s6_addr[8] = (uint8_t)(zeroTierAddress >> 8);
|
||||
sin6->sin6_addr.s6_addr[5] = (uint8_t)(zeroTierAddress >> 32U);
|
||||
sin6->sin6_addr.s6_addr[6] = (uint8_t)(zeroTierAddress >> 24U);
|
||||
sin6->sin6_addr.s6_addr[7] = (uint8_t)(zeroTierAddress >> 16U);
|
||||
sin6->sin6_addr.s6_addr[8] = (uint8_t)(zeroTierAddress >> 8U);
|
||||
sin6->sin6_addr.s6_addr[9] = (uint8_t)zeroTierAddress;
|
||||
sin6->sin6_addr.s6_addr[15] = 0x01;
|
||||
sin6->sin6_port = Utils::hton((uint16_t)40);
|
||||
|
|
|
@ -18,8 +18,9 @@
|
|||
#include <cstring>
|
||||
#include <cstdint>
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "../include/ZeroTierOne.h"
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "MAC.hpp"
|
||||
#include "Buffer.hpp"
|
||||
|
@ -464,16 +465,16 @@ struct InetAddress : public sockaddr_storage
|
|||
unsigned long h = 0;
|
||||
switch(ss_family) {
|
||||
case AF_INET:
|
||||
h = (Utils::ntoh((uint32_t)reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr) & 0xffffff00) >> 8;
|
||||
h ^= (h >> 14);
|
||||
h = (Utils::ntoh((uint32_t)reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr) & 0xffffff00U) >> 8U;
|
||||
h ^= (h >> 14U);
|
||||
break;
|
||||
case AF_INET6: {
|
||||
const uint8_t *ip = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr);
|
||||
h = ((unsigned long)ip[0]); h <<= 1;
|
||||
h += ((unsigned long)ip[1]); h <<= 1;
|
||||
h += ((unsigned long)ip[2]); h <<= 1;
|
||||
h += ((unsigned long)ip[3]); h <<= 1;
|
||||
h += ((unsigned long)ip[4]); h <<= 1;
|
||||
h = ((unsigned long)ip[0]); h <<= 1U;
|
||||
h += ((unsigned long)ip[1]); h <<= 1U;
|
||||
h += ((unsigned long)ip[2]); h <<= 1U;
|
||||
h += ((unsigned long)ip[3]); h <<= 1U;
|
||||
h += ((unsigned long)ip[4]); h <<= 1U;
|
||||
h += ((unsigned long)ip[5]);
|
||||
} break;
|
||||
}
|
||||
|
@ -483,30 +484,31 @@ struct InetAddress : public sockaddr_storage
|
|||
/**
|
||||
* @return True if address family is non-zero
|
||||
*/
|
||||
ZT_ALWAYS_INLINE operator bool() const { return (ss_family != 0); }
|
||||
explicit ZT_ALWAYS_INLINE operator bool() const { return (ss_family != 0); }
|
||||
|
||||
// Marshal interface ///////////////////////////////////////////////////////
|
||||
static ZT_ALWAYS_INLINE int marshalSizeMax() { return 19; }
|
||||
inline int marshal(uint8_t restrict data[19]) const
|
||||
inline int marshal(uint8_t data[19]) const
|
||||
{
|
||||
unsigned int port;
|
||||
switch(ss_family) {
|
||||
case AF_INET:
|
||||
const unsigned int port = Utils::ntoh((uint16_t)reinterpret_cast<const sockaddr_in *>(this)->sin_port);
|
||||
port = Utils::ntoh((uint16_t)reinterpret_cast<const sockaddr_in *>(this)->sin_port);
|
||||
data[0] = 4;
|
||||
data[1] = reinterpret_cast<const uint8_t *>(&(reinterpret_cast<const sockaddr_in *>(this)->sin_addr.s_addr))[0];
|
||||
data[2] = reinterpret_cast<const uint8_t *>(&(reinterpret_cast<const sockaddr_in *>(this)->sin_addr.s_addr))[1];
|
||||
data[3] = reinterpret_cast<const uint8_t *>(&(reinterpret_cast<const sockaddr_in *>(this)->sin_addr.s_addr))[2];
|
||||
data[4] = reinterpret_cast<const uint8_t *>(&(reinterpret_cast<const sockaddr_in *>(this)->sin_addr.s_addr))[3];
|
||||
data[5] = (uint8_t)((port >> 8) & 0xff);
|
||||
data[6] = (uint8_t)(port & 0xff);
|
||||
data[5] = (uint8_t)(port >> 8U);
|
||||
data[6] = (uint8_t)port;
|
||||
return 7;
|
||||
case AF_INET6:
|
||||
const unsigned int port = Utils::ntoh((uint16_t)reinterpret_cast<const sockaddr_in6 *>(this)->sin6_port);
|
||||
port = Utils::ntoh((uint16_t)reinterpret_cast<const sockaddr_in6 *>(this)->sin6_port);
|
||||
data[0] = 6;
|
||||
for(int i=0;i<16;++i)
|
||||
data[i+1] = reinterpret_cast<const sockaddr_in6 *>(this)->sin6_addr.s6_addr[i];
|
||||
data[17] = (uint8_t)((port >> 8) & 0xff);
|
||||
data[18] = (uint8_t)(port & 0xff);
|
||||
data[17] = (uint8_t)(port >> 8U);
|
||||
data[18] = (uint8_t)port;
|
||||
return 19;
|
||||
default:
|
||||
data[0] = 0;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Endpoint.hpp"
|
||||
|
@ -35,7 +36,12 @@ namespace ZeroTier {
|
|||
class Locator
|
||||
{
|
||||
public:
|
||||
ZT_ALWAYS_INLINE Locator() : _ts(0),_endpointCount(0),_signatureLength(0) {}
|
||||
ZT_ALWAYS_INLINE Locator() { this->clear(); }
|
||||
|
||||
/**
|
||||
* Zero the Locator data structure
|
||||
*/
|
||||
ZT_ALWAYS_INLINE void clear() { memset(reinterpret_cast<void *>(this),0,sizeof(Locator)); }
|
||||
|
||||
/**
|
||||
* @return Timestamp (a.k.a. revision number) set by Location signer
|
||||
|
@ -43,31 +49,42 @@ public:
|
|||
ZT_ALWAYS_INLINE int64_t timestamp() const { return _ts; }
|
||||
|
||||
/**
|
||||
* Create and sign a Locator
|
||||
*
|
||||
* @param ts Timestamp
|
||||
* @param id Identity (must include secret to allow signing)
|
||||
* @param at Array of Endpoint objects specifying where this peer might be found
|
||||
* @param endpointCount Number of endpoints (max: ZT_LOCATOR_MAX_ENDPOINTS)
|
||||
* @return True if init and sign were successful
|
||||
* @return True if locator is signed
|
||||
*/
|
||||
inline bool create(const int64_t ts,const Identity &id,const Endpoint *restrict at,const unsigned int endpointCount)
|
||||
ZT_ALWAYS_INLINE bool isSigned() const { return (_signatureLength > 0); }
|
||||
|
||||
/**
|
||||
* Add an endpoint to this locator if not already present
|
||||
*
|
||||
* @param ep Endpoint to add
|
||||
* @return True if endpoint was added (or already present), false if locator is full
|
||||
*/
|
||||
inline bool add(const Endpoint &ep)
|
||||
{
|
||||
if ((endpointCount > ZT_LOCATOR_MAX_ENDPOINTS)||(!id.hasPrivate()))
|
||||
if (_endpointCount >= ZT_LOCATOR_MAX_ENDPOINTS)
|
||||
return false;
|
||||
if (!std::binary_search(_at,_at + _endpointCount,ep)) {
|
||||
_at[_endpointCount++] = ep;
|
||||
std::sort(_at,_at + _endpointCount);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign this locator
|
||||
*
|
||||
* @param id Identity that includes private key
|
||||
* @return True if signature successful
|
||||
*/
|
||||
inline bool sign(const int64_t ts,const Identity &id)
|
||||
{
|
||||
uint8_t signData[ZT_LOCATOR_MARSHAL_SIZE_MAX];
|
||||
if (!id.hasPrivate())
|
||||
return false;
|
||||
_ts = ts;
|
||||
for(unsigned int i=0;i<endpointCount;++i)
|
||||
_at[i] = at[i];
|
||||
_endpointCount = endpointCount;
|
||||
|
||||
uint8_t signData[ZT_LOCATOR_MARSHAL_SIZE_MAX];
|
||||
const unsigned int signLen = marshal(signData,true);
|
||||
if (signLen == 0)
|
||||
return false;
|
||||
if ((_signatureLength = id.sign(signData,signLen,_signature,sizeof(_signature))) == 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
_signatureLength = id.sign(signData, signLen, _signature, sizeof(_signature));
|
||||
return (_signatureLength > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -85,26 +102,19 @@ public:
|
|||
return id.verify(signData,signLen,_signature,_signatureLength);
|
||||
}
|
||||
|
||||
ZT_ALWAYS_INLINE operator bool() const { return (_ts != 0); }
|
||||
explicit ZT_ALWAYS_INLINE operator bool() const { return (_ts != 0); }
|
||||
|
||||
// Marshal interface ///////////////////////////////////////////////////////
|
||||
static ZT_ALWAYS_INLINE int marshalSizeMax() { return ZT_LOCATOR_MARSHAL_SIZE_MAX; }
|
||||
inline int marshal(uint8_t restrict data[ZT_LOCATOR_MARSHAL_SIZE_MAX],const bool excludeSignature = false) const
|
||||
inline int marshal(uint8_t data[ZT_LOCATOR_MARSHAL_SIZE_MAX],const bool excludeSignature = false) const
|
||||
{
|
||||
if ((_endpointCount > ZT_LOCATOR_MAX_ENDPOINTS)||(_signatureLength > ZT_SIGNATURE_BUFFER_SIZE))
|
||||
return -1;
|
||||
|
||||
data[0] = (uint8_t)((uint64_t)_ts >> 56);
|
||||
data[1] = (uint8_t)((uint64_t)_ts >> 48);
|
||||
data[2] = (uint8_t)((uint64_t)_ts >> 40);
|
||||
data[3] = (uint8_t)((uint64_t)_ts >> 32);
|
||||
data[4] = (uint8_t)((uint64_t)_ts >> 24);
|
||||
data[5] = (uint8_t)((uint64_t)_ts >> 16);
|
||||
data[6] = (uint8_t)((uint64_t)_ts >> 8);
|
||||
data[7] = (uint8_t)((uint64_t)_ts);
|
||||
Utils::putUInt64(data,(uint64_t)_ts);
|
||||
int p = 8;
|
||||
|
||||
data[p++] = (uint8_t)(_endpointCount >> 8);
|
||||
data[p++] = (uint8_t)(_endpointCount >> 8U);
|
||||
data[p++] = (uint8_t)_endpointCount;
|
||||
for(unsigned int i=0;i<_endpointCount;++i) {
|
||||
int tmp = _at[i].marshal(data + p);
|
||||
|
@ -114,10 +124,10 @@ public:
|
|||
}
|
||||
|
||||
if (!excludeSignature) {
|
||||
data[p++] = (uint8_t)(_signatureLength >> 8);
|
||||
data[p++] = (uint8_t)(_signatureLength >> 8U);
|
||||
data[p++] = (uint8_t)_signatureLength;
|
||||
memcpy(data + p,_signature,_signatureLength);
|
||||
p += _signatureLength;
|
||||
p += (int)_signatureLength;
|
||||
}
|
||||
|
||||
return p;
|
||||
|
@ -127,21 +137,13 @@ public:
|
|||
if (len <= (8 + 48))
|
||||
return -1;
|
||||
|
||||
uint64_t ts = ((uint64_t)data[0] << 56);
|
||||
ts |= ((uint64_t)data[1] << 48);
|
||||
ts |= ((uint64_t)data[2] << 40);
|
||||
ts |= ((uint64_t)data[3] << 32);
|
||||
ts |= ((uint64_t)data[4] << 24);
|
||||
ts |= ((uint64_t)data[5] << 16);
|
||||
ts |= ((uint64_t)data[6] << 8);
|
||||
ts |= (uint64_t)data[7];
|
||||
_ts = (int64_t)ts;
|
||||
_ts = (int64_t)Utils::readUInt64(data);
|
||||
int p = 8;
|
||||
|
||||
if ((p + 2) > len)
|
||||
return -1;
|
||||
unsigned int ec = (int)data[p++];
|
||||
ec <<= 8;
|
||||
ec <<= 8U;
|
||||
ec |= data[p++];
|
||||
if (ec > ZT_LOCATOR_MAX_ENDPOINTS)
|
||||
return -1;
|
||||
|
@ -156,7 +158,7 @@ public:
|
|||
if ((p + 2) > len)
|
||||
return -1;
|
||||
unsigned int sl = data[p++];
|
||||
sl <<= 8;
|
||||
sl <<= 8U;
|
||||
sl |= data[p++];
|
||||
if (sl > ZT_SIGNATURE_BUFFER_SIZE)
|
||||
return -1;
|
||||
|
|
|
@ -68,7 +68,7 @@ public:
|
|||
/**
|
||||
* @return Time we last pushed credentials to this member
|
||||
*/
|
||||
inline int64_t lastPushedCredentials() const { return _lastPushedCredentials; }
|
||||
ZT_ALWAYS_INLINE int64_t lastPushedCredentials() const { return _lastPushedCredentials; }
|
||||
|
||||
/**
|
||||
* Check whether we should push MULTICAST_LIKEs to this peer, and update last sent time if true
|
||||
|
@ -76,7 +76,7 @@ public:
|
|||
* @param now Current time
|
||||
* @return True if we should update multicasts
|
||||
*/
|
||||
inline bool multicastLikeGate(const int64_t now)
|
||||
ZT_ALWAYS_INLINE bool multicastLikeGate(const int64_t now)
|
||||
{
|
||||
if ((now - _lastUpdatedMulticast) >= ZT_MULTICAST_ANNOUNCE_PERIOD) {
|
||||
_lastUpdatedMulticast = now;
|
||||
|
@ -91,7 +91,7 @@ public:
|
|||
* @param nconf Our network config
|
||||
* @return True if this peer is allowed on this network at all
|
||||
*/
|
||||
inline bool isAllowedOnNetwork(const NetworkConfig &nconf) const
|
||||
ZT_ALWAYS_INLINE bool isAllowedOnNetwork(const NetworkConfig &nconf) const
|
||||
{
|
||||
if (nconf.isPublic()) return true; // public network
|
||||
if (_com.timestamp() <= _comRevocationThreshold) return false; // COM has been revoked
|
||||
|
@ -107,7 +107,7 @@ public:
|
|||
* @return True if this peer has a certificate of ownership for the given resource
|
||||
*/
|
||||
template<typename T>
|
||||
inline bool peerOwnsAddress(const NetworkConfig &nconf,const T &r) const
|
||||
ZT_ALWAYS_INLINE bool peerOwnsAddress(const NetworkConfig &nconf,const T &r) const
|
||||
{
|
||||
if (_isUnspoofableAddress(nconf,r))
|
||||
return true;
|
||||
|
@ -128,7 +128,7 @@ public:
|
|||
* @param id Tag ID
|
||||
* @return Pointer to tag or NULL if not found
|
||||
*/
|
||||
inline const Tag *getTag(const NetworkConfig &nconf,const uint32_t id) const
|
||||
ZT_ALWAYS_INLINE const Tag *getTag(const NetworkConfig &nconf,const uint32_t id) const
|
||||
{
|
||||
const Tag *const t = _remoteTags.get(id);
|
||||
return (((t)&&(_isCredentialTimestampValid(nconf,*t))) ? t : (Tag *)0);
|
||||
|
@ -146,7 +146,7 @@ public:
|
|||
* @param now Current time
|
||||
* @param nconf Current network configuration
|
||||
*/
|
||||
void clean(const int64_t now,const NetworkConfig &nconf);
|
||||
void clean(int64_t now,const NetworkConfig &nconf);
|
||||
|
||||
/**
|
||||
* Generates a key for internal use in indexing credentials by type and credential ID
|
||||
|
@ -156,29 +156,29 @@ public:
|
|||
/**
|
||||
* @return Bytes received so far
|
||||
*/
|
||||
inline uint64_t receivedBytes() const { return _received; }
|
||||
ZT_ALWAYS_INLINE uint64_t receivedBytes() const { return _received; }
|
||||
|
||||
/**
|
||||
* @return Bytes sent so far
|
||||
*/
|
||||
inline uint64_t sentBytes() const { return _sent; }
|
||||
ZT_ALWAYS_INLINE uint64_t sentBytes() const { return _sent; }
|
||||
|
||||
/**
|
||||
* @param bytes Bytes received
|
||||
*/
|
||||
inline void logReceivedBytes(const unsigned int bytes) { _received = (uint64_t)bytes; }
|
||||
ZT_ALWAYS_INLINE void logReceivedBytes(const unsigned int bytes) { _received = (uint64_t)bytes; }
|
||||
|
||||
/**
|
||||
* @param bytes Bytes sent
|
||||
*/
|
||||
inline void logSentBytes(const unsigned int bytes) { _sent = (uint64_t)bytes; }
|
||||
ZT_ALWAYS_INLINE void logSentBytes(const unsigned int bytes) { _sent = (uint64_t)bytes; }
|
||||
|
||||
private:
|
||||
// This returns true if a resource is an IPv6 NDP-emulated address. These embed the ZT
|
||||
// address of the peer and therefore cannot be spoofed, causing peerOwnsAddress() to
|
||||
// always return true for them. A certificate is not required for these.
|
||||
inline bool _isUnspoofableAddress(const NetworkConfig &nconf,const MAC &m) const { return false; }
|
||||
inline bool _isUnspoofableAddress(const NetworkConfig &nconf,const InetAddress &ip) const
|
||||
ZT_ALWAYS_INLINE bool _isUnspoofableAddress(const NetworkConfig &nconf,const MAC &m) const { return false; }
|
||||
ZT_ALWAYS_INLINE bool _isUnspoofableAddress(const NetworkConfig &nconf,const InetAddress &ip) const
|
||||
{
|
||||
if ((ip.isV6())&&(nconf.ndpEmulation())) {
|
||||
const InetAddress sixpl(InetAddress::makeIpv66plane(nconf.networkId,nconf.issuedTo.toInt()));
|
||||
|
@ -219,7 +219,7 @@ private:
|
|||
// This compares the remote credential's timestamp to the timestamp in our network config
|
||||
// plus or minus the permitted maximum timestamp delta.
|
||||
template<typename C>
|
||||
inline bool _isCredentialTimestampValid(const NetworkConfig &nconf,const C &remoteCredential) const
|
||||
ZT_ALWAYS_INLINE bool _isCredentialTimestampValid(const NetworkConfig &nconf,const C &remoteCredential) const
|
||||
{
|
||||
const int64_t ts = remoteCredential.timestamp();
|
||||
if (((ts >= nconf.timestamp) ? (ts - nconf.timestamp) : (nconf.timestamp - ts)) <= nconf.credentialTimeMaxDelta) {
|
||||
|
@ -271,7 +271,7 @@ public:
|
|||
class CapabilityIterator
|
||||
{
|
||||
public:
|
||||
inline CapabilityIterator(Membership &m,const NetworkConfig &nconf) :
|
||||
ZT_ALWAYS_INLINE CapabilityIterator(Membership &m,const NetworkConfig &nconf) :
|
||||
_hti(m._remoteCaps),
|
||||
_k((uint32_t *)0),
|
||||
_c((Capability *)0),
|
||||
|
@ -280,7 +280,7 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
inline Capability *next()
|
||||
ZT_ALWAYS_INLINE Capability *next()
|
||||
{
|
||||
while (_hti.next(_k,_c)) {
|
||||
if (_m._isCredentialTimestampValid(_nconf,*_c))
|
||||
|
|
293
node/Node.cpp
293
node/Node.cpp
|
@ -11,11 +11,11 @@
|
|||
*/
|
||||
/****/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstdarg>
|
||||
#include <cstring>
|
||||
#include <cstdint>
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
|
@ -40,10 +40,10 @@ namespace ZeroTier {
|
|||
/* Public Node interface (C++, exposed via CAPI bindings) */
|
||||
/****************************************************************************/
|
||||
|
||||
Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,int64_t now) :
|
||||
Node::Node(void *uPtr, void *tPtr, const struct ZT_Node_Callbacks *callbacks, int64_t now) :
|
||||
_RR(this),
|
||||
RR(&_RR),
|
||||
_uPtr(uptr),
|
||||
_uPtr(uPtr),
|
||||
_networks(8),
|
||||
_now(now),
|
||||
_lastPing(0),
|
||||
|
@ -61,7 +61,7 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,int64
|
|||
uint64_t idtmp[2];
|
||||
idtmp[0] = 0; idtmp[1] = 0;
|
||||
char tmp[2048];
|
||||
int n = stateObjectGet(tptr,ZT_STATE_OBJECT_IDENTITY_SECRET,idtmp,tmp,sizeof(tmp) - 1);
|
||||
int n = stateObjectGet(tPtr, ZT_STATE_OBJECT_IDENTITY_SECRET, idtmp, tmp, sizeof(tmp) - 1);
|
||||
if (n > 0) {
|
||||
tmp[n] = (char)0;
|
||||
if (RR->identity.fromString(tmp)) {
|
||||
|
@ -77,14 +77,14 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,int64
|
|||
RR->identity.toString(false,RR->publicIdentityStr);
|
||||
RR->identity.toString(true,RR->secretIdentityStr);
|
||||
idtmp[0] = RR->identity.address().toInt(); idtmp[1] = 0;
|
||||
stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_SECRET,idtmp,RR->secretIdentityStr,(unsigned int)strlen(RR->secretIdentityStr));
|
||||
stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,RR->publicIdentityStr,(unsigned int)strlen(RR->publicIdentityStr));
|
||||
stateObjectPut(tPtr, ZT_STATE_OBJECT_IDENTITY_SECRET, idtmp, RR->secretIdentityStr, (unsigned int)strlen(RR->secretIdentityStr));
|
||||
stateObjectPut(tPtr, ZT_STATE_OBJECT_IDENTITY_PUBLIC, idtmp, RR->publicIdentityStr, (unsigned int)strlen(RR->publicIdentityStr));
|
||||
} else {
|
||||
idtmp[0] = RR->identity.address().toInt(); idtmp[1] = 0;
|
||||
n = stateObjectGet(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,tmp,sizeof(tmp) - 1);
|
||||
n = stateObjectGet(tPtr, ZT_STATE_OBJECT_IDENTITY_PUBLIC, idtmp, tmp, sizeof(tmp) - 1);
|
||||
if ((n > 0)&&(n < (int)sizeof(RR->publicIdentityStr))&&(n < (int)sizeof(tmp))) {
|
||||
if (memcmp(tmp,RR->publicIdentityStr,n))
|
||||
stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,RR->publicIdentityStr,(unsigned int)strlen(RR->publicIdentityStr));
|
||||
if (memcmp(tmp,RR->publicIdentityStr,n) != 0)
|
||||
stateObjectPut(tPtr, ZT_STATE_OBJECT_IDENTITY_PUBLIC, idtmp, RR->publicIdentityStr, (unsigned int)strlen(RR->publicIdentityStr));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -117,7 +117,7 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,int64
|
|||
throw;
|
||||
}
|
||||
|
||||
postEvent(tptr,ZT_EVENT_UP);
|
||||
postEvent(tPtr, ZT_EVENT_UP);
|
||||
}
|
||||
|
||||
Node::~Node()
|
||||
|
@ -130,7 +130,7 @@ Node::~Node()
|
|||
if (RR->topology) RR->topology->~Topology();
|
||||
if (RR->sw) RR->sw->~Switch();
|
||||
if (RR->t) RR->t->~Trace();
|
||||
::free(RR->rtmem);
|
||||
free(RR->rtmem);
|
||||
}
|
||||
|
||||
ZT_ResultCode Node::processWirePacket(
|
||||
|
@ -169,74 +169,42 @@ ZT_ResultCode Node::processVirtualNetworkFrame(
|
|||
}
|
||||
}
|
||||
|
||||
// This is passed as the argument to the DNS request handler and
|
||||
// aggregates results.
|
||||
struct _processBackgroundTasks_dnsResultAccumulator
|
||||
// This function object is run past every peer every ZT_PEER_PING_PERIOD.
|
||||
struct _processBackgroundTasks_ping_eachPeer
|
||||
{
|
||||
_processBackgroundTasks_dnsResultAccumulator(const Str &n) : dnsName(n) {}
|
||||
Str dnsName;
|
||||
std::vector<Str> txtRecords;
|
||||
};
|
||||
|
||||
static const ZT_DNSRecordType s_txtRecordType[1] = { ZT_DNS_RECORD_TXT };
|
||||
|
||||
struct _processBackgroundTasks_eachRootName
|
||||
{
|
||||
ZT_Node_Callbacks *cb;
|
||||
Node *n;
|
||||
void *uPtr;
|
||||
void *tPtr;
|
||||
bool updateAll;
|
||||
|
||||
inline bool operator()(const Str &dnsName,const Locator &loc)
|
||||
{
|
||||
if ((strchr(dnsName.c_str(),'.'))&&((updateAll)||(!loc))) {
|
||||
_processBackgroundTasks_dnsResultAccumulator *dnsReq = new _processBackgroundTasks_dnsResultAccumulator(dnsName);
|
||||
cb->dnsResolver(reinterpret_cast<ZT_Node *>(n),uPtr,tPtr,s_txtRecordType,1,dnsName.c_str(),(uintptr_t)dnsReq);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
struct _processBackgroundTasks_ping_eachRoot
|
||||
{
|
||||
Hashtable< void *,bool > roots;
|
||||
int64_t now;
|
||||
void *tPtr;
|
||||
bool online;
|
||||
|
||||
inline bool operator()(const SharedPtr<Peer> &peer,const std::vector<InetAddress> &addrs)
|
||||
ZT_ALWAYS_INLINE bool operator()(const SharedPtr<Peer> &peer,const bool isRoot)
|
||||
{
|
||||
unsigned int v4SendCount = 0,v6SendCount = 0;
|
||||
peer->ping(tPtr,now,v4SendCount,v6SendCount);
|
||||
for(std::vector<InetAddress>::const_iterator a(addrs.begin());a!=addrs.end();++a) {
|
||||
if ( ((a->isV4())&&(v4SendCount == 0)) || ((a->isV6())&&(v6SendCount == 0)) )
|
||||
peer->sendHELLO(tPtr,-1,*a,now);
|
||||
|
||||
if (isRoot) {
|
||||
if ((now - peer->lastReceive()) <= ZT_PEER_PING_PERIOD)
|
||||
online = true;
|
||||
|
||||
if (v4SendCount == 0) {
|
||||
InetAddress try4;
|
||||
parent->externalPathLookup(tPtr,peer->identity(),AF_INET,try4);
|
||||
if (try4.ss_family == AF_INET)
|
||||
peer->sendHELLO(tPtr,-1,try4,now);
|
||||
}
|
||||
|
||||
if (v6SendCount == 0) {
|
||||
InetAddress try6;
|
||||
parent->externalPathLookup(tPtr,peer->identity(),AF_INET6,try6);
|
||||
if (try6.ss_family == AF_INET6)
|
||||
peer->sendHELLO(tPtr,-1,try6,now);
|
||||
}
|
||||
}
|
||||
if (!online)
|
||||
online = ((now - peer->lastReceive()) <= ((ZT_PEER_PING_PERIOD * 2) + 5000));
|
||||
roots.set((void *)peer.ptr(),true);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
struct _processBackgroundTasks_ping_eachPeer
|
||||
{
|
||||
int64_t now;
|
||||
Node *parent;
|
||||
void *tPtr;
|
||||
Hashtable< void *,bool > *roots;
|
||||
|
||||
inline bool operator()(const SharedPtr<Peer> &peer)
|
||||
{
|
||||
if (!roots->contains((void *)peer.ptr())) {
|
||||
unsigned int v4SendCount = 0,v6SendCount = 0;
|
||||
peer->ping(tPtr,now,v4SendCount,v6SendCount);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool online;
|
||||
};
|
||||
|
||||
ZT_ResultCode Node::processBackgroundTasks(void *tptr,int64_t now,volatile int64_t *nextBackgroundTaskDeadline)
|
||||
ZT_ResultCode Node::processBackgroundTasks(void *tPtr, int64_t now, volatile int64_t *nextBackgroundTaskDeadline)
|
||||
{
|
||||
_now = now;
|
||||
Mutex::Lock bl(_backgroundTasksLock);
|
||||
|
@ -252,41 +220,19 @@ ZT_ResultCode Node::processBackgroundTasks(void *tptr,int64_t now,volatile int64
|
|||
if ((now - _lastPing) >= ZT_PEER_PING_PERIOD) {
|
||||
_lastPing = now;
|
||||
try {
|
||||
// Periodically refresh locators for dynamic roots from their DNS names.
|
||||
if (_cb.dnsResolver) {
|
||||
_processBackgroundTasks_eachRootName cr;
|
||||
cr.cb = &_cb;
|
||||
cr.n = this;
|
||||
cr.uPtr = _uPtr;
|
||||
cr.tPtr = tptr;
|
||||
if ((now - _lastDynamicRootUpdate) >= ZT_DYNAMIC_ROOT_UPDATE_PERIOD) {
|
||||
_lastDynamicRootUpdate = now;
|
||||
cr.updateAll = true;
|
||||
} else {
|
||||
cr.updateAll = false;
|
||||
}
|
||||
RR->topology->eachRootName(cr);
|
||||
}
|
||||
|
||||
// Ping each root explicitly no matter what
|
||||
_processBackgroundTasks_ping_eachRoot rf;
|
||||
rf.now = now;
|
||||
rf.tPtr = tptr;
|
||||
rf.online = false;
|
||||
RR->topology->eachRoot(rf);
|
||||
|
||||
// Ping peers that are active and we want to keep alive
|
||||
_processBackgroundTasks_ping_eachPeer pf;
|
||||
pf.now = now;
|
||||
pf.tPtr = tptr;
|
||||
pf.roots = &rf.roots;
|
||||
RR->topology->eachPeer(pf);
|
||||
pf.parent = this;
|
||||
pf.tPtr = tPtr;
|
||||
pf.online = false;
|
||||
RR->topology->eachPeerWithRoot<_processBackgroundTasks_ping_eachPeer &>(pf);
|
||||
|
||||
// Update online status based on whether we can reach a root
|
||||
if (rf.online != _online) {
|
||||
_online = rf.online;
|
||||
postEvent(tptr,_online ? ZT_EVENT_ONLINE : ZT_EVENT_OFFLINE);
|
||||
if (pf.online != _online) {
|
||||
_online = pf.online;
|
||||
postEvent(tPtr, _online ? ZT_EVENT_ONLINE : ZT_EVENT_OFFLINE);
|
||||
}
|
||||
|
||||
RR->topology->rankRoots(now);
|
||||
} catch ( ... ) {
|
||||
return ZT_RESULT_FATAL_ERROR_INTERNAL;
|
||||
}
|
||||
|
@ -300,7 +246,7 @@ ZT_ResultCode Node::processBackgroundTasks(void *tptr,int64_t now,volatile int64
|
|||
uint64_t *nwid = (uint64_t *)0;
|
||||
SharedPtr<Network> *network = (SharedPtr<Network> *)0;
|
||||
while (i.next(nwid,network)) {
|
||||
(*network)->doPeriodicTasks(tptr,now);
|
||||
(*network)->doPeriodicTasks(tPtr, now);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -332,7 +278,7 @@ ZT_ResultCode Node::processBackgroundTasks(void *tptr,int64_t now,volatile int64
|
|||
}
|
||||
|
||||
try {
|
||||
*nextBackgroundTaskDeadline = now + (int64_t)std::max(std::min((unsigned long)ZT_MAX_TIMER_TASK_INTERVAL,RR->sw->doTimerTasks(tptr,now)),(unsigned long)ZT_MIN_TIMER_TASK_INTERVAL);
|
||||
*nextBackgroundTaskDeadline = now + (int64_t)std::max(std::min((unsigned long)ZT_MAX_TIMER_TASK_INTERVAL,RR->sw->doTimerTasks(tPtr, now)), (unsigned long)ZT_MIN_TIMER_TASK_INTERVAL);
|
||||
} catch ( ... ) {
|
||||
return ZT_RESULT_FATAL_ERROR_INTERNAL;
|
||||
}
|
||||
|
@ -340,30 +286,6 @@ ZT_ResultCode Node::processBackgroundTasks(void *tptr,int64_t now,volatile int64
|
|||
return ZT_RESULT_OK;
|
||||
}
|
||||
|
||||
void Node::processDNSResult(
|
||||
void *tptr,
|
||||
uintptr_t dnsRequestID,
|
||||
const char *name,
|
||||
enum ZT_DNSRecordType recordType,
|
||||
const void *result,
|
||||
unsigned int resultLength,
|
||||
int resultIsString)
|
||||
{
|
||||
if (dnsRequestID) {
|
||||
_processBackgroundTasks_dnsResultAccumulator *const acc = reinterpret_cast<_processBackgroundTasks_dnsResultAccumulator *>(dnsRequestID);
|
||||
if (recordType == ZT_DNS_RECORD_TXT) {
|
||||
if (result)
|
||||
acc->txtRecords.emplace_back(reinterpret_cast<const char *>(result));
|
||||
} else if (recordType == ZT_DNS_RECORD__END_OF_RESULTS) {
|
||||
Locator loc;
|
||||
if (loc.decodeTxtRecords(acc->dnsName,acc->txtRecords.begin(),acc->txtRecords.end())) {
|
||||
RR->topology->setRoot(acc->dnsName,loc);
|
||||
delete acc;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ZT_ResultCode Node::join(uint64_t nwid,void *uptr,void *tptr)
|
||||
{
|
||||
Mutex::Lock _l(_networks_m);
|
||||
|
@ -423,44 +345,25 @@ ZT_ResultCode Node::multicastUnsubscribe(uint64_t nwid,uint64_t multicastGroup,u
|
|||
} else return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
|
||||
}
|
||||
|
||||
ZT_RootList *Node::listRoots(int64_t now)
|
||||
ZT_ResultCode Node::addRoot(const char *identity)
|
||||
{
|
||||
return RR->topology->apiRoots(now);
|
||||
}
|
||||
|
||||
enum ZT_ResultCode Node::setRoot(const char *name,const void *locator,unsigned int locatorSize)
|
||||
{
|
||||
try {
|
||||
Locator loc;
|
||||
if ((locator)&&(locatorSize > 0)&&(locatorSize < 65535)) {
|
||||
ScopedPtr< Buffer<65536> > locbuf(new Buffer<65536>());
|
||||
locbuf->append(locator,locatorSize);
|
||||
loc.deserialize(*locbuf,0);
|
||||
if (!loc.verify())
|
||||
return ZT_RESULT_ERROR_BAD_PARAMETER;
|
||||
}
|
||||
Str n;
|
||||
if ((!name)||(strlen(name) == 0)) {
|
||||
if (!loc)
|
||||
return ZT_RESULT_ERROR_BAD_PARAMETER; /* no name and no locator */
|
||||
char tmp[16];
|
||||
loc.id().address().toString(tmp);
|
||||
n = tmp;
|
||||
} else {
|
||||
n = name;
|
||||
}
|
||||
return RR->topology->setRoot(n,loc) ? ZT_RESULT_OK : ZT_RESULT_OK_IGNORED;
|
||||
} catch ( ... ) {
|
||||
if (!identity)
|
||||
return ZT_RESULT_ERROR_BAD_PARAMETER;
|
||||
}
|
||||
Identity id;
|
||||
if (!id.fromString(identity))
|
||||
return ZT_RESULT_ERROR_BAD_PARAMETER;
|
||||
RR->topology->addRoot(id);
|
||||
return ZT_RESULT_OK;
|
||||
}
|
||||
|
||||
enum ZT_ResultCode Node::removeRoot(const char *name)
|
||||
ZT_ResultCode Node::removeRoot(const char *identity)
|
||||
{
|
||||
try {
|
||||
if (name)
|
||||
RR->topology->removeRoot(Str(name));
|
||||
} catch ( ... ) {}
|
||||
if (!identity)
|
||||
return ZT_RESULT_ERROR_BAD_PARAMETER;
|
||||
Identity id;
|
||||
if (!id.fromString(identity))
|
||||
return ZT_RESULT_ERROR_BAD_PARAMETER;
|
||||
RR->topology->removeRoot(id);
|
||||
return ZT_RESULT_OK;
|
||||
}
|
||||
|
||||
|
@ -631,33 +534,6 @@ void Node::setController(void *networkControllerInstance)
|
|||
/* Node methods used only within node/ */
|
||||
/****************************************************************************/
|
||||
|
||||
SharedPtr< const Locator > Node::locator()
|
||||
{
|
||||
Mutex::Lock lck(_locator_m);
|
||||
if (!_locator) {
|
||||
Locator *l = new Locator();
|
||||
try {
|
||||
RR->topology->eachRoot([l](const SharedPtr<Peer> &p,const std::vector<InetAddress> &phyAddr) -> bool {
|
||||
l->add(p->identity());
|
||||
return true;
|
||||
});
|
||||
{
|
||||
Mutex::Lock lck2(_localInterfaceAddresses_m);
|
||||
for(std::vector< ZT_InterfaceAddress >::const_iterator a(_localInterfaceAddresses.begin());a!=_localInterfaceAddresses.end();++a) {
|
||||
if (a->permanent != 0) {
|
||||
l->add(*reinterpret_cast<const InetAddress *>(&(a->address)));
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch ( ... ) {
|
||||
delete l;
|
||||
throw;
|
||||
}
|
||||
_locator.set(l);
|
||||
}
|
||||
return _locator;
|
||||
}
|
||||
|
||||
bool Node::shouldUsePathForZeroTierTraffic(void *tPtr,const Address &ztaddr,const int64_t localSocket,const InetAddress &remoteAddress)
|
||||
{
|
||||
if (!Path::isAddressValidForPath(remoteAddress))
|
||||
|
@ -679,6 +555,13 @@ bool Node::shouldUsePathForZeroTierTraffic(void *tPtr,const Address &ztaddr,cons
|
|||
return ( (_cb.pathCheckFunction) ? (_cb.pathCheckFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,ztaddr.toInt(),localSocket,reinterpret_cast<const struct sockaddr_storage *>(&remoteAddress)) != 0) : true);
|
||||
}
|
||||
|
||||
bool Node::externalPathLookup(void *tPtr,const Identity &id,int family,InetAddress &addr)
|
||||
{
|
||||
char idStr[ZT_IDENTITY_STRING_BUFFER_LENGTH];
|
||||
id.toString(false,idStr);
|
||||
return (_cb.pathLookupFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,id.address().toInt(),idStr,family,reinterpret_cast<sockaddr_storage *>(&addr)) == ZT_RESULT_OK);
|
||||
}
|
||||
|
||||
ZT_ResultCode Node::setPhysicalPathConfiguration(const struct sockaddr_storage *pathNetwork, const ZT_PhysicalPathConfiguration *pathConfig)
|
||||
{
|
||||
RR->topology->setPhysicalPathConfiguration(pathNetwork,pathConfig);
|
||||
|
@ -870,21 +753,6 @@ enum ZT_ResultCode ZT_Node_processBackgroundTasks(ZT_Node *node,void *tptr,int64
|
|||
}
|
||||
}
|
||||
|
||||
void ZT_Node_processDNSResult(
|
||||
ZT_Node *node,
|
||||
void *tptr,
|
||||
uintptr_t dnsRequestID,
|
||||
const char *name,
|
||||
enum ZT_DNSRecordType recordType,
|
||||
const void *result,
|
||||
unsigned int resultLength,
|
||||
int resultIsString)
|
||||
{
|
||||
try {
|
||||
reinterpret_cast<ZeroTier::Node *>(node)->processDNSResult(tptr,dnsRequestID,name,recordType,result,resultLength,resultIsString);
|
||||
} catch ( ... ) {}
|
||||
}
|
||||
|
||||
enum ZT_ResultCode ZT_Node_join(ZT_Node *node,uint64_t nwid,void *uptr,void *tptr)
|
||||
{
|
||||
try {
|
||||
|
@ -929,19 +797,10 @@ enum ZT_ResultCode ZT_Node_multicastUnsubscribe(ZT_Node *node,uint64_t nwid,uint
|
|||
}
|
||||
}
|
||||
|
||||
ZT_RootList *ZT_Node_listRoots(ZT_Node *node,int64_t now)
|
||||
enum ZT_ResultCode ZT_Node_addRoot(ZT_Node *node,const char *identity)
|
||||
{
|
||||
try {
|
||||
return reinterpret_cast<ZeroTier::Node *>(node)->listRoots(now);
|
||||
} catch ( ... ) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
enum ZT_ResultCode ZT_Node_setRoot(ZT_Node *node,const char *name,const void *locator,unsigned int locatorSize)
|
||||
{
|
||||
try {
|
||||
return reinterpret_cast<ZeroTier::Node *>(node)->setRoot(name,locator,locatorSize);
|
||||
return reinterpret_cast<ZeroTier::Node *>(node)->addRoot(identity);
|
||||
} catch (std::bad_alloc &exc) {
|
||||
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
|
||||
} catch ( ... ) {
|
||||
|
@ -949,10 +808,10 @@ enum ZT_ResultCode ZT_Node_setRoot(ZT_Node *node,const char *name,const void *lo
|
|||
}
|
||||
}
|
||||
|
||||
enum ZT_ResultCode ZT_Node_removeRoot(ZT_Node *node,const char *name)
|
||||
enum ZT_ResultCode ZT_Node_removeRoot(ZT_Node *node,const char *identity)
|
||||
{
|
||||
try {
|
||||
return reinterpret_cast<ZeroTier::Node *>(node)->removeRoot(name);
|
||||
return reinterpret_cast<ZeroTier::Node *>(node)->removeRoot(identity);
|
||||
} catch (std::bad_alloc &exc) {
|
||||
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
|
||||
} catch ( ... ) {
|
||||
|
|
|
@ -51,7 +51,7 @@ class Locator;
|
|||
class Node : public NetworkController::Sender
|
||||
{
|
||||
public:
|
||||
Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,int64_t now);
|
||||
Node(void *uPtr, void *tPtr, const struct ZT_Node_Callbacks *callbacks, int64_t now);
|
||||
virtual ~Node();
|
||||
|
||||
// Get rid of alignment warnings on 32-bit Windows and possibly improve performance
|
||||
|
@ -81,22 +81,13 @@ public:
|
|||
const void *frameData,
|
||||
unsigned int frameLength,
|
||||
volatile int64_t *nextBackgroundTaskDeadline);
|
||||
ZT_ResultCode processBackgroundTasks(void *tptr,int64_t now,volatile int64_t *nextBackgroundTaskDeadline);
|
||||
void processDNSResult(
|
||||
void *tptr,
|
||||
uintptr_t dnsRequestID,
|
||||
const char *name,
|
||||
enum ZT_DNSRecordType recordType,
|
||||
const void *result,
|
||||
unsigned int resultLength,
|
||||
int resultIsString);
|
||||
ZT_ResultCode processBackgroundTasks(void *tPtr, int64_t now, volatile int64_t *nextBackgroundTaskDeadline);
|
||||
ZT_ResultCode join(uint64_t nwid,void *uptr,void *tptr);
|
||||
ZT_ResultCode leave(uint64_t nwid,void **uptr,void *tptr);
|
||||
ZT_ResultCode multicastSubscribe(void *tptr,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi);
|
||||
ZT_ResultCode multicastUnsubscribe(uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi);
|
||||
ZT_RootList *listRoots(int64_t now);
|
||||
enum ZT_ResultCode setRoot(const char *name,const void *locator,unsigned int locatorSize);
|
||||
enum ZT_ResultCode removeRoot(const char *name);
|
||||
ZT_ResultCode addRoot(const char *identity);
|
||||
ZT_ResultCode removeRoot(const char *identity);
|
||||
uint64_t address() const;
|
||||
void status(ZT_NodeStatus *status) const;
|
||||
ZT_PeerList *peers() const;
|
||||
|
@ -104,16 +95,15 @@ public:
|
|||
ZT_VirtualNetworkList *networks() const;
|
||||
void setNetworkUserPtr(uint64_t nwid,void *ptr);
|
||||
void freeQueryResult(void *qr);
|
||||
int addLocalInterfaceAddress(const struct sockaddr_storage *addr);
|
||||
void clearLocalInterfaceAddresses();
|
||||
void setInterfaceAddresses(const ZT_InterfaceAddress *addrs,unsigned int addrCount);
|
||||
int sendUserMessage(void *tptr,uint64_t dest,uint64_t typeId,const void *data,unsigned int len);
|
||||
void setController(void *networkControllerInstance);
|
||||
|
||||
// Internal functions ------------------------------------------------------
|
||||
|
||||
inline int64_t now() const { return _now; }
|
||||
ZT_ALWAYS_INLINE int64_t now() const { return _now; }
|
||||
|
||||
inline bool putPacket(void *tPtr,const int64_t localSocket,const InetAddress &addr,const void *data,unsigned int len,unsigned int ttl = 0)
|
||||
ZT_ALWAYS_INLINE bool putPacket(void *tPtr,const int64_t localSocket,const InetAddress &addr,const void *data,unsigned int len,unsigned int ttl = 0)
|
||||
{
|
||||
return (_cb.wirePacketSendFunction(
|
||||
reinterpret_cast<ZT_Node *>(this),
|
||||
|
@ -126,7 +116,7 @@ public:
|
|||
ttl) == 0);
|
||||
}
|
||||
|
||||
inline void putFrame(void *tPtr,uint64_t nwid,void **nuptr,const MAC &source,const MAC &dest,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len)
|
||||
ZT_ALWAYS_INLINE void putFrame(void *tPtr,uint64_t nwid,void **nuptr,const MAC &source,const MAC &dest,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len)
|
||||
{
|
||||
_cb.virtualNetworkFrameFunction(
|
||||
reinterpret_cast<ZT_Node *>(this),
|
||||
|
@ -142,7 +132,7 @@ public:
|
|||
len);
|
||||
}
|
||||
|
||||
inline SharedPtr<Network> network(uint64_t nwid) const
|
||||
ZT_ALWAYS_INLINE SharedPtr<Network> network(uint64_t nwid) const
|
||||
{
|
||||
Mutex::Lock _l(_networks_m);
|
||||
const SharedPtr<Network> *n = _networks.get(nwid);
|
||||
|
@ -151,43 +141,22 @@ public:
|
|||
return SharedPtr<Network>();
|
||||
}
|
||||
|
||||
inline bool belongsToNetwork(uint64_t nwid) const
|
||||
{
|
||||
Mutex::Lock _l(_networks_m);
|
||||
return _networks.contains(nwid);
|
||||
}
|
||||
|
||||
inline std::vector< SharedPtr<Network> > allNetworks() const
|
||||
{
|
||||
std::vector< SharedPtr<Network> > nw;
|
||||
Mutex::Lock _l(_networks_m);
|
||||
Hashtable< uint64_t,SharedPtr<Network> >::Iterator i(*const_cast< Hashtable< uint64_t,SharedPtr<Network> > * >(&_networks));
|
||||
uint64_t *k = (uint64_t *)0;
|
||||
SharedPtr<Network> *v = (SharedPtr<Network> *)0;
|
||||
while (i.next(k,v))
|
||||
nw.push_back(*v);
|
||||
return nw;
|
||||
}
|
||||
|
||||
inline std::vector<ZT_InterfaceAddress> directPaths() const
|
||||
ZT_ALWAYS_INLINE std::vector<ZT_InterfaceAddress> directPaths() const
|
||||
{
|
||||
Mutex::Lock _l(_localInterfaceAddresses_m);
|
||||
return _localInterfaceAddresses;
|
||||
}
|
||||
|
||||
void setInterfaceAddresses(const ZT_InterfaceAddress *addrs,unsigned int addrCount);
|
||||
|
||||
SharedPtr< const Locator > locator();
|
||||
inline void postEvent(void *tPtr,ZT_Event ev,const void *md = (const void *)0) { _cb.eventCallback(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,ev,md); }
|
||||
inline void configureVirtualNetworkPort(void *tPtr,uint64_t nwid,void **nuptr,ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nc) { _cb.virtualNetworkConfigFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,nwid,nuptr,op,nc); }
|
||||
inline bool online() const { return _online; }
|
||||
inline int stateObjectGet(void *const tPtr,ZT_StateObjectType type,const uint64_t id[2],void *const data,const unsigned int maxlen) { return _cb.stateGetFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,type,id,data,maxlen); }
|
||||
inline void stateObjectPut(void *const tPtr,ZT_StateObjectType type,const uint64_t id[2],const void *const data,const unsigned int len) { _cb.statePutFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,type,id,data,(int)len); }
|
||||
inline void stateObjectDelete(void *const tPtr,ZT_StateObjectType type,const uint64_t id[2]) { _cb.statePutFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,type,id,(const void *)0,-1); }
|
||||
ZT_ALWAYS_INLINE void postEvent(void *tPtr,ZT_Event ev,const void *md = (const void *)0) { _cb.eventCallback(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,ev,md); }
|
||||
ZT_ALWAYS_INLINE void configureVirtualNetworkPort(void *tPtr,uint64_t nwid,void **nuptr,ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nc) { _cb.virtualNetworkConfigFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,nwid,nuptr,op,nc); }
|
||||
ZT_ALWAYS_INLINE bool online() const { return _online; }
|
||||
ZT_ALWAYS_INLINE int stateObjectGet(void *const tPtr,ZT_StateObjectType type,const uint64_t id[2],void *const data,const unsigned int maxlen) { return _cb.stateGetFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,type,id,data,maxlen); }
|
||||
ZT_ALWAYS_INLINE void stateObjectPut(void *const tPtr,ZT_StateObjectType type,const uint64_t id[2],const void *const data,const unsigned int len) { _cb.statePutFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,type,id,data,(int)len); }
|
||||
ZT_ALWAYS_INLINE void stateObjectDelete(void *const tPtr,ZT_StateObjectType type,const uint64_t id[2]) { _cb.statePutFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,type,id,(const void *)0,-1); }
|
||||
bool shouldUsePathForZeroTierTraffic(void *tPtr,const Address &ztaddr,const int64_t localSocket,const InetAddress &remoteAddress);
|
||||
inline bool externalPathLookup(void *tPtr,const Address &ztaddr,int family,InetAddress &addr) { return ( (_cb.pathLookupFunction) ? (_cb.pathLookupFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,ztaddr.toInt(),family,reinterpret_cast<struct sockaddr_storage *>(&addr)) != 0) : false ); }
|
||||
bool externalPathLookup(void *tPtr,const Identity &id,int family,InetAddress &addr);
|
||||
ZT_ResultCode setPhysicalPathConfiguration(const struct sockaddr_storage *pathNetwork,const ZT_PhysicalPathConfiguration *pathConfig);
|
||||
inline const Identity &identity() const { return _RR.identity; }
|
||||
ZT_ALWAYS_INLINE const Identity &identity() const { return _RR.identity; }
|
||||
|
||||
/**
|
||||
* Register that we are expecting a reply to a packet ID
|
||||
|
@ -198,9 +167,9 @@ public:
|
|||
*
|
||||
* @param packetId Packet ID to expect reply to
|
||||
*/
|
||||
inline void expectReplyTo(const uint64_t packetId)
|
||||
ZT_ALWAYS_INLINE void expectReplyTo(const uint64_t packetId)
|
||||
{
|
||||
const unsigned long pid2 = (unsigned long)(packetId >> 32);
|
||||
const unsigned long pid2 = (unsigned long)(packetId >> 32U);
|
||||
const unsigned long bucket = (unsigned long)(pid2 & ZT_EXPECTING_REPLIES_BUCKET_MASK1);
|
||||
_expectingRepliesTo[bucket][_expectingRepliesToBucketPtr[bucket]++ & ZT_EXPECTING_REPLIES_BUCKET_MASK2] = (uint32_t)pid2;
|
||||
}
|
||||
|
@ -215,7 +184,7 @@ public:
|
|||
* @param packetId Packet ID to check
|
||||
* @return True if we're expecting a reply
|
||||
*/
|
||||
inline bool expectingReplyTo(const uint64_t packetId) const
|
||||
ZT_ALWAYS_INLINE bool expectingReplyTo(const uint64_t packetId) const
|
||||
{
|
||||
const uint32_t pid2 = (uint32_t)(packetId >> 32);
|
||||
const unsigned long bucket = (unsigned long)(pid2 & ZT_EXPECTING_REPLIES_BUCKET_MASK1);
|
||||
|
@ -233,7 +202,7 @@ public:
|
|||
* @param from Source address of packet
|
||||
* @return True if within rate limits
|
||||
*/
|
||||
inline bool rateGateIdentityVerification(const int64_t now,const InetAddress &from)
|
||||
ZT_ALWAYS_INLINE bool rateGateIdentityVerification(const int64_t now,const InetAddress &from)
|
||||
{
|
||||
unsigned long iph = from.rateGateHash();
|
||||
if ((now - _lastIdentityVerification[iph]) >= ZT_IDENTITY_VALIDATION_SOURCE_RATE_LIMIT) {
|
||||
|
@ -247,9 +216,6 @@ public:
|
|||
virtual void ncSendRevocation(const Address &destination,const Revocation &rev);
|
||||
virtual void ncSendError(uint64_t nwid,uint64_t requestPacketId,const Address &destination,NetworkController::ErrorCode errorCode);
|
||||
|
||||
inline void setMultipathMode(uint8_t mode) { _multipathMode = mode; }
|
||||
inline uint8_t getMultipathMode() { return _multipathMode; }
|
||||
|
||||
inline bool localControllerHasAuthorized(const int64_t now,const uint64_t nwid,const Address &addr) const
|
||||
{
|
||||
_localControllerAuthorizations_m.lock();
|
||||
|
@ -260,6 +226,9 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
inline void setMultipathMode(uint8_t mode) { _multipathMode = mode; }
|
||||
inline uint8_t getMultipathMode() { return _multipathMode; }
|
||||
|
||||
private:
|
||||
RuntimeEnvironment _RR;
|
||||
RuntimeEnvironment *RR;
|
||||
|
@ -281,10 +250,10 @@ private:
|
|||
struct _LocalControllerAuth
|
||||
{
|
||||
uint64_t nwid,address;
|
||||
inline _LocalControllerAuth(const uint64_t nwid_,const Address &address_) : nwid(nwid_),address(address_.toInt()) {}
|
||||
inline unsigned long hashCode() const { return (unsigned long)(nwid ^ address); }
|
||||
inline bool operator==(const _LocalControllerAuth &a) const { return ((a.nwid == nwid)&&(a.address == address)); }
|
||||
inline bool operator!=(const _LocalControllerAuth &a) const { return ((a.nwid != nwid)||(a.address != address)); }
|
||||
ZT_ALWAYS_INLINE _LocalControllerAuth(const uint64_t nwid_,const Address &address_) : nwid(nwid_),address(address_.toInt()) {}
|
||||
ZT_ALWAYS_INLINE unsigned long hashCode() const { return (unsigned long)(nwid ^ address); }
|
||||
ZT_ALWAYS_INLINE bool operator==(const _LocalControllerAuth &a) const { return ((a.nwid == nwid)&&(a.address == address)); }
|
||||
ZT_ALWAYS_INLINE bool operator!=(const _LocalControllerAuth &a) const { return ((a.nwid != nwid)||(a.address != address)); }
|
||||
};
|
||||
Hashtable< _LocalControllerAuth,int64_t > _localControllerAuthorizations;
|
||||
Hashtable< uint64_t,SharedPtr<Network> > _networks;
|
||||
|
@ -293,7 +262,6 @@ private:
|
|||
|
||||
Mutex _localControllerAuthorizations_m;
|
||||
Mutex _networks_m;
|
||||
Mutex _locator_m;
|
||||
Mutex _localInterfaceAddresses_m;
|
||||
Mutex _backgroundTasksLock;
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "Utils.hpp"
|
||||
#include "RingBuffer.hpp"
|
||||
#include "Packet.hpp"
|
||||
#include "Mutex.hpp"
|
||||
|
||||
/**
|
||||
* Maximum return value of preferenceRank()
|
||||
|
@ -52,9 +53,9 @@ public:
|
|||
class HashKey
|
||||
{
|
||||
public:
|
||||
inline HashKey() {}
|
||||
ZT_ALWAYS_INLINE HashKey() {}
|
||||
|
||||
inline HashKey(const int64_t l,const InetAddress &r)
|
||||
ZT_ALWAYS_INLINE HashKey(const int64_t l,const InetAddress &r)
|
||||
{
|
||||
if (r.ss_family == AF_INET) {
|
||||
_k[0] = (uint64_t)reinterpret_cast<const struct sockaddr_in *>(&r)->sin_addr.s_addr;
|
||||
|
@ -69,10 +70,10 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
inline unsigned long hashCode() const { return (unsigned long)(_k[0] + _k[1] + _k[2]); }
|
||||
ZT_ALWAYS_INLINE unsigned long hashCode() const { return (unsigned long)(_k[0] + _k[1] + _k[2]); }
|
||||
|
||||
inline bool operator==(const HashKey &k) const { return ( (_k[0] == k._k[0]) && (_k[1] == k._k[1]) && (_k[2] == k._k[2]) ); }
|
||||
inline bool operator!=(const HashKey &k) const { return (!(*this == k)); }
|
||||
ZT_ALWAYS_INLINE bool operator==(const HashKey &k) const { return ( (_k[0] == k._k[0]) && (_k[1] == k._k[1]) && (_k[2] == k._k[2]) ); }
|
||||
ZT_ALWAYS_INLINE bool operator!=(const HashKey &k) const { return (!(*this == k)); }
|
||||
|
||||
private:
|
||||
uint64_t _k[3];
|
||||
|
|
|
@ -691,12 +691,8 @@ void Peer::sendHELLO(void *tPtr,const int64_t localSocket,const InetAddress &atA
|
|||
|
||||
void Peer::ping(void *tPtr,int64_t now,unsigned int &v4SendCount,unsigned int &v6SendCount)
|
||||
{
|
||||
v4SendCount = 0;
|
||||
v6SendCount = 0;
|
||||
|
||||
Mutex::Lock _l(_paths_m);
|
||||
|
||||
// Emit traces regarding aggregate link status
|
||||
if (_canUseMultipath) {
|
||||
int alivePathCount = aggregateLinkPhysicalPathCount();
|
||||
if ((now - _lastAggregateStatsReport) > ZT_PATH_AGGREGATE_STATS_REPORT_INTERVAL) {
|
||||
|
|
|
@ -30,8 +30,6 @@
|
|||
#include "Hashtable.hpp"
|
||||
#include "Mutex.hpp"
|
||||
|
||||
#define ZT_PEER_MAX_SERIALIZED_STATE_SIZE (sizeof(Peer) + 32 + (sizeof(Path) * 2))
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
/**
|
||||
|
@ -45,7 +43,7 @@ private:
|
|||
inline Peer() {} // disabled to prevent bugs -- should not be constructed uninitialized
|
||||
|
||||
public:
|
||||
inline ~Peer() { Utils::burn(_key,sizeof(_key)); }
|
||||
ZT_ALWAYS_INLINE ~Peer() { Utils::burn(_key,sizeof(_key)); }
|
||||
|
||||
/**
|
||||
* Construct a new peer
|
||||
|
@ -60,12 +58,12 @@ public:
|
|||
/**
|
||||
* @return This peer's ZT address (short for identity().address())
|
||||
*/
|
||||
inline const Address &address() const { return _id.address(); }
|
||||
ZT_ALWAYS_INLINE const Address &address() const { return _id.address(); }
|
||||
|
||||
/**
|
||||
* @return This peer's identity
|
||||
*/
|
||||
inline const Identity &identity() const { return _id; }
|
||||
ZT_ALWAYS_INLINE const Identity &identity() const { return _id; }
|
||||
|
||||
/**
|
||||
* Log receipt of an authenticated packet
|
||||
|
@ -85,13 +83,13 @@ public:
|
|||
void received(
|
||||
void *tPtr,
|
||||
const SharedPtr<Path> &path,
|
||||
const unsigned int hops,
|
||||
const uint64_t packetId,
|
||||
const unsigned int payloadLength,
|
||||
const Packet::Verb verb,
|
||||
const uint64_t inRePacketId,
|
||||
const Packet::Verb inReVerb,
|
||||
const uint64_t networkId);
|
||||
unsigned int hops,
|
||||
uint64_t packetId,
|
||||
unsigned int payloadLength,
|
||||
Packet::Verb verb,
|
||||
uint64_t inRePacketId,
|
||||
Packet::Verb inReVerb,
|
||||
uint64_t networkId);
|
||||
|
||||
/**
|
||||
* Check whether we have an active path to this peer via the given address
|
||||
|
@ -122,7 +120,7 @@ public:
|
|||
* @param force If true, send even if path is not alive
|
||||
* @return True if we actually sent something
|
||||
*/
|
||||
inline bool sendDirect(void *tPtr,const void *data,unsigned int len,int64_t now,bool force)
|
||||
ZT_ALWAYS_INLINE bool sendDirect(void *tPtr,const void *data,unsigned int len,int64_t now,bool force)
|
||||
{
|
||||
SharedPtr<Path> bp(getAppropriatePath(now,force));
|
||||
if (bp)
|
||||
|
@ -139,7 +137,7 @@ public:
|
|||
* @param verb Packet verb
|
||||
* @param now Current time
|
||||
*/
|
||||
void recordOutgoingPacket(const SharedPtr<Path> &path, const uint64_t packetId, uint16_t payloadLength, const Packet::Verb verb, int64_t now);
|
||||
void recordOutgoingPacket(const SharedPtr<Path> &path, uint64_t packetId, uint16_t payloadLength, const Packet::Verb verb, int64_t now);
|
||||
|
||||
/**
|
||||
* Record statistics on incoming packets
|
||||
|
@ -150,7 +148,7 @@ public:
|
|||
* @param verb Packet verb
|
||||
* @param now Current time
|
||||
*/
|
||||
void recordIncomingPacket(void *tPtr, const SharedPtr<Path> &path, const uint64_t packetId, uint16_t payloadLength, const Packet::Verb verb, int64_t now);
|
||||
void recordIncomingPacket(void *tPtr, const SharedPtr<Path> &path, uint64_t packetId, uint16_t payloadLength, const Packet::Verb verb, int64_t now);
|
||||
|
||||
/**
|
||||
* Send an ACK to peer for the most recent packets received
|
||||
|
@ -160,7 +158,7 @@ public:
|
|||
* @param atAddress Destination for the ACK packet
|
||||
* @param now Current time
|
||||
*/
|
||||
void sendACK(void *tPtr, const SharedPtr<Path> &path, const int64_t localSocket,const InetAddress &atAddress,int64_t now);
|
||||
void sendACK(void *tPtr, const SharedPtr<Path> &path, int64_t localSocket,const InetAddress &atAddress,int64_t now);
|
||||
|
||||
/**
|
||||
* Send a QoS packet to peer so that it can evaluate the quality of this link
|
||||
|
@ -170,7 +168,7 @@ public:
|
|||
* @param atAddress Destination for the QoS packet
|
||||
* @param now Current time
|
||||
*/
|
||||
void sendQOS_MEASUREMENT(void *tPtr, const SharedPtr<Path> &path, const int64_t localSocket,const InetAddress &atAddress,int64_t now);
|
||||
void sendQOS_MEASUREMENT(void *tPtr, const SharedPtr<Path> &path, int64_t localSocket,const InetAddress &atAddress,int64_t now);
|
||||
|
||||
/**
|
||||
* Compute relative quality values and allocations for the components of the aggregate link
|
||||
|
@ -217,7 +215,7 @@ public:
|
|||
/**
|
||||
* Send VERB_RENDEZVOUS to this and another peer via the best common IP scope and path
|
||||
*/
|
||||
void introduce(void *const tPtr,const int64_t now,const SharedPtr<Peer> &other) const;
|
||||
void introduce(void *tPtr,int64_t now,const SharedPtr<Peer> &other) const;
|
||||
|
||||
/**
|
||||
* Send a HELLO to this peer at a specified physical address
|
||||
|
@ -229,7 +227,7 @@ public:
|
|||
* @param atAddress Destination address
|
||||
* @param now Current time
|
||||
*/
|
||||
void sendHELLO(void *tPtr,const int64_t localSocket,const InetAddress &atAddress,int64_t now);
|
||||
void sendHELLO(void *tPtr,int64_t localSocket,const InetAddress &atAddress,int64_t now);
|
||||
|
||||
/**
|
||||
* Send pings to active paths
|
||||
|
@ -276,17 +274,17 @@ public:
|
|||
/**
|
||||
* @return Time of last receive of anything, whether direct or relayed
|
||||
*/
|
||||
inline int64_t lastReceive() const { return _lastReceive; }
|
||||
ZT_ALWAYS_INLINE int64_t lastReceive() const { return _lastReceive; }
|
||||
|
||||
/**
|
||||
* @return True if we've heard from this peer in less than ZT_PEER_ACTIVITY_TIMEOUT
|
||||
*/
|
||||
inline bool alive(const int64_t now) const { return ((now - _lastReceive) < ZT_PEER_ACTIVITY_TIMEOUT); }
|
||||
ZT_ALWAYS_INLINE bool alive(const int64_t now) const { return ((now - _lastReceive) < ZT_PEER_ACTIVITY_TIMEOUT); }
|
||||
|
||||
/**
|
||||
* @return Latency in milliseconds of best/aggregate path or 0xffff if unknown / no paths
|
||||
*/
|
||||
inline unsigned int latency(const int64_t now)
|
||||
ZT_ALWAYS_INLINE unsigned int latency(const int64_t now)
|
||||
{
|
||||
if (_canUseMultipath) {
|
||||
return (int)computeAggregateLinkMeanLatency();
|
||||
|
@ -298,32 +296,10 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This computes a quality score for relays and root servers
|
||||
*
|
||||
* If we haven't heard anything from these in ZT_PEER_ACTIVITY_TIMEOUT, they
|
||||
* receive the worst possible quality (max unsigned int). Otherwise the
|
||||
* quality is a product of latency and the number of potential missed
|
||||
* pings. This causes roots and relays to switch over a bit faster if they
|
||||
* fail.
|
||||
*
|
||||
* @return Relay quality score computed from latency and other factors, lower is better
|
||||
*/
|
||||
inline unsigned int relayQuality(const int64_t now)
|
||||
{
|
||||
const uint64_t tsr = now - _lastReceive;
|
||||
if (tsr >= ZT_PEER_ACTIVITY_TIMEOUT)
|
||||
return (~(unsigned int)0);
|
||||
unsigned int l = latency(now);
|
||||
if (!l)
|
||||
l = 0xffff;
|
||||
return (l * (((unsigned int)tsr / (ZT_PEER_PING_PERIOD + 1000)) + 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 256-bit secret symmetric encryption key
|
||||
*/
|
||||
inline const unsigned char *key() const { return _key; }
|
||||
ZT_ALWAYS_INLINE const unsigned char *key() const { return _key; }
|
||||
|
||||
/**
|
||||
* Set the currently known remote version of this peer's client
|
||||
|
@ -333,7 +309,7 @@ public:
|
|||
* @param vmin Minor version
|
||||
* @param vrev Revision
|
||||
*/
|
||||
inline void setRemoteVersion(unsigned int vproto,unsigned int vmaj,unsigned int vmin,unsigned int vrev)
|
||||
ZT_ALWAYS_INLINE void setRemoteVersion(unsigned int vproto,unsigned int vmaj,unsigned int vmin,unsigned int vrev)
|
||||
{
|
||||
_vProto = (uint16_t)vproto;
|
||||
_vMajor = (uint16_t)vmaj;
|
||||
|
@ -341,11 +317,11 @@ public:
|
|||
_vRevision = (uint16_t)vrev;
|
||||
}
|
||||
|
||||
inline unsigned int remoteVersionProtocol() const { return _vProto; }
|
||||
inline unsigned int remoteVersionMajor() const { return _vMajor; }
|
||||
inline unsigned int remoteVersionMinor() const { return _vMinor; }
|
||||
inline unsigned int remoteVersionRevision() const { return _vRevision; }
|
||||
inline bool remoteVersionKnown() const { return ((_vMajor > 0)||(_vMinor > 0)||(_vRevision > 0)); }
|
||||
ZT_ALWAYS_INLINE unsigned int remoteVersionProtocol() const { return _vProto; }
|
||||
ZT_ALWAYS_INLINE unsigned int remoteVersionMajor() const { return _vMajor; }
|
||||
ZT_ALWAYS_INLINE unsigned int remoteVersionMinor() const { return _vMinor; }
|
||||
ZT_ALWAYS_INLINE unsigned int remoteVersionRevision() const { return _vRevision; }
|
||||
ZT_ALWAYS_INLINE bool remoteVersionKnown() const { return ((_vMajor > 0)||(_vMinor > 0)||(_vRevision > 0)); }
|
||||
|
||||
/**
|
||||
* Periodically update known multipath activation constraints. This is done so that we know when and when
|
||||
|
|
|
@ -45,9 +45,9 @@ class Revocation : public Credential
|
|||
friend class Credential;
|
||||
|
||||
public:
|
||||
static inline Credential::Type credentialType() { return Credential::CREDENTIAL_TYPE_REVOCATION; }
|
||||
static ZT_ALWAYS_INLINE Credential::Type credentialType() { return Credential::CREDENTIAL_TYPE_REVOCATION; }
|
||||
|
||||
inline Revocation() :
|
||||
ZT_ALWAYS_INLINE Revocation() :
|
||||
_id(0),
|
||||
_credentialId(0),
|
||||
_networkId(0),
|
||||
|
@ -69,7 +69,7 @@ public:
|
|||
* @param tgt Target node whose credential(s) are being revoked
|
||||
* @param ct Credential type being revoked
|
||||
*/
|
||||
inline Revocation(const uint32_t i,const uint64_t nwid,const uint32_t cid,const uint64_t thr,const uint64_t fl,const Address &tgt,const Credential::Type ct) :
|
||||
ZT_ALWAYS_INLINE Revocation(const uint32_t i,const uint64_t nwid,const uint32_t cid,const uint64_t thr,const uint64_t fl,const Address &tgt,const Credential::Type ct) :
|
||||
_id(i),
|
||||
_credentialId(cid),
|
||||
_networkId(nwid),
|
||||
|
@ -82,16 +82,16 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
inline uint32_t id() const { return _id; }
|
||||
inline uint32_t credentialId() const { return _credentialId; }
|
||||
inline uint64_t networkId() const { return _networkId; }
|
||||
inline int64_t threshold() const { return _threshold; }
|
||||
inline const Address &target() const { return _target; }
|
||||
inline const Address &signer() const { return _signedBy; }
|
||||
inline Credential::Type type() const { return _type; }
|
||||
inline const uint8_t *signature() const { return _signature; }
|
||||
inline unsigned int signatureLength() const { return _signatureLength; }
|
||||
inline bool fastPropagate() const { return ((_flags & ZT_REVOCATION_FLAG_FAST_PROPAGATE) != 0); }
|
||||
ZT_ALWAYS_INLINE uint32_t id() const { return _id; }
|
||||
ZT_ALWAYS_INLINE uint32_t credentialId() const { return _credentialId; }
|
||||
ZT_ALWAYS_INLINE uint64_t networkId() const { return _networkId; }
|
||||
ZT_ALWAYS_INLINE int64_t threshold() const { return _threshold; }
|
||||
ZT_ALWAYS_INLINE const Address &target() const { return _target; }
|
||||
ZT_ALWAYS_INLINE const Address &signer() const { return _signedBy; }
|
||||
ZT_ALWAYS_INLINE Credential::Type type() const { return _type; }
|
||||
ZT_ALWAYS_INLINE const uint8_t *signature() const { return _signature; }
|
||||
ZT_ALWAYS_INLINE unsigned int signatureLength() const { return _signatureLength; }
|
||||
ZT_ALWAYS_INLINE bool fastPropagate() const { return ((_flags & ZT_REVOCATION_FLAG_FAST_PROPAGATE) != 0); }
|
||||
|
||||
/**
|
||||
* @param signer Signing identity, must have private key
|
||||
|
@ -115,7 +115,7 @@ public:
|
|||
* @param RR Runtime environment to provide for peer lookup, etc.
|
||||
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
|
||||
*/
|
||||
inline Credential::VerifyResult verify(const RuntimeEnvironment *RR,void *tPtr) const { return _verify(RR,tPtr,*this); }
|
||||
ZT_ALWAYS_INLINE Credential::VerifyResult verify(const RuntimeEnvironment *RR,void *tPtr) const { return _verify(RR,tPtr,*this); }
|
||||
|
||||
template<unsigned int C>
|
||||
inline void serialize(Buffer<C> &b,const bool forSign = false) const
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#ifndef ZT_SHAREDPTR_HPP
|
||||
#define ZT_SHAREDPTR_HPP
|
||||
|
||||
#include "Mutex.hpp"
|
||||
#include "AtomicCounter.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
|
48
node/Tag.hpp
48
node/Tag.hpp
|
@ -52,9 +52,9 @@ class Tag : public Credential
|
|||
friend class Credential;
|
||||
|
||||
public:
|
||||
static inline Credential::Type credentialType() { return Credential::CREDENTIAL_TYPE_TAG; }
|
||||
static ZT_ALWAYS_INLINE Credential::Type credentialType() { return Credential::CREDENTIAL_TYPE_TAG; }
|
||||
|
||||
inline Tag() :
|
||||
ZT_ALWAYS_INLINE Tag() :
|
||||
_id(0),
|
||||
_value(0),
|
||||
_networkId(0),
|
||||
|
@ -70,7 +70,7 @@ public:
|
|||
* @param id Tag ID
|
||||
* @param value Tag value
|
||||
*/
|
||||
inline Tag(const uint64_t nwid,const int64_t ts,const Address &issuedTo,const uint32_t id,const uint32_t value) :
|
||||
ZT_ALWAYS_INLINE Tag(const uint64_t nwid,const int64_t ts,const Address &issuedTo,const uint32_t id,const uint32_t value) :
|
||||
_id(id),
|
||||
_value(value),
|
||||
_networkId(nwid),
|
||||
|
@ -81,14 +81,14 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
inline uint32_t id() const { return _id; }
|
||||
inline const uint32_t &value() const { return _value; }
|
||||
inline uint64_t networkId() const { return _networkId; }
|
||||
inline int64_t timestamp() const { return _ts; }
|
||||
inline const Address &issuedTo() const { return _issuedTo; }
|
||||
inline const Address &signer() const { return _signedBy; }
|
||||
inline const uint8_t *signature() const { return _signature; }
|
||||
inline unsigned int signatureLength() const { return _signatureLength; }
|
||||
ZT_ALWAYS_INLINE uint32_t id() const { return _id; }
|
||||
ZT_ALWAYS_INLINE const uint32_t &value() const { return _value; }
|
||||
ZT_ALWAYS_INLINE uint64_t networkId() const { return _networkId; }
|
||||
ZT_ALWAYS_INLINE int64_t timestamp() const { return _ts; }
|
||||
ZT_ALWAYS_INLINE const Address &issuedTo() const { return _issuedTo; }
|
||||
ZT_ALWAYS_INLINE const Address &signer() const { return _signedBy; }
|
||||
ZT_ALWAYS_INLINE const uint8_t *signature() const { return _signature; }
|
||||
ZT_ALWAYS_INLINE unsigned int signatureLength() const { return _signatureLength; }
|
||||
|
||||
/**
|
||||
* Sign this tag
|
||||
|
@ -114,7 +114,7 @@ public:
|
|||
* @param RR Runtime environment to allow identity lookup for signedBy
|
||||
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
|
||||
*/
|
||||
inline Credential::VerifyResult verify(const RuntimeEnvironment *RR,void *tPtr) const { return _verify(RR,tPtr,*this); }
|
||||
ZT_ALWAYS_INLINE Credential::VerifyResult verify(const RuntimeEnvironment *RR,void *tPtr) const { return _verify(RR,tPtr,*this); }
|
||||
|
||||
template<unsigned int C>
|
||||
inline void serialize(Buffer<C> &b,const bool forSign = false) const
|
||||
|
@ -172,23 +172,23 @@ public:
|
|||
}
|
||||
|
||||
// Provides natural sort order by ID
|
||||
inline bool operator<(const Tag &t) const { return (_id < t._id); }
|
||||
ZT_ALWAYS_INLINE bool operator<(const Tag &t) const { return (_id < t._id); }
|
||||
|
||||
inline bool operator==(const Tag &t) const { return (memcmp(this,&t,sizeof(Tag)) == 0); }
|
||||
inline bool operator!=(const Tag &t) const { return (memcmp(this,&t,sizeof(Tag)) != 0); }
|
||||
ZT_ALWAYS_INLINE bool operator==(const Tag &t) const { return (memcmp(this,&t,sizeof(Tag)) == 0); }
|
||||
ZT_ALWAYS_INLINE bool operator!=(const Tag &t) const { return (memcmp(this,&t,sizeof(Tag)) != 0); }
|
||||
|
||||
// For searching sorted arrays or lists of Tags by ID
|
||||
struct IdComparePredicate
|
||||
{
|
||||
inline bool operator()(const Tag &a,const Tag &b) const { return (a.id() < b.id()); }
|
||||
inline bool operator()(const uint32_t a,const Tag &b) const { return (a < b.id()); }
|
||||
inline bool operator()(const Tag &a,const uint32_t b) const { return (a.id() < b); }
|
||||
inline bool operator()(const Tag *a,const Tag *b) const { return (a->id() < b->id()); }
|
||||
inline bool operator()(const Tag *a,const Tag &b) const { return (a->id() < b.id()); }
|
||||
inline bool operator()(const Tag &a,const Tag *b) const { return (a.id() < b->id()); }
|
||||
inline bool operator()(const uint32_t a,const Tag *b) const { return (a < b->id()); }
|
||||
inline bool operator()(const Tag *a,const uint32_t b) const { return (a->id() < b); }
|
||||
inline bool operator()(const uint32_t a,const uint32_t b) const { return (a < b); }
|
||||
ZT_ALWAYS_INLINE bool operator()(const Tag &a,const Tag &b) const { return (a.id() < b.id()); }
|
||||
ZT_ALWAYS_INLINE bool operator()(const uint32_t a,const Tag &b) const { return (a < b.id()); }
|
||||
ZT_ALWAYS_INLINE bool operator()(const Tag &a,const uint32_t b) const { return (a.id() < b); }
|
||||
ZT_ALWAYS_INLINE bool operator()(const Tag *a,const Tag *b) const { return (a->id() < b->id()); }
|
||||
ZT_ALWAYS_INLINE bool operator()(const Tag *a,const Tag &b) const { return (a->id() < b.id()); }
|
||||
ZT_ALWAYS_INLINE bool operator()(const Tag &a,const Tag *b) const { return (a.id() < b->id()); }
|
||||
ZT_ALWAYS_INLINE bool operator()(const uint32_t a,const Tag *b) const { return (a < b->id()); }
|
||||
ZT_ALWAYS_INLINE bool operator()(const Tag *a,const uint32_t b) const { return (a->id() < b); }
|
||||
ZT_ALWAYS_INLINE bool operator()(const uint32_t a,const uint32_t b) const { return (a < b); }
|
||||
};
|
||||
|
||||
private:
|
||||
|
|
|
@ -55,8 +55,6 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
ZT_ALWAYS_INLINE ~Topology() {}
|
||||
|
||||
/**
|
||||
* Add a peer to database
|
||||
*
|
||||
|
@ -173,6 +171,34 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a function or function object to all peers
|
||||
*
|
||||
* This locks the peer map during execution, so calls to get() etc. during
|
||||
* eachPeer() will deadlock.
|
||||
*
|
||||
* @param f Function to apply
|
||||
* @tparam F Function or function object type
|
||||
*/
|
||||
template<typename F>
|
||||
ZT_ALWAYS_INLINE void eachPeerWithRoot(F f)
|
||||
{
|
||||
Mutex::Lock l(_peers_l);
|
||||
|
||||
std::vector<uintptr_t> rootPeerPtrs;
|
||||
for(std::vector< SharedPtr<Peer> >::iterator i(_rootPeers.begin());i!=_rootPeers.end();++i)
|
||||
rootPeerPtrs.push_back((uintptr_t)i->ptr());
|
||||
std::sort(rootPeerPtrs.begin(),rootPeerPtrs.end());
|
||||
|
||||
Hashtable< Address,SharedPtr<Peer> >::Iterator i(_peers);
|
||||
Address *a = (Address *)0;
|
||||
SharedPtr<Peer> *p = (SharedPtr<Peer> *)0;
|
||||
while (i.next(a,p)) {
|
||||
if (!f(*((const SharedPtr<Peer> *)p),std::binary_search(rootPeerPtrs.begin(),rootPeerPtrs.end(),(uintptr_t)p->ptr())))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the best relay to a given address, which may or may not be a root
|
||||
*
|
||||
|
@ -346,14 +372,24 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort roots in asecnding order of apparent latency
|
||||
*
|
||||
* @param now Current time
|
||||
*/
|
||||
ZT_ALWAYS_INLINE void rankRoots(const int64_t now)
|
||||
{
|
||||
Mutex::Lock l1(_peers_l);
|
||||
std::sort(_rootPeers.begin(),_rootPeers.end(),_RootSortComparisonOperator(now));
|
||||
}
|
||||
|
||||
/**
|
||||
* Do periodic tasks such as database cleanup
|
||||
*/
|
||||
inline void doPeriodicTasks(const int64_t now)
|
||||
ZT_ALWAYS_INLINE void doPeriodicTasks(const int64_t now)
|
||||
{
|
||||
{
|
||||
Mutex::Lock l1(_peers_l);
|
||||
std::sort(_rootPeers.begin(),_rootPeers.end(),_RootSortComparisonOperator(now));
|
||||
Hashtable< Address,SharedPtr<Peer> >::Iterator i(_peers);
|
||||
Address *a = (Address *)0;
|
||||
SharedPtr<Peer> *p = (SharedPtr<Peer> *)0;
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
|
||||
//#define ZT_TRACE
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
|
||||
#include "Trace.hpp"
|
||||
#include "RuntimeEnvironment.hpp"
|
||||
|
|
|
@ -372,6 +372,41 @@ template<typename T>
|
|||
static ZT_ALWAYS_INLINE T ntoh(T n) { return n; }
|
||||
#endif
|
||||
|
||||
static ZT_ALWAYS_INLINE uint64_t readUInt64(const void *const p)
|
||||
{
|
||||
#ifdef ZT_NO_TYPE_PUNNING
|
||||
const uint8_t *const b = reinterpret_cast<const uint8_t *>(p);
|
||||
return (
|
||||
((uint64_t)b[0] << 56) |
|
||||
((uint64_t)b[1] << 48) |
|
||||
((uint64_t)b[2] << 40) |
|
||||
((uint64_t)b[3] << 32) |
|
||||
((uint64_t)b[4] << 24) |
|
||||
((uint64_t)b[5] << 16) |
|
||||
((uint64_t)b[6] << 8) |
|
||||
(uint64_t)b[7]);
|
||||
#else
|
||||
return ntoh(*reinterpret_cast<const uint64_t *>(p));
|
||||
#endif
|
||||
}
|
||||
|
||||
static ZT_ALWAYS_INLINE void putUInt64(void *const p,const uint64_t i)
|
||||
{
|
||||
#ifdef ZT_NO_TYPE_PUNNING
|
||||
uint8_t *const b = reinterpret_cast<uint8_t *>(p);
|
||||
p[0] = (uint8_t)(i << 56);
|
||||
p[1] = (uint8_t)(i << 48);
|
||||
p[2] = (uint8_t)(i << 40);
|
||||
p[3] = (uint8_t)(i << 32);
|
||||
p[4] = (uint8_t)(i << 24);
|
||||
p[5] = (uint8_t)(i << 16);
|
||||
p[6] = (uint8_t)(i << 8);
|
||||
p[7] = (uint8_t)i;
|
||||
#else
|
||||
*reinterpret_cast<uint64_t *>(p) = Utils::hton(i);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace Utils
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -11,10 +11,10 @@
|
|||
*/
|
||||
/****/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
|
|
Loading…
Add table
Reference in a new issue