Bunch more fixes, implement C API for Identity operations.

This commit is contained in:
Adam Ierymenko 2020-01-09 13:50:51 -08:00
parent 57710cbc38
commit 2fbeaaf148
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3
12 changed files with 601 additions and 600 deletions

View file

@ -13,29 +13,25 @@
#include "GoGlue.h"
#include <cstring>
#include <cstdlib>
#include <cerrno>
#include <ctime>
#include "../../node/Constants.hpp"
#include "../../node/InetAddress.hpp"
#include "../../node/Node.hpp"
#include "../../node/Utils.hpp"
#include "../../node/MAC.hpp"
#include "../../node/Address.hpp"
#include "../../node/Locator.hpp"
#include "../../osdep/OSUtils.hpp"
#include "../../osdep/EthernetTap.hpp"
#include "../../osdep/ManagedRoute.hpp"
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#ifndef __WINDOWS__
#include <errno.h>
#include <signal.h>
extern "C" {
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <arpa/inet.h>
@ -45,6 +41,7 @@
#ifdef __BSD__
#include <net/if.h>
#endif
}
#ifdef __LINUX__
#ifndef IPV6_DONTFRAG
#define IPV6_DONTFRAG 62
@ -56,7 +53,6 @@
#include <mutex>
#include <map>
#include <vector>
#include <array>
#include <set>
#include <memory>
#include <atomic>
@ -114,7 +110,6 @@ extern "C" int goPathCheckFunc(void *,uint64_t,int,const void *,int);
extern "C" int goPathLookupFunc(void *,uint64_t,int,int *,uint8_t [16],int *);
extern "C" void goStateObjectPutFunc(void *,int,const uint64_t [2],const void *,int);
extern "C" int goStateObjectGetFunc(void *,int,const uint64_t [2],void *,unsigned int);
extern "C" void goDNSResolverFunc(void *,const uint8_t *,int,const char *,uintptr_t);
extern "C" void goVirtualNetworkConfigFunc(void *,ZT_GoTap *,uint64_t,int,const ZT_VirtualNetworkConfig *);
extern "C" void goZtEvent(void *,int,const void *);
extern "C" void goHandleTapAddedMulticastGroup(void *,ZT_GoTap *,uint64_t,uint64_t,uint32_t);
@ -279,6 +274,7 @@ static int ZT_GoNode_PathLookupFunction(
void *uptr,
void *tptr,
uint64_t ztAddress,
const ZT_Identity *id,
int desiredAddressFamily,
struct sockaddr_storage *sa)
{
@ -310,20 +306,6 @@ static int ZT_GoNode_PathLookupFunction(
return 0;
}
static void ZT_GoNode_DNSResolver(
ZT_Node *node,
void *uptr,
void *tptr,
const enum ZT_DNSRecordType *types,
unsigned int numTypes,
const char *name,
uintptr_t requestId)
{
uint8_t t[256];
for(unsigned int i=0;(i<numTypes)&&(i<256);++i) t[i] = (uint8_t)types[i];
goDNSResolverFunc(reinterpret_cast<ZT_GoNode *>(uptr)->goUserPtr,t,(int)numTypes,name,requestId);
}
/****************************************************************************/
extern "C" ZT_GoNode *ZT_GoNode_new(const char *workingPath,uintptr_t userPtr)
@ -336,7 +318,6 @@ extern "C" ZT_GoNode *ZT_GoNode_new(const char *workingPath,uintptr_t userPtr)
cb.virtualNetworkFrameFunction = &ZT_GoNode_VirtualNetworkFrameFunction;
cb.virtualNetworkConfigFunction = &ZT_GoNode_VirtualNetworkConfigFunction;
cb.eventCallback = &ZT_GoNode_EventCallback;
cb.dnsResolver = &ZT_GoNode_DNSResolver;
cb.pathCheckFunction = &ZT_GoNode_PathCheckFunction;
cb.pathLookupFunction = &ZT_GoNode_PathLookupFunction;
@ -727,133 +708,3 @@ extern "C" int ZT_GoTap_removeRoute(ZT_GoTap *tap,int targetAf,const void *targe
}
return reinterpret_cast<EthernetTap *>(tap)->removeRoute(target,via,metric);
}
/****************************************************************************/
extern "C" const char *ZT_GoIdentity_generate(int type)
{
Identity id;
id.generate((Identity::Type)type);
char *tmp = (char *)malloc(ZT_IDENTITY_STRING_BUFFER_LENGTH);
if (tmp)
id.toString(true,tmp);
return tmp;
}
extern "C" int ZT_GoIdentity_validate(const char *idStr)
{
Identity id;
if (!id.fromString(idStr))
return 0;
if (!id.locallyValidate())
return 0;
return 1;
}
extern "C" int ZT_GoIdentity_sign(const char *idStr,const void *data,unsigned int len,void *sigbuf,unsigned int sigbuflen)
{
Identity id;
if (!id.fromString(idStr))
return 0;
return (int)id.sign(data,len,sigbuf,sigbuflen);
}
extern "C" int ZT_GoIdentity_verify(const char *idStr,const void *data,unsigned int len,const void *sig,unsigned int siglen)
{
Identity id;
if (!id.fromString(idStr))
return 0;
return id.verify(data,len,sig,siglen) ? 1 : 0;
}
/****************************************************************************/
extern "C" int ZT_GoLocator_makeSecureDNSName(char *name,unsigned int nameBufSize,uint8_t *privateKey,unsigned int privateKeyBufSize)
{
if ((privateKeyBufSize < ZT_ECC384_PRIVATE_KEY_SIZE)||(nameBufSize < 256))
return -1;
uint8_t pub[ZT_ECC384_PUBLIC_KEY_SIZE];
ECC384GenerateKey(pub,privateKey);
const Str n(Locator::makeSecureDnsName(pub));
if (n.length() >= nameBufSize)
return -1;
Utils::scopy(name,nameBufSize,n.c_str());
return ZT_ECC384_PRIVATE_KEY_SIZE;
}
extern "C" int ZT_GoLocator_makeLocator(
uint8_t *buf,
unsigned int bufSize,
int64_t ts,
const char *id,
const struct sockaddr_storage *physicalAddresses,
unsigned int physicalAddressCount,
const char **virtualAddresses,
unsigned int virtualAddressCount)
{
Locator loc;
for(unsigned int i=0;i<physicalAddressCount;++i) {
loc.add(*reinterpret_cast<const InetAddress *>(physicalAddresses + i));
}
for(unsigned int i=0;i<virtualAddressCount;++i) {
Identity id;
if (!id.fromString(virtualAddresses[i]))
return -1;
loc.add(id);
}
Identity signingId;
if (!signingId.fromString(id))
return -1;
if (!signingId.hasPrivate())
return -1;
if (!loc.finish(signingId,ts))
return -1;
Buffer<65536> *tmp = new Buffer<65536>();
loc.serialize(*tmp);
if (tmp->size() > bufSize) {
delete tmp;
return -1;
}
memcpy(buf,tmp->data(),tmp->size());
int s = (int)tmp->size();
delete tmp;
return s;
}
extern "C" int ZT_GoLocator_decodeLocator(const uint8_t *locatorBytes,unsigned int locatorSize,struct ZT_GoLocator_Info *info)
{
Locator loc;
if (!loc.deserialize(locatorBytes,locatorSize))
return -1;
if (!loc.verify())
return -2;
loc.id().toString(false,info->id);
info->phyCount = 0;
info->virtCount = 0;
for(auto p=loc.phy().begin();p!=loc.phy().end();++p)
memcpy(&(info->phy[info->phyCount++]),&(*p),sizeof(struct sockaddr_storage));
for(auto v=loc.virt().begin();v!=loc.virt().end();++v)
v->toString(false,info->virt[info->virtCount++]);
return 1;
}
int ZT_GoLocator_makeSignedTxtRecords(
const uint8_t *locator,
unsigned int locatorSize,
const char *name,
const uint8_t *privateKey,
unsigned int privateKeySize,
char results[256][256])
{
if (privateKeySize != ZT_ECC384_PRIVATE_KEY_SIZE)
return -1;
Locator loc;
if (!loc.deserialize(locator,locatorSize))
return -1;
std::vector<Str> r(loc.makeTxtRecords(privateKey));
if (r.size() > 256)
return -1;
for(unsigned long i=0;i<r.size();++i)
Utils::scopy(results[i],256,r[i].c_str());
return (int)r.size();
}

View file

@ -14,9 +14,15 @@
#ifndef ZT_GONODE_H
#define ZT_GONODE_H
#ifdef __cplusplus
#include <cstdint>
#include <cstdlib>
#include <cstring>
#else
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#endif
#include "../../include/ZeroTierCore.h"
#include "../../node/Constants.hpp"

View file

