mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-07-20 17:32:50 +02:00
160 lines
4.3 KiB
C++
160 lines
4.3 KiB
C++
/*
|
|
* Copyright (c)2013-2020 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: 2024-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 "Endpoint.hpp"
|
|
#include "Utils.hpp"
|
|
|
|
namespace ZeroTier {
|
|
|
|
Endpoint::Endpoint(const InetAddress &sa,const Protocol proto) noexcept // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
|
|
{
|
|
switch (sa.family()) {
|
|
case AF_INET:
|
|
_t = TYPE_INETADDR_V4;
|
|
break;
|
|
case AF_INET6:
|
|
_t = TYPE_INETADDR_V6;
|
|
break;
|
|
default:
|
|
_t = TYPE_NIL;
|
|
return;
|
|
}
|
|
_proto = proto;
|
|
asInetAddress(_v.sa) = sa;
|
|
}
|
|
|
|
bool Endpoint::operator==(const Endpoint &ep) const noexcept
|
|
{
|
|
if ((_t == ep._t)&&(_proto == ep._proto)) {
|
|
switch(_t) {
|
|
default:
|
|
return true;
|
|
case TYPE_ZEROTIER:
|
|
return ((_v.zt.address == ep._v.zt.address) && (memcmp(_v.zt.hash,ep._v.zt.hash,sizeof(_v.zt.hash)) == 0));
|
|
case TYPE_ETHERNET:
|
|
return memcmp(_v.eth,ep._v.eth,6) == 0;
|
|
case TYPE_INETADDR_V4:
|
|
case TYPE_INETADDR_V6:
|
|
return asInetAddress(_v.sa) == asInetAddress(ep._v.sa);
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Endpoint::operator<(const Endpoint &ep) const noexcept
|
|
{
|
|
if ((int)_t < (int)ep._t) {
|
|
return true;
|
|
} else if (_t == ep._t) {
|
|
if ((int)_proto < (int)ep._proto) {
|
|
return true;
|
|
} else {
|
|
switch (_t) {
|
|
case TYPE_ZEROTIER:
|
|
return (_v.zt.address < ep._v.zt.address) ? true : ((_v.zt.address == ep._v.zt.address) && (memcmp(_v.zt.hash,ep._v.zt.hash,sizeof(_v.zt.hash)) < 0));
|
|
case TYPE_ETHERNET:
|
|
return memcmp(_v.eth,ep._v.eth,6) < 0;
|
|
case TYPE_INETADDR_V4:
|
|
case TYPE_INETADDR_V6:
|
|
return asInetAddress(_v.sa) < asInetAddress(ep._v.sa);
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
int Endpoint::marshal(uint8_t data[ZT_ENDPOINT_MARSHAL_SIZE_MAX]) const noexcept
|
|
{
|
|
data[0] = (uint8_t)_t;
|
|
Utils::storeBigEndian(data + 1,(uint16_t)_proto);
|
|
Utils::storeBigEndian(data + 3,(uint16_t)_l[0]);
|
|
Utils::storeBigEndian(data + 5,(uint16_t)_l[1]);
|
|
Utils::storeBigEndian(data + 7,(uint16_t)_l[2]);
|
|
|
|
int p;
|
|
switch(_t) {
|
|
case TYPE_ZEROTIER:
|
|
data[9] = (uint8_t)(_v.zt.address >> 32U);
|
|
data[10] = (uint8_t)(_v.zt.address >> 24U);
|
|
data[11] = (uint8_t)(_v.zt.address >> 16U);
|
|
data[12] = (uint8_t)(_v.zt.address >> 8U);
|
|
data[13] = (uint8_t)_v.zt.address;
|
|
Utils::copy<ZT_FINGERPRINT_HASH_SIZE>(data + 14,_v.zt.hash);
|
|
return ZT_FINGERPRINT_HASH_SIZE + 14;
|
|
case TYPE_ETHERNET:
|
|
Utils::copy<6>(data + 9,_v.eth);
|
|
return 15;
|
|
case TYPE_INETADDR_V4:
|
|
case TYPE_INETADDR_V6:
|
|
p = 9 + asInetAddress(_v.sa).marshal(data + 7);
|
|
if (p <= 9)
|
|
return -1;
|
|
return p;
|
|
default:
|
|
data[0] = (uint8_t)TYPE_NIL;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
int Endpoint::unmarshal(const uint8_t *restrict data,const int len) noexcept
|
|
{
|
|
if (len < 1)
|
|
return -1;
|
|
|
|
_t = (Type)data[0];
|
|
if (_t == TYPE_NIL)
|
|
return 1;
|
|
|
|
_proto = (Protocol)Utils::loadBigEndian<uint16_t>(data + 1);
|
|
_l[0] = (int)Utils::loadBigEndian<uint16_t>(data + 3);
|
|
_l[1] = (int)Utils::loadBigEndian<uint16_t>(data + 5);
|
|
_l[2] = (int)Utils::loadBigEndian<uint16_t>(data + 7);
|
|
|
|
int p;
|
|
switch(_t) {
|
|
case TYPE_ZEROTIER:
|
|
if (len < (14 + ZT_FINGERPRINT_HASH_SIZE))
|
|
return -1;
|
|
_v.zt.address = ((uint64_t)data[9]) << 32U;
|
|
_v.zt.address |= ((uint64_t)data[10]) << 24U;
|
|
_v.zt.address |= ((uint64_t)data[11]) << 16U;
|
|
_v.zt.address |= ((uint64_t)data[12]) << 8U;
|
|
_v.zt.address |= (uint64_t)data[13];
|
|
Utils::copy<ZT_FINGERPRINT_HASH_SIZE>(_v.zt.hash,data + 14);
|
|
return ZT_FINGERPRINT_HASH_SIZE + 14;
|
|
case TYPE_ETHERNET:
|
|
if (len < 15)
|
|
return -1;
|
|
Utils::copy<6>(_v.eth,data + 9);
|
|
return 15;
|
|
case TYPE_INETADDR_V4:
|
|
case TYPE_INETADDR_V6:
|
|
if (len <= 9)
|
|
return -1;
|
|
p = 9 + asInetAddress(_v.sa).unmarshal(data + 9,len - 9);
|
|
if ((p <= 9)||(p >= len))
|
|
return -1;
|
|
return p;
|
|
default:
|
|
// Unrecognized endpoint types not yet specified must start with a 16-bit
|
|
// length so that older versions of ZeroTier can skip them.
|
|
if (len < 11)
|
|
return -1;
|
|
p = 11 + (int)Utils::loadBigEndian<uint16_t>(data + 9);
|
|
return (p > len) ? -1 : p;
|
|
}
|
|
}
|
|
|
|
} // namespace ZeroTier
|