mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-05 20:13:44 +02:00
Bunch more fixes, implement C API for Identity operations.
This commit is contained in:
parent
57710cbc38
commit
2fbeaaf148
12 changed files with 601 additions and 600 deletions
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
106
node/Locator.cpp
Normal 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
|
103
node/Locator.hpp
103
node/Locator.hpp
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Reference in a new issue