mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-05 03:53:44 +02:00
Move self-test so it can be called from CLI and always builds, implement Endpoint and Locator deserialization in Go as well as C++.
This commit is contained in:
parent
cba7a5d4d7
commit
b2f0b35608
20 changed files with 718 additions and 628 deletions
|
@ -177,7 +177,3 @@ add_custom_command(
|
|||
DEPENDS zt_osdep zt_core zt_go_native
|
||||
)
|
||||
add_custom_target(build_zerotier ALL DEPENDS zerotier)
|
||||
|
||||
add_executable(zerotier-selftest selftest.cpp)
|
||||
target_link_libraries(zerotier-selftest ${libs} zt_core zt_osdep)
|
||||
target_compile_features(zerotier-selftest PUBLIC cxx_std_11)
|
||||
|
|
|
@ -37,14 +37,17 @@ Global Options:
|
|||
Commands:
|
||||
help Show this help
|
||||
version Print version
|
||||
service Start in system service mode
|
||||
status Show ZeroTier service status and config
|
||||
selftest Run internal tests
|
||||
service [mode] Start as service (default mode: node)
|
||||
node Start in normal node mode (default)
|
||||
root [options] Start in root server mode (see docs)
|
||||
status Show ZeroTier status and config
|
||||
peers Show VL1 peers
|
||||
roots Show configured VL1 root servers
|
||||
addroot <identity> Add VL1 root server
|
||||
addroot <url|identity> [ip/port] [...] Add VL1 root server
|
||||
removeroot <identity|address> Remove VL1 root server
|
||||
identity <command> [args] Identity management commands
|
||||
new [c25519|p384] Create new identity (including secret)
|
||||
new [c25519|p384] Create identity (including secret)
|
||||
getpublic <identity> Extract only public part of identity
|
||||
validate <identity> Locally validate an identity
|
||||
sign <identity> <file> Sign a file with an identity's key
|
||||
|
@ -56,7 +59,7 @@ Commands:
|
|||
set <network ID> <option> <value> Set a network local config option
|
||||
manageips <boolean> Is IP management allowed?
|
||||
manageroutes <boolean> Is route management allowed?
|
||||
globalips <boolean> Can IPs in global IP space be managed?
|
||||
globalips <boolean> Allow assignment of global IPs?
|
||||
globalroutes <boolean> Can global IP space routes be set?
|
||||
defaultroute <boolean> Can default route be overridden?
|
||||
set <local config option> <value> Set a local configuration option
|
||||
|
@ -67,8 +70,7 @@ Commands:
|
|||
secondaryport <port/0> Set or disable secondary VL1 P2P port
|
||||
tertiaryport <port/0> Set or disable tertiary VL1 P2P port
|
||||
portsearch <boolean> Set or disable port search on startup
|
||||
portmapping <boolean> Set or disable use of uPnP and NAT-PMP
|
||||
explicitaddresses <IP/port> [...] Set explicit external IPs to advertise
|
||||
portmapping <boolean> Set or disable use of uPnP/NAT-PMP
|
||||
|
||||
Most commands require a secret token to permit control of a running ZeroTier
|
||||
service. The CLI will automatically try to read this token from the
|
||||
|
|
30
go/cmd/zerotier/cli/selftest.go
Normal file
30
go/cmd/zerotier/cli/selftest.go
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
/****/
|
||||
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"zerotier/pkg/zerotier"
|
||||
)
|
||||
|
||||
func SelfTest() {
|
||||
fmt.Print("Running ZeroTier core tests...\n\n")
|
||||
if !zerotier.CSelfTest() {
|
||||
fmt.Println("FAILED: at least one ZeroTier core test reported failure.")
|
||||
os.Exit(1)
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
|
@ -110,6 +110,9 @@ func main() {
|
|||
case "version":
|
||||
fmt.Printf("%d.%d.%d\n", zerotier.CoreVersionMajor, zerotier.CoreVersionMinor, zerotier.CoreVersionRevision)
|
||||
os.Exit(0)
|
||||
case "selftest":
|
||||
cli.SelfTest()
|
||||
os.Exit(0)
|
||||
case "service":
|
||||
cli.Service(basePath, authToken, cmdArgs)
|
||||
case "status":
|
||||
|
|
|
@ -3,6 +3,7 @@ project(zt_go_native)
|
|||
|
||||
set(src
|
||||
GoGlue.cpp
|
||||
CoreTests.cpp
|
||||
)
|
||||
|
||||
set(headers
|
||||
|
|
|
@ -11,41 +11,33 @@
|
|||
*/
|
||||
/****/
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <thread>
|
||||
|
||||
#include "node/Constants.hpp"
|
||||
#include "node/Hashtable.hpp"
|
||||
#include "node/RuntimeEnvironment.hpp"
|
||||
#include "node/InetAddress.hpp"
|
||||
#include "node/Utils.hpp"
|
||||
#include "node/Identity.hpp"
|
||||
#include "node/Buffer.hpp"
|
||||
#include "node/Packet.hpp"
|
||||
#include "node/Salsa20.hpp"
|
||||
#include "node/AES.hpp"
|
||||
#include "node/Locator.hpp"
|
||||
#include "node/MAC.hpp"
|
||||
#include "node/NetworkConfig.hpp"
|
||||
#include "node/Peer.hpp"
|
||||
#include "node/Dictionary.hpp"
|
||||
#include "node/SHA512.hpp"
|
||||
#include "node/C25519.hpp"
|
||||
#include "node/ECC384.hpp"
|
||||
#include "node/Poly1305.hpp"
|
||||
#include "node/CertificateOfMembership.hpp"
|
||||
#include "node/Node.hpp"
|
||||
#include "node/IncomingPacket.hpp"
|
||||
#include "GoGlue.h"
|
||||
|
||||
#include "osdep/OSUtils.hpp"
|
||||
#include "../../node/Constants.hpp"
|
||||
#include "../../node/InetAddress.hpp"
|
||||
#include "../../node/Utils.hpp"
|
||||
#include "../../node/Identity.hpp"
|
||||
#include "../../node/Buffer.hpp"
|
||||
#include "../../node/Salsa20.hpp"
|
||||
#include "../../node/AES.hpp"
|
||||
#include "../../node/Locator.hpp"
|
||||
#include "../../node/NetworkConfig.hpp"
|
||||
#include "../../node/Dictionary.hpp"
|
||||
#include "../../node/SHA512.hpp"
|
||||
#include "../../node/C25519.hpp"
|
||||
#include "../../node/ECC384.hpp"
|
||||
#include "../../node/Poly1305.hpp"
|
||||
|
||||
#include "../../osdep/OSUtils.hpp"
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
#include <tchar.h>
|
||||
|
@ -53,10 +45,8 @@
|
|||
|
||||
using namespace ZeroTier;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define KNOWN_GOOD_IDENTITY "8e4df28b72:0:ac3d46abe0c21f3cfe7a6c8d6a85cfcffcb82fbd55af6a4d6350657c68200843fa2e16f9418bbd9702cae365f2af5fb4c420908b803a681d4daef6114d78a2d7:bd8dd6e4ce7022d2f812797a80c6ee8ad180dc4ebf301dec8b06d1be08832bddd63a2f1cfa7b2c504474c75bdc8898ba476ef92e8e2d0509f8441985171ff16e"
|
||||
#define KNOWN_BAD_IDENTITY "9e4df28b72:0:ac3d46abe0c21f3cfe7a6c8d6a85cfcffcb82fbd55af6a4d6350657c68200843fa2e16f9418bbd9702cae365f2af5fb4c420908b803a681d4daef6114d78a2d7:bd8dd6e4ce7022d2f812797a80c6ee8ad180dc4ebf301dec8b06d1be08832bddd63a2f1cfa7b2c504474c75bdc8898ba476ef92e8e2d0509f8441985171ff16e"
|
||||
#define KNOWN_GOOD_IDENTITY_0 "8e4df28b72:0:ac3d46abe0c21f3cfe7a6c8d6a85cfcffcb82fbd55af6a4d6350657c68200843fa2e16f9418bbd9702cae365f2af5fb4c420908b803a681d4daef6114d78a2d7:bd8dd6e4ce7022d2f812797a80c6ee8ad180dc4ebf301dec8b06d1be08832bddd63a2f1cfa7b2c504474c75bdc8898ba476ef92e8e2d0509f8441985171ff16e"
|
||||
#define KNOWN_BAD_IDENTITY_0 "9e4df28b72:0:ac3d46abe0c21f3cfe7a6c8d6a85cfcffcb82fbd55af6a4d6350657c68200843fa2e16f9418bbd9702cae365f2af5fb4c420908b803a681d4daef6114d78a2d7:bd8dd6e4ce7022d2f812797a80c6ee8ad180dc4ebf301dec8b06d1be08832bddd63a2f1cfa7b2c504474c75bdc8898ba476ef92e8e2d0509f8441985171ff16e"
|
||||
|
||||
// These were generated with some Go code using the NIST P-384 elliptic curve. There
|
||||
// are official P-384 test vectors but the format of these is funny and converting is
|
||||
|
@ -153,9 +143,7 @@ static const uint8_t AES_GMAC_VECTOR_2_IV[12] = { 0x00,0x01,0x02,0x03,0x04,0x05,
|
|||
static const uint8_t AES_GMAC_VECTOR_2_IN[541] = { 0xc8,0x36,0x38,0xe8,0x53,0xc8,0x86,0xa3,0xe3,0xad,0x9e,0x2a,0x91,0x47,0xb9,0x51,0xad,0xf7,0x78,0x89,0x9a,0xeb,0x80,0x41,0x67,0xa9,0x16,0xc4,0x93,0xcc,0x77,0x3d,0x8c,0xcf,0x4d,0xb5,0x0b,0xda,0xfd,0xc2,0x8c,0x83,0x5d,0x66,0x43,0x74,0x21,0xbd,0xc4,0xab,0x41,0xd8,0x40,0x53,0x34,0xe8,0x05,0xcb,0x89,0x45,0x09,0xb0,0xa4,0xa6,0x04,0x95,0x19,0x2c,0xab,0x94,0xe1,0x8d,0x7b,0x59,0x8b,0xb9,0x31,0xae,0x3c,0x25,0xd3,0x23,0xab,0x8f,0x95,0xa3,0x8b,0xa5,0xc1,0x66,0x8b,0x57,0xe4,0x88,0x70,0xc9,0xe0,0xa1,0x16,0x39,0xf8,0x12,0xb3,0xe5,0x95,0x38,0x3a,0x01,0x1d,0xcc,0xc0,0xc3,0xa9,0x1c,0x72,0xa7,0x46,0x79,0x51,0x05,0xb2,0x85,0x5a,0x97,0x16,0x97,0xa6,0x85,0xa4,0xf2,0x0b,0x3c,0x90,0x52,0xa3,0xe0,0xbe,0xad,0x06,0x1b,0x8e,0x04,0x22,0xeb,0x3a,0x48,0xb9,0x84,0x24,0x0b,0x24,0x42,0xd9,0xed,0x6b,0x5c,0xc1,0xb6,0x2e,0xa5,0xc0,0x07,0xfe,0x3e,0xbc,0x9a,0x92,0x26,0xb5,0xa6,0x5f,0x09,0x13,0x85,0x5a,0xcf,0x61,0x56,0x65,0x0f,0x4c,0x64,0x79,0xfa,0x0a,0xcf,0xc0,0x95,0x8d,0x4d,0xc6,0xbe,0xee,0xb3,0x67,0xd8,0xa7,0x40,0x90,0x61,0xe3,0xba,0xcb,0x18,0xe0,0x61,0x7b,0x33,0x86,0xf7,0xef,0x64,0xe5,0x36,0xf0,0x9c,0xb6,0x34,0xb1,0xe1,0x2a,0xd8,0xd8,0x5e,0x6b,0x61,0x92,0xa0,0x8e,0x04,0x7b,0xbf,0xa5,0x84,0x39,0x3a,0xe0,0x27,0xc7,0xb0,0x83,0x88,0x4f,0x3e,0x49,0x14,0xaa,0x34,0xde,0xb4,0xbb,0x4c,0xe4,0xbf,0xae,0x9a,0xf9,0x88,0x7a,0x1f,0x18,0xa0,0x8c,0x60,0xc0,0x5c,0x46,0xa1,0xd1,0x36,0x99,0x60,0x9b,0x73,0xa2,0x9a,0x0b,0x8d,0x6e,0x2f,0xe1,0x58,0x7a,0x39,0x71,0xed,0xfc,0x34,0xe4,0x98,0x57,0x7e,0x86,0xf1,0xe5,0x00,0x7d,0x1b,0x6a,0xfa,0xf8,0x6e,0x7b,0x12,0x44,0x04,0x60,0x02,0x81,0x12,0x09,0x00,0xb4,0x35,0x9e,0x03,0x73,0x79,0x9b,0x13,0xc5,0xd7,0x0e,0xce,0x49,0x87,0x48,0x1a,0x67,0x89,0x93,0xef,0xd1,0xdf,0x2d,0x48,0x6d,0x30,0xd5,0xec,0x49,0xfe,0x15,0x1b,0xa6,0x2b,0x6c,0x08,0x8e,0x39,0x73,0x68,0x87,0xa7,0x43,0x28,0x16,0x77,0x86,0xd1,0xcb,0x13,0xe4,0xd3,0xda,0x63,0xcd,0x3a,0x2a,0x35,0xd5,0xfa,0x36,0x67,0xc8,0x4c,0x6b,0xa1,0x8a,0xaf,0x7b,0x4c,0x43,0xb0,0x2f,0x4a,0xcc,0xc0,0x11,0xc6,0x30,0x8e,0xa3,0xd2,0x4a,0x1b,0x2a,0x4f,0xec,0x97,0x83,0xa6,0x4c,0xee,0x51,0xaf,0x06,0x0a,0x1d,0x80,0xd9,0xcf,0xb7,0x69,0x23,0x15,0x3a,0x26,0x04,0x34,0x33,0x76,0x30,0x9f,0xfb,0x56,0xb4,0x26,0xee,0xfa,0x54,0x6c,0x18,0xf9,0xd5,0x32,0x5d,0x03,0xcb,0x2c,0x20,0x30,0x0c,0xa0,0xbb,0xde,0x01,0x77,0x65,0xb0,0x18,0x30,0xd2,0x55,0x9f,0x9b,0xcf,0xb8,0x9b,0xb4,0xbc,0x0b,0x49,0x52,0x53,0x30,0x48,0xa5,0x12,0xe5,0x3b,0x47,0x84,0xff,0xf1,0x53,0x5d,0x5c,0x04,0x70,0x63,0x91,0xc3,0xc0,0xf0,0xea,0xcb,0x44,0x4f,0x8c,0x85,0x42,0x6a,0xc7,0xfa,0xc7,0xb5,0x30,0x03,0x12,0x65,0xca,0xba,0x4f,0x67,0xbb,0xef,0xb6,0xc6,0x3f,0x19,0xe2,0xb5,0x4b,0x8c,0xfc,0x9e,0x18,0xb0,0x33,0x89,0x6e,0xde,0x61,0x0a,0xe3,0x5e,0xa3,0x5d,0x2e,0x80,0x3e,0x53,0x67,0xfb,0x7b,0x7a,0xbf,0xd5,0xf4,0x47 };
|
||||
static const uint8_t AES_GMAC_VECTOR_2_OUT[16] = { 0x67,0x39,0x4f,0x00,0x04,0x28,0xaf,0xe9,0xb4,0x2e,0xb5,0x3c,0x42,0x24,0x86,0xa3 };
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static int testCrypto()
|
||||
extern "C" int ZT_TestCrypto()
|
||||
{
|
||||
static uint8_t buf1[16384],buf2[16384],buf3[16384];
|
||||
static char hexbuf[1024];
|
||||
|
@ -508,14 +496,14 @@ static int testCrypto()
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int testIdentity()
|
||||
extern "C" int ZT_TestIdentity()
|
||||
{
|
||||
Identity id;
|
||||
Buffer<512> buf;
|
||||
char buf2[1024];
|
||||
|
||||
std::cout << "[identity] Validate known-good identity... "; std::cout.flush();
|
||||
if (!id.fromString(KNOWN_GOOD_IDENTITY)) {
|
||||
if (!id.fromString(KNOWN_GOOD_IDENTITY_0)) {
|
||||
std::cout << "FAIL (1)" ZT_EOL_S;
|
||||
return -1;
|
||||
}
|
||||
|
@ -530,7 +518,7 @@ static int testIdentity()
|
|||
std::cout << "PASS (" << ((double)(vet - vst) / 10.0) << "ms per validation)" ZT_EOL_S;
|
||||
|
||||
std::cout << "[identity] Validate known-bad identity... "; std::cout.flush();
|
||||
if (!id.fromString(KNOWN_BAD_IDENTITY)) {
|
||||
if (!id.fromString(KNOWN_BAD_IDENTITY_0)) {
|
||||
std::cout << "FAIL (1)" ZT_EOL_S;
|
||||
return -1;
|
||||
}
|
||||
|
@ -613,114 +601,7 @@ static int testIdentity()
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int testCertificate()
|
||||
{
|
||||
char buf[4096];
|
||||
|
||||
Identity authority;
|
||||
std::cout << "[certificate] Generating identity to act as authority... "; std::cout.flush();
|
||||
authority.generate(Identity::C25519);
|
||||
std::cout << authority.address().toString(buf) << ZT_EOL_S;
|
||||
|
||||
Identity idA,idB;
|
||||
std::cout << "[certificate] Generating identities A and B... "; std::cout.flush();
|
||||
idA.generate(Identity::C25519);
|
||||
idB.generate(Identity::C25519);
|
||||
std::cout << idA.address().toString(buf) << ", " << idB.address().toString(buf) << ZT_EOL_S;
|
||||
|
||||
std::cout << "[certificate] Generating certificates A and B...";
|
||||
CertificateOfMembership cA(10000,100,1,idA.address());
|
||||
CertificateOfMembership cB(10099,100,1,idB.address());
|
||||
std::cout << ZT_EOL_S;
|
||||
|
||||
std::cout << "[certificate] Signing certificates A and B with authority...";
|
||||
cA.sign(authority);
|
||||
cB.sign(authority);
|
||||
std::cout << ZT_EOL_S;
|
||||
|
||||
//std::cout << "[certificate] A: " << cA.toString() << ZT_EOL_S;
|
||||
//std::cout << "[certificate] B: " << cB.toString() << ZT_EOL_S;
|
||||
|
||||
std::cout << "[certificate] A agrees with B and B with A... ";
|
||||
if (cA.agreesWith(cB))
|
||||
std::cout << "yes, ";
|
||||
else {
|
||||
std::cout << "FAIL" ZT_EOL_S;
|
||||
return -1;
|
||||
}
|
||||
if (cB.agreesWith(cA))
|
||||
std::cout << "yes." ZT_EOL_S;
|
||||
else {
|
||||
std::cout << "FAIL" ZT_EOL_S;
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::cout << "[certificate] Generating two certificates that should not agree...";
|
||||
cA = CertificateOfMembership(10000,100,1,idA.address());
|
||||
cB = CertificateOfMembership(10101,100,1,idB.address());
|
||||
std::cout << ZT_EOL_S;
|
||||
|
||||
std::cout << "[certificate] A agrees with B and B with A... ";
|
||||
if (!cA.agreesWith(cB))
|
||||
std::cout << "no, ";
|
||||
else {
|
||||
std::cout << "FAIL" ZT_EOL_S;
|
||||
return -1;
|
||||
}
|
||||
if (!cB.agreesWith(cA))
|
||||
std::cout << "no." ZT_EOL_S;
|
||||
else {
|
||||
std::cout << "FAIL" ZT_EOL_S;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int testPacket()
|
||||
{
|
||||
unsigned char salsaKey[32];
|
||||
Packet a,b;
|
||||
|
||||
a.burn();
|
||||
b.burn();
|
||||
|
||||
for(unsigned int i=0;i<32;++i)
|
||||
salsaKey[i] = (unsigned char)rand();
|
||||
|
||||
std::cout << "[packet] Testing Packet encoder/decoder... ";
|
||||
|
||||
a.reset(Address(),Address(),Packet::VERB_HELLO);
|
||||
for(int i=0;i<32;++i)
|
||||
a.append("supercalifragilisticexpealidocious",(unsigned int)strlen("supercalifragilisticexpealidocious"));
|
||||
|
||||
b = a;
|
||||
if (a != b) {
|
||||
std::cout << "FAIL (assign)" ZT_EOL_S;
|
||||
return -1;
|
||||
}
|
||||
|
||||
a.compress();
|
||||
unsigned int complen = a.size();
|
||||
a.uncompress();
|
||||
|
||||
std::cout << "(compressed: " << complen << ", decompressed: " << a.size() << ") ";
|
||||
if (a != b) {
|
||||
std::cout << "FAIL (compresssion)" ZT_EOL_S;
|
||||
return -1;
|
||||
}
|
||||
|
||||
a.armor(salsaKey,true);
|
||||
if (!a.dearmor(salsaKey)) {
|
||||
std::cout << "FAIL (encrypt-decrypt/verify)" ZT_EOL_S;
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::cout << "PASS" ZT_EOL_S;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int testOther()
|
||||
extern "C" int ZT_TestOther()
|
||||
{
|
||||
char buf[1024];
|
||||
char buf2[4096];
|
||||
|
@ -864,35 +745,3 @@ static int testOther()
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
int __cdecl _tmain(int argc, _TCHAR* argv[])
|
||||
#else
|
||||
int main(int argc,char **argv)
|
||||
#endif
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
WSADATA wsaData;
|
||||
WSAStartup(MAKEWORD(2,2),&wsaData);
|
||||
#endif
|
||||
|
||||
std::cout << "[info] sizeof(void *) == " << sizeof(void *) << ZT_EOL_S;
|
||||
std::cout << "[info] OSUtils::now() == " << OSUtils::now() << ZT_EOL_S;
|
||||
std::cout << "[info] hardware concurrency == " << std::thread::hardware_concurrency() << ZT_EOL_S;
|
||||
std::cout << "[info] sizeof(NetworkConfig) == " << sizeof(ZeroTier::NetworkConfig) << ZT_EOL_S;
|
||||
|
||||
srand((unsigned int)time(0));
|
||||
|
||||
r |= testOther();
|
||||
r |= testCrypto();
|
||||
r |= testPacket();
|
||||
r |= testIdentity();
|
||||
r |= testCertificate();
|
||||
|
||||
if (r)
|
||||
std::cout << ZT_EOL_S << "SOMETHING FAILED!" ZT_EOL_S;
|
||||
|
||||
return r;
|
||||
}
|
|
@ -49,10 +49,10 @@ void ZT_GoNode_delete(ZT_GoNode *gn);
|
|||
ZT_Node *ZT_GoNode_getNode(ZT_GoNode *gn);
|
||||
|
||||
/* This can be called more than once to start multiple listener threads */
|
||||
int ZT_GoNode_phyStartListen(ZT_GoNode *gn,const char *dev,const char *ip,const int port);
|
||||
int ZT_GoNode_phyStartListen(ZT_GoNode *gn,const char *dev,const char *ip,int port);
|
||||
|
||||
/* Close all listener threads for a given local IP and port */
|
||||
int ZT_GoNode_phyStopListen(ZT_GoNode *gn,const char *dev,const char *ip,const int port);
|
||||
int ZT_GoNode_phyStopListen(ZT_GoNode *gn,const char *dev,const char *ip,int port);
|
||||
|
||||
ZT_GoTap *ZT_GoNode_join(ZT_GoNode *gn,uint64_t nwid);
|
||||
|
||||
|
@ -84,6 +84,11 @@ int ZT_GoTap_addRoute(ZT_GoTap *tap,int targetAf,const void *targetIp,int target
|
|||
|
||||
int ZT_GoTap_removeRoute(ZT_GoTap *tap,int targetAf,const void *targetIp,int targetNetmaskBits,int viaAf,const void *viaIp,unsigned int metric);
|
||||
|
||||
/* Core self-tests that output results to stdout and return non-zero on failure. */
|
||||
int ZT_TestCrypto();
|
||||
int ZT_TestIdentity();
|
||||
int ZT_TestOther();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
115
go/pkg/zerotier/endpoint.go
Normal file
115
go/pkg/zerotier/endpoint.go
Normal file
|
@ -0,0 +1,115 @@
|
|||
package zerotier
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
)
|
||||
|
||||
// Endpoint types are the same as the enum values in Endpoint.hpp in the core.
|
||||
const (
|
||||
EndpointTypeNil = 0
|
||||
EndpointTypeInetAddr = 1
|
||||
EndpointTypeDnsName = 2
|
||||
EndpointTypeZeroTier = 3
|
||||
EndpointTypeUrl = 4
|
||||
EndpointTypeEthernet = 5
|
||||
EndpointTypeUnrecognized = 255
|
||||
)
|
||||
|
||||
type Endpoint struct {
|
||||
Type int
|
||||
value, value2 interface{}
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidEndpoint = errors.New("invalid marshaled endpoint object")
|
||||
)
|
||||
|
||||
func (ep *Endpoint) unmarshalZT(b []byte) (int, error) {
|
||||
if len(b) == 0 {
|
||||
return 0, ErrInvalidEndpoint
|
||||
}
|
||||
switch b[0] {
|
||||
case EndpointTypeNil:
|
||||
*ep = Endpoint{Type: EndpointTypeNil}
|
||||
return 1, nil
|
||||
case EndpointTypeInetAddr:
|
||||
ina := new(InetAddress)
|
||||
inlen, err := ina.unmarshalZT(b[1:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
*ep = Endpoint{
|
||||
Type: EndpointTypeInetAddr,
|
||||
value: ina,
|
||||
}
|
||||
return 1 + inlen, nil
|
||||
case EndpointTypeDnsName:
|
||||
zeroAt := 1
|
||||
for i := 1; i < len(b); i++ {
|
||||
if b[i] == 0 {
|
||||
zeroAt = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if zeroAt == 1 || (1 + zeroAt + 3) > len(b) {
|
||||
return 0, ErrInvalidEndpoint
|
||||
}
|
||||
port := binary.BigEndian.Uint16(b[zeroAt+1:zeroAt+3])
|
||||
*ep = Endpoint{
|
||||
Type: EndpointTypeDnsName,
|
||||
value: string(b[1:zeroAt]),
|
||||
value2: &port,
|
||||
}
|
||||
return zeroAt + 3, nil
|
||||
case EndpointTypeZeroTier:
|
||||
if len(b) != 54 {
|
||||
return 0, ErrInvalidEndpoint
|
||||
}
|
||||
a, err := NewAddressFromBytes(b[1:6])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
*ep = Endpoint{
|
||||
Type: EndpointTypeZeroTier,
|
||||
value: a,
|
||||
value2: append(make([]byte, 0, 48), b[6:54]...),
|
||||
}
|
||||
return 54, nil
|
||||
case EndpointTypeUrl:
|
||||
zeroAt := 1
|
||||
for i := 1; i < len(b); i++ {
|
||||
if b[i] == 0 {
|
||||
zeroAt = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if zeroAt == 1 {
|
||||
return 0, ErrInvalidEndpoint
|
||||
}
|
||||
*ep = Endpoint{
|
||||
Type: EndpointTypeUrl,
|
||||
value: string(b[1:zeroAt]),
|
||||
}
|
||||
return zeroAt + 2, nil
|
||||
case EndpointTypeEthernet:
|
||||
if len(b) != 7 {
|
||||
return 0, ErrInvalidEndpoint
|
||||
}
|
||||
m, err := NewMACFromBytes(b[1:7])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
*ep = Endpoint{
|
||||
Type: EndpointTypeEthernet,
|
||||
value: m,
|
||||
}
|
||||
return 7, nil
|
||||
default:
|
||||
if len(b) < 2 {
|
||||
return 0, ErrInvalidEndpoint
|
||||
}
|
||||
*ep = Endpoint{Type: EndpointTypeUnrecognized}
|
||||
return 1 + int(b[1]), nil
|
||||
}
|
||||
}
|
|
@ -13,15 +13,87 @@
|
|||
|
||||
package zerotier
|
||||
|
||||
//#include "../../native/GoGlue.h"
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func sockaddrStorageToIPNet(ss *C.struct_sockaddr_storage) *net.IPNet {
|
||||
var a net.IPNet
|
||||
switch ss.ss_family {
|
||||
case AFInet:
|
||||
sa4 := (*C.struct_sockaddr_in)(unsafe.Pointer(ss))
|
||||
var ip4 [4]byte
|
||||
copy(ip4[:], (*[4]byte)(unsafe.Pointer(&sa4.sin_addr))[:])
|
||||
a.IP = ip4[:]
|
||||
a.Mask = net.CIDRMask(int(binary.BigEndian.Uint16(((*[2]byte)(unsafe.Pointer(&sa4.sin_port)))[:])), 32)
|
||||
return &a
|
||||
case AFInet6:
|
||||
sa6 := (*C.struct_sockaddr_in6)(unsafe.Pointer(ss))
|
||||
var ip6 [16]byte
|
||||
copy(ip6[:], (*[16]byte)(unsafe.Pointer(&sa6.sin6_addr))[:])
|
||||
a.IP = ip6[:]
|
||||
a.Mask = net.CIDRMask(int(binary.BigEndian.Uint16(((*[2]byte)(unsafe.Pointer(&sa6.sin6_port)))[:])), 128)
|
||||
return &a
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func sockaddrStorageToUDPAddr(ss *C.struct_sockaddr_storage) *net.UDPAddr {
|
||||
var a net.UDPAddr
|
||||
switch ss.ss_family {
|
||||
case AFInet:
|
||||
sa4 := (*C.struct_sockaddr_in)(unsafe.Pointer(ss))
|
||||
var ip4 [4]byte
|
||||
copy(ip4[:], (*[4]byte)(unsafe.Pointer(&sa4.sin_addr))[:])
|
||||
a.IP = ip4[:]
|
||||
a.Port = int(binary.BigEndian.Uint16(((*[2]byte)(unsafe.Pointer(&sa4.sin_port)))[:]))
|
||||
return &a
|
||||
case AFInet6:
|
||||
sa6 := (*C.struct_sockaddr_in6)(unsafe.Pointer(ss))
|
||||
var ip6 [16]byte
|
||||
copy(ip6[:], (*[16]byte)(unsafe.Pointer(&sa6.sin6_addr))[:])
|
||||
a.IP = ip6[:]
|
||||
a.Port = int(binary.BigEndian.Uint16(((*[2]byte)(unsafe.Pointer(&sa6.sin6_port)))[:]))
|
||||
return &a
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func sockaddrStorageToUDPAddr2(ss unsafe.Pointer) *net.UDPAddr {
|
||||
return sockaddrStorageToUDPAddr((*C.struct_sockaddr_storage)(ss))
|
||||
}
|
||||
|
||||
func makeSockaddrStorage(ip net.IP, port int, ss *C.struct_sockaddr_storage) bool {
|
||||
C.memset(unsafe.Pointer(ss), 0, C.sizeof_struct_sockaddr_storage)
|
||||
if len(ip) == 4 {
|
||||
sa4 := (*C.struct_sockaddr_in)(unsafe.Pointer(ss))
|
||||
sa4.sin_family = AFInet
|
||||
copy(((*[4]byte)(unsafe.Pointer(&sa4.sin_addr)))[:], ip)
|
||||
binary.BigEndian.PutUint16(((*[2]byte)(unsafe.Pointer(&sa4.sin_port)))[:], uint16(port))
|
||||
return true
|
||||
}
|
||||
if len(ip) == 16 {
|
||||
sa6 := (*C.struct_sockaddr_in6)(unsafe.Pointer(ss))
|
||||
sa6.sin6_family = AFInet6
|
||||
copy(((*[16]byte)(unsafe.Pointer(&sa6.sin6_addr)))[:], ip)
|
||||
binary.BigEndian.PutUint16(((*[2]byte)(unsafe.Pointer(&sa6.sin6_port)))[:], uint16(port))
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var ErrInvalidInetAddress = errors.New("invalid marshaled InetAddress object")
|
||||
|
||||
// InetAddress implements net.Addr but has a ZeroTier-like string representation
|
||||
type InetAddress struct {
|
||||
IP net.IP
|
||||
|
@ -29,13 +101,13 @@ type InetAddress struct {
|
|||
}
|
||||
|
||||
// Less returns true if this IP/port is lexicographically less than another
|
||||
func (i *InetAddress) Less(i2 *InetAddress) bool {
|
||||
c := bytes.Compare(i.IP, i2.IP)
|
||||
func (ina *InetAddress) Less(i2 *InetAddress) bool {
|
||||
c := bytes.Compare(ina.IP, i2.IP)
|
||||
if c < 0 {
|
||||
return true
|
||||
}
|
||||
if c == 0 {
|
||||
return i.Port < i2.Port
|
||||
return ina.Port < i2.Port
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
@ -73,18 +145,18 @@ func NewInetAddressFromSockaddr(sa unsafe.Pointer) *InetAddress {
|
|||
}
|
||||
|
||||
// Network returns "udp" to implement net.Addr
|
||||
func (i *InetAddress) Network() string {
|
||||
func (ina *InetAddress) Network() string {
|
||||
return "udp"
|
||||
}
|
||||
|
||||
// String returns this address in ZeroTier-canonical IP/port format
|
||||
func (i *InetAddress) String() string {
|
||||
return i.IP.String() + "/" + strconv.FormatInt(int64(i.Port), 10)
|
||||
func (ina *InetAddress) String() string {
|
||||
return ina.IP.String() + "/" + strconv.FormatInt(int64(ina.Port), 10)
|
||||
}
|
||||
|
||||
// Family returns the address family (AFInet etc.) or 0 if none
|
||||
func (i *InetAddress) Family() int {
|
||||
switch len(i.IP) {
|
||||
func (ina *InetAddress) Family() int {
|
||||
switch len(ina.IP) {
|
||||
case 4:
|
||||
return AFInet
|
||||
case 16:
|
||||
|
@ -94,30 +166,58 @@ func (i *InetAddress) Family() int {
|
|||
}
|
||||
|
||||
// Valid returns true if both the IP and port have valid values
|
||||
func (i *InetAddress) Valid() bool {
|
||||
return (len(i.IP) == 4 || len(i.IP) == 16) && (i.Port > 0 && i.Port < 65536)
|
||||
func (ina *InetAddress) Valid() bool {
|
||||
return (len(ina.IP) == 4 || len(ina.IP) == 16) && (ina.Port > 0 && ina.Port < 65536)
|
||||
}
|
||||
|
||||
// MarshalJSON marshals this MAC as a string
|
||||
func (i *InetAddress) MarshalJSON() ([]byte, error) {
|
||||
s := i.String()
|
||||
func (ina *InetAddress) MarshalJSON() ([]byte, error) {
|
||||
s := ina.String()
|
||||
return json.Marshal(&s)
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals this MAC from a string
|
||||
func (i *InetAddress) UnmarshalJSON(j []byte) error {
|
||||
func (ina *InetAddress) UnmarshalJSON(j []byte) error {
|
||||
var s string
|
||||
err := json.Unmarshal(j, &s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*i = *NewInetAddressFromString(s)
|
||||
*ina = *NewInetAddressFromString(s)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ina *InetAddress) unmarshalZT(b []byte) (int, error) {
|
||||
if len(b) <= 0 {
|
||||
return 0, ErrInvalidInetAddress
|
||||
}
|
||||
switch b[0] {
|
||||
case 0:
|
||||
ina.IP = nil
|
||||
ina.Port = 0
|
||||
return 1, nil
|
||||
case 4:
|
||||
if len(b) != 7 {
|
||||
return 0, ErrInvalidInetAddress
|
||||
}
|
||||
ina.IP = []byte{b[1], b[2], b[3], b[4]}
|
||||
ina.Port = int(binary.BigEndian.Uint16(b[5:7]))
|
||||
return 7, nil
|
||||
case 6:
|
||||
if len(b) != 19 {
|
||||
return 0, ErrInvalidInetAddress
|
||||
}
|
||||
ina.IP = append(make([]byte, 0, 16), b[1:17]...)
|
||||
ina.Port = int(binary.BigEndian.Uint16(b[17:19]))
|
||||
return 19, nil
|
||||
default:
|
||||
return 0, ErrInvalidInetAddress
|
||||
}
|
||||
}
|
||||
|
||||
// key returns a short array suitable for use as a map[] key for this IP
|
||||
func (i *InetAddress) key() (k [3]uint64) {
|
||||
copy(((*[16]byte)(unsafe.Pointer(&k[0])))[:], i.IP)
|
||||
k[2] = uint64(i.Port)
|
||||
func (ina *InetAddress) key() (k [3]uint64) {
|
||||
copy(((*[16]byte)(unsafe.Pointer(&k[0])))[:], ina.IP)
|
||||
k[2] = uint64(ina.Port)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -1,7 +1,46 @@
|
|||
package zerotier
|
||||
|
||||
type Locator struct {
|
||||
Timestamp int64
|
||||
Endpoints []InetAddress
|
||||
Bytes []byte
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
)
|
||||
|
||||
// Locator objects are signed collections of physical or virtual endpoints for a node.
|
||||
type Locator []byte
|
||||
|
||||
var (
|
||||
ErrInvalidLocator = errors.New("invalid marshaled locator object")
|
||||
)
|
||||
|
||||
func (l Locator) Timestamp() int64 {
|
||||
if len(l) >= 8 {
|
||||
return int64(binary.BigEndian.Uint64(l))
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Endpoints obtains the endpoints described by this locator.
|
||||
func (l Locator) Endpoints() (eps []Endpoint,err error) {
|
||||
if len(l) <= (8 + 2) {
|
||||
err = ErrInvalidLocator
|
||||
return
|
||||
}
|
||||
|
||||
endpointCount := int(binary.BigEndian.Uint16(l[8:10]))
|
||||
eps = make([]Endpoint,endpointCount)
|
||||
p := 10
|
||||
for e:=0;e<endpointCount;e++ {
|
||||
if p >= len(l) {
|
||||
err = ErrInvalidLocator
|
||||
return
|
||||
}
|
||||
var elen int
|
||||
elen, err = eps[e].unmarshalZT(l[p:])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
p += elen
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ import "C"
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
@ -87,73 +86,22 @@ var (
|
|||
nodesByUserPtrLock sync.RWMutex
|
||||
)
|
||||
|
||||
func sockaddrStorageToIPNet(ss *C.struct_sockaddr_storage) *net.IPNet {
|
||||
var a net.IPNet
|
||||
switch ss.ss_family {
|
||||
case AFInet:
|
||||
sa4 := (*C.struct_sockaddr_in)(unsafe.Pointer(ss))
|
||||
var ip4 [4]byte
|
||||
copy(ip4[:], (*[4]byte)(unsafe.Pointer(&sa4.sin_addr))[:])
|
||||
a.IP = ip4[:]
|
||||
a.Mask = net.CIDRMask(int(binary.BigEndian.Uint16(((*[2]byte)(unsafe.Pointer(&sa4.sin_port)))[:])), 32)
|
||||
return &a
|
||||
case AFInet6:
|
||||
sa6 := (*C.struct_sockaddr_in6)(unsafe.Pointer(ss))
|
||||
var ip6 [16]byte
|
||||
copy(ip6[:], (*[16]byte)(unsafe.Pointer(&sa6.sin6_addr))[:])
|
||||
a.IP = ip6[:]
|
||||
a.Mask = net.CIDRMask(int(binary.BigEndian.Uint16(((*[2]byte)(unsafe.Pointer(&sa6.sin6_port)))[:])), 128)
|
||||
return &a
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func sockaddrStorageToUDPAddr(ss *C.struct_sockaddr_storage) *net.UDPAddr {
|
||||
var a net.UDPAddr
|
||||
switch ss.ss_family {
|
||||
case AFInet:
|
||||
sa4 := (*C.struct_sockaddr_in)(unsafe.Pointer(ss))
|
||||
var ip4 [4]byte
|
||||
copy(ip4[:], (*[4]byte)(unsafe.Pointer(&sa4.sin_addr))[:])
|
||||
a.IP = ip4[:]
|
||||
a.Port = int(binary.BigEndian.Uint16(((*[2]byte)(unsafe.Pointer(&sa4.sin_port)))[:]))
|
||||
return &a
|
||||
case AFInet6:
|
||||
sa6 := (*C.struct_sockaddr_in6)(unsafe.Pointer(ss))
|
||||
var ip6 [16]byte
|
||||
copy(ip6[:], (*[16]byte)(unsafe.Pointer(&sa6.sin6_addr))[:])
|
||||
a.IP = ip6[:]
|
||||
a.Port = int(binary.BigEndian.Uint16(((*[2]byte)(unsafe.Pointer(&sa6.sin6_port)))[:]))
|
||||
return &a
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func sockaddrStorageToUDPAddr2(ss unsafe.Pointer) *net.UDPAddr {
|
||||
return sockaddrStorageToUDPAddr((*C.struct_sockaddr_storage)(ss))
|
||||
}
|
||||
|
||||
func makeSockaddrStorage(ip net.IP, port int, ss *C.struct_sockaddr_storage) bool {
|
||||
C.memset(unsafe.Pointer(ss), 0, C.sizeof_struct_sockaddr_storage)
|
||||
if len(ip) == 4 {
|
||||
sa4 := (*C.struct_sockaddr_in)(unsafe.Pointer(ss))
|
||||
sa4.sin_family = AFInet
|
||||
copy(((*[4]byte)(unsafe.Pointer(&sa4.sin_addr)))[:], ip)
|
||||
binary.BigEndian.PutUint16(((*[2]byte)(unsafe.Pointer(&sa4.sin_port)))[:], uint16(port))
|
||||
return true
|
||||
}
|
||||
if len(ip) == 16 {
|
||||
sa6 := (*C.struct_sockaddr_in6)(unsafe.Pointer(ss))
|
||||
sa6.sin6_family = AFInet6
|
||||
copy(((*[16]byte)(unsafe.Pointer(&sa6.sin6_addr)))[:], ip)
|
||||
binary.BigEndian.PutUint16(((*[2]byte)(unsafe.Pointer(&sa6.sin6_port)))[:], uint16(port))
|
||||
return true
|
||||
}
|
||||
// CSelfTest runs self-test functions from the core, sending results to stdout and returning true on success.
|
||||
func CSelfTest() bool {
|
||||
if C.ZT_TestOther() != 0 {
|
||||
return false
|
||||
}
|
||||
fmt.Println()
|
||||
if C.ZT_TestCrypto() != 0 {
|
||||
return false
|
||||
}
|
||||
fmt.Println()
|
||||
if C.ZT_TestIdentity() != 0 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Node is an instance of the ZeroTier core node and related C++ I/O code
|
||||
type Node struct {
|
||||
networks map[NetworkID]*Network
|
||||
|
|
|
@ -3,12 +3,12 @@ package zerotier
|
|||
// Root nodes are long-lived nodes at stable physical addresses that can help locate other nodes.
|
||||
type Root struct {
|
||||
// Identity is this root's address and public key(s).
|
||||
Identity Identity
|
||||
Identity Identity `json:"identity"`
|
||||
|
||||
// Locator describes the endpoints where this root may be found.
|
||||
Locator Locator
|
||||
Locator Locator `json:"locator"`
|
||||
|
||||
// URL is an optional URL where the latest Locator may be fetched.
|
||||
// URL is an optional URL where the latest Root may be fetched.
|
||||
// This is one method of locator update, while in-band mechanisms are the other.
|
||||
URL string
|
||||
URL string `json:"url"`
|
||||
}
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
cmake_minimum_required (VERSION 2.8)
|
||||
project(zt_core)
|
||||
|
||||
if(WIN32)
|
||||
add_definitions(-DNOMINMAX)
|
||||
endif(WIN32)
|
||||
|
||||
set(core_headers
|
||||
Address.hpp
|
||||
AtomicCounter.hpp
|
||||
|
@ -55,6 +51,7 @@ set(core_src
|
|||
C25519.cpp
|
||||
Credential.cpp
|
||||
ECC384.cpp
|
||||
Endpoint.cpp
|
||||
Identity.cpp
|
||||
IncomingPacket.cpp
|
||||
InetAddress.cpp
|
||||
|
|
185
node/Endpoint.cpp
Normal file
185
node/Endpoint.cpp
Normal file
|
@ -0,0 +1,185 @@
|
|||
/*
|
||||
* 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 "Endpoint.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
bool Endpoint::operator==(const Endpoint &ep) const
|
||||
{
|
||||
if (_t == ep._t) {
|
||||
switch(_t) {
|
||||
case INETADDR: return (*sockaddr() == *ep.sockaddr());
|
||||
case DNSNAME: return ((_v.dns.port == ep._v.dns.port)&&(strcmp(_v.dns.name,ep._v.dns.name) == 0));
|
||||
case ZEROTIER: return ((_v.zt.a == ep._v.zt.a)&&(memcmp(_v.zt.idh,ep._v.zt.idh,sizeof(_v.zt.idh)) == 0));
|
||||
case URL: return (strcmp(_v.url,ep._v.url) == 0);
|
||||
case ETHERNET: return (_v.eth == ep._v.eth);
|
||||
default: return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Endpoint::operator<(const Endpoint &ep) const
|
||||
{
|
||||
if ((int)_t < (int)ep._t) {
|
||||
return true;
|
||||
} else if (_t == ep._t) {
|
||||
int ncmp;
|
||||
switch(_t) {
|
||||
case INETADDR: return (*sockaddr() < *ep.sockaddr());
|
||||
case DNSNAME:
|
||||
ncmp = strcmp(_v.dns.name,ep._v.dns.name);
|
||||
return ((ncmp < 0) ? true : (ncmp == 0)&&(_v.dns.port < ep._v.dns.port));
|
||||
case ZEROTIER: return (_v.zt.a < ep._v.zt.a) ? true : ((_v.zt.a == ep._v.zt.a)&&(memcmp(_v.zt.idh,ep._v.zt.idh,sizeof(_v.zt.idh)) < 0));
|
||||
case URL: return (strcmp(_v.url,ep._v.url) < 0);
|
||||
case ETHERNET: return (_v.eth < ep._v.eth);
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int Endpoint::marshal(uint8_t data[ZT_ENDPOINT_MARSHAL_SIZE_MAX]) const
|
||||
{
|
||||
int p;
|
||||
switch(_t) {
|
||||
case INETADDR:
|
||||
data[0] = (uint8_t)INETADDR;
|
||||
return 1 + reinterpret_cast<const InetAddress *>(&_v.sa)->marshal(data+1);
|
||||
case DNSNAME:
|
||||
data[0] = (uint8_t)DNSNAME;
|
||||
p = 1;
|
||||
for (;;) {
|
||||
if ((data[p] = (uint8_t)_v.dns.name[p-1]) == 0)
|
||||
break;
|
||||
++p;
|
||||
if (p == (ZT_ENDPOINT_MAX_NAME_SIZE+1))
|
||||
return -1;
|
||||
}
|
||||
data[p++] = (uint8_t)(_v.dns.port >> 8U);
|
||||
data[p++] = (uint8_t)_v.dns.port;
|
||||
return p;
|
||||
case ZEROTIER:
|
||||
data[0] = (uint8_t)ZEROTIER;
|
||||
data[1] = (uint8_t)(_v.zt.a >> 32U);
|
||||
data[2] = (uint8_t)(_v.zt.a >> 24U);
|
||||
data[3] = (uint8_t)(_v.zt.a >> 16U);
|
||||
data[4] = (uint8_t)(_v.zt.a >> 8U);
|
||||
data[5] = (uint8_t)_v.zt.a;
|
||||
memcpy(data + 6,_v.zt.idh,ZT_IDENTITY_HASH_SIZE);
|
||||
return (ZT_IDENTITY_HASH_SIZE + 6);
|
||||
case URL:
|
||||
data[0] = (uint8_t)URL;
|
||||
p = 1;
|
||||
for (;;) {
|
||||
if ((data[p] = (uint8_t)_v.url[p-1]) == 0)
|
||||
break;
|
||||
++p;
|
||||
if (p == (ZT_ENDPOINT_MAX_NAME_SIZE+1))
|
||||
return -1;
|
||||
}
|
||||
return p;
|
||||
case ETHERNET:
|
||||
data[0] = (uint8_t)ETHERNET;
|
||||
data[1] = (uint8_t)(_v.eth >> 40U);
|
||||
data[2] = (uint8_t)(_v.eth >> 32U);
|
||||
data[3] = (uint8_t)(_v.eth >> 24U);
|
||||
data[4] = (uint8_t)(_v.eth >> 16U);
|
||||
data[5] = (uint8_t)(_v.eth >> 8U);
|
||||
data[6] = (uint8_t)_v.eth;
|
||||
return 7;
|
||||
default:
|
||||
data[0] = (uint8_t)NIL;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int Endpoint::unmarshal(const uint8_t *restrict data,const int len)
|
||||
{
|
||||
if (len <= 0)
|
||||
return -1;
|
||||
int p;
|
||||
switch((Type)data[0]) {
|
||||
case NIL:
|
||||
_t = NIL;
|
||||
return 1;
|
||||
case INETADDR:
|
||||
_t = INETADDR;
|
||||
return reinterpret_cast<InetAddress *>(&_v.sa)->unmarshal(data+1,len-1);
|
||||
case DNSNAME:
|
||||
if (len < 4)
|
||||
return -1;
|
||||
_t = DNSNAME;
|
||||
p = 1;
|
||||
for (;;) {
|
||||
if ((_v.dns.name[p-1] = (char)data[p]) == 0) {
|
||||
++p;
|
||||
break;
|
||||
}
|
||||
++p;
|
||||
if ((p >= (ZT_ENDPOINT_MAX_NAME_SIZE+1))||(p >= (len-2)))
|
||||
return -1;
|
||||
}
|
||||
_v.dns.port = (uint16_t)(((unsigned int)data[p++]) << 8U);
|
||||
_v.dns.port |= (uint16_t)data[p++];
|
||||
return p;
|
||||
case ZEROTIER:
|
||||
if (len < (ZT_IDENTITY_HASH_SIZE + 6))
|
||||
return -1;
|
||||
_t = ZEROTIER;
|
||||
_v.zt.a = ((uint64_t)data[1]) << 32U;
|
||||
_v.zt.a |= ((uint64_t)data[2]) << 24U;
|
||||
_v.zt.a |= ((uint64_t)data[3]) << 16U;
|
||||
_v.zt.a |= ((uint64_t)data[4]) << 8U;
|
||||
_v.zt.a |= (uint64_t)data[5];
|
||||
memcpy(_v.zt.idh,data + 6,ZT_IDENTITY_HASH_SIZE);
|
||||
return (ZT_IDENTITY_HASH_SIZE + 6);
|
||||
case URL:
|
||||
if (len < 2)
|
||||
return -1;
|
||||
_t = URL;
|
||||
p = 1;
|
||||
for (;;) {
|
||||
if ((_v.url[p-1] = (char)data[p]) == 0) {
|
||||
++p;
|
||||
break;
|
||||
}
|
||||
++p;
|
||||
if ((p >= (ZT_ENDPOINT_MAX_NAME_SIZE+1))||(p >= len))
|
||||
return -1;
|
||||
}
|
||||
return p;
|
||||
case ETHERNET:
|
||||
if (len < 7)
|
||||
return -1;
|
||||
_t = ZEROTIER;
|
||||
_v.eth = ((uint64_t)data[1]) << 40U;
|
||||
_v.eth |= ((uint64_t)data[2]) << 32U;
|
||||
_v.eth |= ((uint64_t)data[3]) << 24U;
|
||||
_v.eth |= ((uint64_t)data[4]) << 16U;
|
||||
_v.eth |= ((uint64_t)data[5]) << 8U;
|
||||
_v.eth |= (uint64_t)data[6];
|
||||
return 7;
|
||||
default:
|
||||
// Unrecognized endpoint types not yet specified must start with a byte
|
||||
// length size so that older versions of ZeroTier can skip them.
|
||||
if (len < 2)
|
||||
return -1;
|
||||
_t = UNRECOGNIZED;
|
||||
return 1 + (int)data[1];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
|
@ -41,7 +41,8 @@ public:
|
|||
DNSNAME = 2, // DNS name and port that resolves to InetAddress
|
||||
ZEROTIER = 3, // ZeroTier Address (for relaying and meshy behavior)
|
||||
URL = 4, // URL for http/https/ws/etc. (not implemented yet)
|
||||
ETHERNET = 5 // 48-bit LAN-local Ethernet address
|
||||
ETHERNET = 5, // 48-bit LAN-local Ethernet address
|
||||
UNRECOGNIZED = 255 // Unrecognized endpoint type encountered in stream
|
||||
};
|
||||
|
||||
ZT_ALWAYS_INLINE Endpoint() { memset(reinterpret_cast<void *>(this),0,sizeof(Endpoint)); }
|
||||
|
@ -61,170 +62,16 @@ public:
|
|||
|
||||
ZT_ALWAYS_INLINE Type type() const { return _t; }
|
||||
|
||||
ZT_ALWAYS_INLINE bool operator==(const Endpoint &ep) const
|
||||
{
|
||||
if (_t == ep._t) {
|
||||
switch(_t) {
|
||||
case INETADDR: return (*sockaddr() == *ep.sockaddr());
|
||||
case DNSNAME: return ((_v.dns.port == ep._v.dns.port)&&(strcmp(_v.dns.name,ep._v.dns.name) == 0));
|
||||
case ZEROTIER: return ((_v.zt.a == ep._v.zt.a)&&(memcmp(_v.zt.idh,ep._v.zt.idh,sizeof(_v.zt.idh)) == 0));
|
||||
case URL: return (strcmp(_v.url,ep._v.url) == 0);
|
||||
case ETHERNET: return (_v.eth == ep._v.eth);
|
||||
default: return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool operator==(const Endpoint &ep) const;
|
||||
ZT_ALWAYS_INLINE bool operator!=(const Endpoint &ep) const { return (!(*this == ep)); }
|
||||
ZT_ALWAYS_INLINE bool operator<(const Endpoint &ep) const
|
||||
{
|
||||
if ((int)_t < (int)ep._t) {
|
||||
return true;
|
||||
} else if (_t == ep._t) {
|
||||
int ncmp;
|
||||
switch(_t) {
|
||||
case INETADDR: return (*sockaddr() < *ep.sockaddr());
|
||||
case DNSNAME:
|
||||
ncmp = strcmp(_v.dns.name,ep._v.dns.name);
|
||||
return ((ncmp < 0) ? true : (ncmp == 0)&&(_v.dns.port < ep._v.dns.port));
|
||||
case ZEROTIER: return (_v.zt.a < ep._v.zt.a) ? true : ((_v.zt.a == ep._v.zt.a)&&(memcmp(_v.zt.idh,ep._v.zt.idh,sizeof(_v.zt.idh)) < 0));
|
||||
case URL: return (strcmp(_v.url,ep._v.url) < 0);
|
||||
case ETHERNET: return (_v.eth < ep._v.eth);
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool operator<(const Endpoint &ep) const;
|
||||
ZT_ALWAYS_INLINE bool operator>(const Endpoint &ep) const { return (ep < *this); }
|
||||
ZT_ALWAYS_INLINE bool operator<=(const Endpoint &ep) const { return !(ep < *this); }
|
||||
ZT_ALWAYS_INLINE bool operator>=(const Endpoint &ep) const { return !(*this < ep); }
|
||||
|
||||
// Marshal interface ///////////////////////////////////////////////////////
|
||||
static ZT_ALWAYS_INLINE int marshalSizeMax() { return ZT_ENDPOINT_MARSHAL_SIZE_MAX; }
|
||||
inline int marshal(uint8_t data[ZT_ENDPOINT_MARSHAL_SIZE_MAX]) const
|
||||
{
|
||||
int p;
|
||||
switch(_t) {
|
||||
case INETADDR:
|
||||
data[0] = (uint8_t)INETADDR;
|
||||
return 1 + reinterpret_cast<const InetAddress *>(&_v.sa)->marshal(data+1);
|
||||
case DNSNAME:
|
||||
data[0] = (uint8_t)DNSNAME;
|
||||
p = 1;
|
||||
for (;;) {
|
||||
if ((data[p] = (uint8_t)_v.dns.name[p-1]) == 0)
|
||||
break;
|
||||
++p;
|
||||
if (p == (ZT_ENDPOINT_MAX_NAME_SIZE+1))
|
||||
return -1;
|
||||
}
|
||||
data[p++] = (uint8_t)(_v.dns.port >> 8U);
|
||||
data[p++] = (uint8_t)_v.dns.port;
|
||||
return p;
|
||||
case ZEROTIER:
|
||||
data[0] = (uint8_t)ZEROTIER;
|
||||
data[1] = (uint8_t)(_v.zt.a >> 32U);
|
||||
data[2] = (uint8_t)(_v.zt.a >> 24U);
|
||||
data[3] = (uint8_t)(_v.zt.a >> 16U);
|
||||
data[4] = (uint8_t)(_v.zt.a >> 8U);
|
||||
data[5] = (uint8_t)_v.zt.a;
|
||||
memcpy(data + 6,_v.zt.idh,ZT_IDENTITY_HASH_SIZE);
|
||||
return (ZT_IDENTITY_HASH_SIZE + 6);
|
||||
case URL:
|
||||
data[0] = (uint8_t)URL;
|
||||
p = 1;
|
||||
for (;;) {
|
||||
if ((data[p] = (uint8_t)_v.url[p-1]) == 0)
|
||||
break;
|
||||
++p;
|
||||
if (p == (ZT_ENDPOINT_MAX_NAME_SIZE+1))
|
||||
return -1;
|
||||
}
|
||||
return p;
|
||||
case ETHERNET:
|
||||
data[0] = (uint8_t)ETHERNET;
|
||||
data[1] = (uint8_t)(_v.eth >> 40U);
|
||||
data[2] = (uint8_t)(_v.eth >> 32U);
|
||||
data[3] = (uint8_t)(_v.eth >> 24U);
|
||||
data[4] = (uint8_t)(_v.eth >> 16U);
|
||||
data[5] = (uint8_t)(_v.eth >> 8U);
|
||||
data[6] = (uint8_t)_v.eth;
|
||||
return 7;
|
||||
default:
|
||||
data[0] = (uint8_t)NIL;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
inline int unmarshal(const uint8_t *restrict data,const int len)
|
||||
{
|
||||
if (len <= 0)
|
||||
return -1;
|
||||
int p;
|
||||
switch((Type)data[0]) {
|
||||
case NIL:
|
||||
_t = NIL;
|
||||
return 1;
|
||||
case INETADDR:
|
||||
_t = INETADDR;
|
||||
return reinterpret_cast<InetAddress *>(&_v.sa)->unmarshal(data+1,len-1);
|
||||
case DNSNAME:
|
||||
if (len < 4)
|
||||
return -1;
|
||||
_t = DNSNAME;
|
||||
p = 1;
|
||||
for (;;) {
|
||||
if ((_v.dns.name[p-1] = (char)data[p]) == 0) {
|
||||
++p;
|
||||
break;
|
||||
}
|
||||
++p;
|
||||
if ((p >= (ZT_ENDPOINT_MAX_NAME_SIZE+1))||(p >= (len-2)))
|
||||
return -1;
|
||||
}
|
||||
_v.dns.port = (uint16_t)(((unsigned int)data[p++]) << 8U);
|
||||
_v.dns.port |= (uint16_t)data[p++];
|
||||
return p;
|
||||
case ZEROTIER:
|
||||
if (len < (ZT_IDENTITY_HASH_SIZE + 6))
|
||||
return -1;
|
||||
_t = ZEROTIER;
|
||||
_v.zt.a = ((uint64_t)data[1]) << 32U;
|
||||
_v.zt.a |= ((uint64_t)data[2]) << 24U;
|
||||
_v.zt.a |= ((uint64_t)data[3]) << 16U;
|
||||
_v.zt.a |= ((uint64_t)data[4]) << 8U;
|
||||
_v.zt.a |= (uint64_t)data[5];
|
||||
memcpy(_v.zt.idh,data + 6,ZT_IDENTITY_HASH_SIZE);
|
||||
return (ZT_IDENTITY_HASH_SIZE + 6);
|
||||
case URL:
|
||||
if (len < 2)
|
||||
return -1;
|
||||
_t = URL;
|
||||
p = 1;
|
||||
for (;;) {
|
||||
if ((_v.url[p-1] = (char)data[p]) == 0) {
|
||||
++p;
|
||||
break;
|
||||
}
|
||||
++p;
|
||||
if ((p >= (ZT_ENDPOINT_MAX_NAME_SIZE+1))||(p >= len))
|
||||
return -1;
|
||||
}
|
||||
return p;
|
||||
case ETHERNET:
|
||||
if (len < 7)
|
||||
return -1;
|
||||
_t = ZEROTIER;
|
||||
_v.eth = ((uint64_t)data[1]) << 40U;
|
||||
_v.eth |= ((uint64_t)data[2]) << 32U;
|
||||
_v.eth |= ((uint64_t)data[3]) << 24U;
|
||||
_v.eth |= ((uint64_t)data[4]) << 16U;
|
||||
_v.eth |= ((uint64_t)data[5]) << 8U;
|
||||
_v.eth |= (uint64_t)data[6];
|
||||
return 7;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
int marshal(uint8_t data[ZT_ENDPOINT_MARSHAL_SIZE_MAX]) const;
|
||||
int unmarshal(const uint8_t *restrict data,const int len);
|
||||
|
||||
private:
|
||||
Type _t;
|
||||
|
|
|
@ -313,6 +313,68 @@ bool InetAddress::isNetwork() const
|
|||
return false;
|
||||
}
|
||||
|
||||
int InetAddress::marshal(uint8_t data[19]) const
|
||||
{
|
||||
unsigned int port;
|
||||
switch(ss_family) {
|
||||
case AF_INET:
|
||||
port = Utils::ntoh((uint16_t)reinterpret_cast<const sockaddr_in *>(this)->sin_port);
|
||||
data[0] = 4;
|
||||
data[1] = reinterpret_cast<const uint8_t *>(&(reinterpret_cast<const sockaddr_in *>(this)->sin_addr.s_addr))[0];
|
||||
data[2] = reinterpret_cast<const uint8_t *>(&(reinterpret_cast<const sockaddr_in *>(this)->sin_addr.s_addr))[1];
|
||||
data[3] = reinterpret_cast<const uint8_t *>(&(reinterpret_cast<const sockaddr_in *>(this)->sin_addr.s_addr))[2];
|
||||
data[4] = reinterpret_cast<const uint8_t *>(&(reinterpret_cast<const sockaddr_in *>(this)->sin_addr.s_addr))[3];
|
||||
data[5] = (uint8_t)(port >> 8U);
|
||||
data[6] = (uint8_t)port;
|
||||
return 7;
|
||||
case AF_INET6:
|
||||
port = Utils::ntoh((uint16_t)reinterpret_cast<const sockaddr_in6 *>(this)->sin6_port);
|
||||
data[0] = 6;
|
||||
for(int i=0;i<16;++i)
|
||||
data[i+1] = reinterpret_cast<const sockaddr_in6 *>(this)->sin6_addr.s6_addr[i];
|
||||
data[17] = (uint8_t)(port >> 8U);
|
||||
data[18] = (uint8_t)port;
|
||||
return 19;
|
||||
default:
|
||||
data[0] = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int InetAddress::unmarshal(const uint8_t *restrict data,const int len)
|
||||
{
|
||||
if (len <= 0)
|
||||
return -1;
|
||||
switch(data[0]) {
|
||||
case 0:
|
||||
return 1;
|
||||
case 4:
|
||||
if (len < 7)
|
||||
return -1;
|
||||
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<uint8_t *>(&(reinterpret_cast<sockaddr_in *>(this)->sin_port))[sizeof(reinterpret_cast<sockaddr_in *>(this)->sin_port)-2] = data[5];
|
||||
reinterpret_cast<uint8_t *>(&(reinterpret_cast<sockaddr_in *>(this)->sin_port))[sizeof(reinterpret_cast<sockaddr_in *>(this)->sin_port)-1] = data[6];
|
||||
return 7;
|
||||
case 6:
|
||||
if (len < 19)
|
||||
return -1;
|
||||
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<uint8_t *>(&(reinterpret_cast<sockaddr_in6 *>(this)->sin6_port))[sizeof(reinterpret_cast<sockaddr_in6 *>(this)->sin6_port)-2] = data[17];
|
||||
reinterpret_cast<uint8_t *>(&(reinterpret_cast<sockaddr_in6 *>(this)->sin6_port))[sizeof(reinterpret_cast<sockaddr_in6 *>(this)->sin6_port)-1] = data[18];
|
||||
return 19;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
bool InetAddress::operator==(const InetAddress &a) const
|
||||
{
|
||||
if (ss_family == a.ss_family) {
|
||||
|
|
|
@ -463,80 +463,9 @@ public:
|
|||
*/
|
||||
explicit ZT_ALWAYS_INLINE operator bool() const { return (ss_family != 0); }
|
||||
|
||||
// Marshal interface ///////////////////////////////////////////////////////
|
||||
static ZT_ALWAYS_INLINE int marshalSizeMax() { return 19; }
|
||||
inline int marshal(uint8_t data[19]) const
|
||||
{
|
||||
unsigned int port;
|
||||
switch(ss_family) {
|
||||
case AF_INET:
|
||||
port = Utils::ntoh((uint16_t)reinterpret_cast<const sockaddr_in *>(this)->sin_port);
|
||||
data[0] = 4;
|
||||
data[1] = reinterpret_cast<const uint8_t *>(&(reinterpret_cast<const sockaddr_in *>(this)->sin_addr.s_addr))[0];
|
||||
data[2] = reinterpret_cast<const uint8_t *>(&(reinterpret_cast<const sockaddr_in *>(this)->sin_addr.s_addr))[1];
|
||||
data[3] = reinterpret_cast<const uint8_t *>(&(reinterpret_cast<const sockaddr_in *>(this)->sin_addr.s_addr))[2];
|
||||
data[4] = reinterpret_cast<const uint8_t *>(&(reinterpret_cast<const sockaddr_in *>(this)->sin_addr.s_addr))[3];
|
||||
data[5] = (uint8_t)(port >> 8U);
|
||||
data[6] = (uint8_t)port;
|
||||
return 7;
|
||||
case AF_INET6:
|
||||
port = Utils::ntoh((uint16_t)reinterpret_cast<const sockaddr_in6 *>(this)->sin6_port);
|
||||
data[0] = 6;
|
||||
for(int i=0;i<16;++i)
|
||||
data[i+1] = reinterpret_cast<const sockaddr_in6 *>(this)->sin6_addr.s6_addr[i];
|
||||
data[17] = (uint8_t)(port >> 8U);
|
||||
data[18] = (uint8_t)port;
|
||||
return 19;
|
||||
default:
|
||||
data[0] = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
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]) {
|
||||
case 0:
|
||||
return 1;
|
||||
case 4:
|
||||
if (len < 7)
|
||||
return -1;
|
||||
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];
|
||||
#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(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];
|
||||
#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;
|
||||
}
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
int marshal(uint8_t data[19]) const;
|
||||
int unmarshal(const uint8_t *restrict data,const int len);
|
||||
|
||||
template<unsigned int C>
|
||||
inline void serialize(Buffer<C> &b) const
|
||||
|
|
|
@ -66,14 +66,12 @@ int Locator::marshal(uint8_t data[ZT_LOCATOR_MARSHAL_SIZE_MAX],const bool exclud
|
|||
|
||||
int Locator::unmarshal(const uint8_t *restrict data,const int len)
|
||||
{
|
||||
if (len <= (8 + 48))
|
||||
if (len <= (8 + 2 + 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++];
|
||||
|
|
67
node/OS.hpp
67
node/OS.hpp
|
@ -27,13 +27,33 @@
|
|||
// Also makes sure __BYTE_ORDER is defined reasonably.
|
||||
//
|
||||
|
||||
// Hack: make sure __GCC__ is defined on old GCC compilers
|
||||
#ifndef __GCC__
|
||||
#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1) || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2) || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
|
||||
#define __GCC__
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#ifndef __WINDOWS__
|
||||
#define __WINDOWS__
|
||||
#endif
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
#undef __UNIX_LIKE__
|
||||
#undef __BSD__
|
||||
#if !defined(__GNUC__) && !defined (__clang__) && !defined(__INTEL_COMPILER)
|
||||
#define ZT_PACKED_STRUCT(D) __pragma(pack(push,1)) D __pragma(pack(pop))
|
||||
#pragma warning(disable : 4290)
|
||||
#pragma warning(disable : 4996)
|
||||
#pragma warning(disable : 4101)
|
||||
#else
|
||||
#define ZT_PACKED_STRUCT(D) D __attribute__((packed))
|
||||
#endif
|
||||
#include <WinSock2.h>
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) || defined(linux) || defined(__LINUX__) || defined(__linux)
|
||||
#ifndef __LINUX__
|
||||
#define __LINUX__
|
||||
|
@ -69,30 +89,13 @@
|
|||
#define __BIG_ENDIAN _BIG_ENDIAN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#ifndef __WINDOWS__
|
||||
#define __WINDOWS__
|
||||
#endif
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
#pragma warning(disable : 4290)
|
||||
#pragma warning(disable : 4996)
|
||||
#pragma warning(disable : 4101)
|
||||
#undef __UNIX_LIKE__
|
||||
#undef __BSD__
|
||||
#include <WinSock2.h>
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef __NetBSD__
|
||||
#ifndef RTF_MULTICAST
|
||||
#define RTF_MULTICAST 0x20000000
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Define ZT_NO_TYPE_PUNNING to disable reckless casts on anything other than x86 and x86_64.
|
||||
// Avoid unaligned type casts on all but x86/x64 architecture.
|
||||
#if (!(defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_AMD64) || defined(_M_X64) || defined(i386) || defined(__i386) || defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(_M_IX86) || defined(__X86__) || defined(_X86_) || defined(__I86__) || defined(__INTEL__) || defined(__386)))
|
||||
#ifndef ZT_NO_TYPE_PUNNING
|
||||
#define ZT_NO_TYPE_PUNNING
|
||||
|
@ -112,16 +115,6 @@
|
|||
#include <endian.h>
|
||||
#endif
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
#define ZT_PATH_SEPARATOR '\\'
|
||||
#define ZT_PATH_SEPARATOR_S "\\"
|
||||
#define ZT_EOL_S "\r\n"
|
||||
#else
|
||||
#define ZT_PATH_SEPARATOR '/'
|
||||
#define ZT_PATH_SEPARATOR_S "/"
|
||||
#define ZT_EOL_S "\n"
|
||||
#endif
|
||||
|
||||
#if (defined(__GNUC__) && (__GNUC__ >= 3)) || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) || defined(__clang__)
|
||||
#define ZT_ALWAYS_INLINE __attribute__((always_inline))
|
||||
#ifndef restrict
|
||||
|
@ -146,12 +139,6 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__WINDOWS__) && !defined(__GNUC__) && !defined (__clang__) && !defined(__INTEL_COMPILER)
|
||||
#define ZT_PACKED_STRUCT(D) __pragma(pack(push,1)) D __pragma(pack(pop))
|
||||
#else
|
||||
#define ZT_PACKED_STRUCT(D) D __attribute__((packed))
|
||||
#endif
|
||||
|
||||
#if __cplusplus > 199711L
|
||||
#ifndef __CPP11__
|
||||
#define __CPP11__
|
||||
|
@ -169,6 +156,16 @@
|
|||
#define ZT_INVALID_SOCKET -1
|
||||
#endif
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
#define ZT_PATH_SEPARATOR '\\'
|
||||
#define ZT_PATH_SEPARATOR_S "\\"
|
||||
#define ZT_EOL_S "\r\n"
|
||||
#else
|
||||
#define ZT_PATH_SEPARATOR '/'
|
||||
#define ZT_PATH_SEPARATOR_S "/"
|
||||
#define ZT_EOL_S "\n"
|
||||
#endif
|
||||
|
||||
#ifndef ZT_ALWAYS_INLINE
|
||||
#define ZT_ALWAYS_INLINE inline
|
||||
#endif
|
||||
|
|
|
@ -234,6 +234,36 @@
|
|||
#define ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_FLAGS (ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_ADI + 4)
|
||||
#define ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_COM_AND_GATHER_RESULTS (ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_FLAGS + 1)
|
||||
|
||||
/**
|
||||
* Signed locator for this node
|
||||
*/
|
||||
#define ZT_PROTO_NODE_META_LOCATOR "L"
|
||||
|
||||
/**
|
||||
* Dictionary mapping identity hash to timestamp to request newer locators for other nodes if known
|
||||
*/
|
||||
#define ZT_PROTO_NODE_META_REFRESH_LOCATORS_IF_NEWER "lt"
|
||||
|
||||
/**
|
||||
* Dictionary mapping identity hash to locator to supply newer revisions of requested locators
|
||||
*/
|
||||
#define ZT_PROTO_NODE_META_REFRESH_LOCATORS "lr"
|
||||
|
||||
/**
|
||||
* Ephemeral C25519 public key
|
||||
*/
|
||||
#define ZT_PROTO_NODE_META_EPHEMERAL_KEY_C25519 "e0"
|
||||
|
||||
/**
|
||||
* Ephemeral NIST P-384 public key
|
||||
*/
|
||||
#define ZT_PROTO_NODE_META_EPHEMERAL_KEY_P384 "e1"
|
||||
|
||||
/**
|
||||
* Addresses of ZeroTier nodes to whom this node will relay or one entry for 0000000000 if promiscuous.
|
||||
*/
|
||||
#define ZT_PROTO_NODE_META_WILL_RELAY_TO "r"
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
namespace ZeroTier {
|
||||
|
@ -801,50 +831,7 @@ public:
|
|||
*/
|
||||
VERB_PUSH_DIRECT_PATHS = 0x10,
|
||||
|
||||
/**
|
||||
* An acknowledgment of receipt of a series of recent packets from another
|
||||
* peer. This is used to calculate relative throughput values and to detect
|
||||
* packet loss. Only VERB_FRAME and VERB_EXT_FRAME packets are counted.
|
||||
*
|
||||
* ACK response format:
|
||||
* <[4] 32-bit number of bytes received since last ACK>
|
||||
*
|
||||
* Upon receipt of this packet, the local peer will verify that the correct
|
||||
* number of bytes were received by the remote peer. If these values do
|
||||
* not agree that could be an indicator of packet loss.
|
||||
*
|
||||
* Additionally, the local peer knows the interval of time that has
|
||||
* elapsed since the last received ACK. With this information it can compute
|
||||
* a rough estimate of the current throughput.
|
||||
*
|
||||
* This is sent at a maximum rate of once per every ZT_PATH_ACK_INTERVAL
|
||||
*/
|
||||
VERB_ACK = 0x12,
|
||||
|
||||
/**
|
||||
* A packet containing timing measurements useful for estimating path quality.
|
||||
* Composed of a list of <packet ID:internal sojourn time> pairs for an
|
||||
* arbitrary set of recent packets. This is used to sample for latency and
|
||||
* packet delay variance (PDV, "jitter").
|
||||
*
|
||||
* QoS record format:
|
||||
*
|
||||
* <[8] 64-bit packet ID of previously-received packet>
|
||||
* <[1] 8-bit packet sojourn time>
|
||||
* <...repeat until end of max 1400 byte packet...>
|
||||
*
|
||||
* The number of possible records per QoS packet is: (1400 * 8) / 72 = 155
|
||||
* This packet should be sent very rarely (every few seconds) as it can be
|
||||
* somewhat large if the connection is saturated. Future versions might use
|
||||
* a bloom table to probabilistically determine these values in a vastly
|
||||
* more space-efficient manner.
|
||||
*
|
||||
* Note: The 'internal packet sojourn time' is a slight misnomer as it is a
|
||||
* measure of the amount of time between when a packet was received and the
|
||||
* egress time of its tracking QoS packet.
|
||||
*
|
||||
* This is sent at a maximum rate of once per every ZT_PATH_QOS_INTERVAL
|
||||
*/
|
||||
VERB_QOS_MEASUREMENT = 0x13,
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Reference in a new issue