@ -21,6 +21,7 @@
#ifdef __cplusplus
#include <cstdint>
extern "C" {
#else
#include <stdint.h>
#endif
@ -43,10 +44,6 @@
#define ZT_SDK_API
#endif
#ifdef __cplusplus
extern "C" {
#endif
/****************************************************************************/
/* Core constants */
/****************************************************************************/
@ -95,11 +92,6 @@ extern "C" {
*/
#define ZT_MAX_PHYSMTU (ZT_MAX_PHYSPAYLOAD + ZT_MAX_HEADROOM)
/**
* Maximum size of a remote trace message's serialized Dictionary
*/
#define ZT_MAX_REMOTE_TRACE_SIZE 10000
/**
* Maximum length of network short name
*/
@ -262,78 +254,6 @@ extern "C" {
*/
#define ZT_RULE_PACKET_CHARACTERISTICS_TCP_FIN 0x0000000000000001ULL
/****************************************************************************/
// Fields in remote trace dictionaries
#define ZT_REMOTE_TRACE_FIELD__EVENT "event"
#define ZT_REMOTE_TRACE_FIELD__NODE_ID "nodeId"
#define ZT_REMOTE_TRACE_FIELD__PACKET_ID "packetId"
#define ZT_REMOTE_TRACE_FIELD__PACKET_VERB "packetVerb"
#define ZT_REMOTE_TRACE_FIELD__PACKET_TRUSTED_PATH_ID "packetTrustedPathId"
#define ZT_REMOTE_TRACE_FIELD__PACKET_TRUSTED_PATH_APPROVED "packetTrustedPathApproved"
#define ZT_REMOTE_TRACE_FIELD__PACKET_HOPS "packetHops"
#define ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR "remoteZtAddr"
#define ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR "remotePhyAddr"
#define ZT_REMOTE_TRACE_FIELD__LOCAL_ZTADDR "localZtAddr"
#define ZT_REMOTE_TRACE_FIELD__LOCAL_PHYADDR "localPhyAddr"
#define ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET "localSocket"
#define ZT_REMOTE_TRACE_FIELD__IP_SCOPE "phyAddrIpScope"
#define ZT_REMOTE_TRACE_FIELD__NETWORK_ID "networkId"
#define ZT_REMOTE_TRACE_FIELD__SOURCE_ZTADDR "sourceZtAddr"
#define ZT_REMOTE_TRACE_FIELD__DEST_ZTADDR "destZtAddr"
#define ZT_REMOTE_TRACE_FIELD__SOURCE_MAC "sourceMac"
#define ZT_REMOTE_TRACE_FIELD__DEST_MAC "destMac"
#define ZT_REMOTE_TRACE_FIELD__ETHERTYPE "etherType"
#define ZT_REMOTE_TRACE_FIELD__VLAN_ID "vlanId"
#define ZT_REMOTE_TRACE_FIELD__FRAME_LENGTH "frameLength"
#define ZT_REMOTE_TRACE_FIELD__FRAME_DATA "frameData"
#define ZT_REMOTE_TRACE_FIELD__FILTER_FLAG_NOTEE "filterNoTee"
#define ZT_REMOTE_TRACE_FIELD__FILTER_FLAG_INBOUND "filterInbound"
#define ZT_REMOTE_TRACE_FIELD__FILTER_RESULT "filterResult"
#define ZT_REMOTE_TRACE_FIELD__FILTER_BASE_RULE_LOG "filterBaseRuleLog"
#define ZT_REMOTE_TRACE_FIELD__FILTER_CAP_RULE_LOG "filterCapRuleLog"
#define ZT_REMOTE_TRACE_FIELD__FILTER_CAP_ID "filterMatchingCapId"
#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE "credType"
#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID "credId"
#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP "credTs"
#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_INFO "credInfo"
#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO "credIssuedTo"
#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_REVOCATION_TARGET "credRevocationTarget"
#define ZT_REMOTE_TRACE_FIELD__REASON "reason"
#define ZT_REMOTE_TRACE_FIELD__NETWORK_CONTROLLER_ID "networkControllerId"
// Event types in remote traces
#define ZT_REMOTE_TRACE_EVENT__RESETTING_PATHS_IN_SCOPE 0x1000
#define ZT_REMOTE_TRACE_EVENT__PEER_CONFIRMING_UNKNOWN_PATH 0x1001
#define ZT_REMOTE_TRACE_EVENT__PEER_LEARNED_NEW_PATH 0x1002
#define ZT_REMOTE_TRACE_EVENT__PEER_REDIRECTED 0x1003
#define ZT_REMOTE_TRACE_EVENT__PACKET_MAC_FAILURE 0x1004
#define ZT_REMOTE_TRACE_EVENT__PACKET_INVALID 0x1005
#define ZT_REMOTE_TRACE_EVENT__DROPPED_HELLO 0x1006
#define ZT_REMOTE_TRACE_EVENT__OUTGOING_NETWORK_FRAME_DROPPED 0x2000
#define ZT_REMOTE_TRACE_EVENT__INCOMING_NETWORK_ACCESS_DENIED 0x2001
#define ZT_REMOTE_TRACE_EVENT__INCOMING_NETWORK_FRAME_DROPPED 0x2002
#define ZT_REMOTE_TRACE_EVENT__CREDENTIAL_REJECTED 0x2003
#define ZT_REMOTE_TRACE_EVENT__CREDENTIAL_ACCEPTED 0x2004
#define ZT_REMOTE_TRACE_EVENT__NETWORK_CONFIG_REQUEST_SENT 0x2005
#define ZT_REMOTE_TRACE_EVENT__NETWORK_FILTER_TRACE 0x2006
// Event types in remote traces in hex string form
#define ZT_REMOTE_TRACE_EVENT__RESETTING_PATHS_IN_SCOPE_S "1000"
#define ZT_REMOTE_TRACE_EVENT__PEER_CONFIRMING_UNKNOWN_PATH_S "1001"
#define ZT_REMOTE_TRACE_EVENT__PEER_LEARNED_NEW_PATH_S "1002"
#define ZT_REMOTE_TRACE_EVENT__PEER_REDIRECTED_S "1003"
#define ZT_REMOTE_TRACE_EVENT__PACKET_MAC_FAILURE_S "1004"
#define ZT_REMOTE_TRACE_EVENT__PACKET_INVALID_S "1005"
#define ZT_REMOTE_TRACE_EVENT__DROPPED_HELLO_S "1006"
#define ZT_REMOTE_TRACE_EVENT__OUTGOING_NETWORK_FRAME_DROPPED_S "2000"
#define ZT_REMOTE_TRACE_EVENT__INCOMING_NETWORK_ACCESS_DENIED_S "2001"
#define ZT_REMOTE_TRACE_EVENT__INCOMING_NETWORK_FRAME_DROPPED_S "2002"
#define ZT_REMOTE_TRACE_EVENT__CREDENTIAL_REJECTED_S "2003"
#define ZT_REMOTE_TRACE_EVENT__CREDENTIAL_ACCEPTED_S "2004"
#define ZT_REMOTE_TRACE_EVENT__NETWORK_CONFIG_REQUEST_SENT_S "2005"
#define ZT_REMOTE_TRACE_EVENT__NETWORK_FILTER_TRACE_S "2006"
/****************************************************************************/
/* Structures and other types */
/****************************************************************************/
@ -503,48 +423,23 @@ enum ZT_Event
*
* Meta-data: ZT_UserMessage structure
*/
ZT_EVENT_USER_MESSAGE = 6,
/**
* Remote trace received
*
* NOTE: any node can fling a VERB_REMOTE_TRACE at you. It's up to you
* to determine if you want to do anything with it or just silently
* drop it on the floor. It's also up to you to handle these securely!
*
* Meta-data: ZT_RemoteTrace structure
*/
ZT_EVENT_REMOTE_TRACE = 7
ZT_EVENT_USER_MESSAGE = 6
};
/**
* Payload of REMOTE_TRACE event
* Identity type codes
*/
typedef struct
enum ZT_Identity_Type
{
/**
* ZeroTier address of sender (in least significant 40 bits only)
*/
uint64_t origin;
/* These values must be the same as in Identity.hpp in the core. */
ZT_IDENTITY_TYPE_C25519 = 0,
ZT_IDENTITY_TYPE_P384 = 1
};
/**
* Null-terminated Dictionary containing key/value pairs sent by origin
*
* This *should* be a dictionary, but the implementation only checks
* that it is a valid non-empty C-style null-terminated string. Be very
* careful to use a well-tested parser to parse this as it represents
* data received from a potentially un-trusted peer on the network.
* Invalid payloads should be dropped.
*
* The contents of data[] may be modified.
*/
const char *data;
/**
* Length of dict[] in bytes, INCLUDING terminating null
*/
unsigned int len;
} ZT_RemoteTrace;
/**
* A ZeroTier identity (opaque)
*/
typedef void ZT_Identity;
/**
* User message used with ZT_EVENT_USER_MESSAGE
@ -589,6 +484,11 @@ typedef struct
*/
uint64_t address;
/**
* Actual identity object for this node
*/
const ZT_Identity *identity;
/**
* Public identity in string-serialized form (safe to send to others)
*
@ -965,16 +865,6 @@ enum ZT_VirtualNetworkConfigOperation
ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY = 4
};
/**
* What trust hierarchy role does this peer have?
*/
enum ZT_PeerRole
{
ZT_PEER_ROLE_LEAF = 0, // ordinary node
ZT_PEER_ROLE_MOON = 1, // moon root
ZT_PEER_ROLE_PLANET = 2 // planetary root
};
/**
* Virtual network configuration
*/
@ -1183,6 +1073,15 @@ typedef struct
int preferred;
} ZT_PeerPhysicalPath;
/**
* What trust hierarchy role does this peer have?
*/
enum ZT_PeerRole
{
ZT_PEER_ROLE_LEAF = 0, // ordinary node
ZT_PEER_ROLE_ROOT = 1 // root server
};
/**
* Peer status result buffer
*/
@ -1193,6 +1092,11 @@ typedef struct
*/
uint64_t address;
/**
* Peer identity
*/
const ZT_Identity *identity;
/**
* Remote major version or -1 if not known
*/
@ -1497,7 +1401,7 @@ typedef int (*ZT_PathLookupFunction)(
void *, /* User ptr */
void *, /* Thread ptr */
uint64_t, /* ZeroTier address (40 bits) */
const char *, /* Identity in string form */
const ZT_Identity *, /* Full identity of node */
int, /* Desired ss_family or -1 for any */
struct sockaddr_storage *); /* Result buffer */
@ -1541,12 +1445,12 @@ struct ZT_Node_Callbacks
ZT_EventCallback eventCallback;
/**
* OPTIONAL: Function to check whether a given physical path should be used
* OPTIONAL: Function to check whether a given physical path should be used for ZeroTier traffic
*/
ZT_PathCheckFunction pathCheckFunction;
/**
* OPTIONAL: Function to get hints to physical paths to ZeroTier addresses
* RECOMMENDED: Function to look up paths to ZeroTier nodes
*/
ZT_PathLookupFunction pathLookupFunction;
};
@ -1865,6 +1769,115 @@ ZT_SDK_API void ZT_Node_setController(ZT_Node *node,void *networkConfigMasterIns
*/
ZT_SDK_API enum ZT_ResultCode ZT_Node_setPhysicalPathConfiguration(ZT_Node *node,const struct sockaddr_storage *pathNetwork,const ZT_PhysicalPathConfiguration *pathConfig);
/**
* Generate a new identity
*
* Due to a small amount of proof of work this can be a time consuming and CPU
* intensive operation. It takes less than a second on most desktop-class systems
* but can take longer on e.g. phones.
*
* @param type Type of identity to generate
* @return New identity or NULL on error
*/
ZT_SDK_API ZT_Identity *ZT_Identity_new(enum ZT_Identity_Type type);
/**
* Create a new identity object from a string-serialized identity
*
* @param idStr Identity in string format
* @return Identity object or NULL if the supplied identity string was not valid
*/
ZT_SDK_API ZT_Identity *ZT_Identity_fromString(const char *idStr);
/**
* Validate this identity
*
* This can be slightly time consuming due to address derivation (work) checking.
*
* @return Non-zero if identity is valid
*/
ZT_SDK_API int ZT_Identity_validate(const ZT_Identity *id);
/**
* Sign a data object with this identity
*
* The identity must have a private key or this will fail.
*
* @param id Identity to use to sign
* @param data Data to sign
* @param len Length of data
* @param signature Buffer to store signature
* @param signatureBufferLength Length of buffer (must be at least 96 bytes)
* @return Length of signature in bytes or 0 on failure.
*/
ZT_SDK_API unsigned int ZT_Identity_sign(const ZT_Identity *id,const void *data,unsigned int len,void *signature,unsigned int signatureBufferLength);
/**
* Verify a signature
*
* @param id Identity to use to verify
* @param data Data to verify
* @param len Length of data
* @param signature Signature to check
* @param sigLen Length of signature in bytes
* @return Non-zero if signature is valid
*/
ZT_SDK_API int ZT_Identity_verify(const ZT_Identity *id,const void *data,unsigned int len,const void *signature,unsigned int sigLen);
/**
* Get identity type
*
* @param id Identity to query
* @return Identity type code
*/
ZT_SDK_API enum ZT_Identity_Type ZT_Identity_type(const ZT_Identity *id);
/**
* Convert an identity to its string representation
*
* @param id Identity to convert
* @param buf Buffer to store identity (should be at least about 1024 bytes in length)
* @param capacity Capacity of buffer
* @param includePrivate If true include the private key if present
* @return Pointer to buf or NULL on overflow or other error
*/
ZT_SDK_API char *ZT_Identity_toString(const ZT_Identity *id,char *buf,int capacity,int includePrivate);
/**
* Check whether this identity object also holds a private key
*
* @param id Identity to query
* @return Non-zero if a private key is held
*/
ZT_SDK_API int ZT_Identity_hasPrivate(const ZT_Identity *id);
/**
* Get the ZeroTier address associated with this identity
*
* @param id Identity to query
* @return ZeroTier address (only least significant 40 bits are meaningful, rest will be 0)
*/
ZT_SDK_API uint64_t ZT_Identity_address(const ZT_Identity *id);
/**
* Compute a hash of this identity's public keys (or both public and private if includePrivate is true)
*
* @param id Identity to query
* @param h Buffer for 384-bit hash
* @param includePrivate If true include private keys if any
*/
ZT_SDK_API void ZT_Identity_hash(const ZT_Identity *id,uint8_t h[48],int includePrivate);
/**
* Delete an identity and free associated memory
*
* This should only be used with identities created via Identity_new
* and Identity_fromString().
*
* @param id Identity to delete
*/
ZT_SDK_API void ZT_Identity_delete(ZT_Identity *id);
/**
* Get ZeroTier One version
*

View file

@ -56,6 +56,7 @@ set(core_src
Identity.cpp
IncomingPacket.cpp
InetAddress.cpp
Locator.cpp
Membership.cpp
Network.cpp
NetworkConfig.cpp
@ -74,16 +75,3 @@ set(core_src
add_library(${PROJECT_NAME} STATIC ${core_src} ${core_headers})
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_11)
target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_BINARY_DIR})
#if(UNIX)
# set_source_files_properties(
# AES.cpp
# AES-aesni.c
# ECC384.cpp
# Salsa20.cpp
# C25519.cpp
# Poly1305.cpp
# PROPERTIES
# COMPILE_FLAGS "-Wall -O3"
# )
#endif(UNIX)

View file

@ -11,10 +11,8 @@
*/
/****/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <cstring>
#include <cstdint>
#include "Constants.hpp"
#include "Identity.hpp"
@ -143,6 +141,108 @@ bool Identity::locallyValidate() const
return false;
}
bool Identity::hash(uint8_t h[48],const bool includePrivate) const
{
switch(_type) {
case C25519:
if ((_hasPrivate)&&(includePrivate))
SHA384(h,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN,_priv.c25519,ZT_C25519_PRIVATE_KEY_LEN);
else SHA384(h,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN);
return true;
case P384:
if ((_hasPrivate)&&(includePrivate))
SHA384(h,&_pub,sizeof(_pub),&_priv,sizeof(_priv));
else SHA384(h,&_pub,sizeof(_pub));
return true;
}
return false;
}
unsigned int Identity::sign(const void *data,unsigned int len,void *sig,unsigned int siglen) const
{
if (_hasPrivate) {
switch(_type) {
case C25519:
if (siglen >= ZT_C25519_SIGNATURE_LEN) {
C25519::sign(_priv.c25519,_pub.c25519,data,len,sig);
return ZT_C25519_SIGNATURE_LEN;
}
case P384:
if (siglen >= ZT_ECC384_SIGNATURE_SIZE) {
// When signing with P384 we also hash the C25519 public key as an
// extra measure to ensure that only this identity can verify.
uint8_t h[48];
SHA384(h,data,len,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN);
ECC384ECDSASign(_priv.p384,h,(uint8_t *)sig);
return ZT_ECC384_SIGNATURE_SIZE;
}
}
}
return 0;
}
bool Identity::verify(const void *data,unsigned int len,const void *sig,unsigned int siglen) const
{
switch(_type) {
case C25519:
return C25519::verify(_pub.c25519,data,len,sig,siglen);
case P384:
if (siglen == ZT_ECC384_SIGNATURE_SIZE) {
uint8_t h[48];
SHA384(h,data,len,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN);
return ECC384ECDSAVerify(_pub.p384,h,(const uint8_t *)sig);
}
break;
}
return false;
}
bool Identity::agree(const Identity &id,uint8_t key[ZT_PEER_SECRET_KEY_LENGTH]) const
{
uint8_t rawkey[128];
uint8_t h[64];
if (_hasPrivate) {
if (_type == C25519) {
if ((id._type == C25519)||(id._type == P384)) {
// If we are a C25519 key we can agree with another C25519 key or with only the
// C25519 portion of a type 1 P-384 key.
C25519::agree(_priv.c25519,id._pub.c25519,rawkey);
SHA512(h,rawkey,ZT_C25519_SHARED_KEY_LEN);
memcpy(key,h,ZT_PEER_SECRET_KEY_LENGTH);
return true;
}
} else if (_type == P384) {
if (id._type == P384) {
C25519::agree(_priv.c25519,id._pub.c25519,rawkey);
ECC384ECDH(id._pub.p384,_priv.p384,rawkey + ZT_C25519_SHARED_KEY_LEN);
SHA384(h,rawkey,ZT_C25519_SHARED_KEY_LEN + ZT_ECC384_SHARED_SECRET_SIZE);
memcpy(key,h,ZT_PEER_SECRET_KEY_LENGTH);
return true;
} else if (id._type == C25519) {
// If the other identity is a C25519 identity we can agree using only that type.
C25519::agree(_priv.c25519,id._pub.c25519,rawkey);
SHA512(h,rawkey,ZT_C25519_SHARED_KEY_LEN);
memcpy(key,h,ZT_PEER_SECRET_KEY_LENGTH);
return true;
}
}
}
return false;
}
char *Identity::toString(bool includePrivate,char buf[ZT_IDENTITY_STRING_BUFFER_LENGTH]) const
{
switch(_type) {
@ -286,3 +386,99 @@ bool Identity::fromString(const char *str)
}
} // namespace ZeroTier
extern "C" {
ZT_Identity *ZT_Identity_new(enum ZT_Identity_Type type)
{
if ((type != ZT_IDENTITY_TYPE_C25519)&&(type != ZT_IDENTITY_TYPE_P384))
return nullptr;
try {
ZeroTier::Identity *id = new ZeroTier::Identity();
id->generate((ZeroTier::Identity::Type)type);
return reinterpret_cast<ZT_Identity *>(id);
} catch ( ... ) {
return nullptr;
}
}
ZT_Identity *ZT_Identity_fromString(const char *idStr)
{
if (!idStr)
return nullptr;
try {
ZeroTier::Identity *id = new ZeroTier::Identity();
if (!id->fromString(idStr)) {
delete id;
return nullptr;
}
return reinterpret_cast<ZT_Identity *>(id);
} catch ( ... ) {
return nullptr;
}
}
int ZT_Identity_validate(const ZT_Identity *id)
{
if (!id)
return 0;
return reinterpret_cast<const ZeroTier::Identity *>(id)->locallyValidate() ? 1 : 0;
}
unsigned int ZT_Identity_sign(const ZT_Identity *id,const void *data,unsigned int len,void *signature,unsigned int signatureBufferLength)
{
if (!id)
return 0;
if (signatureBufferLength < ZT_SIGNATURE_BUFFER_SIZE)
return 0;
return reinterpret_cast<const ZeroTier::Identity *>(id)->sign(data,len,signature,signatureBufferLength);
}
int ZT_Identity_verify(const ZT_Identity *id,const void *data,unsigned int len,const void *signature,unsigned int sigLen)
{
if ((!id)||(!signature)||(!sigLen))
return 0;
return reinterpret_cast<const ZeroTier::Identity *>(id)->verify(data,len,signature,sigLen) ? 1 : 0;
}
enum ZT_Identity_Type ZT_Identity_type(const ZT_Identity *id)
{
if (!id)
return (ZT_Identity_Type)0;
return (enum ZT_Identity_Type)reinterpret_cast<const ZeroTier::Identity *>(id)->type();
}
char *ZT_Identity_toString(const ZT_Identity *id,char *buf,int capacity,int includePrivate)
{
if ((!id)||(!buf)||(capacity < ZT_IDENTITY_STRING_BUFFER_LENGTH))
return nullptr;
reinterpret_cast<const ZeroTier::Identity *>(id)->toString(includePrivate != 0,buf);
return buf;
}
int ZT_Identity_hasPrivate(const ZT_Identity *id)
{
if (!id)
return 0;
return reinterpret_cast<const ZeroTier::Identity *>(id)->hasPrivate() ? 1 : 0;
}
uint64_t ZT_Identity_address(const ZT_Identity *id)
{
if (!id)
return 0;
return reinterpret_cast<const ZeroTier::Identity *>(id)->address().toInt();
}
void ZT_Identity_hash(const ZT_Identity *id,uint8_t h[48],int includePrivate)
{
reinterpret_cast<const ZeroTier::Identity *>(id)->hash(h,includePrivate != 0);
}
ZT_SDK_API void ZT_Identity_delete(ZT_Identity *id)
{
if (id)
delete reinterpret_cast<ZeroTier::Identity *>(id);
}
}

