mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-07 13:03:45 +02:00
Bunch of new-gen serialization work
This commit is contained in:
parent
6267c67888
commit
3b94ef99ae
4 changed files with 336 additions and 70 deletions
|
@ -37,34 +37,37 @@ public:
|
||||||
enum Type
|
enum Type
|
||||||
{
|
{
|
||||||
NIL = 0, // NIL value
|
NIL = 0, // NIL value
|
||||||
SOCKADDR = 1, // InetAddress
|
INETADDR = 1, // InetAddress (v4 or v6)
|
||||||
DNSNAME = 2, // DNS name and port that resolves to InetAddress
|
DNSNAME = 2, // DNS name and port that resolves to InetAddress
|
||||||
ZEROTIER = 3, // ZeroTier Address (for relaying and meshy behavior)
|
ZEROTIER = 3, // ZeroTier Address (for relaying and meshy behavior)
|
||||||
URL = 4 // URL for http/https/ws/etc. (not implemented yet)
|
URL = 4, // URL for http/https/ws/etc. (not implemented yet)
|
||||||
|
ETHERNET = 5 // 48-bit LAN-local Ethernet address
|
||||||
};
|
};
|
||||||
|
|
||||||
inline Endpoint() { memset(reinterpret_cast<void *>(this),0,sizeof(Endpoint)); }
|
inline Endpoint() { memset(reinterpret_cast<void *>(this),0,sizeof(Endpoint)); }
|
||||||
|
|
||||||
inline Endpoint(const InetAddress &sa) : _t(SOCKADDR) { _v.sa = sa; }
|
inline Endpoint(const InetAddress &sa) : _t(INETADDR) { _v.sa = sa; }
|
||||||
inline Endpoint(const Address &zt,const uint8_t identityHash[ZT_IDENTITY_HASH_SIZE]) : _t(ZEROTIER) { _v.zt.a = zt.toInt(); memcpy(_v.zt.idh,identityHash,ZT_IDENTITY_HASH_SIZE); }
|
inline Endpoint(const Address &zt,const uint8_t identityHash[ZT_IDENTITY_HASH_SIZE]) : _t(ZEROTIER) { _v.zt.a = zt.toInt(); memcpy(_v.zt.idh,identityHash,ZT_IDENTITY_HASH_SIZE); }
|
||||||
inline Endpoint(const char *name,const int port) : _t(DNSNAME) { Utils::scopy(_v.dns.name,sizeof(_v.dns.name),name); _v.dns.port = port; }
|
inline Endpoint(const char *name,const int port) : _t(DNSNAME) { Utils::scopy(_v.dns.name,sizeof(_v.dns.name),name); _v.dns.port = port; }
|
||||||
inline Endpoint(const char *url) : _t(URL) { Utils::scopy(_v.url,sizeof(_v.url),url); }
|
inline Endpoint(const char *url) : _t(URL) { Utils::scopy(_v.url,sizeof(_v.url),url); }
|
||||||
|
|
||||||
inline const InetAddress *sockaddr() const { return (_t == SOCKADDR) ? reinterpret_cast<const InetAddress *>(&_v.sa) : nullptr; }
|
inline const InetAddress *sockaddr() const { return (_t == INETADDR) ? reinterpret_cast<const InetAddress *>(&_v.sa) : nullptr; }
|
||||||
inline const char *dnsName() const { return (_t == DNSNAME) ? _v.dns.name : nullptr; }
|
inline const char *dnsName() const { return (_t == DNSNAME) ? _v.dns.name : nullptr; }
|
||||||
inline const int dnsPort() const { return (_t == DNSNAME) ? _v.dns.port : -1; }
|
inline const int dnsPort() const { return (_t == DNSNAME) ? _v.dns.port : -1; }
|
||||||
inline Address ztAddress() const { return (_t == ZEROTIER) ? Address(_v.zt.a) : Address(); }
|
inline Address ztAddress() const { return (_t == ZEROTIER) ? Address(_v.zt.a) : Address(); }
|
||||||
inline const uint8_t *ztIdentityHash() const { return (_t == ZEROTIER) ? _v.zt.idh : nullptr; }
|
inline const uint8_t *ztIdentityHash() const { return (_t == ZEROTIER) ? _v.zt.idh : nullptr; }
|
||||||
inline const char *url() const { return (_t == URL) ? _v.url : nullptr; }
|
inline const char *url() const { return (_t == URL) ? _v.url : nullptr; }
|
||||||
|
inline MAC ethernet() const { return (_t == ETHERNET) ? MAC(_v.eth) : MAC(); }
|
||||||
|
|
||||||
inline Type type() const { return _t; }
|
inline Type type() const { return _t; }
|
||||||
|
|
||||||
inline unsigned int marshal(uint8_t data[ZT_ENDPOINT_MARSHAL_SIZE_MAX])
|
static inline int marshalSizeMax() { return ZT_ENDPOINT_MARSHAL_SIZE_MAX; }
|
||||||
|
inline int marshal(uint8_t data[ZT_ENDPOINT_MARSHAL_SIZE_MAX])
|
||||||
{
|
{
|
||||||
unsigned int p;
|
int p;
|
||||||
switch(_t) {
|
switch(_t) {
|
||||||
case SOCKADDR:
|
case INETADDR:
|
||||||
data[0] = (uint8_t)SOCKADDR;
|
data[0] = (uint8_t)INETADDR;
|
||||||
return 1 + reinterpret_cast<const InetAddress *>(&_v.sa)->marshal(data+1);
|
return 1 + reinterpret_cast<const InetAddress *>(&_v.sa)->marshal(data+1);
|
||||||
case DNSNAME:
|
case DNSNAME:
|
||||||
data[0] = (uint8_t)DNSNAME;
|
data[0] = (uint8_t)DNSNAME;
|
||||||
|
@ -74,7 +77,7 @@ public:
|
||||||
break;
|
break;
|
||||||
++p;
|
++p;
|
||||||
if (p == (ZT_ENDPOINT_MAX_NAME_SIZE+1))
|
if (p == (ZT_ENDPOINT_MAX_NAME_SIZE+1))
|
||||||
return 0;
|
return -1;
|
||||||
}
|
}
|
||||||
data[p++] = (uint8_t)((_v.dns.port >> 8) & 0xff);
|
data[p++] = (uint8_t)((_v.dns.port >> 8) & 0xff);
|
||||||
data[p++] = (uint8_t)(_v.dns.port & 0xff);
|
data[p++] = (uint8_t)(_v.dns.port & 0xff);
|
||||||
|
@ -96,45 +99,55 @@ public:
|
||||||
break;
|
break;
|
||||||
++p;
|
++p;
|
||||||
if (p == (ZT_ENDPOINT_MAX_NAME_SIZE+1))
|
if (p == (ZT_ENDPOINT_MAX_NAME_SIZE+1))
|
||||||
return 0;
|
return -1;
|
||||||
}
|
}
|
||||||
return p;
|
return p;
|
||||||
|
case ETHERNET:
|
||||||
|
data[0] = (uint8_t)ETHERNET;
|
||||||
|
data[1] = (uint8_t)((_v.eth >> 40) & 0xff);
|
||||||
|
data[2] = (uint8_t)((_v.eth >> 32) & 0xff);
|
||||||
|
data[3] = (uint8_t)((_v.eth >> 24) & 0xff);
|
||||||
|
data[4] = (uint8_t)((_v.eth >> 16) & 0xff);
|
||||||
|
data[5] = (uint8_t)((_v.eth >> 8) & 0xff);
|
||||||
|
data[6] = (uint8_t)(_v.eth & 0xff);
|
||||||
|
return 7;
|
||||||
default:
|
default:
|
||||||
data[0] = (uint8_t)NIL;
|
data[0] = (uint8_t)NIL;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
inline int unmarshal(const uint8_t *restrict data,const int len)
|
||||||
inline bool unmarshal(const uint8_t *restrict data,const unsigned int len)
|
|
||||||
{
|
{
|
||||||
if (len == 0)
|
if (len <= 0)
|
||||||
return false;
|
return -1;
|
||||||
unsigned int p;
|
int p;
|
||||||
switch((Type)data[0]) {
|
switch((Type)data[0]) {
|
||||||
case NIL:
|
case NIL:
|
||||||
_t = NIL;
|
_t = NIL;
|
||||||
return true;
|
return 1;
|
||||||
case SOCKADDR:
|
case INETADDR:
|
||||||
_t = SOCKADDR;
|
_t = INETADDR;
|
||||||
return reinterpret_cast<InetAddress *>(&_v.sa)->unmarshal(data+1,len-1);
|
return reinterpret_cast<InetAddress *>(&_v.sa)->unmarshal(data+1,len-1);
|
||||||
case DNSNAME:
|
case DNSNAME:
|
||||||
if (len < 4)
|
if (len < 4)
|
||||||
return false;
|
return -1;
|
||||||
_t = DNSNAME;
|
_t = DNSNAME;
|
||||||
p = 1;
|
p = 1;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if ((_v.dns.name[p-1] = (char)data[p]) == 0)
|
if ((_v.dns.name[p-1] = (char)data[p]) == 0) {
|
||||||
|
++p;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
++p;
|
++p;
|
||||||
if ((p >= (ZT_ENDPOINT_MAX_NAME_SIZE+1))||(p >= (len-2)))
|
if ((p >= (ZT_ENDPOINT_MAX_NAME_SIZE+1))||(p >= (len-2)))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_v.dns.port = ((int)data[p++]) << 8;
|
_v.dns.port = ((int)data[p++]) << 8;
|
||||||
_v.dns.port |= (int)data[p++];
|
_v.dns.port |= (int)data[p++];
|
||||||
return true;
|
return p;
|
||||||
case ZEROTIER:
|
case ZEROTIER:
|
||||||
if (len != (ZT_IDENTITY_HASH_SIZE + 6))
|
if (len < (ZT_IDENTITY_HASH_SIZE + 6))
|
||||||
return false;
|
return -1;
|
||||||
_t = ZEROTIER;
|
_t = ZEROTIER;
|
||||||
_v.zt.a = ((uint64_t)data[1]) << 32;
|
_v.zt.a = ((uint64_t)data[1]) << 32;
|
||||||
_v.zt.a |= ((uint64_t)data[2]) << 24;
|
_v.zt.a |= ((uint64_t)data[2]) << 24;
|
||||||
|
@ -142,20 +155,33 @@ public:
|
||||||
_v.zt.a |= ((uint64_t)data[4]) << 8;
|
_v.zt.a |= ((uint64_t)data[4]) << 8;
|
||||||
_v.zt.a |= (uint64_t)data[5];
|
_v.zt.a |= (uint64_t)data[5];
|
||||||
memcpy(_v.zt.idh,data + 6,ZT_IDENTITY_HASH_SIZE);
|
memcpy(_v.zt.idh,data + 6,ZT_IDENTITY_HASH_SIZE);
|
||||||
return true;
|
return (ZT_IDENTITY_HASH_SIZE + 6);
|
||||||
case URL:
|
case URL:
|
||||||
if (len < 2)
|
if (len < 2)
|
||||||
return false;
|
return -1;
|
||||||
_t = URL;
|
_t = URL;
|
||||||
p = 1;
|
p = 1;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if ((_v.url[p-1] = (char)data[p]) == 0)
|
if ((_v.url[p-1] = (char)data[p]) == 0) {
|
||||||
|
++p;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
++p;
|
++p;
|
||||||
if ((p >= (ZT_ENDPOINT_MAX_NAME_SIZE+1))||(p >= len))
|
if ((p >= (ZT_ENDPOINT_MAX_NAME_SIZE+1))||(p >= len))
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
return true;
|
return p;
|
||||||
|
case ETHERNET:
|
||||||
|
if (len < 7)
|
||||||
|
return -1;
|
||||||
|
_t = ZEROTIER;
|
||||||
|
_v.eth = ((uint64_t)data[1]) << 40;
|
||||||
|
_v.eth |= ((uint64_t)data[2]) << 32;
|
||||||
|
_v.eth |= ((uint64_t)data[3]) << 24;
|
||||||
|
_v.eth |= ((uint64_t)data[4]) << 16;
|
||||||
|
_v.eth |= ((uint64_t)data[5]) << 8;
|
||||||
|
_v.eth |= (uint64_t)data[6];
|
||||||
|
return 7;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -173,6 +199,7 @@ private:
|
||||||
uint8_t idh[ZT_IDENTITY_HASH_SIZE];
|
uint8_t idh[ZT_IDENTITY_HASH_SIZE];
|
||||||
} zt;
|
} zt;
|
||||||
char url[ZT_ENDPOINT_MAX_NAME_SIZE];
|
char url[ZT_ENDPOINT_MAX_NAME_SIZE];
|
||||||
|
uint64_t eth;
|
||||||
} _v;
|
} _v;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,11 @@
|
||||||
|
|
||||||
#define ZT_IDENTITY_STRING_BUFFER_LENGTH 1024
|
#define ZT_IDENTITY_STRING_BUFFER_LENGTH 1024
|
||||||
|
|
||||||
|
#define ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE (ZT_C25519_PUBLIC_KEY_LEN + ZT_ECC384_PUBLIC_KEY_SIZE + ZT_C25519_SIGNATURE_LEN + ZT_ECC384_SIGNATURE_SIZE)
|
||||||
|
#define ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE (ZT_C25519_PRIVATE_KEY_LEN + ZT_ECC384_PRIVATE_KEY_SIZE)
|
||||||
|
|
||||||
|
#define ZT_IDENTITY_MARSHAL_SIZE_MAX (ZT_ADDRESS_LENGTH + 4 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE)
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -241,6 +246,87 @@ public:
|
||||||
*/
|
*/
|
||||||
inline const Address &address() const { return _address; }
|
inline const Address &address() const { return _address; }
|
||||||
|
|
||||||
|
static inline int marshalSizeMax() { return ZT_IDENTITY_MARSHAL_SIZE_MAX; }
|
||||||
|
inline int marshal(uint8_t restrict data[ZT_IDENTITY_MARSHAL_SIZE_MAX],const bool includePrivate = false) const
|
||||||
|
{
|
||||||
|
_address.copyTo(data,ZT_ADDRESS_LENGTH);
|
||||||
|
switch(_type) {
|
||||||
|
|
||||||
|
case C25519:
|
||||||
|
data[ZT_ADDRESS_LENGTH] = (uint8_t)C25519;
|
||||||
|
memcpy(data + ZT_ADDRESS_LENGTH + 1,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN);
|
||||||
|
if ((includePrivate)&&(_hasPrivate)) {
|
||||||
|
data[ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN] = ZT_C25519_PRIVATE_KEY_LEN;
|
||||||
|
memcpy(data + ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1,_priv.c25519,ZT_C25519_PRIVATE_KEY_LEN);
|
||||||
|
return (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1 + ZT_C25519_PRIVATE_KEY_LEN);
|
||||||
|
}
|
||||||
|
data[ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN] = 0;
|
||||||
|
return (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1);
|
||||||
|
|
||||||
|
case P384:
|
||||||
|
data[ZT_ADDRESS_LENGTH] = (uint8_t)P384;
|
||||||
|
memcpy(data + ZT_ADDRESS_LENGTH + 1,&_pub,ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE);
|
||||||
|
if ((includePrivate)&&(_hasPrivate)) {
|
||||||
|
data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE] = ZT_C25519_PRIVATE_KEY_LEN + ZT_ECC384_PRIVATE_KEY_SIZE;
|
||||||
|
memcpy(data + ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1,&_priv,ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE);
|
||||||
|
data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE] = 0;
|
||||||
|
return (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE + 1);
|
||||||
|
}
|
||||||
|
data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE] = 0;
|
||||||
|
data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1] = 0;
|
||||||
|
return (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 2);
|
||||||
|
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
inline int unmarshal(const uint8_t *restrict data,const int len)
|
||||||
|
{
|
||||||
|
if (len < (ZT_ADDRESS_LENGTH + 1))
|
||||||
|
return -1;
|
||||||
|
unsigned int privlen;
|
||||||
|
switch((_type = (Type)data[ZT_ADDRESS_LENGTH])) {
|
||||||
|
|
||||||
|
case C25519:
|
||||||
|
if (len < (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1))
|
||||||
|
return -1;
|
||||||
|
memcpy(_pub.c25519,data + ZT_ADDRESS_LENGTH + 1,ZT_C25519_PUBLIC_KEY_LEN);
|
||||||
|
privlen = data[ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN];
|
||||||
|
if (privlen == ZT_C25519_PRIVATE_KEY_LEN) {
|
||||||
|
if (len < (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1 + ZT_C25519_PRIVATE_KEY_LEN))
|
||||||
|
return -1;
|
||||||
|
_hasPrivate = true;
|
||||||
|
memcpy(_priv.c25519,data + ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1,ZT_C25519_PRIVATE_KEY_LEN);
|
||||||
|
return (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1 + ZT_C25519_PRIVATE_KEY_LEN);
|
||||||
|
} else if (privlen == 0) {
|
||||||
|
_hasPrivate = false;
|
||||||
|
return (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case P384:
|
||||||
|
if (len < (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 2))
|
||||||
|
return -1;
|
||||||
|
memcpy(&_pub,data + ZT_ADDRESS_LENGTH + 1,ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE);
|
||||||
|
privlen = data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE];
|
||||||
|
if (privlen == ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE) {
|
||||||
|
if (len < (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE + 1))
|
||||||
|
return -1;
|
||||||
|
_hasPrivate = true;
|
||||||
|
memcpy(&_priv,data + ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1,ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE);
|
||||||
|
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));
|
||||||
|
} else if (privlen == 0) {
|
||||||
|
_hasPrivate = false;
|
||||||
|
return (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 2);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize this identity (binary)
|
* Serialize this identity (binary)
|
||||||
*
|
*
|
||||||
|
@ -274,7 +360,7 @@ public:
|
||||||
} else {
|
} else {
|
||||||
b.append((uint8_t)0);
|
b.append((uint8_t)0);
|
||||||
}
|
}
|
||||||
b.append((uint16_t)0); // size of additional fields (should have included such a thing in v0!)
|
b.append((uint8_t)0); // size of additional fields (should have included such a thing in v0!)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -332,7 +418,7 @@ public:
|
||||||
} else {
|
} else {
|
||||||
_hasPrivate = false;
|
_hasPrivate = false;
|
||||||
}
|
}
|
||||||
p += b.template at<uint16_t>(p) + 2;
|
p += b.template at<uint8_t>(p) + 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -489,7 +489,8 @@ struct InetAddress : public sockaddr_storage
|
||||||
*/
|
*/
|
||||||
inline operator bool() const { return (ss_family != 0); }
|
inline operator bool() const { return (ss_family != 0); }
|
||||||
|
|
||||||
inline unsigned int marshal(uint8_t restrict data[20]) const
|
static inline int marshalSizeMax() { return 19; }
|
||||||
|
inline int marshal(uint8_t restrict data[19]) const
|
||||||
{
|
{
|
||||||
switch(ss_family) {
|
switch(ss_family) {
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
|
@ -515,37 +516,36 @@ struct InetAddress : public sockaddr_storage
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
inline int unmarshal(const uint8_t *restrict data,const int len)
|
||||||
inline bool unmarshal(const uint8_t *restrict data,const unsigned int len)
|
|
||||||
{
|
{
|
||||||
if (len) {
|
if (len <= 0)
|
||||||
memset(this,0,sizeof(InetAddress));
|
return -1;
|
||||||
switch(data[0]) {
|
switch(data[0]) {
|
||||||
case 0:
|
case 0:
|
||||||
return true;
|
return 1;
|
||||||
case 4:
|
case 4:
|
||||||
if (len != 7)
|
if (len < 7)
|
||||||
return false;
|
return -1;
|
||||||
reinterpret_cast<sockaddr_in *>(this)->sin_family = AF_INET;
|
memset(this,0,sizeof(InetAddress));
|
||||||
reinterpret_cast<uint8_t *>(&(reinterpret_cast<sockaddr_in *>(this)->sin_addr.s_addr))[0] = data[1];
|
reinterpret_cast<sockaddr_in *>(this)->sin_family = AF_INET;
|
||||||
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))[0] = data[1];
|
||||||
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))[1] = data[2];
|
||||||
reinterpret_cast<uint8_t *>(&(reinterpret_cast<sockaddr_in *>(this)->sin_addr.s_addr))[3] = data[4];
|
reinterpret_cast<uint8_t *>(&(reinterpret_cast<sockaddr_in *>(this)->sin_addr.s_addr))[2] = data[3];
|
||||||
reinterpret_cast<sockaddr_in *>(this)->sin_port = Utils::hton((((uint16_t)data[5]) << 8) | (uint16_t)data[6]);
|
reinterpret_cast<uint8_t *>(&(reinterpret_cast<sockaddr_in *>(this)->sin_addr.s_addr))[3] = data[4];
|
||||||
return true;
|
reinterpret_cast<sockaddr_in *>(this)->sin_port = Utils::hton((((uint16_t)data[5]) << 8) | (uint16_t)data[6]);
|
||||||
case 6:
|
return 7;
|
||||||
if (len != 19)
|
case 6:
|
||||||
return false;
|
if (len < 19)
|
||||||
reinterpret_cast<sockaddr_in6 *>(this)->sin6_family = AF_INET6;
|
return -1;
|
||||||
for(int i=0;i<16;i++)
|
memset(this,0,sizeof(InetAddress));
|
||||||
(reinterpret_cast<sockaddr_in6 *>(this)->sin6_addr.s6_addr)[i] = data[i+1];
|
reinterpret_cast<sockaddr_in6 *>(this)->sin6_family = AF_INET6;
|
||||||
reinterpret_cast<sockaddr_in6 *>(this)->sin6_port = Utils::hton((((uint16_t)data[17]) << 8) | (uint16_t)data[18]);
|
for(int i=0;i<16;i++)
|
||||||
return true;
|
(reinterpret_cast<sockaddr_in6 *>(this)->sin6_addr.s6_addr)[i] = data[i+1];
|
||||||
default:
|
reinterpret_cast<sockaddr_in6 *>(this)->sin6_port = Utils::hton((((uint16_t)data[17]) << 8) | (uint16_t)data[18]);
|
||||||
return false;
|
return 19;
|
||||||
}
|
default:
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<unsigned int C>
|
template<unsigned int C>
|
||||||
|
|
173
node/Locator.hpp
173
node/Locator.hpp
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include "Constants.hpp"
|
#include "Constants.hpp"
|
||||||
#include "Endpoint.hpp"
|
#include "Endpoint.hpp"
|
||||||
|
#include "Identity.hpp"
|
||||||
|
|
||||||
#define ZT_LOCATOR_MAX_ENDPOINTS 8
|
#define ZT_LOCATOR_MAX_ENDPOINTS 8
|
||||||
|
|
||||||
|
@ -29,26 +30,178 @@ namespace ZeroTier {
|
||||||
/**
|
/**
|
||||||
* Signed information about a node's location on the network
|
* Signed information about a node's location on the network
|
||||||
*
|
*
|
||||||
* A locator is a signed record that contains information about where a node
|
* A locator contains long-lived endpoints for a node such as IP/port pairs,
|
||||||
* may be found. It can contain static physical addresses or virtual ZeroTier
|
* URLs, or other nodes, and is signed by the node it describes.
|
||||||
* addresses of nodes that can forward to the target node. Locator records
|
|
||||||
* can be stored in signed DNS TXT record sets, in LF by roots, in caches,
|
|
||||||
* etc.
|
|
||||||
*/
|
*/
|
||||||
class Locator
|
class Locator
|
||||||
{
|
{
|
||||||
friend class SharedPtr<Locator>;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline Locator() : _ts(0),_signatureLength(0) {}
|
inline Locator() : _ts(0),_at(nullptr),_signatureLength(0) {}
|
||||||
|
inline ~Locator() { delete [] _at; }
|
||||||
|
|
||||||
|
inline Locator(const Locator &l) :
|
||||||
|
_ts(l._ts),
|
||||||
|
_id(l._id),
|
||||||
|
_at((l._endpointCount > 0) ? new Endpoint[l._endpointCount] : nullptr),
|
||||||
|
_endpointCount(l._endpointCount),
|
||||||
|
_signatureLength(l._signatureLength)
|
||||||
|
{
|
||||||
|
for(unsigned int i=0;i<_endpointCount;++i)
|
||||||
|
_at[i] = l._at[i];
|
||||||
|
memcpy(_signature,l._signature,_signatureLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Locator &operator=(const Locator &l)
|
||||||
|
{
|
||||||
|
_ts = l._ts;
|
||||||
|
_id = l._id;
|
||||||
|
delete [] _at;
|
||||||
|
_at = (l._endpointCount > 0) ? new Endpoint[l._endpointCount] : nullptr;
|
||||||
|
for(unsigned int i=0;i<l._endpointCount;++i)
|
||||||
|
_at[i] = l._at[i];
|
||||||
|
_endpointCount = l._endpointCount;
|
||||||
|
_signatureLength = l._signatureLength;
|
||||||
|
memcpy(_signature,l._signature,_signatureLength);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
inline int64_t timestamp() const { return _ts; }
|
inline int64_t timestamp() const { return _ts; }
|
||||||
inline const Identity &id() const { return _id; }
|
inline const Identity &id() const { return _id; }
|
||||||
|
|
||||||
inline operator bool() const { return (_ts != 0); }
|
/**
|
||||||
|
* Create and sign a Locator
|
||||||
|
*
|
||||||
|
* @param ts Timestamp
|
||||||
|
* @param id Identity (must include secret to allow signing)
|
||||||
|
* @param at Array of Endpoint objects specifying where this peer might be found
|
||||||
|
* @param endpointCount Number of endpoints (max: ZT_LOCATOR_MAX_ENDPOINTS)
|
||||||
|
* @return True if init and sign were successful
|
||||||
|
*/
|
||||||
inline bool create(const int64_t ts,const Identity &id,const Endpoint *restrict at,const unsigned int endpointCount)
|
inline bool create(const int64_t ts,const Identity &id,const Endpoint *restrict at,const unsigned int endpointCount)
|
||||||
{
|
{
|
||||||
|
if ((endpointCount > ZT_LOCATOR_MAX_ENDPOINTS)||(!id.hasPrivate()))
|
||||||
|
return false;
|
||||||
|
_ts = ts;
|
||||||
|
_id = id;
|
||||||
|
if (_at)
|
||||||
|
delete [] _at;
|
||||||
|
_at = new Endpoint[endpointCount];
|
||||||
|
for(unsigned int i=0;i<endpointCount;++i)
|
||||||
|
_at[i] = at[i];
|
||||||
|
_endpointCount = endpointCount;
|
||||||
|
|
||||||
|
uint8_t signData[ZT_LOCATOR_MARSHAL_SIZE_MAX];
|
||||||
|
const unsigned int signLen = marshal(signData,true);
|
||||||
|
if (signLen == 0)
|
||||||
|
return false;
|
||||||
|
if ((_signatureLength = id.sign(signData,signLen,_signature,sizeof(_signature))) == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify this Locator's validity and signature
|
||||||
|
*
|
||||||
|
* @return True if valid and signature checks out
|
||||||
|
*/
|
||||||
|
inline bool verify() 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline operator bool() const { return (_ts != 0); }
|
||||||
|
|
||||||
|
static inline int marshalSizeMax() { return ZT_LOCATOR_MARSHAL_SIZE_MAX; }
|
||||||
|
inline int marshal(uint8_t restrict data[ZT_LOCATOR_MARSHAL_SIZE_MAX],const bool excludeSignature = false) const
|
||||||
|
{
|
||||||
|
if ((_endpointCount > ZT_LOCATOR_MAX_ENDPOINTS)||(_signatureLength > ZT_SIGNATURE_BUFFER_SIZE))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
data[0] = (uint8_t)((uint64_t)_ts >> 56);
|
||||||
|
data[1] = (uint8_t)((uint64_t)_ts >> 48);
|
||||||
|
data[2] = (uint8_t)((uint64_t)_ts >> 40);
|
||||||
|
data[3] = (uint8_t)((uint64_t)_ts >> 32);
|
||||||
|
data[4] = (uint8_t)((uint64_t)_ts >> 24);
|
||||||
|
data[5] = (uint8_t)((uint64_t)_ts >> 16);
|
||||||
|
data[6] = (uint8_t)((uint64_t)_ts >> 8);
|
||||||
|
data[7] = (uint8_t)((uint64_t)_ts);
|
||||||
|
|
||||||
|
int p = _id.marshal(data + 8,false);
|
||||||
|
if (p <= 0)
|
||||||
|
return -1;
|
||||||
|
p += 8;
|
||||||
|
|
||||||
|
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 >> 8);
|
||||||
|
data[p++] = (uint8_t)_signatureLength;
|
||||||
|
memcpy(data + p,_signature,_signatureLength);
|
||||||
|
p += _signatureLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
inline int unmarshal(const uint8_t *restrict data,const int len)
|
||||||
|
{
|
||||||
|
if (len <= 8)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
uint64_t ts = ((uint64_t)data[0] << 56);
|
||||||
|
ts |= ((uint64_t)data[1] << 48);
|
||||||
|
ts |= ((uint64_t)data[2] << 40);
|
||||||
|
ts |= ((uint64_t)data[3] << 32);
|
||||||
|
ts |= ((uint64_t)data[4] << 24);
|
||||||
|
ts |= ((uint64_t)data[5] << 16);
|
||||||
|
ts |= ((uint64_t)data[6] << 8);
|
||||||
|
ts |= (uint64_t)data[7];
|
||||||
|
_ts = (int64_t)ts;
|
||||||
|
|
||||||
|
int p = _id.unmarshal(data + 8,len - 8);
|
||||||
|
if (p <= 0)
|
||||||
|
return -1;
|
||||||
|
p += 8;
|
||||||
|
|
||||||
|
if (p >= len)
|
||||||
|
return -1;
|
||||||
|
unsigned int ec = (int)data[p++];
|
||||||
|
if (ec > ZT_LOCATOR_MAX_ENDPOINTS)
|
||||||
|
return -1;
|
||||||
|
if (_at)
|
||||||
|
delete [] _at;
|
||||||
|
_at = new Endpoint[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 <<= 8;
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
Loading…
Add table
Reference in a new issue