mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-06 20:43: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
|
DEPENDS zt_osdep zt_core zt_go_native
|
||||||
)
|
)
|
||||||
add_custom_target(build_zerotier ALL DEPENDS zerotier)
|
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)
|
|
||||||
|
|
|
@ -30,45 +30,47 @@ func Help() {
|
||||||
Usage: zerotier [-options] <command> [command args]
|
Usage: zerotier [-options] <command> [command args]
|
||||||
|
|
||||||
Global Options:
|
Global Options:
|
||||||
-j Output raw JSON where applicable
|
-j Output raw JSON where applicable
|
||||||
-p <path> Use alternate base path
|
-p <path> Use alternate base path
|
||||||
-t <path> Use secret auth token from this file
|
-t <path> Use secret auth token from this file
|
||||||
|
|
||||||
Commands:
|
Commands:
|
||||||
help Show this help
|
help Show this help
|
||||||
version Print version
|
version Print version
|
||||||
service Start in system service mode
|
selftest Run internal tests
|
||||||
status Show ZeroTier service status and config
|
service [mode] Start as service (default mode: node)
|
||||||
peers Show VL1 peers
|
node Start in normal node mode (default)
|
||||||
roots Show configured VL1 root servers
|
root [options] Start in root server mode (see docs)
|
||||||
addroot <identity> Add VL1 root server
|
status Show ZeroTier status and config
|
||||||
removeroot <identity|address> Remove VL1 root server
|
peers Show VL1 peers
|
||||||
identity <command> [args] Identity management commands
|
roots Show configured VL1 root servers
|
||||||
new [c25519|p384] Create new identity (including secret)
|
addroot <url|identity> [ip/port] [...] Add VL1 root server
|
||||||
getpublic <identity> Extract only public part of identity
|
removeroot <identity|address> Remove VL1 root server
|
||||||
validate <identity> Locally validate an identity
|
identity <command> [args] Identity management commands
|
||||||
sign <identity> <file> Sign a file with an identity's key
|
new [c25519|p384] Create identity (including secret)
|
||||||
verify <identity> <file> <sig> Verify a signature
|
getpublic <identity> Extract only public part of identity
|
||||||
networks List joined VL2 virtual networks
|
validate <identity> Locally validate an identity
|
||||||
network <network ID> Show verbose network info
|
sign <identity> <file> Sign a file with an identity's key
|
||||||
join <network ID> Join a virtual network
|
verify <identity> <file> <sig> Verify a signature
|
||||||
leave <network ID> Leave a virtual network
|
networks List joined VL2 virtual networks
|
||||||
set <network ID> <option> <value> Set a network local config option
|
network <network ID> Show verbose network info
|
||||||
manageips <boolean> Is IP management allowed?
|
join <network ID> Join a virtual network
|
||||||
manageroutes <boolean> Is route management allowed?
|
leave <network ID> Leave a virtual network
|
||||||
globalips <boolean> Can IPs in global IP space be managed?
|
set <network ID> <option> <value> Set a network local config option
|
||||||
globalroutes <boolean> Can global IP space routes be set?
|
manageips <boolean> Is IP management allowed?
|
||||||
defaultroute <boolean> Can default route be overridden?
|
manageroutes <boolean> Is route management allowed?
|
||||||
set <local config option> <value> Set a local configuration option
|
globalips <boolean> Allow assignment of global IPs?
|
||||||
phy <IP/bits> blacklist <boolean> Set or clear blacklist for CIDR
|
globalroutes <boolean> Can global IP space routes be set?
|
||||||
phy <IP/bits> trust <path ID/0> Set or clear trusted path ID for CIDR
|
defaultroute <boolean> Can default route be overridden?
|
||||||
virt <address> try <IP/port> [...] Set explicit IPs for reaching a peer
|
set <local config option> <value> Set a local configuration option
|
||||||
port <port> Set primary local port for VL1 P2P
|
phy <IP/bits> blacklist <boolean> Set or clear blacklist for CIDR
|
||||||
secondaryport <port/0> Set or disable secondary VL1 P2P port
|
phy <IP/bits> trust <path ID/0> Set or clear trusted path ID for CIDR
|
||||||
tertiaryport <port/0> Set or disable tertiary VL1 P2P port
|
virt <address> try <IP/port> [...] Set explicit IPs for reaching a peer
|
||||||
portsearch <boolean> Set or disable port search on startup
|
port <port> Set primary local port for VL1 P2P
|
||||||
portmapping <boolean> Set or disable use of uPnP and NAT-PMP
|
secondaryport <port/0> Set or disable secondary VL1 P2P port
|
||||||
explicitaddresses <IP/port> [...] Set explicit external IPs to advertise
|
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/NAT-PMP
|
||||||
|
|
||||||
Most commands require a secret token to permit control of a running ZeroTier
|
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
|
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":
|
case "version":
|
||||||
fmt.Printf("%d.%d.%d\n", zerotier.CoreVersionMajor, zerotier.CoreVersionMinor, zerotier.CoreVersionRevision)
|
fmt.Printf("%d.%d.%d\n", zerotier.CoreVersionMajor, zerotier.CoreVersionMinor, zerotier.CoreVersionRevision)
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
|
case "selftest":
|
||||||
|
cli.SelfTest()
|
||||||
|
os.Exit(0)
|
||||||
case "service":
|
case "service":
|
||||||
cli.Service(basePath, authToken, cmdArgs)
|
cli.Service(basePath, authToken, cmdArgs)
|
||||||
case "status":
|
case "status":
|
||||||
|
|
|
@ -3,6 +3,7 @@ project(zt_go_native)
|
||||||
|
|
||||||
set(src
|
set(src
|
||||||
GoGlue.cpp
|
GoGlue.cpp
|
||||||
|
CoreTests.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(headers
|
set(headers
|
||||||
|
|
|
@ -11,41 +11,33 @@
|
||||||
*/
|
*/
|
||||||
/****/
|
/****/
|
||||||
|
|
||||||
#include <cstdio>
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#include "node/Constants.hpp"
|
#include "GoGlue.h"
|
||||||
#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 "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__
|
#ifdef __WINDOWS__
|
||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
|
@ -53,10 +45,8 @@
|
||||||
|
|
||||||
using namespace ZeroTier;
|
using namespace ZeroTier;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
#define KNOWN_GOOD_IDENTITY_0 "8e4df28b72:0:ac3d46abe0c21f3cfe7a6c8d6a85cfcffcb82fbd55af6a4d6350657c68200843fa2e16f9418bbd9702cae365f2af5fb4c420908b803a681d4daef6114d78a2d7:bd8dd6e4ce7022d2f812797a80c6ee8ad180dc4ebf301dec8b06d1be08832bddd63a2f1cfa7b2c504474c75bdc8898ba476ef92e8e2d0509f8441985171ff16e"
|
||||||
|
#define KNOWN_BAD_IDENTITY_0 "9e4df28b72:0:ac3d46abe0c21f3cfe7a6c8d6a85cfcffcb82fbd55af6a4d6350657c68200843fa2e16f9418bbd9702cae365f2af5fb4c420908b803a681d4daef6114d78a2d7:bd8dd6e4ce7022d2f812797a80c6ee8ad180dc4ebf301dec8b06d1be08832bddd63a2f1cfa7b2c504474c75bdc8898ba476ef92e8e2d0509f8441985171ff16e"
|
||||||
#define KNOWN_GOOD_IDENTITY "8e4df28b72:0:ac3d46abe0c21f3cfe7a6c8d6a85cfcffcb82fbd55af6a4d6350657c68200843fa2e16f9418bbd9702cae365f2af5fb4c420908b803a681d4daef6114d78a2d7:bd8dd6e4ce7022d2f812797a80c6ee8ad180dc4ebf301dec8b06d1be08832bddd63a2f1cfa7b2c504474c75bdc8898ba476ef92e8e2d0509f8441985171ff16e"
|
|
||||||
#define KNOWN_BAD_IDENTITY "9e4df28b72:0:ac3d46abe0c21f3cfe7a6c8d6a85cfcffcb82fbd55af6a4d6350657c68200843fa2e16f9418bbd9702cae365f2af5fb4c420908b803a681d4daef6114d78a2d7:bd8dd6e4ce7022d2f812797a80c6ee8ad180dc4ebf301dec8b06d1be08832bddd63a2f1cfa7b2c504474c75bdc8898ba476ef92e8e2d0509f8441985171ff16e"
|
|
||||||
|
|
||||||
// These were generated with some Go code using the NIST P-384 elliptic curve. There
|
// 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
|
// 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_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 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 };
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
extern "C" int ZT_TestCrypto()
|
||||||
|
|
||||||
static int testCrypto()
|
|
||||||
{
|
{
|
||||||
static uint8_t buf1[16384],buf2[16384],buf3[16384];
|
static uint8_t buf1[16384],buf2[16384],buf3[16384];
|
||||||
static char hexbuf[1024];
|
static char hexbuf[1024];
|
||||||
|
@ -508,14 +496,14 @@ static int testCrypto()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int testIdentity()
|
extern "C" int ZT_TestIdentity()
|
||||||
{
|
{
|
||||||
Identity id;
|
Identity id;
|
||||||
Buffer<512> buf;
|
Buffer<512> buf;
|
||||||
char buf2[1024];
|
char buf2[1024];
|
||||||
|
|
||||||
std::cout << "[identity] Validate known-good identity... "; std::cout.flush();
|
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;
|
std::cout << "FAIL (1)" ZT_EOL_S;
|
||||||
return -1;
|
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 << "PASS (" << ((double)(vet - vst) / 10.0) << "ms per validation)" ZT_EOL_S;
|
||||||
|
|
||||||
std::cout << "[identity] Validate known-bad identity... "; std::cout.flush();
|
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;
|
std::cout << "FAIL (1)" ZT_EOL_S;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -613,114 +601,7 @@ static int testIdentity()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int testCertificate()
|
extern "C" int ZT_TestOther()
|
||||||
{
|
|
||||||
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()
|
|
||||||
{
|
{
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
char buf2[4096];
|
char buf2[4096];
|
||||||
|
@ -864,35 +745,3 @@ static int testOther()
|
||||||
|
|
||||||
return 0;
|
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);
|
ZT_Node *ZT_GoNode_getNode(ZT_GoNode *gn);
|
||||||
|
|
||||||
/* This can be called more than once to start multiple listener threads */
|
/* 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 */
|
/* 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);
|
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);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
package zerotier
|
||||||
|
|
||||||
|
//#include "../../native/GoGlue.h"
|
||||||
|
import "C"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"unsafe"
|
"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
|
// InetAddress implements net.Addr but has a ZeroTier-like string representation
|
||||||
type InetAddress struct {
|
type InetAddress struct {
|
||||||
IP net.IP
|
IP net.IP
|
||||||
|
@ -29,13 +101,13 @@ type InetAddress struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Less returns true if this IP/port is lexicographically less than another
|
// Less returns true if this IP/port is lexicographically less than another
|
||||||
func (i *InetAddress) Less(i2 *InetAddress) bool {
|
func (ina *InetAddress) Less(i2 *InetAddress) bool {
|
||||||
c := bytes.Compare(i.IP, i2.IP)
|
c := bytes.Compare(ina.IP, i2.IP)
|
||||||
if c < 0 {
|
if c < 0 {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if c == 0 {
|
if c == 0 {
|
||||||
return i.Port < i2.Port
|
return ina.Port < i2.Port
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -73,18 +145,18 @@ func NewInetAddressFromSockaddr(sa unsafe.Pointer) *InetAddress {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Network returns "udp" to implement net.Addr
|
// Network returns "udp" to implement net.Addr
|
||||||
func (i *InetAddress) Network() string {
|
func (ina *InetAddress) Network() string {
|
||||||
return "udp"
|
return "udp"
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns this address in ZeroTier-canonical IP/port format
|
// String returns this address in ZeroTier-canonical IP/port format
|
||||||
func (i *InetAddress) String() string {
|
func (ina *InetAddress) String() string {
|
||||||
return i.IP.String() + "/" + strconv.FormatInt(int64(i.Port), 10)
|
return ina.IP.String() + "/" + strconv.FormatInt(int64(ina.Port), 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Family returns the address family (AFInet etc.) or 0 if none
|
// Family returns the address family (AFInet etc.) or 0 if none
|
||||||
func (i *InetAddress) Family() int {
|
func (ina *InetAddress) Family() int {
|
||||||
switch len(i.IP) {
|
switch len(ina.IP) {
|
||||||
case 4:
|
case 4:
|
||||||
return AFInet
|
return AFInet
|
||||||
case 16:
|
case 16:
|
||||||
|
@ -94,30 +166,58 @@ func (i *InetAddress) Family() int {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Valid returns true if both the IP and port have valid values
|
// Valid returns true if both the IP and port have valid values
|
||||||
func (i *InetAddress) Valid() bool {
|
func (ina *InetAddress) Valid() bool {
|
||||||
return (len(i.IP) == 4 || len(i.IP) == 16) && (i.Port > 0 && i.Port < 65536)
|
return (len(ina.IP) == 4 || len(ina.IP) == 16) && (ina.Port > 0 && ina.Port < 65536)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalJSON marshals this MAC as a string
|
// MarshalJSON marshals this MAC as a string
|
||||||
func (i *InetAddress) MarshalJSON() ([]byte, error) {
|
func (ina *InetAddress) MarshalJSON() ([]byte, error) {
|
||||||
s := i.String()
|
s := ina.String()
|
||||||
return json.Marshal(&s)
|
return json.Marshal(&s)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON unmarshals this MAC from a string
|
// UnmarshalJSON unmarshals this MAC from a string
|
||||||
func (i *InetAddress) UnmarshalJSON(j []byte) error {
|
func (ina *InetAddress) UnmarshalJSON(j []byte) error {
|
||||||
var s string
|
var s string
|
||||||
err := json.Unmarshal(j, &s)
|
err := json.Unmarshal(j, &s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
*i = *NewInetAddressFromString(s)
|
*ina = *NewInetAddressFromString(s)
|
||||||
return nil
|
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
|
// key returns a short array suitable for use as a map[] key for this IP
|
||||||
func (i *InetAddress) key() (k [3]uint64) {
|
func (ina *InetAddress) key() (k [3]uint64) {
|
||||||
copy(((*[16]byte)(unsafe.Pointer(&k[0])))[:], i.IP)
|
copy(((*[16]byte)(unsafe.Pointer(&k[0])))[:], ina.IP)
|
||||||
k[2] = uint64(i.Port)
|
k[2] = uint64(ina.Port)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,46 @@
|
||||||
package zerotier
|
package zerotier
|
||||||
|
|
||||||
type Locator struct {
|
import (
|
||||||
Timestamp int64
|
"encoding/binary"
|
||||||
Endpoints []InetAddress
|
"errors"
|
||||||
Bytes []byte
|
)
|
||||||
|
|
||||||
|
// 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 (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
@ -87,73 +86,22 @@ var (
|
||||||
nodesByUserPtrLock sync.RWMutex
|
nodesByUserPtrLock sync.RWMutex
|
||||||
)
|
)
|
||||||
|
|
||||||
func sockaddrStorageToIPNet(ss *C.struct_sockaddr_storage) *net.IPNet {
|
// CSelfTest runs self-test functions from the core, sending results to stdout and returning true on success.
|
||||||
var a net.IPNet
|
func CSelfTest() bool {
|
||||||
switch ss.ss_family {
|
if C.ZT_TestOther() != 0 {
|
||||||
case AFInet:
|
return false
|
||||||
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
|
fmt.Println()
|
||||||
}
|
if C.ZT_TestCrypto() != 0 {
|
||||||
|
return false
|
||||||
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
|
fmt.Println()
|
||||||
}
|
if C.ZT_TestIdentity() != 0 {
|
||||||
|
return false
|
||||||
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 {
|
return true
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Node is an instance of the ZeroTier core node and related C++ I/O code
|
// Node is an instance of the ZeroTier core node and related C++ I/O code
|
||||||
type Node struct {
|
type Node struct {
|
||||||
networks map[NetworkID]*Network
|
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.
|
// Root nodes are long-lived nodes at stable physical addresses that can help locate other nodes.
|
||||||
type Root struct {
|
type Root struct {
|
||||||
// Identity is this root's address and public key(s).
|
// 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 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.
|
// 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)
|
cmake_minimum_required (VERSION 2.8)
|
||||||
project(zt_core)
|
project(zt_core)
|
||||||
|
|
||||||
if(WIN32)
|
|
||||||
add_definitions(-DNOMINMAX)
|
|
||||||
endif(WIN32)
|
|
||||||
|
|
||||||
set(core_headers
|
set(core_headers
|
||||||
Address.hpp
|
Address.hpp
|
||||||
AtomicCounter.hpp
|
AtomicCounter.hpp
|
||||||
|
@ -55,6 +51,7 @@ set(core_src
|
||||||
C25519.cpp
|
C25519.cpp
|
||||||
Credential.cpp
|
Credential.cpp
|
||||||
ECC384.cpp
|
ECC384.cpp
|
||||||
|
Endpoint.cpp
|
||||||
Identity.cpp
|
Identity.cpp
|
||||||
IncomingPacket.cpp
|
IncomingPacket.cpp
|
||||||
InetAddress.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
|
|
@ -36,12 +36,13 @@ class Endpoint
|
||||||
public:
|
public:
|
||||||
enum Type
|
enum Type
|
||||||
{
|
{
|
||||||
NIL = 0, // NIL value
|
NIL = 0, // NIL value
|
||||||
INETADDR = 1, // InetAddress (v4 or v6)
|
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
|
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)); }
|
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 Type type() const { return _t; }
|
||||||
|
|
||||||
ZT_ALWAYS_INLINE bool operator==(const Endpoint &ep) const
|
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;
|
|
||||||
}
|
|
||||||
ZT_ALWAYS_INLINE bool operator!=(const Endpoint &ep) const { return (!(*this == ep)); }
|
ZT_ALWAYS_INLINE bool operator!=(const Endpoint &ep) const { return (!(*this == ep)); }
|
||||||
ZT_ALWAYS_INLINE bool operator<(const Endpoint &ep) const
|
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;
|
|
||||||
}
|
|
||||||
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 !(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); }
|
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; }
|
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 marshal(uint8_t data[ZT_ENDPOINT_MARSHAL_SIZE_MAX]) const;
|
||||||
{
|
int unmarshal(const uint8_t *restrict data,const int len);
|
||||||
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;
|
|
||||||
}
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Type _t;
|
Type _t;
|
||||||
|
|
|
@ -313,6 +313,68 @@ bool InetAddress::isNetwork() const
|
||||||
return false;
|
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
|
bool InetAddress::operator==(const InetAddress &a) const
|
||||||
{
|
{
|
||||||
if (ss_family == a.ss_family) {
|
if (ss_family == a.ss_family) {
|
||||||
|
|
|
@ -463,80 +463,9 @@ public:
|
||||||
*/
|
*/
|
||||||
explicit ZT_ALWAYS_INLINE operator bool() const { return (ss_family != 0); }
|
explicit ZT_ALWAYS_INLINE operator bool() const { return (ss_family != 0); }
|
||||||
|
|
||||||
// Marshal interface ///////////////////////////////////////////////////////
|
|
||||||
static ZT_ALWAYS_INLINE int marshalSizeMax() { return 19; }
|
static ZT_ALWAYS_INLINE int marshalSizeMax() { return 19; }
|
||||||
inline int marshal(uint8_t data[19]) const
|
int marshal(uint8_t data[19]) const;
|
||||||
{
|
int unmarshal(const uint8_t *restrict data,const int len);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
template<unsigned int C>
|
template<unsigned int C>
|
||||||
inline void serialize(Buffer<C> &b) const
|
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)
|
int Locator::unmarshal(const uint8_t *restrict data,const int len)
|
||||||
{
|
{
|
||||||
if (len <= (8 + 48))
|
if (len <= (8 + 2 + 48))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
_ts = (int64_t)Utils::readUInt64(data);
|
_ts = (int64_t)Utils::readUInt64(data);
|
||||||
int p = 8;
|
int p = 8;
|
||||||
|
|
||||||
if ((p + 2) > len)
|
|
||||||
return -1;
|
|
||||||
unsigned int ec = (int)data[p++];
|
unsigned int ec = (int)data[p++];
|
||||||
ec <<= 8U;
|
ec <<= 8U;
|
||||||
ec |= data[p++];
|
ec |= data[p++];
|
||||||
|
|
67
node/OS.hpp
67
node/OS.hpp
|
@ -27,13 +27,33 @@
|
||||||
// Also makes sure __BYTE_ORDER is defined reasonably.
|
// Also makes sure __BYTE_ORDER is defined reasonably.
|
||||||
//
|
//
|
||||||
|
|
||||||
// Hack: make sure __GCC__ is defined on old GCC compilers
|
|
||||||
#ifndef __GCC__
|
#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)
|
#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__
|
#define __GCC__
|
||||||
#endif
|
#endif
|
||||||
#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)
|
#if defined(__linux__) || defined(linux) || defined(__LINUX__) || defined(__linux)
|
||||||
#ifndef __LINUX__
|
#ifndef __LINUX__
|
||||||
#define __LINUX__
|
#define __LINUX__
|
||||||
|
@ -69,30 +89,13 @@
|
||||||
#define __BIG_ENDIAN _BIG_ENDIAN
|
#define __BIG_ENDIAN _BIG_ENDIAN
|
||||||
#endif
|
#endif
|
||||||
#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__
|
#ifdef __NetBSD__
|
||||||
#ifndef RTF_MULTICAST
|
#ifndef RTF_MULTICAST
|
||||||
#define RTF_MULTICAST 0x20000000
|
#define RTF_MULTICAST 0x20000000
|
||||||
#endif
|
#endif
|
||||||
#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)))
|
#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
|
#ifndef ZT_NO_TYPE_PUNNING
|
||||||
#define ZT_NO_TYPE_PUNNING
|
#define ZT_NO_TYPE_PUNNING
|
||||||
|
@ -112,16 +115,6 @@
|
||||||
#include <endian.h>
|
#include <endian.h>
|
||||||
#endif
|
#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__)
|
#if (defined(__GNUC__) && (__GNUC__ >= 3)) || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) || defined(__clang__)
|
||||||
#define ZT_ALWAYS_INLINE __attribute__((always_inline))
|
#define ZT_ALWAYS_INLINE __attribute__((always_inline))
|
||||||
#ifndef restrict
|
#ifndef restrict
|
||||||
|
@ -146,12 +139,6 @@
|
||||||
#endif
|
#endif
|
||||||
#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
|
#if __cplusplus > 199711L
|
||||||
#ifndef __CPP11__
|
#ifndef __CPP11__
|
||||||
#define __CPP11__
|
#define __CPP11__
|
||||||
|
@ -169,6 +156,16 @@
|
||||||
#define ZT_INVALID_SOCKET -1
|
#define ZT_INVALID_SOCKET -1
|
||||||
#endif
|
#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
|
#ifndef ZT_ALWAYS_INLINE
|
||||||
#define ZT_ALWAYS_INLINE inline
|
#define ZT_ALWAYS_INLINE inline
|
||||||
#endif
|
#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_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)
|
#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 {
|
namespace ZeroTier {
|
||||||
|
@ -801,50 +831,7 @@ public:
|
||||||
*/
|
*/
|
||||||
VERB_PUSH_DIRECT_PATHS = 0x10,
|
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,
|
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,
|
VERB_QOS_MEASUREMENT = 0x13,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Reference in a new issue