View file

@ -67,7 +67,7 @@ public:
*
* @param str Identity in canonical string format
*/
ZT_ALWAYS_INLINE Identity(const char *str) { fromString(str); }
explicit ZT_ALWAYS_INLINE Identity(const char *str) { fromString(str); }
/**
* Set identity to NIL value (all zero)
@ -86,7 +86,7 @@ public:
*
* @param t Type of identity to generate
*/
void generate(const Type t);
void generate(Type t);
/**
* Check the validity of this identity's pairing of key to address
@ -106,25 +106,7 @@ public:
* @param h Buffer to receive SHA384 of public key(s)
* @param includePrivate If true, hash private key(s) as well
*/
inline bool hash(uint8_t h[48],const bool includePrivate = false) const
{
switch(_type) {
case C25519:
if ((_hasPrivate)&&(includePrivate))
SHA384(h,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN,_priv.c25519,ZT_C25519_PRIVATE_KEY_LEN);
else SHA384(h,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN);
return true;
case P384:
if ((_hasPrivate)&&(includePrivate))
SHA384(h,&_pub,sizeof(_pub),&_priv,sizeof(_priv));
else SHA384(h,&_pub,sizeof(_pub));
return true;
}
return false;
}
bool hash(uint8_t h[48],bool includePrivate = false) const;
/**
* Sign a message with this identity (private key required)
@ -138,31 +120,7 @@ public:
* @param siglen Length of buffer
* @return Number of bytes actually written to sig or 0 on error
*/
inline unsigned int sign(const void *data,unsigned int len,void *sig,unsigned int siglen) const
{
if (_hasPrivate) {
switch(_type) {
case C25519:
if (siglen >= ZT_C25519_SIGNATURE_LEN) {
C25519::sign(_priv.c25519,_pub.c25519,data,len,sig);
return ZT_C25519_SIGNATURE_LEN;
}
case P384:
if (siglen >= ZT_ECC384_SIGNATURE_SIZE) {
// When signing with P384 we also hash the C25519 public key as an
// extra measure to ensure that only this identity can verify.
uint8_t h[48];
SHA384(h,data,len,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN);
ECC384ECDSASign(_priv.p384,h,(uint8_t *)sig);
return ZT_ECC384_SIGNATURE_SIZE;
}
}
}
return 0;
}
unsigned int sign(const void *data,unsigned int len,void *sig,unsigned int siglen) const;
/**
* Verify a message signature against this identity
@ -173,24 +131,7 @@ public:
* @param siglen Length of signature in bytes
* @return True if signature validates and data integrity checks
*/
inline bool verify(const void *data,unsigned int len,const void *sig,unsigned int siglen) const
{
switch(_type) {
case C25519:
return C25519::verify(_pub.c25519,data,len,sig,siglen);
case P384:
if (siglen == ZT_ECC384_SIGNATURE_SIZE) {
uint8_t h[48];
SHA384(h,data,len,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN);
return ECC384ECDSAVerify(_pub.p384,h,(const uint8_t *)sig);
}
break;
}
return false;
}
bool verify(const void *data,unsigned int len,const void *sig,unsigned int siglen) const;
/**
* Shortcut method to perform key agreement with another identity
@ -201,42 +142,7 @@ public:
* @param key Result parameter to fill with key bytes
* @return Was agreement successful?
*/
inline bool agree(const Identity &id,uint8_t key[ZT_PEER_SECRET_KEY_LENGTH]) const
{
uint8_t rawkey[128];
uint8_t h[64];
if (_hasPrivate) {
if (_type == C25519) {
if ((id._type == C25519)||(id._type == P384)) {
// If we are a C25519 key we can agree with another C25519 key or with only the
// C25519 portion of a type 1 P-384 key.
C25519::agree(_priv.c25519,id._pub.c25519,rawkey);
SHA512(h,rawkey,ZT_C25519_SHARED_KEY_LEN);
memcpy(key,h,ZT_PEER_SECRET_KEY_LENGTH);
return true;
}
} else if (_type == P384) {
if (id._type == P384) {
C25519::agree(_priv.c25519,id._pub.c25519,rawkey);
ECC384ECDH(id._pub.p384,_priv.p384,rawkey + ZT_C25519_SHARED_KEY_LEN);
SHA384(h,rawkey,ZT_C25519_SHARED_KEY_LEN + ZT_ECC384_SHARED_SECRET_SIZE);
memcpy(key,h,ZT_PEER_SECRET_KEY_LENGTH);
return true;
} else if (id._type == C25519) {
// If the other identity is a C25519 identity we can agree using only that type.
C25519::agree(_priv.c25519,id._pub.c25519,rawkey);
SHA512(h,rawkey,ZT_C25519_SHARED_KEY_LEN);
memcpy(key,h,ZT_PEER_SECRET_KEY_LENGTH);
return true;
}
}
}
return false;
}
bool agree(const Identity &id,uint8_t key[ZT_PEER_SECRET_KEY_LENGTH]) const;
/**
* @return This identity's address
@ -476,7 +382,7 @@ public:
privlen = data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE];
if (len < (privlen + (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE + 1)))
return -1;
return (privlen + (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE + 1));
return (int)(privlen + (unsigned int)(ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE + 1));
} else if (privlen == 0) {
_hasPrivate = false;
return (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 2);

View file

@ -41,7 +41,7 @@ namespace {
// Implementation of each protocol verb //
//////////////////////////////////////////////////////////////////////////////
static void _sendErrorNeedCredentials(IncomingPacket &pkt,const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer,const uint64_t nwid,const SharedPtr<Path> &path)
void _sendErrorNeedCredentials(IncomingPacket &pkt,const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer,const uint64_t nwid,const SharedPtr<Path> &path)
{
Packet outp(pkt.source(),RR->identity.address(),Packet::VERB_ERROR);
outp.append((uint8_t)pkt.verb());
@ -52,7 +52,7 @@ static void _sendErrorNeedCredentials(IncomingPacket &pkt,const RuntimeEnvironme
path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now());
}
static inline bool _doHELLO(IncomingPacket &pkt,const RuntimeEnvironment *const RR,void *const tPtr,const bool alreadyAuthenticated,const SharedPtr<Path> &path)
ZT_ALWAYS_INLINE bool _doHELLO(IncomingPacket &pkt,const RuntimeEnvironment *const RR,void *const tPtr,const bool alreadyAuthenticated,const SharedPtr<Path> &path)
{
const int64_t now = RR->node->now();
@ -181,15 +181,15 @@ static inline bool _doHELLO(IncomingPacket &pkt,const RuntimeEnvironment *const
return true;
}
static inline bool _doACK(IncomingPacket &pkt,const RuntimeEnvironment *const RR,void *const tPtr,const SharedPtr<Peer> &peer,const SharedPtr<Path> &path)
ZT_ALWAYS_INLINE bool _doACK(IncomingPacket &pkt,const RuntimeEnvironment *const RR,void *const tPtr,const SharedPtr<Peer> &peer,const SharedPtr<Path> &path)
{
}
static inline bool _doQOS_MEASUREMENT(IncomingPacket &pkt,const RuntimeEnvironment *const RR,void *const tPtr,const SharedPtr<Peer> &peer,const SharedPtr<Path> &path)
ZT_ALWAYS_INLINE bool _doQOS_MEASUREMENT(IncomingPacket &pkt,const RuntimeEnvironment *const RR,void *const tPtr,const SharedPtr<Peer> &peer,const SharedPtr<Path> &path)
{
}
static inline bool _doERROR(IncomingPacket &pkt,const RuntimeEnvironment *const RR,void *const tPtr,const SharedPtr<Peer> &peer,const SharedPtr<Path> &path)
ZT_ALWAYS_INLINE bool _doERROR(IncomingPacket &pkt,const RuntimeEnvironment *const RR,void *const tPtr,const SharedPtr<Peer> &peer,const SharedPtr<Path> &path)
{
const Packet::Verb inReVerb = (Packet::Verb)pkt[ZT_PROTO_VERB_ERROR_IDX_IN_RE_VERB];
const uint64_t inRePacketId = pkt.at<uint64_t>(ZT_PROTO_VERB_ERROR_IDX_IN_RE_PACKET_ID);
@ -251,7 +251,7 @@ static inline bool _doERROR(IncomingPacket &pkt,const RuntimeEnvironment *const
return true;
}
static inline bool _doOK(IncomingPacket &pkt,const RuntimeEnvironment *const RR,void *const tPtr,const SharedPtr<Peer> &peer,const SharedPtr<Path> &path)
ZT_ALWAYS_INLINE bool _doOK(IncomingPacket &pkt,const RuntimeEnvironment *const RR,void *const tPtr,const SharedPtr<Peer> &peer,const SharedPtr<Path> &path)
{
const Packet::Verb inReVerb = (Packet::Verb)pkt[ZT_PROTO_VERB_OK_IDX_IN_RE_VERB];
const uint64_t inRePacketId = pkt.at<uint64_t>(ZT_PROTO_VERB_OK_IDX_IN_RE_PACKET_ID);
@ -318,7 +318,7 @@ static inline bool _doOK(IncomingPacket &pkt,const RuntimeEnvironment *const RR,
return true;
}
static inline bool _doWHOIS(IncomingPacket &pkt,const RuntimeEnvironment *const RR,void *const tPtr,const SharedPtr<Peer> &peer,const SharedPtr<Path> &path)
ZT_ALWAYS_INLINE bool _doWHOIS(IncomingPacket &pkt,const RuntimeEnvironment *const RR,void *const tPtr,const SharedPtr<Peer> &peer,const SharedPtr<Path> &path)
{
if (!peer->rateGateInboundWhoisRequest(RR->node->now()))
return true;
@ -353,7 +353,7 @@ static inline bool _doWHOIS(IncomingPacket &pkt,const RuntimeEnvironment *const
return true;
}
static inline bool _doRENDEZVOUS(IncomingPacket &pkt,const RuntimeEnvironment *const RR,void *const tPtr,const SharedPtr<Peer> &peer,const SharedPtr<Path> &path)
ZT_ALWAYS_INLINE bool _doRENDEZVOUS(IncomingPacket &pkt,const RuntimeEnvironment *const RR,void *const tPtr,const SharedPtr<Peer> &peer,const SharedPtr<Path> &path)
{
if (RR->topology->isRoot(peer->identity())) {
const Address with(pkt.field(ZT_PROTO_VERB_RENDEZVOUS_IDX_ZTADDRESS,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH);
@ -375,7 +375,7 @@ static inline bool _doRENDEZVOUS(IncomingPacket &pkt,const RuntimeEnvironment *c
return true;
}
static inline bool _doFRAME(IncomingPacket &pkt,const RuntimeEnvironment *const RR,void *const tPtr,const SharedPtr<Peer> &peer,const SharedPtr<Path> &path)
ZT_ALWAYS_INLINE bool _doFRAME(IncomingPacket &pkt,const RuntimeEnvironment *const RR,void *const tPtr,const SharedPtr<Peer> &peer,const SharedPtr<Path> &path)
{
const uint64_t nwid = pkt.at<uint64_t>(ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID);
const SharedPtr<Network> network(RR->node->network(nwid));
@ -398,7 +398,7 @@ static inline bool _doFRAME(IncomingPacket &pkt,const RuntimeEnvironment *const
return true;
}
static inline bool _doEXT_FRAME(IncomingPacket &pkt,const RuntimeEnvironment *const RR,void *const tPtr,const SharedPtr<Peer> &peer,const SharedPtr<Path> &path)
ZT_ALWAYS_INLINE bool _doEXT_FRAME(IncomingPacket &pkt,const RuntimeEnvironment *const RR,void *const tPtr,const SharedPtr<Peer> &peer,const SharedPtr<Path> &path)
{
const uint64_t nwid = pkt.at<uint64_t>(ZT_PROTO_VERB_EXT_FRAME_IDX_NETWORK_ID);
const SharedPtr<Network> network(RR->node->network(nwid));
@ -476,7 +476,7 @@ static inline bool _doEXT_FRAME(IncomingPacket &pkt,const RuntimeEnvironment *co
return true;
}
static inline bool _doECHO(IncomingPacket &pkt,const RuntimeEnvironment *const RR,void *const tPtr,const SharedPtr<Peer> &peer,const SharedPtr<Path> &path)
ZT_ALWAYS_INLINE bool _doECHO(IncomingPacket &pkt,const RuntimeEnvironment *const RR,void *const tPtr,const SharedPtr<Peer> &peer,const SharedPtr<Path> &path)
{
if (!peer->rateGateEchoRequest(RR->node->now()))
return true;
@ -495,7 +495,7 @@ static inline bool _doECHO(IncomingPacket &pkt,const RuntimeEnvironment *const R
return true;
}
static inline bool _doNETWORK_CREDENTIALS(IncomingPacket &pkt,const RuntimeEnvironment *const RR,void *const tPtr,const SharedPtr<Peer> &peer,const SharedPtr<Path> &path)
ZT_ALWAYS_INLINE bool _doNETWORK_CREDENTIALS(IncomingPacket &pkt,const RuntimeEnvironment *const RR,void *const tPtr,const SharedPtr<Peer> &peer,const SharedPtr<Path> &path)
{
if (!peer->rateGateCredentialsReceived(RR->node->now()))
return true;
@ -577,7 +577,7 @@ static inline bool _doNETWORK_CREDENTIALS(IncomingPacket &pkt,const RuntimeEnvir
return true;
}
static inline bool _doNETWORK_CONFIG_REQUEST(IncomingPacket &pkt,const RuntimeEnvironment *const RR,void *const tPtr,const SharedPtr<Peer> &peer,const SharedPtr<Path> &path)
ZT_ALWAYS_INLINE bool _doNETWORK_CONFIG_REQUEST(IncomingPacket &pkt,const RuntimeEnvironment *const RR,void *const tPtr,const SharedPtr<Peer> &peer,const SharedPtr<Path> &path)
{
const uint64_t nwid = pkt.at<uint64_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_NETWORK_ID);
const unsigned int hopCount = pkt.hops();
@ -603,7 +603,7 @@ static inline bool _doNETWORK_CONFIG_REQUEST(IncomingPacket &pkt,const RuntimeEn
return true;
}
static inline bool _doNETWORK_CONFIG(IncomingPacket &pkt,const RuntimeEnvironment *const RR,void *const tPtr,const SharedPtr<Peer> &peer,const SharedPtr<Path> &path)
ZT_ALWAYS_INLINE bool _doNETWORK_CONFIG(IncomingPacket &pkt,const RuntimeEnvironment *const RR,void *const tPtr,const SharedPtr<Peer> &peer,const SharedPtr<Path> &path)
{
const SharedPtr<Network> network(RR->node->network(pkt.at<uint64_t>(ZT_PACKET_IDX_PAYLOAD)));
if (network) {
@ -622,7 +622,7 @@ static inline bool _doNETWORK_CONFIG(IncomingPacket &pkt,const RuntimeEnvironmen
return true;
}
static inline bool _doMULTICAST_GATHER(IncomingPacket &pkt,const RuntimeEnvironment *const RR,void *const tPtr,const SharedPtr<Peer> &peer,const SharedPtr<Path> &path)
ZT_ALWAYS_INLINE bool _doMULTICAST_GATHER(IncomingPacket &pkt,const RuntimeEnvironment *const RR,void *const tPtr,const SharedPtr<Peer> &peer,const SharedPtr<Path> &path)
{
const uint64_t nwid = pkt.at<uint64_t>(ZT_PROTO_VERB_MULTICAST_GATHER_IDX_NETWORK_ID);
const unsigned int flags = pkt[ZT_PROTO_VERB_MULTICAST_GATHER_IDX_FLAGS];
@ -670,7 +670,7 @@ static inline bool _doMULTICAST_GATHER(IncomingPacket &pkt,const RuntimeEnvironm
return true;
}
static inline bool _doPUSH_DIRECT_PATHS(IncomingPacket &pkt,const RuntimeEnvironment *const RR,void *const tPtr,const SharedPtr<Peer> &peer,const SharedPtr<Path> &path)
ZT_ALWAYS_INLINE bool _doPUSH_DIRECT_PATHS(IncomingPacket &pkt,const RuntimeEnvironment *const RR,void *const tPtr,const SharedPtr<Peer> &peer,const SharedPtr<Path> &path)
{
const int64_t now = RR->node->now();
@ -720,7 +720,7 @@ static inline bool _doPUSH_DIRECT_PATHS(IncomingPacket &pkt,const RuntimeEnviron
return true;
}
static inline bool _doUSER_MESSAGE(IncomingPacket &pkt,const RuntimeEnvironment *const RR,void *const tPtr,const SharedPtr<Peer> &peer,const SharedPtr<Path> &path)
ZT_ALWAYS_INLINE bool _doUSER_MESSAGE(IncomingPacket &pkt,const RuntimeEnvironment *const RR,void *const tPtr,const SharedPtr<Peer> &peer,const SharedPtr<Path> &path)
{
if (likely(pkt.size() >= (ZT_PACKET_IDX_PAYLOAD + 8))) {
ZT_UserMessage um;

View file

@ -376,7 +376,7 @@ bool InetAddress::operator<(const InetAddress &a) const
InetAddress InetAddress::makeIpv6LinkLocal(const MAC &mac)
{
InetAddress r;
sockaddr_in6 *const sin6 = reinterpret_cast<struct sockaddr_in6 *>(&r);
sockaddr_in6 *const sin6 = reinterpret_cast<sockaddr_in6 *>(&r);
sin6->sin6_family = AF_INET6;
sin6->sin6_addr.s6_addr[0] = 0xfe;
sin6->sin6_addr.s6_addr[1] = 0x80;
@ -401,7 +401,7 @@ InetAddress InetAddress::makeIpv6LinkLocal(const MAC &mac)
InetAddress InetAddress::makeIpv6rfc4193(uint64_t nwid,uint64_t zeroTierAddress)
{
InetAddress r;
sockaddr_in6 *const sin6 = reinterpret_cast<struct sockaddr_in6 *>(&r);
sockaddr_in6 *const sin6 = reinterpret_cast<sockaddr_in6 *>(&r);
sin6->sin6_family = AF_INET6;
sin6->sin6_addr.s6_addr[0] = 0xfd;
sin6->sin6_addr.s6_addr[1] = (uint8_t)(nwid >> 56U);
@ -427,7 +427,7 @@ InetAddress InetAddress::makeIpv66plane(uint64_t nwid,uint64_t zeroTierAddress)
{
nwid ^= (nwid >> 32U);
InetAddress r;
sockaddr_in6 *const sin6 = reinterpret_cast<struct sockaddr_in6 *>(&r);
sockaddr_in6 *const sin6 = reinterpret_cast<sockaddr_in6 *>(&r);
sin6->sin6_family = AF_INET6;
sin6->sin6_addr.s6_addr[0] = 0xfc;
sin6->sin6_addr.s6_addr[1] = (uint8_t)(nwid >> 24U);

View file

@ -42,6 +42,16 @@ namespace ZeroTier {
*/
struct InetAddress : public sockaddr_storage
{
private:
template<typename SA>
ZT_ALWAYS_INLINE void copySockaddrToThis(const SA *sa)
{
memcpy(reinterpret_cast<void *>(this),sa,sizeof(SA));
if (sizeof(SA) < sizeof(InetAddress))
memset(reinterpret_cast<char *>(this) + sizeof(SA),0,sizeof(InetAddress) - sizeof(SA));
}
public:
/**
* Loopback IPv4 address (no port)
*/
@ -79,116 +89,83 @@ struct InetAddress : public sockaddr_storage
// Hasher for unordered sets and maps in C++11
struct Hasher { ZT_ALWAYS_INLINE std::size_t operator()(const InetAddress &a) const { return (std::size_t)a.hashCode(); } };
ZT_ALWAYS_INLINE InetAddress() { memset(this,0,sizeof(InetAddress)); }
ZT_ALWAYS_INLINE InetAddress(const InetAddress &a) { memcpy(this,&a,sizeof(InetAddress)); }
ZT_ALWAYS_INLINE InetAddress(const InetAddress *a) { memcpy(this,a,sizeof(InetAddress)); }
ZT_ALWAYS_INLINE InetAddress(const struct sockaddr_storage &ss) { *this = ss; }
ZT_ALWAYS_INLINE InetAddress(const struct sockaddr_storage *ss) { *this = ss; }
ZT_ALWAYS_INLINE InetAddress(const struct sockaddr &sa) { *this = sa; }
ZT_ALWAYS_INLINE InetAddress(const struct sockaddr *sa) { *this = sa; }
ZT_ALWAYS_INLINE InetAddress(const struct sockaddr_in &sa) { *this = sa; }
ZT_ALWAYS_INLINE InetAddress(const struct sockaddr_in *sa) { *this = sa; }
ZT_ALWAYS_INLINE InetAddress(const struct sockaddr_in6 &sa) { *this = sa; }
ZT_ALWAYS_INLINE InetAddress(const struct sockaddr_in6 *sa) { *this = sa; }
ZT_ALWAYS_INLINE InetAddress() { memset(reinterpret_cast<void *>(this),0,sizeof(InetAddress)); }
explicit ZT_ALWAYS_INLINE InetAddress(const struct sockaddr_storage &ss) { *this = ss; }
explicit ZT_ALWAYS_INLINE InetAddress(const struct sockaddr_storage *ss) { *this = ss; }
explicit ZT_ALWAYS_INLINE InetAddress(const struct sockaddr &sa) { *this = sa; }
explicit ZT_ALWAYS_INLINE InetAddress(const struct sockaddr *sa) { *this = sa; }
explicit ZT_ALWAYS_INLINE InetAddress(const struct sockaddr_in &sa) { *this = sa; }
explicit ZT_ALWAYS_INLINE InetAddress(const struct sockaddr_in *sa) { *this = sa; }
explicit ZT_ALWAYS_INLINE InetAddress(const struct sockaddr_in6 &sa) { *this = sa; }
explicit ZT_ALWAYS_INLINE InetAddress(const struct sockaddr_in6 *sa) { *this = sa; }
ZT_ALWAYS_INLINE InetAddress(const void *ipBytes,unsigned int ipLen,unsigned int port) { this->set(ipBytes,ipLen,port); }
ZT_ALWAYS_INLINE InetAddress(const uint32_t ipv4,unsigned int port) { this->set(&ipv4,4,port); }
ZT_ALWAYS_INLINE InetAddress(const char *ipSlashPort) { this->fromString(ipSlashPort); }
explicit ZT_ALWAYS_INLINE InetAddress(const char *ipSlashPort) { this->fromString(ipSlashPort); }
ZT_ALWAYS_INLINE void clear() { memset(this,0,sizeof(InetAddress)); }
ZT_ALWAYS_INLINE InetAddress &operator=(const InetAddress &a)
{
if (&a != this)
memcpy(this,&a,sizeof(InetAddress));
return *this;
}
ZT_ALWAYS_INLINE InetAddress &operator=(const InetAddress *a)
{
if (a != this)
memcpy(this,a,sizeof(InetAddress));
return *this;
}
ZT_ALWAYS_INLINE void clear() { memset(reinterpret_cast<void *>(this),0,sizeof(InetAddress)); }
ZT_ALWAYS_INLINE InetAddress &operator=(const struct sockaddr_storage &ss)
{
if (reinterpret_cast<const InetAddress *>(&ss) != this)
memcpy(this,&ss,sizeof(InetAddress));
memcpy(reinterpret_cast<void *>(this),&ss,sizeof(InetAddress));
return *this;
}
ZT_ALWAYS_INLINE InetAddress &operator=(const struct sockaddr_storage *ss)
{
if (reinterpret_cast<const InetAddress *>(ss) != this)
memcpy(this,ss,sizeof(InetAddress));
if (ss)
memcpy(reinterpret_cast<void *>(this),ss,sizeof(InetAddress));
else memset(reinterpret_cast<void *>(this),0,sizeof(InetAddress));
return *this;
}
ZT_ALWAYS_INLINE InetAddress &operator=(const struct sockaddr_in &sa)
{
if (reinterpret_cast<const InetAddress *>(&sa) != this) {
memset(this,0,sizeof(InetAddress));
memcpy(this,&sa,sizeof(struct sockaddr_in));
}
copySockaddrToThis(&sa);
return *this;
}
ZT_ALWAYS_INLINE InetAddress &operator=(const struct sockaddr_in *sa)
{
if (reinterpret_cast<const InetAddress *>(sa) != this) {
memset(this,0,sizeof(InetAddress));
memcpy(this,sa,sizeof(struct sockaddr_in));
}
if (sa)
copySockaddrToThis(sa);
else memset(reinterpret_cast<void *>(this),0,sizeof(InetAddress));
return *this;
}
ZT_ALWAYS_INLINE InetAddress &operator=(const struct sockaddr_in6 &sa)
{
if (reinterpret_cast<const InetAddress *>(&sa) != this) {
memset(this,0,sizeof(InetAddress));
memcpy(this,&sa,sizeof(struct sockaddr_in6));
}
copySockaddrToThis(&sa);
return *this;
}
ZT_ALWAYS_INLINE InetAddress &operator=(const struct sockaddr_in6 *sa)
{
if (reinterpret_cast<const InetAddress *>(sa) != this) {
memset(this,0,sizeof(InetAddress));
memcpy(this,sa,sizeof(struct sockaddr_in6));
}
if (sa)
copySockaddrToThis(sa);
else memset(reinterpret_cast<void *>(this),0,sizeof(InetAddress));
return *this;
}
ZT_ALWAYS_INLINE InetAddress &operator=(const struct sockaddr &sa)
{
if (reinterpret_cast<const InetAddress *>(&sa) != this) {
memset(this,0,sizeof(InetAddress));
switch(sa.sa_family) {
case AF_INET:
memcpy(this,&sa,sizeof(struct sockaddr_in));
break;
case AF_INET6:
memcpy(this,&sa,sizeof(struct sockaddr_in6));
break;
}
}
if (sa.sa_family == AF_INET)
copySockaddrToThis(reinterpret_cast<const sockaddr_in *>(&sa));
else if (sa.sa_family == AF_INET6)
copySockaddrToThis(reinterpret_cast<const sockaddr_in6 *>(&sa));
else memset(reinterpret_cast<void *>(this),0,sizeof(InetAddress));
return *this;
}
ZT_ALWAYS_INLINE InetAddress &operator=(const struct sockaddr *sa)
{
if (reinterpret_cast<const InetAddress *>(sa) != this) {
memset(this,0,sizeof(InetAddress));
switch(sa->sa_family) {
case AF_INET:
memcpy(this,sa,sizeof(struct sockaddr_in));
break;
case AF_INET6:
memcpy(this,sa,sizeof(struct sockaddr_in6));
break;
}
if (sa) {
if (sa->sa_family == AF_INET)
copySockaddrToThis(reinterpret_cast<const sockaddr_in *>(sa));
else if (sa->sa_family == AF_INET6)
copySockaddrToThis(reinterpret_cast<const sockaddr_in6 *>(sa));
return *this;
}
memset(reinterpret_cast<void *>(this),0,sizeof(InetAddress));
return *this;
}
@ -517,6 +494,9 @@ struct InetAddress : public sockaddr_storage
}
inline int unmarshal(const uint8_t *restrict data,const int len)
{
#ifdef ZT_NO_TYPE_PUNNING
uint16_t tmp;
#endif
if (len <= 0)
return -1;
switch(data[0]) {
@ -525,22 +505,32 @@ struct InetAddress : public sockaddr_storage
case 4:
if (len < 7)
return -1;
memset(this,0,sizeof(InetAddress));
memset(reinterpret_cast<void *>(this),0,sizeof(InetAddress));
reinterpret_cast<sockaddr_in *>(this)->sin_family = AF_INET;
reinterpret_cast<uint8_t *>(&(reinterpret_cast<sockaddr_in *>(this)->sin_addr.s_addr))[0] = data[1];
reinterpret_cast<uint8_t *>(&(reinterpret_cast<sockaddr_in *>(this)->sin_addr.s_addr))[1] = data[2];
reinterpret_cast<uint8_t *>(&(reinterpret_cast<sockaddr_in *>(this)->sin_addr.s_addr))[2] = data[3];
reinterpret_cast<uint8_t *>(&(reinterpret_cast<sockaddr_in *>(this)->sin_addr.s_addr))[3] = data[4];
reinterpret_cast<sockaddr_in *>(this)->sin_port = Utils::hton((((uint16_t)data[5]) << 8) | (uint16_t)data[6]);
#ifdef ZT_NO_TYPE_PUNNING
memcpy(&tmp,data + 5,2);
reinterpret_cast<sockaddr_in *>(this)->sin_port = tmp;
#else
reinterpret_cast<sockaddr_in *>(this)->sin_port = *((const uint16_t *)(data + 5));
#endif
return 7;
case 6:
if (len < 19)
return -1;
memset(this,0,sizeof(InetAddress));
memset(reinterpret_cast<void *>(this),0,sizeof(InetAddress));
reinterpret_cast<sockaddr_in6 *>(this)->sin6_family = AF_INET6;
for(int i=0;i<16;i++)
(reinterpret_cast<sockaddr_in6 *>(this)->sin6_addr.s6_addr)[i] = data[i+1];
reinterpret_cast<sockaddr_in6 *>(this)->sin6_port = Utils::hton((((uint16_t)data[17]) << 8) | (uint16_t)data[18]);
#ifdef ZT_NO_TYPE_PUNNING
memcpy(&tmp,data + 17,2);
reinterpret_cast<sockaddr_in *>(this)->sin_port = tmp;
#else
reinterpret_cast<sockaddr_in *>(this)->sin_port = *((const uint16_t *)(data + 17));
#endif
return 19;
default:
return -1;
@ -666,6 +656,13 @@ struct InetAddress : public sockaddr_storage
static InetAddress makeIpv66plane(uint64_t nwid,uint64_t zeroTierAddress);
};
InetAddress *asInetAddress(sockaddr_in *p) { return reinterpret_cast<InetAddress *>(p); }
InetAddress *asInetAddress(sockaddr_in6 *p) { return reinterpret_cast<InetAddress *>(p); }
InetAddress *asInetAddress(sockaddr *p) { return reinterpret_cast<InetAddress *>(p); }
const InetAddress *asInetAddress(const sockaddr_in *p) { return reinterpret_cast<const InetAddress *>(p); }
const InetAddress *asInetAddress(const sockaddr_in6 *p) { return reinterpret_cast<const InetAddress *>(p); }
const InetAddress *asInetAddress(const sockaddr *p) { return reinterpret_cast<const InetAddress *>(p); }
} // namespace ZeroTier
#endif

106
node/Locator.cpp Normal file
View file

@ -0,0 +1,106 @@
/*
* Copyright (c)2019 ZeroTier, Inc.
*
* Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file in the project's root directory.
*
* Change Date: 2023-01-01
*
* On the date above, in accordance with the Business Source License, use
* of this software will be governed by version 2.0 of the Apache License.
*/
/****/
#include "Locator.hpp"
namespace ZeroTier {
bool Locator::sign(const int64_t ts,const Identity &id)
{
uint8_t signData[ZT_LOCATOR_MARSHAL_SIZE_MAX];
if (!id.hasPrivate())
return false;
_ts = ts;
if (_endpointCount > 0)
std::sort(_at,_at + _endpointCount);
const unsigned int signLen = marshal(signData,true);
_signatureLength = id.sign(signData, signLen, _signature, sizeof(_signature));
return (_signatureLength > 0);
}
bool Locator::verify(const Identity &id) const
{
if ((_ts == 0)||(_endpointCount > ZT_LOCATOR_MAX_ENDPOINTS)||(_signatureLength > ZT_SIGNATURE_BUFFER_SIZE))
return false;
uint8_t signData[ZT_LOCATOR_MARSHAL_SIZE_MAX];
const unsigned int signLen = marshal(signData,true);
return id.verify(signData,signLen,_signature,_signatureLength);
}
int Locator::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;
Utils::putUInt64(data,(uint64_t)_ts);
int p = 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);
if (tmp < 0)
return -1;
p += tmp;
}
if (!excludeSignature) {
data[p++] = (uint8_t)(_signatureLength >> 8U);
data[p++] = (uint8_t)_signatureLength;
memcpy(data + p,_signature,_signatureLength);
p += (int)_signatureLength;
}
return p;
}
int Locator::unmarshal(const uint8_t *restrict data,const int len)
{
if (len <= (8 + 48))
return -1;
_ts = (int64_t)Utils::readUInt64(data);
int p = 8;
if ((p + 2) > len)
return -1;
unsigned int ec = (int)data[p++];
ec <<= 8U;
ec |= data[p++];
if (ec > ZT_LOCATOR_MAX_ENDPOINTS)
return -1;
_endpointCount = ec;
for(int i=0;i<ec;++i) {
int tmp = _at[i].unmarshal(data + p,len - p);
if (tmp < 0)
return -1;
p += tmp;
}
if ((p + 2) > len)
return -1;
unsigned int sl = data[p++];
sl <<= 8U;
sl |= data[p++];
if (sl > ZT_SIGNATURE_BUFFER_SIZE)
return -1;
_signatureLength = sl;
if ((p + sl) > len)
return -1;
memcpy(_signature,data + p,sl);
p += (int)sl;
return p;
}
} // namespace ZeroTier

View file

@ -54,38 +54,32 @@ public:
ZT_ALWAYS_INLINE bool isSigned() const { return (_signatureLength > 0); }
/**
* Add an endpoint to this locator if not already present
* Add an endpoint to this locator
*
* This doesn't check for the presence of the endpoint, so take
* care not to add duplicates.
*
* @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)
ZT_ALWAYS_INLINE bool add(const Endpoint &ep)
{
if (_endpointCount >= ZT_LOCATOR_MAX_ENDPOINTS)
return false;
if (!std::binary_search(_at,_at + _endpointCount,ep)) {
_at[_endpointCount++] = ep;
std::sort(_at,_at + _endpointCount);
}
_at[_endpointCount++] = ep;
return true;
}
/**
* Sign this locator
*
* This sets timestamp, sorts endpoints so that the same set of endpoints
* will always produce the same locator, and signs.
*
* @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;
const unsigned int signLen = marshal(signData,true);
_signatureLength = id.sign(signData, signLen, _signature, sizeof(_signature));
return (_signatureLength > 0);
}
bool sign(int64_t ts,const Identity &id);
/**
* Verify this Locator's validity and signature
@ -93,84 +87,13 @@ public:
* @param id Identity corresponding to hash
* @return True if valid and signature checks out
*/
inline bool verify(const Identity &id) const
{
if ((_ts == 0)||(_endpointCount > ZT_LOCATOR_MAX_ENDPOINTS)||(_signatureLength > ZT_SIGNATURE_BUFFER_SIZE))
return false;
uint8_t signData[ZT_LOCATOR_MARSHAL_SIZE_MAX];
const unsigned int signLen = marshal(signData,true);
return id.verify(signData,signLen,_signature,_signatureLength);
}
bool verify(const Identity &id) const;
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 data[ZT_LOCATOR_MARSHAL_SIZE_MAX],const bool excludeSignature = false) const
{
if ((_endpointCount > ZT_LOCATOR_MAX_ENDPOINTS)||(_signatureLength > ZT_SIGNATURE_BUFFER_SIZE))
return -1;
Utils::putUInt64(data,(uint64_t)_ts);
int p = 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);
if (tmp < 0)
return -1;
p += tmp;
}
if (!excludeSignature) {
data[p++] = (uint8_t)(_signatureLength >> 8U);
data[p++] = (uint8_t)_signatureLength;
memcpy(data + p,_signature,_signatureLength);
p += (int)_signatureLength;
}
return p;
}
inline int unmarshal(const uint8_t *restrict data,const int len)
{
if (len <= (8 + 48))
return -1;
_ts = (int64_t)Utils::readUInt64(data);
int p = 8;
if ((p + 2) > len)
return -1;
unsigned int ec = (int)data[p++];
ec <<= 8U;
ec |= data[p++];
if (ec > ZT_LOCATOR_MAX_ENDPOINTS)
return -1;
_endpointCount = ec;
for(int i=0;i<ec;++i) {
int tmp = _at[i].unmarshal(data + p,len - p);
if (tmp < 0)
return -1;
p += tmp;
}
if ((p + 2) > len)
return -1;
unsigned int sl = data[p++];
sl <<= 8U;
sl |= data[p++];
if (sl > ZT_SIGNATURE_BUFFER_SIZE)
return -1;
_signatureLength = sl;
if ((p + sl) > len)
return -1;
memcpy(_signature,data + p,sl);
p += (int)sl;
return p;
}
////////////////////////////////////////////////////////////////////////////
int marshal(uint8_t data[ZT_LOCATOR_MARSHAL_SIZE_MAX],const bool excludeSignature = false) const;
int unmarshal(const uint8_t *restrict data,const int len);
private:
int64_t _ts;

View file

@ -371,6 +371,7 @@ uint64_t Node::address() const
void Node::status(ZT_NodeStatus *status) const
{
status->address = RR->identity.address().toInt();
status->identity = reinterpret_cast<const ZT_Identity *>(&RR->identity);
status->publicIdentity = RR->publicIdentityStr;
status->secretIdentity = RR->secretIdentityStr;
status->online = _online ? 1 : 0;
@ -384,34 +385,38 @@ ZT_PeerList *Node::peers() const
RR->topology->getAllPeers(peers);
std::sort(peers.begin(),peers.end(),_sortPeerPtrsByAddress());
char *buf = (char *)::malloc(sizeof(ZT_PeerList) + (sizeof(ZT_Peer) * peers.size()));
char *buf = (char *)::malloc(sizeof(ZT_PeerList) + (sizeof(ZT_Peer) * peers.size()) + (sizeof(Identity) * peers.size()));
if (!buf)
return (ZT_PeerList *)0;
ZT_PeerList *pl = (ZT_PeerList *)buf;
pl->peers = (ZT_Peer *)(buf + sizeof(ZT_PeerList));
Identity *identities = (Identity *)(buf + sizeof(ZT_PeerList) + (sizeof(ZT_Peer) * peers.size()));
const int64_t now = _now;
pl->peerCount = 0;
for(std::vector< SharedPtr<Peer> >::iterator pi(peers.begin());pi!=peers.end();++pi) {
ZT_Peer *p = &(pl->peers[pl->peerCount++]);
ZT_Peer *p = &(pl->peers[pl->peerCount]);
p->address = (*pi)->address().toInt();
identities[pl->peerCount] = (*pi)->identity(); // need to make a copy in case peer gets deleted
p->identity = &identities[pl->peerCount];
p->hadAggregateLink = 0;
if ((*pi)->remoteVersionKnown()) {
p->versionMajor = (*pi)->remoteVersionMajor();
p->versionMinor = (*pi)->remoteVersionMinor();
p->versionRev = (*pi)->remoteVersionRevision();
p->versionMajor = (int)(*pi)->remoteVersionMajor();
p->versionMinor = (int)(*pi)->remoteVersionMinor();
p->versionRev = (int)(*pi)->remoteVersionRevision();
} else {
p->versionMajor = -1;
p->versionMinor = -1;
p->versionRev = -1;
}
p->latency = (*pi)->latency(_now);
p->latency = (int)(*pi)->latency(now);
if (p->latency >= 0xffff)
p->latency = -1;
p->role = RR->topology->isRoot((*pi)->identity()) ? ZT_PEER_ROLE_PLANET : ZT_PEER_ROLE_LEAF;
p->role = RR->topology->isRoot((*pi)->identity()) ? ZT_PEER_ROLE_ROOT : ZT_PEER_ROLE_LEAF;
const int64_t now = _now;
std::vector< SharedPtr<Path> > paths((*pi)->paths(_now));
SharedPtr<Path> bestp((*pi)->getAppropriatePath(_now,false));
std::vector< SharedPtr<Path> > paths((*pi)->paths(now));
SharedPtr<Path> bestp((*pi)->getAppropriatePath(now,false));
p->hadAggregateLink |= (*pi)->hasAggregateLink();
p->pathCount = 0;
for(std::vector< SharedPtr<Path> >::iterator path(paths.begin());path!=paths.end();++path) {
@ -434,6 +439,8 @@ ZT_PeerList *Node::peers() const
++p->pathCount;
}
++pl->peerCount;
}
return pl;
@ -553,9 +560,17 @@ bool Node::shouldUsePathForZeroTierTraffic(void *tPtr,const Address &ztaddr,cons
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);
if (_cb.pathLookupFunction) {
return (_cb.pathLookupFunction(
reinterpret_cast<ZT_Node *>(this),
_uPtr,
tPtr,
id.address().toInt(),
reinterpret_cast<const ZT_Identity *>(&id),
family,
reinterpret_cast<sockaddr_storage *>(&addr)) == ZT_RESULT_OK);
}
return false;
}
ZT_ResultCode Node::setPhysicalPathConfiguration(const struct sockaddr_storage *pathNetwork, const ZT_PhysicalPathConfiguration *pathConfig)