Clang-format!!!

This commit is contained in:
Adam Ierymenko 2024-09-26 08:52:29 -04:00
parent f190df8621
commit 96ba1079b2
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3
122 changed files with 41245 additions and 39820 deletions

View file

@ -57,7 +57,7 @@ SpacesInCStyleCastParentheses: 'false'
SpacesInContainerLiterals: 'true' SpacesInContainerLiterals: 'true'
SpacesInParentheses: 'false' SpacesInParentheses: 'false'
SpacesInSquareBrackets: 'false' SpacesInSquareBrackets: 'false'
UseTab: 'Always' UseTab: 'Never'
--- ---
Language: Cpp Language: Cpp

View file

@ -21,8 +21,8 @@
#define ZT_DEBUG_H #define ZT_DEBUG_H
#if defined(__linux__) || defined(__APPLE__) #if defined(__linux__) || defined(__APPLE__)
#include <sys/syscall.h>
#include <pthread.h> #include <pthread.h>
#include <sys/syscall.h>
#include <unistd.h> #include <unistd.h>
#endif #endif
@ -79,16 +79,13 @@
#if defined(ZT_DEBUG_TRACE) #if defined(ZT_DEBUG_TRACE)
#if ZT_MSG_INFO == true #if ZT_MSG_INFO == true
#if defined(__ANDROID__) #if defined(__ANDROID__)
#define DEBUG_INFO(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \ #define DEBUG_INFO(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, "INFO : %17s:%5d:%20s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args))
"INFO : %17s:%5d:%20s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args))
#endif #endif
#if defined(_WIN32) #if defined(_WIN32)
#define DEBUG_INFO(fmt, ...) fprintf(stderr, ZT_GRN "INFO [%ld]: %17s:%5d:%25s: " fmt "\n" \ #define DEBUG_INFO(fmt, ...) fprintf(stderr, ZT_GRN "INFO [%ld]: %17s:%5d:%25s: " fmt "\n" ZT_RESET, ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, __VA_ARGS__)
ZT_RESET, ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, __VA_ARGS__)
#endif #endif
#if defined(__linux__) or defined(__APPLE__) or defined(__FreeBSD__) #if defined(__linux__) or defined(__APPLE__) or defined(__FreeBSD__)
#define DEBUG_INFO(fmt, args ...) fprintf(stderr, ZT_GRN "INFO [%ld]: %17s:%5d:%25s: " fmt "\n" \ #define DEBUG_INFO(fmt, args...) fprintf(stderr, ZT_GRN "INFO [%ld]: %17s:%5d:%25s: " fmt "\n" ZT_RESET, ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args)
ZT_RESET, ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args)
#endif #endif
#else #else
#define DEBUG_INFO(fmt, args...) #define DEBUG_INFO(fmt, args...)

View file

@ -23,14 +23,14 @@
// For the struct sockaddr_storage structure // For the struct sockaddr_storage structure
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
#include <windows.h>
#include <winsock2.h> #include <winsock2.h>
#include <ws2tcpip.h> #include <ws2tcpip.h>
#include <windows.h>
#else /* not Windows */ #else /* not Windows */
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/types.h>
#endif /* Windows or not */ #endif /* Windows or not */
#if defined(_MSC_VER) #if defined(_MSC_VER)
@ -372,8 +372,7 @@ extern "C" {
* indicate serious problems like an inaccessible data store or a compile * indicate serious problems like an inaccessible data store or a compile
* problem. * problem.
*/ */
enum ZT_ResultCode enum ZT_ResultCode {
{
/** /**
* Operation completed normally * Operation completed normally
*/ */
@ -428,8 +427,7 @@ enum ZT_ResultCode
/** /**
* Status codes sent to status update callback when things happen * Status codes sent to status update callback when things happen
*/ */
enum ZT_Event enum ZT_Event {
{
/** /**
* Node has been initialized * Node has been initialized
* *
@ -534,8 +532,7 @@ enum ZT_Event
/** /**
* Payload of REMOTE_TRACE event * Payload of REMOTE_TRACE event
*/ */
typedef struct typedef struct {
{
/** /**
* ZeroTier address of sender * ZeroTier address of sender
*/ */
@ -570,8 +567,7 @@ typedef struct
* in the world can send you a user message! (Unless your network is air * in the world can send you a user message! (Unless your network is air
* gapped.) * gapped.)
*/ */
typedef struct typedef struct {
{
/** /**
* ZeroTier address of sender (least significant 40 bits) * ZeroTier address of sender (least significant 40 bits)
*/ */
@ -596,8 +592,7 @@ typedef struct
/** /**
* Current node status * Current node status
*/ */
typedef struct typedef struct {
{
/** /**
* 40-bit ZeroTier address of this node * 40-bit ZeroTier address of this node
*/ */
@ -628,8 +623,7 @@ typedef struct
* *
* This structure is subject to change between versions. * This structure is subject to change between versions.
*/ */
typedef struct typedef struct {
{
/** /**
* Number of each protocol verb (possible verbs 0..31) received * Number of each protocol verb (possible verbs 0..31) received
*/ */
@ -644,8 +638,7 @@ typedef struct
/** /**
* Virtual network status codes * Virtual network status codes
*/ */
enum ZT_VirtualNetworkStatus enum ZT_VirtualNetworkStatus {
{
/** /**
* Waiting for network configuration (also means revision == 0) * Waiting for network configuration (also means revision == 0)
*/ */
@ -685,8 +678,7 @@ enum ZT_VirtualNetworkStatus
/** /**
* Virtual network type codes * Virtual network type codes
*/ */
enum ZT_VirtualNetworkType enum ZT_VirtualNetworkType {
{
/** /**
* Private networks are authorized via certificates of membership * Private networks are authorized via certificates of membership
*/ */
@ -707,8 +699,7 @@ enum ZT_VirtualNetworkType
* Each rule is composed of zero or more MATCHes followed by an ACTION. * Each rule is composed of zero or more MATCHes followed by an ACTION.
* An ACTION with no MATCHes is always taken. * An ACTION with no MATCHes is always taken.
*/ */
enum ZT_VirtualNetworkRuleType enum ZT_VirtualNetworkRuleType {
{
// 0 to 15 reserved for actions // 0 to 15 reserved for actions
/** /**
@ -799,8 +790,7 @@ enum ZT_VirtualNetworkRuleType
* This is designed to be a more memory-efficient way of storing rules than * This is designed to be a more memory-efficient way of storing rules than
* a wide table, yet still fast and simple to access in code. * a wide table, yet still fast and simple to access in code.
*/ */
typedef struct typedef struct {
{
/** /**
* Type and flags * Type and flags
* *
@ -947,8 +937,7 @@ typedef struct
/** /**
* A route to be pushed on a virtual network * A route to be pushed on a virtual network
*/ */
typedef struct typedef struct {
{
/** /**
* Target network / netmask bits (in port field) or NULL or 0.0.0.0/0 for default * Target network / netmask bits (in port field) or NULL or 0.0.0.0/0 for default
*/ */
@ -973,8 +962,7 @@ typedef struct
/** /**
* DNS configuration to be pushed on a virtual network * DNS configuration to be pushed on a virtual network
*/ */
typedef struct typedef struct {
{
char domain[128]; char domain[128];
struct sockaddr_storage server_addr[ZT_MAX_DNS_SERVERS]; struct sockaddr_storage server_addr[ZT_MAX_DNS_SERVERS];
} ZT_VirtualNetworkDNS; } ZT_VirtualNetworkDNS;
@ -982,8 +970,7 @@ typedef struct
/** /**
* An Ethernet multicast group * An Ethernet multicast group
*/ */
typedef struct typedef struct {
{
/** /**
* MAC address (least significant 48 bits) * MAC address (least significant 48 bits)
*/ */
@ -998,8 +985,7 @@ typedef struct
/** /**
* Virtual network configuration update type * Virtual network configuration update type
*/ */
enum ZT_VirtualNetworkConfigOperation enum ZT_VirtualNetworkConfigOperation {
{
/** /**
* Network is coming up (either for the first time or after service restart) * Network is coming up (either for the first time or after service restart)
*/ */
@ -1024,8 +1010,7 @@ enum ZT_VirtualNetworkConfigOperation
/** /**
* What trust hierarchy role does this peer have? * What trust hierarchy role does this peer have?
*/ */
enum ZT_PeerRole enum ZT_PeerRole {
{
ZT_PEER_ROLE_LEAF = 0, // ordinary node ZT_PEER_ROLE_LEAF = 0, // ordinary node
ZT_PEER_ROLE_MOON = 1, // moon root ZT_PEER_ROLE_MOON = 1, // moon root
ZT_PEER_ROLE_PLANET = 2 // planetary root ZT_PEER_ROLE_PLANET = 2 // planetary root
@ -1034,17 +1019,12 @@ enum ZT_PeerRole
/** /**
* Vendor ID * Vendor ID
*/ */
enum ZT_Vendor enum ZT_Vendor { ZT_VENDOR_UNSPECIFIED = 0, ZT_VENDOR_ZEROTIER = 1 };
{
ZT_VENDOR_UNSPECIFIED = 0,
ZT_VENDOR_ZEROTIER = 1
};
/** /**
* Platform type * Platform type
*/ */
enum ZT_Platform enum ZT_Platform {
{
ZT_PLATFORM_UNSPECIFIED = 0, ZT_PLATFORM_UNSPECIFIED = 0,
ZT_PLATFORM_LINUX = 1, ZT_PLATFORM_LINUX = 1,
ZT_PLATFORM_WINDOWS = 2, ZT_PLATFORM_WINDOWS = 2,
@ -1066,8 +1046,7 @@ enum ZT_Platform
/** /**
* Architecture type * Architecture type
*/ */
enum ZT_Architecture enum ZT_Architecture {
{
ZT_ARCHITECTURE_UNSPECIFIED = 0, ZT_ARCHITECTURE_UNSPECIFIED = 0,
ZT_ARCHITECTURE_X86 = 1, ZT_ARCHITECTURE_X86 = 1,
ZT_ARCHITECTURE_X64 = 2, ZT_ARCHITECTURE_X64 = 2,
@ -1091,8 +1070,7 @@ enum ZT_Architecture
/** /**
* Virtual network configuration * Virtual network configuration
*/ */
typedef struct typedef struct {
{
/** /**
* 64-bit ZeroTier network ID * 64-bit ZeroTier network ID
*/ */
@ -1200,8 +1178,6 @@ typedef struct
*/ */
ZT_VirtualNetworkDNS dns; ZT_VirtualNetworkDNS dns;
/** /**
* sso enabled * sso enabled
*/ */
@ -1256,8 +1232,7 @@ typedef struct
/** /**
* A list of networks * A list of networks
*/ */
typedef struct typedef struct {
{
ZT_VirtualNetworkConfig* networks; ZT_VirtualNetworkConfig* networks;
unsigned long networkCount; unsigned long networkCount;
} ZT_VirtualNetworkList; } ZT_VirtualNetworkList;
@ -1280,8 +1255,7 @@ typedef struct {
/** /**
* Physical network path to a peer * Physical network path to a peer
*/ */
typedef struct typedef struct {
{
/** /**
* Address of endpoint * Address of endpoint
*/ */
@ -1386,8 +1360,7 @@ typedef struct
/** /**
* Peer status result buffer * Peer status result buffer
*/ */
typedef struct typedef struct {
{
/** /**
* ZeroTier address (40 bits) * ZeroTier address (40 bits)
*/ */
@ -1457,8 +1430,7 @@ typedef struct
/** /**
* List of peers * List of peers
*/ */
typedef struct typedef struct {
{
ZT_Peer* peers; ZT_Peer* peers;
unsigned long peerCount; unsigned long peerCount;
} ZT_PeerList; } ZT_PeerList;
@ -1466,8 +1438,7 @@ typedef struct
/** /**
* ZeroTier core state objects * ZeroTier core state objects
*/ */
enum ZT_StateObjectType enum ZT_StateObjectType {
{
/** /**
* Null object -- ignored * Null object -- ignored
*/ */
@ -1730,8 +1701,7 @@ typedef int (*ZT_PathLookupFunction)(
/** /**
* Structure for configuring ZeroTier core callback functions * Structure for configuring ZeroTier core callback functions
*/ */
struct ZT_Node_Callbacks struct ZT_Node_Callbacks {
{
/** /**
* Struct version -- must currently be 0 * Struct version -- must currently be 0
*/ */
@ -1818,15 +1788,8 @@ ZT_SDK_API void ZT_Node_delete(ZT_Node *node);
* @param nextBackgroundTaskDeadline Value/result: set to deadline for next call to processBackgroundTasks() * @param nextBackgroundTaskDeadline Value/result: set to deadline for next call to processBackgroundTasks()
* @return OK (0) or error code if a fatal error condition has occurred * @return OK (0) or error code if a fatal error condition has occurred
*/ */
ZT_SDK_API enum ZT_ResultCode ZT_Node_processWirePacket( ZT_SDK_API enum ZT_ResultCode
ZT_Node *node, ZT_Node_processWirePacket(ZT_Node* node, void* tptr, int64_t now, int64_t localSocket, const struct sockaddr_storage* remoteAddress, const void* packetData, unsigned int packetLength, volatile int64_t* nextBackgroundTaskDeadline);
void *tptr,
int64_t now,
int64_t localSocket,
const struct sockaddr_storage *remoteAddress,
const void *packetData,
unsigned int packetLength,
volatile int64_t *nextBackgroundTaskDeadline);
/** /**
* Process a frame from a virtual network port (tap) * Process a frame from a virtual network port (tap)

View file

@ -11,9 +11,10 @@
*/ */
/****/ /****/
#include "Constants.hpp"
#include "AES.hpp" #include "AES.hpp"
#include "Constants.hpp"
#ifdef __GNUC__ #ifdef __GNUC__
#pragma GCC diagnostic ignored "-Wstrict-aliasing" #pragma GCC diagnostic ignored "-Wstrict-aliasing"
#endif #endif
@ -343,7 +344,8 @@ void AES::CTR::crypt(const void *const input, unsigned int len) noexcept
*reinterpret_cast<uint64_t*>(out + 8) = in1 ^ Utils::hton(((uint64_t)s2 << 32U) | (uint64_t)s3); *reinterpret_cast<uint64_t*>(out + 8) = in1 ^ Utils::hton(((uint64_t)s2 << 32U) | (uint64_t)s3);
out += 16; out += 16;
} while ((len -= 16) >= 16); } while ((len -= 16) >= 16);
} else { }
else {
do { do {
uint32_t s0, s1, s2, s3, t0, t1, t2, t3; uint32_t s0, s1, s2, s3, t0, t1, t2, t3;
s0 = ctr0rk0; s0 = ctr0rk0;
@ -454,34 +456,62 @@ void AES::CTR::finish() noexcept
// Software AES and AES key expansion --------------------------------------------------------------------------------- // Software AES and AES key expansion ---------------------------------------------------------------------------------
const uint32_t AES::Te0[256] = {0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554, 0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d, 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a, 0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87, 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b, 0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea, 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b, 0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a, 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f, 0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108, 0xe2717193, 0xabd8d873, 0x62313153, const uint32_t AES::Te0[256] = { 0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554, 0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d, 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a,
0x2a15153f, 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, 0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5, 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d, 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f, 0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87, 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b, 0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea, 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b,
0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e, 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb, 0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497, 0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c, 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed, 0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b, 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a, 0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16, 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594, 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81, 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a, 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f, 0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108, 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f,
0x4ba8a8e3, 0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a, 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504, 0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d, 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, 0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5, 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d, 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f,
0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f, 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739, 0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47, 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395, 0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883, 0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c, 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76, 0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e, 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4, 0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6, 0x399191a8, 0x319595a4, 0xd3e4e437, 0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e, 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb, 0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497,
0xf279798b, 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7, 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0, 0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25, 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818, 0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c, 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed, 0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b, 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a,
0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, 0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651, 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21, 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85, 0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa, 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12, 0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9, 0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133, 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7, 0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920, 0x87cece49, 0xaa5555ff, 0x50282878, 0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16, 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594, 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81, 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3,
0xa5dfdf7a, 0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17, 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8, 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11, 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a}; 0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a, 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504, 0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d,
const uint32_t AES::Te4[256] = {0x63636363, 0x7c7c7c7c, 0x77777777, 0x7b7b7b7b, 0xf2f2f2f2, 0x6b6b6b6b, 0x6f6f6f6f, 0xc5c5c5c5, 0x30303030, 0x01010101, 0x67676767, 0x2b2b2b2b, 0xfefefefe, 0xd7d7d7d7, 0xabababab, 0x76767676, 0xcacacaca, 0x82828282, 0xc9c9c9c9, 0x7d7d7d7d, 0xfafafafa, 0x59595959, 0x47474747, 0xf0f0f0f0, 0xadadadad, 0xd4d4d4d4, 0xa2a2a2a2, 0xafafafaf, 0x9c9c9c9c, 0xa4a4a4a4, 0x72727272, 0xc0c0c0c0, 0xb7b7b7b7, 0xfdfdfdfd, 0x93939393, 0x26262626, 0x36363636, 0x3f3f3f3f, 0xf7f7f7f7, 0xcccccccc, 0x34343434, 0xa5a5a5a5, 0xe5e5e5e5, 0xf1f1f1f1, 0x71717171, 0xd8d8d8d8, 0x31313131, 0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f, 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739, 0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47, 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395,
0x15151515, 0x04040404, 0xc7c7c7c7, 0x23232323, 0xc3c3c3c3, 0x18181818, 0x96969696, 0x05050505, 0x9a9a9a9a, 0x07070707, 0x12121212, 0x80808080, 0xe2e2e2e2, 0xebebebeb, 0x27272727, 0xb2b2b2b2, 0x75757575, 0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883, 0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c, 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76,
0x09090909, 0x83838383, 0x2c2c2c2c, 0x1a1a1a1a, 0x1b1b1b1b, 0x6e6e6e6e, 0x5a5a5a5a, 0xa0a0a0a0, 0x52525252, 0x3b3b3b3b, 0xd6d6d6d6, 0xb3b3b3b3, 0x29292929, 0xe3e3e3e3, 0x2f2f2f2f, 0x84848484, 0x53535353, 0xd1d1d1d1, 0x00000000, 0xedededed, 0x20202020, 0xfcfcfcfc, 0xb1b1b1b1, 0x5b5b5b5b, 0x6a6a6a6a, 0xcbcbcbcb, 0xbebebebe, 0x39393939, 0x4a4a4a4a, 0x4c4c4c4c, 0x58585858, 0xcfcfcfcf, 0xd0d0d0d0, 0xefefefef, 0xaaaaaaaa, 0xfbfbfbfb, 0x43434343, 0x4d4d4d4d, 0x33333333, 0x85858585, 0x45454545, 0xf9f9f9f9, 0x02020202, 0x7f7f7f7f, 0x50505050, 0x3c3c3c3c, 0x9f9f9f9f, 0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e, 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4, 0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6, 0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b,
0xa8a8a8a8, 0x51515151, 0xa3a3a3a3, 0x40404040, 0x8f8f8f8f, 0x92929292, 0x9d9d9d9d, 0x38383838, 0xf5f5f5f5, 0xbcbcbcbc, 0xb6b6b6b6, 0xdadadada, 0x21212121, 0x10101010, 0xffffffff, 0xf3f3f3f3, 0xd2d2d2d2, 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7, 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0, 0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25, 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818,
0xcdcdcdcd, 0x0c0c0c0c, 0x13131313, 0xecececec, 0x5f5f5f5f, 0x97979797, 0x44444444, 0x17171717, 0xc4c4c4c4, 0xa7a7a7a7, 0x7e7e7e7e, 0x3d3d3d3d, 0x64646464, 0x5d5d5d5d, 0x19191919, 0x73737373, 0x60606060, 0x81818181, 0x4f4f4f4f, 0xdcdcdcdc, 0x22222222, 0x2a2a2a2a, 0x90909090, 0x88888888, 0x46464646, 0xeeeeeeee, 0xb8b8b8b8, 0x14141414, 0xdededede, 0x5e5e5e5e, 0x0b0b0b0b, 0xdbdbdbdb, 0xe0e0e0e0, 0x32323232, 0x3a3a3a3a, 0x0a0a0a0a, 0x49494949, 0x06060606, 0x24242424, 0x5c5c5c5c, 0xc2c2c2c2, 0xd3d3d3d3, 0xacacacac, 0x62626262, 0x91919191, 0x95959595, 0xe4e4e4e4, 0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, 0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651, 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21, 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85,
0x79797979, 0xe7e7e7e7, 0xc8c8c8c8, 0x37373737, 0x6d6d6d6d, 0x8d8d8d8d, 0xd5d5d5d5, 0x4e4e4e4e, 0xa9a9a9a9, 0x6c6c6c6c, 0x56565656, 0xf4f4f4f4, 0xeaeaeaea, 0x65656565, 0x7a7a7a7a, 0xaeaeaeae, 0x08080808, 0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa, 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12, 0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9,
0xbabababa, 0x78787878, 0x25252525, 0x2e2e2e2e, 0x1c1c1c1c, 0xa6a6a6a6, 0xb4b4b4b4, 0xc6c6c6c6, 0xe8e8e8e8, 0xdddddddd, 0x74747474, 0x1f1f1f1f, 0x4b4b4b4b, 0xbdbdbdbd, 0x8b8b8b8b, 0x8a8a8a8a, 0x70707070, 0x3e3e3e3e, 0xb5b5b5b5, 0x66666666, 0x48484848, 0x03030303, 0xf6f6f6f6, 0x0e0e0e0e, 0x61616161, 0x35353535, 0x57575757, 0xb9b9b9b9, 0x86868686, 0xc1c1c1c1, 0x1d1d1d1d, 0x9e9e9e9e, 0xe1e1e1e1, 0xf8f8f8f8, 0x98989898, 0x11111111, 0x69696969, 0xd9d9d9d9, 0x8e8e8e8e, 0x94949494, 0x9b9b9b9b, 0x1e1e1e1e, 0x87878787, 0xe9e9e9e9, 0xcececece, 0x55555555, 0x28282828, 0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133, 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7, 0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920, 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a,
0xdfdfdfdf, 0x8c8c8c8c, 0xa1a1a1a1, 0x89898989, 0x0d0d0d0d, 0xbfbfbfbf, 0xe6e6e6e6, 0x42424242, 0x68686868, 0x41414141, 0x99999999, 0x2d2d2d2d, 0x0f0f0f0f, 0xb0b0b0b0, 0x54545454, 0xbbbbbbbb, 0x16161616}; 0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17, 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8, 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11, 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a };
const uint32_t AES::Td0[256] = {0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96, 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393, 0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25, 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f, 0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1, 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6, 0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da, 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844, 0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd, 0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4, 0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45, 0xb16477e0, 0xbb6bae84, 0xfe81a01c, const uint32_t AES::Te4[256] = { 0x63636363, 0x7c7c7c7c, 0x77777777, 0x7b7b7b7b, 0xf2f2f2f2, 0x6b6b6b6b, 0x6f6f6f6f, 0xc5c5c5c5, 0x30303030, 0x01010101, 0x67676767, 0x2b2b2b2b, 0xfefefefe, 0xd7d7d7d7, 0xabababab, 0x76767676,
0xf9082b94, 0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7, 0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a, 0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5, 0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c, 0xcacacaca, 0x82828282, 0xc9c9c9c9, 0x7d7d7d7d, 0xfafafafa, 0x59595959, 0x47474747, 0xf0f0f0f0, 0xadadadad, 0xd4d4d4d4, 0xa2a2a2a2, 0xafafafaf, 0x9c9c9c9c, 0xa4a4a4a4, 0x72727272, 0xc0c0c0c0,
0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1, 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a, 0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75, 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051, 0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46, 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff, 0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77, 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb, 0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000, 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e, 0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927, 0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0xb7b7b7b7, 0xfdfdfdfd, 0x93939393, 0x26262626, 0x36363636, 0x3f3f3f3f, 0xf7f7f7f7, 0xcccccccc, 0x34343434, 0xa5a5a5a5, 0xe5e5e5e5, 0xf1f1f1f1, 0x71717171, 0xd8d8d8d8, 0x31313131, 0x15151515,
0x24362e3a, 0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e, 0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16, 0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d, 0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8, 0x04040404, 0xc7c7c7c7, 0x23232323, 0xc3c3c3c3, 0x18181818, 0x96969696, 0x05050505, 0x9a9a9a9a, 0x07070707, 0x12121212, 0x80808080, 0xe2e2e2e2, 0xebebebeb, 0x27272727, 0xb2b2b2b2, 0x75757575,
0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd, 0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34, 0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163, 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120, 0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d, 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0, 0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422, 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef, 0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36, 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4, 0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662, 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x09090909, 0x83838383, 0x2c2c2c2c, 0x1a1a1a1a, 0x1b1b1b1b, 0x6e6e6e6e, 0x5a5a5a5a, 0xa0a0a0a0, 0x52525252, 0x3b3b3b3b, 0xd6d6d6d6, 0xb3b3b3b3, 0x29292929, 0xe3e3e3e3, 0x2f2f2f2f, 0x84848484,
0x82c3aff5, 0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3, 0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b, 0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8, 0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6, 0x53535353, 0xd1d1d1d1, 0x00000000, 0xedededed, 0x20202020, 0xfcfcfcfc, 0xb1b1b1b1, 0x5b5b5b5b, 0x6a6a6a6a, 0xcbcbcbcb, 0xbebebebe, 0x39393939, 0x4a4a4a4a, 0x4c4c4c4c, 0x58585858, 0xcfcfcfcf,
0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6, 0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0, 0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815, 0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f, 0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df, 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f, 0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e, 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713, 0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89, 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c, 0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf, 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0xd0d0d0d0, 0xefefefef, 0xaaaaaaaa, 0xfbfbfbfb, 0x43434343, 0x4d4d4d4d, 0x33333333, 0x85858585, 0x45454545, 0xf9f9f9f9, 0x02020202, 0x7f7f7f7f, 0x50505050, 0x3c3c3c3c, 0x9f9f9f9f, 0xa8a8a8a8,
0x7844db86, 0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f, 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541, 0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190, 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742}; 0x51515151, 0xa3a3a3a3, 0x40404040, 0x8f8f8f8f, 0x92929292, 0x9d9d9d9d, 0x38383838, 0xf5f5f5f5, 0xbcbcbcbc, 0xb6b6b6b6, 0xdadadada, 0x21212121, 0x10101010, 0xffffffff, 0xf3f3f3f3, 0xd2d2d2d2,
const uint8_t AES::Td4[256] = {0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0xcdcdcdcd, 0x0c0c0c0c, 0x13131313, 0xecececec, 0x5f5f5f5f, 0x97979797, 0x44444444, 0x17171717, 0xc4c4c4c4, 0xa7a7a7a7, 0x7e7e7e7e, 0x3d3d3d3d, 0x64646464, 0x5d5d5d5d, 0x19191919, 0x73737373,
0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x60606060, 0x81818181, 0x4f4f4f4f, 0xdcdcdcdc, 0x22222222, 0x2a2a2a2a, 0x90909090, 0x88888888, 0x46464646, 0xeeeeeeee, 0xb8b8b8b8, 0x14141414, 0xdededede, 0x5e5e5e5e, 0x0b0b0b0b, 0xdbdbdbdb,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xe0e0e0e0, 0x32323232, 0x3a3a3a3a, 0x0a0a0a0a, 0x49494949, 0x06060606, 0x24242424, 0x5c5c5c5c, 0xc2c2c2c2, 0xd3d3d3d3, 0xacacacac, 0x62626262, 0x91919191, 0x95959595, 0xe4e4e4e4, 0x79797979,
0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d}; 0xe7e7e7e7, 0xc8c8c8c8, 0x37373737, 0x6d6d6d6d, 0x8d8d8d8d, 0xd5d5d5d5, 0x4e4e4e4e, 0xa9a9a9a9, 0x6c6c6c6c, 0x56565656, 0xf4f4f4f4, 0xeaeaeaea, 0x65656565, 0x7a7a7a7a, 0xaeaeaeae, 0x08080808,
0xbabababa, 0x78787878, 0x25252525, 0x2e2e2e2e, 0x1c1c1c1c, 0xa6a6a6a6, 0xb4b4b4b4, 0xc6c6c6c6, 0xe8e8e8e8, 0xdddddddd, 0x74747474, 0x1f1f1f1f, 0x4b4b4b4b, 0xbdbdbdbd, 0x8b8b8b8b, 0x8a8a8a8a,
0x70707070, 0x3e3e3e3e, 0xb5b5b5b5, 0x66666666, 0x48484848, 0x03030303, 0xf6f6f6f6, 0x0e0e0e0e, 0x61616161, 0x35353535, 0x57575757, 0xb9b9b9b9, 0x86868686, 0xc1c1c1c1, 0x1d1d1d1d, 0x9e9e9e9e,
0xe1e1e1e1, 0xf8f8f8f8, 0x98989898, 0x11111111, 0x69696969, 0xd9d9d9d9, 0x8e8e8e8e, 0x94949494, 0x9b9b9b9b, 0x1e1e1e1e, 0x87878787, 0xe9e9e9e9, 0xcececece, 0x55555555, 0x28282828, 0xdfdfdfdf,
0x8c8c8c8c, 0xa1a1a1a1, 0x89898989, 0x0d0d0d0d, 0xbfbfbfbf, 0xe6e6e6e6, 0x42424242, 0x68686868, 0x41414141, 0x99999999, 0x2d2d2d2d, 0x0f0f0f0f, 0xb0b0b0b0, 0x54545454, 0xbbbbbbbb, 0x16161616 };
const uint32_t AES::Td0[256] = { 0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96, 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393, 0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25, 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f,
0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1, 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6, 0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da, 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844,
0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd, 0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4, 0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45, 0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94,
0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7, 0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a, 0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5, 0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c,
0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1, 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a, 0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75, 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051,
0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46, 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff, 0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77, 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb,
0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000, 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e, 0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927, 0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a,
0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e, 0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16, 0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d, 0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8,
0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd, 0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34, 0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163, 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120,
0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d, 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0, 0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422, 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef,
0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36, 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4, 0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662, 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5,
0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3, 0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b, 0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8, 0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6,
0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6, 0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0, 0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815, 0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f,
0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df, 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f, 0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e, 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713,
0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89, 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c, 0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf, 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86,
0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f, 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541, 0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190, 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742 };
const uint8_t AES::Td4[256] = { 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d };
const uint32_t AES::rcon[15] = { 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000, 0x6c000000, 0xd8000000, 0xab000000, 0x4d000000, 0x9a000000 }; const uint32_t AES::rcon[15] = { 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000, 0x6c000000, 0xd8000000, 0xab000000, 0x4d000000, 0x9a000000 };
void AES::p_initSW(const uint8_t* key) noexcept void AES::p_initSW(const uint8_t* key) noexcept

View file

@ -15,8 +15,8 @@
#define ZT_AES_HPP #define ZT_AES_HPP
#include "Constants.hpp" #include "Constants.hpp"
#include "Utils.hpp"
#include "SHA512.hpp" #include "SHA512.hpp"
#include "Utils.hpp"
// Uncomment to disable all hardware acceleration (usually for testing) // Uncomment to disable all hardware acceleration (usually for testing)
// #define ZT_AES_NO_ACCEL // #define ZT_AES_NO_ACCEL
@ -40,8 +40,7 @@ namespace ZeroTier {
* This includes hardware acceleration for certain processors. The software * This includes hardware acceleration for certain processors. The software
* mode is fallback and is significantly slower. * mode is fallback and is significantly slower.
*/ */
class AES class AES {
{
public: public:
/** /**
* @return True if this system has hardware AES acceleration * @return True if this system has hardware AES acceleration
@ -63,7 +62,8 @@ public:
* Create an un-initialized AES instance (must call init() before use) * Create an un-initialized AES instance (must call init() before use)
*/ */
ZT_INLINE AES() noexcept ZT_INLINE AES() noexcept
{} {
}
/** /**
* Create an AES instance with the given key * Create an AES instance with the given key
@ -71,10 +71,14 @@ public:
* @param key 256-bit key * @param key 256-bit key
*/ */
explicit ZT_INLINE AES(const void* const key) noexcept explicit ZT_INLINE AES(const void* const key) noexcept
{ this->init(key); } {
this->init(key);
}
ZT_INLINE ~AES() ZT_INLINE ~AES()
{ Utils::burn(&p_k, sizeof(p_k)); } {
Utils::burn(&p_k, sizeof(p_k));
}
/** /**
* Set (or re-set) this AES256 cipher's key * Set (or re-set) this AES256 cipher's key
@ -150,8 +154,7 @@ public:
/** /**
* Streaming GMAC calculator * Streaming GMAC calculator
*/ */
class GMAC class GMAC {
{
friend class GMACSIVEncryptor; friend class GMACSIVEncryptor;
friend class GMACSIVDecryptor; friend class GMACSIVDecryptor;
@ -178,7 +181,8 @@ public:
* @param aes Keyed AES instance to use * @param aes Keyed AES instance to use
*/ */
ZT_INLINE GMAC(const AES& aes) : _aes(aes) ZT_INLINE GMAC(const AES& aes) : _aes(aes)
{} {
}
/** /**
* Reset and initialize for a new GMAC calculation * Reset and initialize for a new GMAC calculation
@ -249,14 +253,14 @@ public:
* NOTE: this doesn't support overflow of the counter in the least significant 32 bits. * NOTE: this doesn't support overflow of the counter in the least significant 32 bits.
* AES-GMAC-CTR doesn't need this, so we don't support it as an optimization. * AES-GMAC-CTR doesn't need this, so we don't support it as an optimization.
*/ */
class CTR class CTR {
{
friend class GMACSIVEncryptor; friend class GMACSIVEncryptor;
friend class GMACSIVDecryptor; friend class GMACSIVDecryptor;
public: public:
ZT_INLINE CTR(const AES& aes) noexcept : _aes(aes) ZT_INLINE CTR(const AES& aes) noexcept : _aes(aes)
{} {
}
/** /**
* Initialize this CTR instance to encrypt a new stream * Initialize this CTR instance to encrypt a new stream
@ -325,8 +329,7 @@ public:
* This supports encryption of a maximum of 2^31 bytes of data per * This supports encryption of a maximum of 2^31 bytes of data per
* call to init(). * call to init().
*/ */
class GMACSIVEncryptor class GMACSIVEncryptor {
{
public: public:
/** /**
* Create a new AES-GMAC-SIV encryptor keyed with the provided AES instances * Create a new AES-GMAC-SIV encryptor keyed with the provided AES instances
@ -334,10 +337,11 @@ public:
* @param k0 First of two AES instances keyed with K0 * @param k0 First of two AES instances keyed with K0
* @param k1 Second of two AES instances keyed with K1 * @param k1 Second of two AES instances keyed with K1
*/ */
ZT_INLINE GMACSIVEncryptor(const AES &k0, const AES &k1) noexcept : ZT_INLINE GMACSIVEncryptor(const AES& k0, const AES& k1) noexcept
_gmac(k0), : _gmac(k0)
_ctr(k1) , _ctr(k1)
{} {
}
/** /**
* Initialize AES-GMAC-SIV * Initialize AES-GMAC-SIV
@ -386,7 +390,9 @@ public:
* @param len Length of plaintext chunk * @param len Length of plaintext chunk
*/ */
ZT_INLINE void update1(const void* const input, const unsigned int len) noexcept ZT_INLINE void update1(const void* const input, const unsigned int len) noexcept
{ _gmac.update(input, len); } {
_gmac.update(input, len);
}
/** /**
* Finish first pass, compute CTR IV, initialize second pass. * Finish first pass, compute CTR IV, initialize second pass.
@ -428,7 +434,9 @@ public:
* @param len Length of plaintext chunk * @param len Length of plaintext chunk
*/ */
ZT_INLINE void update2(const void* const input, const unsigned int len) noexcept ZT_INLINE void update2(const void* const input, const unsigned int len) noexcept
{ _ctr.crypt(input, len); } {
_ctr.crypt(input, len);
}
/** /**
* Finish second pass and return a pointer to the opaque 128-bit IV+MAC block * Finish second pass and return a pointer to the opaque 128-bit IV+MAC block
@ -456,13 +464,13 @@ public:
* *
* GMAC-SIV decryption is single-pass. AAD (if any) must be processed first. * GMAC-SIV decryption is single-pass. AAD (if any) must be processed first.
*/ */
class GMACSIVDecryptor class GMACSIVDecryptor {
{
public: public:
ZT_INLINE GMACSIVDecryptor(const AES &k0, const AES &k1) noexcept: ZT_INLINE GMACSIVDecryptor(const AES& k0, const AES& k1) noexcept
_ctr(k1), : _ctr(k1)
_gmac(k0) , _gmac(k0)
{} {
}
/** /**
* Initialize decryptor for a new message * Initialize decryptor for a new message
@ -550,11 +558,9 @@ private:
void p_encryptSW(const uint8_t* in, uint8_t* out) const noexcept; void p_encryptSW(const uint8_t* in, uint8_t* out) const noexcept;
void p_decryptSW(const uint8_t* in, uint8_t* out) const noexcept; void p_decryptSW(const uint8_t* in, uint8_t* out) const noexcept;
union union {
{
#ifdef ZT_AES_AESNI #ifdef ZT_AES_AESNI
struct struct {
{
__m128i k[28]; __m128i k[28];
__m128i h[4]; // h, hh, hhh, hhhh __m128i h[4]; // h, hh, hhh, hhhh
__m128i h2[4]; // _mm_xor_si128(_mm_shuffle_epi32(h, 78), h), etc. __m128i h2[4]; // _mm_xor_si128(_mm_shuffle_epi32(h, 78), h), etc.
@ -562,8 +568,7 @@ private:
#endif #endif
#ifdef ZT_AES_NEON #ifdef ZT_AES_NEON
struct struct {
{
uint64_t hsw[2]; // in case it has AES but not PMULL, not sure if that ever happens uint64_t hsw[2]; // in case it has AES but not PMULL, not sure if that ever happens
uint8x16_t ek[15]; uint8x16_t ek[15];
uint8x16_t dk[15]; uint8x16_t dk[15];
@ -571,8 +576,7 @@ private:
} neon; } neon;
#endif #endif
struct struct {
{
uint64_t h[2]; uint64_t h[2];
uint32_t ek[60]; uint32_t ek[60];
uint32_t dk[60]; uint32_t dk[60];

View file

@ -11,8 +11,8 @@
*/ */
/****/ /****/
#include "Constants.hpp"
#include "AES.hpp" #include "AES.hpp"
#include "Constants.hpp"
#ifdef ZT_AES_AESNI #ifdef ZT_AES_AESNI
@ -29,7 +29,8 @@ const __m128i s_sseSwapBytes = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
#ifdef __GNUC__ #ifdef __GNUC__
__attribute__((__target__("ssse3,sse4,sse4.1,sse4.2,pclmul"))) __attribute__((__target__("ssse3,sse4,sse4.1,sse4.2,pclmul")))
#endif #endif
__m128i p_gmacPCLMUL128(const __m128i h, __m128i y) noexcept __m128i
p_gmacPCLMUL128(const __m128i h, __m128i y) noexcept
{ {
y = _mm_shuffle_epi8(y, s_sseSwapBytes); y = _mm_shuffle_epi8(y, s_sseSwapBytes);
__m128i t1 = _mm_clmulepi64_si128(h, y, 0x00); __m128i t1 = _mm_clmulepi64_si128(h, y, 0x00);
@ -81,11 +82,7 @@ void p_aesCtrInnerVAES512(unsigned int &len, const uint64_t c0, uint64_t &c1, co
const __m512i kk14 = _mm512_broadcast_i32x4(k[14]); const __m512i kk14 = _mm512_broadcast_i32x4(k[14]);
do { do {
__m512i p0 = _mm512_loadu_si512(reinterpret_cast<const __m512i*>(in)); __m512i p0 = _mm512_loadu_si512(reinterpret_cast<const __m512i*>(in));
__m512i d0 = _mm512_set_epi64( __m512i d0 = _mm512_set_epi64((long long)Utils::hton(c1 + 3ULL), (long long)c0, (long long)Utils::hton(c1 + 2ULL), (long long)c0, (long long)Utils::hton(c1 + 1ULL), (long long)c0, (long long)Utils::hton(c1), (long long)c0);
(long long)Utils::hton(c1 + 3ULL), (long long)c0,
(long long)Utils::hton(c1 + 2ULL), (long long)c0,
(long long)Utils::hton(c1 + 1ULL), (long long)c0,
(long long)Utils::hton(c1), (long long)c0);
c1 += 4; c1 += 4;
in += 64; in += 64;
len -= 64; len -= 64;
@ -134,12 +131,8 @@ void p_aesCtrInnerVAES256(unsigned int &len, const uint64_t c0, uint64_t &c1, co
do { do {
__m256i p0 = _mm256_loadu_si256(reinterpret_cast<const __m256i*>(in)); __m256i p0 = _mm256_loadu_si256(reinterpret_cast<const __m256i*>(in));
__m256i p1 = _mm256_loadu_si256(reinterpret_cast<const __m256i*>(in + 32)); __m256i p1 = _mm256_loadu_si256(reinterpret_cast<const __m256i*>(in + 32));
__m256i d0 = _mm256_set_epi64x( __m256i d0 = _mm256_set_epi64x((long long)Utils::hton(c1 + 1ULL), (long long)c0, (long long)Utils::hton(c1), (long long)c0);
(long long)Utils::hton(c1 + 1ULL), (long long)c0, __m256i d1 = _mm256_set_epi64x((long long)Utils::hton(c1 + 3ULL), (long long)c0, (long long)Utils::hton(c1 + 2ULL), (long long)c0);
(long long)Utils::hton(c1), (long long)c0);
__m256i d1 = _mm256_set_epi64x(
(long long)Utils::hton(c1 + 3ULL), (long long)c0,
(long long)Utils::hton(c1 + 2ULL), (long long)c0);
c1 += 4; c1 += 4;
in += 64; in += 64;
len -= 64; len -= 64;
@ -184,7 +177,8 @@ void p_aesCtrInnerVAES256(unsigned int &len, const uint64_t c0, uint64_t &c1, co
#ifdef __GNUC__ #ifdef __GNUC__
__attribute__((__target__("ssse3,sse4,sse4.1,sse4.2,aes,pclmul"))) __attribute__((__target__("ssse3,sse4,sse4.1,sse4.2,aes,pclmul")))
#endif #endif
__m128i p_init256_1_aesni(__m128i a, __m128i b) noexcept __m128i
p_init256_1_aesni(__m128i a, __m128i b) noexcept
{ {
__m128i x, y; __m128i x, y;
b = _mm_shuffle_epi32(b, 0xff); b = _mm_shuffle_epi32(b, 0xff);
@ -201,7 +195,8 @@ __m128i p_init256_1_aesni(__m128i a, __m128i b) noexcept
#ifdef __GNUC__ #ifdef __GNUC__
__attribute__((__target__("ssse3,sse4,sse4.1,sse4.2,aes,pclmul"))) __attribute__((__target__("ssse3,sse4,sse4.1,sse4.2,aes,pclmul")))
#endif #endif
__m128i p_init256_2_aesni(__m128i a, __m128i b) noexcept __m128i
p_init256_2_aesni(__m128i a, __m128i b) noexcept
{ {
__m128i x, y, z; __m128i x, y, z;
y = _mm_aeskeygenassist_si128(a, 0x00); y = _mm_aeskeygenassist_si128(a, 0x00);
@ -260,7 +255,11 @@ void AES::GMAC::p_aesNIUpdate(const uint8_t *in, unsigned int len) noexcept
in += 64; in += 64;
__m128i a = _mm_xor_si128(_mm_xor_si128(_mm_clmulepi64_si128(hhhh, d1, 0x00), _mm_clmulepi64_si128(hhh, d2, 0x00)), _mm_xor_si128(_mm_clmulepi64_si128(hh, d3, 0x00), _mm_clmulepi64_si128(h, d4, 0x00))); __m128i a = _mm_xor_si128(_mm_xor_si128(_mm_clmulepi64_si128(hhhh, d1, 0x00), _mm_clmulepi64_si128(hhh, d2, 0x00)), _mm_xor_si128(_mm_clmulepi64_si128(hh, d3, 0x00), _mm_clmulepi64_si128(h, d4, 0x00)));
__m128i b = _mm_xor_si128(_mm_xor_si128(_mm_clmulepi64_si128(hhhh, d1, 0x11), _mm_clmulepi64_si128(hhh, d2, 0x11)), _mm_xor_si128(_mm_clmulepi64_si128(hh, d3, 0x11), _mm_clmulepi64_si128(h, d4, 0x11))); __m128i b = _mm_xor_si128(_mm_xor_si128(_mm_clmulepi64_si128(hhhh, d1, 0x11), _mm_clmulepi64_si128(hhh, d2, 0x11)), _mm_xor_si128(_mm_clmulepi64_si128(hh, d3, 0x11), _mm_clmulepi64_si128(h, d4, 0x11)));
__m128i c = _mm_xor_si128(_mm_xor_si128(_mm_xor_si128(_mm_clmulepi64_si128(hhhh2, _mm_xor_si128(_mm_shuffle_epi32(d1, 78), d1), 0x00), _mm_clmulepi64_si128(hhh2, _mm_xor_si128(_mm_shuffle_epi32(d2, 78), d2), 0x00)), _mm_xor_si128(_mm_clmulepi64_si128(hh2, _mm_xor_si128(_mm_shuffle_epi32(d3, 78), d3), 0x00), _mm_clmulepi64_si128(h2, _mm_xor_si128(_mm_shuffle_epi32(d4, 78), d4), 0x00))), _mm_xor_si128(a, b)); __m128i c = _mm_xor_si128(
_mm_xor_si128(
_mm_xor_si128(_mm_clmulepi64_si128(hhhh2, _mm_xor_si128(_mm_shuffle_epi32(d1, 78), d1), 0x00), _mm_clmulepi64_si128(hhh2, _mm_xor_si128(_mm_shuffle_epi32(d2, 78), d2), 0x00)),
_mm_xor_si128(_mm_clmulepi64_si128(hh2, _mm_xor_si128(_mm_shuffle_epi32(d3, 78), d3), 0x00), _mm_clmulepi64_si128(h2, _mm_xor_si128(_mm_shuffle_epi32(d4, 78), d4), 0x00))),
_mm_xor_si128(a, b));
a = _mm_xor_si128(_mm_slli_si128(c, 8), a); a = _mm_xor_si128(_mm_slli_si128(c, 8), a);
b = _mm_xor_si128(_mm_srli_si128(c, 8), b); b = _mm_xor_si128(_mm_srli_si128(c, 8), b);
c = _mm_srli_epi32(a, 31); c = _mm_srli_epi32(a, 31);
@ -427,12 +426,12 @@ void AES::CTR::p_aesNICrypt(const uint8_t *in, uint8_t *out, unsigned int len) n
_len = totalLen + len; _len = totalLen + len;
if (likely(len >= 64)) { if (likely(len >= 64)) {
#if defined(ZT_AES_VAES512) && defined(ZT_AES_VAES256) #if defined(ZT_AES_VAES512) && defined(ZT_AES_VAES256)
if (Utils::CPUID.vaes && (len >= 256)) { if (Utils::CPUID.vaes && (len >= 256)) {
if (Utils::CPUID.avx512f) { if (Utils::CPUID.avx512f) {
p_aesCtrInnerVAES512(len, _ctr[0], c1, in, out, k); p_aesCtrInnerVAES512(len, _ctr[0], c1, in, out, k);
} else { }
else {
p_aesCtrInnerVAES256(len, _ctr[0], c1, in, out, k); p_aesCtrInnerVAES256(len, _ctr[0], c1, in, out, k);
} }
goto skip_conventional_aesni_64; goto skip_conventional_aesni_64;
@ -526,7 +525,6 @@ void AES::CTR::p_aesNICrypt(const uint8_t *in, uint8_t *out, unsigned int len) n
_mm_storeu_si128(reinterpret_cast<__m128i*>(out + 48), d3); _mm_storeu_si128(reinterpret_cast<__m128i*>(out + 48), d3);
out += 64; out += 64;
} while (likely(in != eof64)); } while (likely(in != eof64));
} }
skip_conventional_aesni_64: skip_conventional_aesni_64:

View file

@ -11,8 +11,8 @@
*/ */
/****/ /****/
#include "Constants.hpp"
#include "AES.hpp" #include "AES.hpp"
#include "Constants.hpp"
#ifdef ZT_AES_NEON #ifdef ZT_AES_NEON
@ -309,9 +309,14 @@ void AES::CTR::p_armCrypt(const uint8_t *in, uint8_t *out, unsigned int len) noe
void AES::p_init_armneon_crypto(const uint8_t* key) noexcept void AES::p_init_armneon_crypto(const uint8_t* key) noexcept
{ {
static const uint8_t s_sbox[256] = {0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, static const uint8_t s_sbox[256] = { 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16}; 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 };
uint64_t h[2]; uint64_t h[2];
uint32_t* const w = reinterpret_cast<uint32_t*>(p_k.neon.ek); uint32_t* const w = reinterpret_cast<uint32_t*>(p_k.neon.ek);
@ -326,7 +331,8 @@ void AES::p_init_armneon_crypto(const uint8_t *key) noexcept
const unsigned int imod = i & (ZT_INIT_ARMNEON_CRYPTO_NK - 1); const unsigned int imod = i & (ZT_INIT_ARMNEON_CRYPTO_NK - 1);
if (imod == 0) { if (imod == 0) {
t = ZT_INIT_ARMNEON_CRYPTO_SUBWORD(ZT_INIT_ARMNEON_CRYPTO_ROTWORD(t)) ^ rcon[(i - 1) / ZT_INIT_ARMNEON_CRYPTO_NK]; t = ZT_INIT_ARMNEON_CRYPTO_SUBWORD(ZT_INIT_ARMNEON_CRYPTO_ROTWORD(t)) ^ rcon[(i - 1) / ZT_INIT_ARMNEON_CRYPTO_NK];
} else if (imod == 4) { }
else if (imod == 4) {
t = ZT_INIT_ARMNEON_CRYPTO_SUBWORD(t); t = ZT_INIT_ARMNEON_CRYPTO_SUBWORD(t);
} }
w[i] = w[i - ZT_INIT_ARMNEON_CRYPTO_NK] ^ t; w[i] = w[i - ZT_INIT_ARMNEON_CRYPTO_NK] ^ t;

View file

@ -14,37 +14,52 @@
#ifndef ZT_ADDRESS_HPP #ifndef ZT_ADDRESS_HPP
#define ZT_ADDRESS_HPP #define ZT_ADDRESS_HPP
#include <stdio.h> #include "Buffer.hpp"
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <string>
#include "Constants.hpp" #include "Constants.hpp"
#include "Utils.hpp" #include "Utils.hpp"
#include "Buffer.hpp"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
namespace ZeroTier { namespace ZeroTier {
/** /**
* A ZeroTier address * A ZeroTier address
*/ */
class Address class Address {
{
public: public:
Address() : _a(0) {} Address() : _a(0)
Address(const Address &a) : _a(a._a) {} {
Address(uint64_t a) : _a(a & 0xffffffffffULL) {} }
Address(const Address& a) : _a(a._a)
{
}
Address(uint64_t a) : _a(a & 0xffffffffffULL)
{
}
/** /**
* @param bits Raw address -- 5 bytes, big-endian byte order * @param bits Raw address -- 5 bytes, big-endian byte order
* @param len Length of array * @param len Length of array
*/ */
Address(const void *bits,unsigned int len) { setTo(bits,len); } Address(const void* bits, unsigned int len)
{
setTo(bits, len);
}
inline Address &operator=(const Address &a) { _a = a._a; return *this; } inline Address& operator=(const Address& a)
inline Address &operator=(const uint64_t a) { _a = (a & 0xffffffffffULL); return *this; } {
_a = a._a;
return *this;
}
inline Address& operator=(const uint64_t a)
{
_a = (a & 0xffffffffffULL);
return *this;
}
/** /**
* @param bits Raw address -- 5 bytes, big-endian byte order * @param bits Raw address -- 5 bytes, big-endian byte order
@ -87,8 +102,7 @@ public:
* *
* @param b Buffer to append to * @param b Buffer to append to
*/ */
template<unsigned int C> template <unsigned int C> inline void appendTo(Buffer<C>& b) const
inline void appendTo(Buffer<C> &b) const
{ {
unsigned char* p = (unsigned char*)b.appendField(ZT_ADDRESS_LENGTH); unsigned char* p = (unsigned char*)b.appendField(ZT_ADDRESS_LENGTH);
*(p++) = (unsigned char)((_a >> 32) & 0xff); *(p++) = (unsigned char)((_a >> 32) & 0xff);
@ -101,22 +115,34 @@ public:
/** /**
* @return Integer containing address (0 to 2^40) * @return Integer containing address (0 to 2^40)
*/ */
inline uint64_t toInt() const { return _a; } inline uint64_t toInt() const
{
return _a;
}
/** /**
* @return Hash code for use with Hashtable * @return Hash code for use with Hashtable
*/ */
inline unsigned long hashCode() const { return (unsigned long)_a; } inline unsigned long hashCode() const
{
return (unsigned long)_a;
}
/** /**
* @return Hexadecimal string * @return Hexadecimal string
*/ */
inline char *toString(char buf[11]) const { return Utils::hex10(_a,buf); } inline char* toString(char buf[11]) const
{
return Utils::hex10(_a, buf);
}
/** /**
* @return True if this address is not zero * @return True if this address is not zero
*/ */
inline operator bool() const { return (_a != 0); } inline operator bool() const
{
return (_a != 0);
}
/** /**
* Check if this address is reserved * Check if this address is reserved
@ -127,29 +153,74 @@ public:
* *
* @return True if address is reserved and may not be used * @return True if address is reserved and may not be used
*/ */
inline bool isReserved() const { return ((!_a)||((_a >> 32) == ZT_ADDRESS_RESERVED_PREFIX)); } inline bool isReserved() const
{
return ((! _a) || ((_a >> 32) == ZT_ADDRESS_RESERVED_PREFIX));
}
/** /**
* @param i Value from 0 to 4 (inclusive) * @param i Value from 0 to 4 (inclusive)
* @return Byte at said position (address interpreted in big-endian order) * @return Byte at said position (address interpreted in big-endian order)
*/ */
inline uint8_t operator[](unsigned int i) const { return (uint8_t)(_a >> (32 - (i * 8))); } inline uint8_t operator[](unsigned int i) const
{
return (uint8_t)(_a >> (32 - (i * 8)));
}
inline void zero() { _a = 0; } inline void zero()
{
_a = 0;
}
inline bool operator==(const uint64_t &a) const { return (_a == (a & 0xffffffffffULL)); } inline bool operator==(const uint64_t& a) const
inline bool operator!=(const uint64_t &a) const { return (_a != (a & 0xffffffffffULL)); } {
inline bool operator>(const uint64_t &a) const { return (_a > (a & 0xffffffffffULL)); } return (_a == (a & 0xffffffffffULL));
inline bool operator<(const uint64_t &a) const { return (_a < (a & 0xffffffffffULL)); } }
inline bool operator>=(const uint64_t &a) const { return (_a >= (a & 0xffffffffffULL)); } inline bool operator!=(const uint64_t& a) const
inline bool operator<=(const uint64_t &a) const { return (_a <= (a & 0xffffffffffULL)); } {
return (_a != (a & 0xffffffffffULL));
}
inline bool operator>(const uint64_t& a) const
{
return (_a > (a & 0xffffffffffULL));
}
inline bool operator<(const uint64_t& a) const
{
return (_a < (a & 0xffffffffffULL));
}
inline bool operator>=(const uint64_t& a) const
{
return (_a >= (a & 0xffffffffffULL));
}
inline bool operator<=(const uint64_t& a) const
{
return (_a <= (a & 0xffffffffffULL));
}
inline bool operator==(const Address &a) const { return (_a == a._a); } inline bool operator==(const Address& a) const
inline bool operator!=(const Address &a) const { return (_a != a._a); } {
inline bool operator>(const Address &a) const { return (_a > a._a); } return (_a == a._a);
inline bool operator<(const Address &a) const { return (_a < a._a); } }
inline bool operator>=(const Address &a) const { return (_a >= a._a); } inline bool operator!=(const Address& a) const
inline bool operator<=(const Address &a) const { return (_a <= a._a); } {
return (_a != a._a);
}
inline bool operator>(const Address& a) const
{
return (_a > a._a);
}
inline bool operator<(const Address& a) const
{
return (_a < a._a);
}
inline bool operator>=(const Address& a) const
{
return (_a >= a._a);
}
inline bool operator<=(const Address& a) const
{
return (_a <= a._a);
}
private: private:
uint64_t _a; uint64_t _a;

View file

@ -25,10 +25,12 @@ namespace ZeroTier {
/** /**
* Simple atomic counter supporting increment and decrement * Simple atomic counter supporting increment and decrement
*/ */
class AtomicCounter class AtomicCounter {
{
public: public:
AtomicCounter() { _v = 0; } AtomicCounter()
{
_v = 0;
}
inline int load() const inline int load() const
{ {
@ -58,8 +60,13 @@ public:
} }
private: private:
AtomicCounter(const AtomicCounter &) {} AtomicCounter(const AtomicCounter&)
const AtomicCounter &operator=(const AtomicCounter &) { return *this; } {
}
const AtomicCounter& operator=(const AtomicCounter&)
{
return *this;
}
#ifdef __GNUC__ #ifdef __GNUC__
int _v; int _v;

View file

@ -14,17 +14,16 @@
#ifndef ZT_BUFFER_HPP #ifndef ZT_BUFFER_HPP
#define ZT_BUFFER_HPP #define ZT_BUFFER_HPP
#include <string.h>
#include <stdint.h>
#include <stdexcept>
#include <string>
#include <algorithm>
#include <utility>
#include "Constants.hpp" #include "Constants.hpp"
#include "Utils.hpp" #include "Utils.hpp"
#include <algorithm>
#include <stdexcept>
#include <stdint.h>
#include <string.h>
#include <string>
#include <utility>
#if defined(__GNUC__) && (! defined(ZT_NO_TYPE_PUNNING)) #if defined(__GNUC__) && (! defined(ZT_NO_TYPE_PUNNING))
#define ZT_VAR_MAY_ALIAS __attribute__((__may_alias__)) #define ZT_VAR_MAY_ALIAS __attribute__((__may_alias__))
#else #else
@ -46,9 +45,7 @@ namespace ZeroTier {
* *
* @tparam C Total capacity * @tparam C Total capacity
*/ */
template<unsigned int C> template <unsigned int C> class Buffer {
class Buffer
{
// I love me! // I love me!
template <unsigned int C2> friend class Buffer; template <unsigned int C2> friend class Buffer;
@ -65,17 +62,40 @@ public:
typedef int difference_type; typedef int difference_type;
typedef std::reverse_iterator<iterator> reverse_iterator; typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator; typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
inline iterator begin() { return _b; } inline iterator begin()
inline iterator end() { return (_b + _l); } {
inline const_iterator begin() const { return _b; } return _b;
inline const_iterator end() const { return (_b + _l); } }
inline reverse_iterator rbegin() { return reverse_iterator(begin()); } inline iterator end()
inline reverse_iterator rend() { return reverse_iterator(end()); } {
inline const_reverse_iterator rbegin() const { return const_reverse_iterator(begin()); } return (_b + _l);
inline const_reverse_iterator rend() const { return const_reverse_iterator(end()); } }
inline const_iterator begin() const
{
return _b;
}
inline const_iterator end() const
{
return (_b + _l);
}
inline reverse_iterator rbegin()
{
return reverse_iterator(begin());
}
inline reverse_iterator rend()
{
return reverse_iterator(end());
}
inline const_reverse_iterator rbegin() const
{
return const_reverse_iterator(begin());
}
inline const_reverse_iterator rend() const
{
return const_reverse_iterator(end());
}
Buffer() : Buffer() : _l(0)
_l(0)
{ {
} }
@ -87,8 +107,7 @@ public:
_l = l; _l = l;
} }
template<unsigned int C2> template <unsigned int C2> Buffer(const Buffer<C2>& b)
Buffer(const Buffer<C2> &b)
{ {
*this = b; *this = b;
} }
@ -98,15 +117,15 @@ public:
copyFrom(b, l); copyFrom(b, l);
} }
template<unsigned int C2> template <unsigned int C2> inline Buffer& operator=(const Buffer<C2>& b)
inline Buffer &operator=(const Buffer<C2> &b)
{ {
if (unlikely(b._l > C)) { if (unlikely(b._l > C)) {
throw ZT_EXCEPTION_OUT_OF_BOUNDS; throw ZT_EXCEPTION_OUT_OF_BOUNDS;
} }
if (C2 == C) { if (C2 == C) {
memcpy(this, &b, sizeof(Buffer<C>)); memcpy(this, &b, sizeof(Buffer<C>));
} else { }
else {
memcpy(_b, b._b, _l = b._l); memcpy(_b, b._b, _l = b._l);
} }
return *this; return *this;
@ -172,8 +191,7 @@ public:
* @param v Value * @param v Value
* @tparam T Integer type (e.g. uint16_t, int64_t) * @tparam T Integer type (e.g. uint16_t, int64_t)
*/ */
template<typename T> template <typename T> inline void setAt(unsigned int i, const T v)
inline void setAt(unsigned int i,const T v)
{ {
if (unlikely((i + sizeof(T)) > _l)) { if (unlikely((i + sizeof(T)) > _l)) {
throw ZT_EXCEPTION_OUT_OF_BOUNDS; throw ZT_EXCEPTION_OUT_OF_BOUNDS;
@ -196,8 +214,7 @@ public:
* @tparam T Integer type (e.g. uint16_t, int64_t) * @tparam T Integer type (e.g. uint16_t, int64_t)
* @return Integer value * @return Integer value
*/ */
template<typename T> template <typename T> inline T at(unsigned int i) const
inline T at(unsigned int i) const
{ {
if (unlikely((i + sizeof(T)) > _l)) { if (unlikely((i + sizeof(T)) > _l)) {
throw ZT_EXCEPTION_OUT_OF_BOUNDS; throw ZT_EXCEPTION_OUT_OF_BOUNDS;
@ -223,8 +240,7 @@ public:
* @tparam T Integer type (e.g. uint16_t, int64_t) * @tparam T Integer type (e.g. uint16_t, int64_t)
* @throws std::out_of_range Attempt to append beyond capacity * @throws std::out_of_range Attempt to append beyond capacity
*/ */
template<typename T> template <typename T> inline void append(const T v)
inline void append(const T v)
{ {
if (unlikely((_l + sizeof(T)) > C)) { if (unlikely((_l + sizeof(T)) > C)) {
throw ZT_EXCEPTION_OUT_OF_BOUNDS; throw ZT_EXCEPTION_OUT_OF_BOUNDS;
@ -313,8 +329,7 @@ public:
* @tparam C2 Capacity of second buffer (typically inferred) * @tparam C2 Capacity of second buffer (typically inferred)
* @throws std::out_of_range Attempt to append beyond capacity * @throws std::out_of_range Attempt to append beyond capacity
*/ */
template<unsigned int C2> template <unsigned int C2> inline void append(const Buffer<C2>& b)
inline void append(const Buffer<C2> &b)
{ {
append(b._b, b._l); append(b._b, b._l);
} }
@ -408,70 +423,88 @@ public:
/** /**
* Set buffer data length to zero * Set buffer data length to zero
*/ */
inline void clear() { _l = 0; } inline void clear()
{
_l = 0;
}
/** /**
* Zero buffer up to size() * Zero buffer up to size()
*/ */
inline void zero() { memset(_b,0,_l); } inline void zero()
{
memset(_b, 0, _l);
}
/** /**
* Zero unused capacity area * Zero unused capacity area
*/ */
inline void zeroUnused() { memset(_b + _l,0,C - _l); } inline void zeroUnused()
{
memset(_b + _l, 0, C - _l);
}
/** /**
* Unconditionally and securely zero buffer's underlying memory * Unconditionally and securely zero buffer's underlying memory
*/ */
inline void burn() { Utils::burn(_b,sizeof(_b)); } inline void burn()
{
Utils::burn(_b, sizeof(_b));
}
/** /**
* @return Constant pointer to data in buffer * @return Constant pointer to data in buffer
*/ */
inline const void *data() const { return _b; } inline const void* data() const
{
return _b;
}
/** /**
* @return Non-constant pointer to data in buffer * @return Non-constant pointer to data in buffer
*/ */
inline void *unsafeData() { return _b; } inline void* unsafeData()
{
return _b;
}
/** /**
* @return Size of data in buffer * @return Size of data in buffer
*/ */
inline unsigned int size() const { return _l; } inline unsigned int size() const
{
return _l;
}
/** /**
* @return Capacity of buffer * @return Capacity of buffer
*/ */
inline unsigned int capacity() const { return C; } inline unsigned int capacity() const
{
return C;
}
template<unsigned int C2> template <unsigned int C2> inline bool operator==(const Buffer<C2>& b) const
inline bool operator==(const Buffer<C2> &b) const
{ {
return ((_l == b._l) && (! memcmp(_b, b._b, _l))); return ((_l == b._l) && (! memcmp(_b, b._b, _l)));
} }
template<unsigned int C2> template <unsigned int C2> inline bool operator!=(const Buffer<C2>& b) const
inline bool operator!=(const Buffer<C2> &b) const
{ {
return ((_l != b._l) || (memcmp(_b, b._b, _l))); return ((_l != b._l) || (memcmp(_b, b._b, _l)));
} }
template<unsigned int C2> template <unsigned int C2> inline bool operator<(const Buffer<C2>& b) const
inline bool operator<(const Buffer<C2> &b) const
{ {
return (memcmp(_b, b._b, std::min(_l, b._l)) < 0); return (memcmp(_b, b._b, std::min(_l, b._l)) < 0);
} }
template<unsigned int C2> template <unsigned int C2> inline bool operator>(const Buffer<C2>& b) const
inline bool operator>(const Buffer<C2> &b) const
{ {
return (b < *this); return (b < *this);
} }
template<unsigned int C2> template <unsigned int C2> inline bool operator<=(const Buffer<C2>& b) const
inline bool operator<=(const Buffer<C2> &b) const
{ {
return ! (b < *this); return ! (b < *this);
} }
template<unsigned int C2> template <unsigned int C2> inline bool operator>=(const Buffer<C2>& b) const
inline bool operator>=(const Buffer<C2> &b) const
{ {
return ! (*this < b); return ! (*this < b);
} }

View file

@ -12,12 +12,13 @@
/****/ /****/
#include "Capability.hpp" #include "Capability.hpp"
#include "RuntimeEnvironment.hpp"
#include "Identity.hpp" #include "Identity.hpp"
#include "Topology.hpp"
#include "Switch.hpp"
#include "Network.hpp" #include "Network.hpp"
#include "Node.hpp" #include "Node.hpp"
#include "RuntimeEnvironment.hpp"
#include "Switch.hpp"
#include "Topology.hpp"
namespace ZeroTier { namespace ZeroTier {
@ -37,10 +38,12 @@ int Capability::verify(const RuntimeEnvironment *RR,void *tPtr) const
if ((! _custody[c].to) || (! _custody[c].from) || (_custody[c].from != Network::controllerFor(_nwid))) { if ((! _custody[c].to) || (! _custody[c].from) || (_custody[c].from != Network::controllerFor(_nwid))) {
return -1; // the first entry must be present and from the network's controller return -1; // the first entry must be present and from the network's controller
} }
} else { }
else {
if (! _custody[c].to) { if (! _custody[c].to) {
return 0; // all previous entries were valid, so we are valid return 0; // all previous entries were valid, so we are valid
} else if ((!_custody[c].from)||(_custody[c].from != _custody[c-1].to)) { }
else if ((! _custody[c].from) || (_custody[c].from != _custody[c - 1].to)) {
return -1; // otherwise if we have another entry it must be from the previous holder in the chain return -1; // otherwise if we have another entry it must be from the previous holder in the chain
} }
} }
@ -50,7 +53,8 @@ int Capability::verify(const RuntimeEnvironment *RR,void *tPtr) const
if (! id.verify(tmp.data(), tmp.size(), _custody[c].signature)) { if (! id.verify(tmp.data(), tmp.size(), _custody[c].signature)) {
return -1; return -1;
} }
} else { }
else {
RR->sw->requestWhois(tPtr, RR->node->now(), _custody[c].from); RR->sw->requestWhois(tPtr, RR->node->now(), _custody[c].from);
return 1; return 1;
} }
@ -58,7 +62,9 @@ int Capability::verify(const RuntimeEnvironment *RR,void *tPtr) const
// We reached max custody chain length and everything was valid // We reached max custody chain length and everything was valid
return 0; return 0;
} catch ( ... ) {} }
catch (...) {
}
return -1; return -1;
} }

View file

@ -14,19 +14,19 @@
#ifndef ZT_CAPABILITY_HPP #ifndef ZT_CAPABILITY_HPP
#define ZT_CAPABILITY_HPP #define ZT_CAPABILITY_HPP
#include "../include/ZeroTierOne.h"
#include "Address.hpp"
#include "Buffer.hpp"
#include "Constants.hpp"
#include "Credential.hpp"
#include "ECC.hpp"
#include "Identity.hpp"
#include "Utils.hpp"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "Constants.hpp"
#include "Credential.hpp"
#include "Address.hpp"
#include "ECC.hpp"
#include "Utils.hpp"
#include "Buffer.hpp"
#include "Identity.hpp"
#include "../include/ZeroTierOne.h"
namespace ZeroTier { namespace ZeroTier {
class RuntimeEnvironment; class RuntimeEnvironment;
@ -54,17 +54,14 @@ class RuntimeEnvironment;
* handed off between nodes. Limited transferability of capabilities is * handed off between nodes. Limited transferability of capabilities is
* a feature of true capability based security. * a feature of true capability based security.
*/ */
class Capability : public Credential class Capability : public Credential {
{
public: public:
static inline Credential::Type credentialType() { return Credential::CREDENTIAL_TYPE_CAPABILITY; } static inline Credential::Type credentialType()
{
return Credential::CREDENTIAL_TYPE_CAPABILITY;
}
Capability() : Capability() : _nwid(0), _ts(0), _id(0), _maxCustodyChainLength(0), _ruleCount(0)
_nwid(0),
_ts(0),
_id(0),
_maxCustodyChainLength(0),
_ruleCount(0)
{ {
memset(_rules, 0, sizeof(_rules)); memset(_rules, 0, sizeof(_rules));
memset(_custody, 0, sizeof(_custody)); memset(_custody, 0, sizeof(_custody));
@ -78,12 +75,12 @@ public:
* @param rules Network flow rules for this capability * @param rules Network flow rules for this capability
* @param ruleCount Number of flow rules * @param ruleCount Number of flow rules
*/ */
Capability(uint32_t id,uint64_t nwid,int64_t ts,unsigned int mccl,const ZT_VirtualNetworkRule *rules,unsigned int ruleCount) : Capability(uint32_t id, uint64_t nwid, int64_t ts, unsigned int mccl, const ZT_VirtualNetworkRule* rules, unsigned int ruleCount)
_nwid(nwid), : _nwid(nwid)
_ts(ts), , _ts(ts)
_id(id), , _id(id)
_maxCustodyChainLength((mccl > 0) ? ((mccl < ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH) ? mccl : (unsigned int)ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH) : 1), , _maxCustodyChainLength((mccl > 0) ? ((mccl < ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH) ? mccl : (unsigned int)ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH) : 1)
_ruleCount((ruleCount < ZT_MAX_CAPABILITY_RULES) ? ruleCount : ZT_MAX_CAPABILITY_RULES) , _ruleCount((ruleCount < ZT_MAX_CAPABILITY_RULES) ? ruleCount : ZT_MAX_CAPABILITY_RULES)
{ {
if (_ruleCount > 0) { if (_ruleCount > 0) {
memcpy(_rules, rules, sizeof(ZT_VirtualNetworkRule) * _ruleCount); memcpy(_rules, rules, sizeof(ZT_VirtualNetworkRule) * _ruleCount);
@ -93,27 +90,42 @@ public:
/** /**
* @return Rules -- see ruleCount() for size of array * @return Rules -- see ruleCount() for size of array
*/ */
inline const ZT_VirtualNetworkRule *rules() const { return _rules; } inline const ZT_VirtualNetworkRule* rules() const
{
return _rules;
}
/** /**
* @return Number of rules in rules() * @return Number of rules in rules()
*/ */
inline unsigned int ruleCount() const { return _ruleCount; } inline unsigned int ruleCount() const
{
return _ruleCount;
}
/** /**
* @return ID and evaluation order of this capability in network * @return ID and evaluation order of this capability in network
*/ */
inline uint32_t id() const { return _id; } inline uint32_t id() const
{
return _id;
}
/** /**
* @return Network ID for which this capability was issued * @return Network ID for which this capability was issued
*/ */
inline uint64_t networkId() const { return _nwid; } inline uint64_t networkId() const
{
return _nwid;
}
/** /**
* @return Timestamp * @return Timestamp
*/ */
inline int64_t timestamp() const { return _ts; } inline int64_t timestamp() const
{
return _ts;
}
/** /**
* @return Last 'to' address in chain of custody * @return Last 'to' address in chain of custody
@ -124,7 +136,8 @@ public:
for (unsigned int i = 0; i < ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH; ++i) { for (unsigned int i = 0; i < ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH; ++i) {
if (! _custody[i].to) { if (! _custody[i].to) {
return i2; return i2;
} else { }
else {
i2 = _custody[i].to; i2 = _custody[i].to;
} }
} }
@ -157,7 +170,9 @@ public:
return true; return true;
} }
} }
} catch ( ... ) {} }
catch (...) {
}
return false; return false;
} }
@ -169,8 +184,7 @@ public:
*/ */
int verify(const RuntimeEnvironment* RR, void* tPtr) const; int verify(const RuntimeEnvironment* RR, void* tPtr) const;
template<unsigned int C> template <unsigned int C> static inline void serializeRules(Buffer<C>& b, const ZT_VirtualNetworkRule* rules, unsigned int ruleCount)
static inline void serializeRules(Buffer<C> &b,const ZT_VirtualNetworkRule *rules,unsigned int ruleCount)
{ {
for (unsigned int i = 0; i < ruleCount; ++i) { for (unsigned int i = 0; i < ruleCount; ++i) {
// Each rule consists of its 8-bit type followed by the size of that type's // Each rule consists of its 8-bit type followed by the size of that type's
@ -284,8 +298,7 @@ public:
} }
} }
template<unsigned int C> template <unsigned int C> static inline void deserializeRules(const Buffer<C>& b, unsigned int& p, ZT_VirtualNetworkRule* rules, unsigned int& ruleCount, const unsigned int maxRuleCount)
static inline void deserializeRules(const Buffer<C> &b,unsigned int &p,ZT_VirtualNetworkRule *rules,unsigned int &ruleCount,const unsigned int maxRuleCount)
{ {
while ((ruleCount < maxRuleCount) && (p < b.size())) { while ((ruleCount < maxRuleCount) && (p < b.size())) {
rules[ruleCount].t = (uint8_t)b[p++]; rules[ruleCount].t = (uint8_t)b[p++];
@ -380,8 +393,7 @@ public:
} }
} }
template<unsigned int C> template <unsigned int C> inline void serialize(Buffer<C>& b, const bool forSign = false) const
inline void serialize(Buffer<C> &b,const bool forSign = false) const
{ {
if (forSign) { if (forSign) {
b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL); b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
@ -404,7 +416,8 @@ public:
b.append((uint8_t)1); // 1 == Ed25519 signature b.append((uint8_t)1); // 1 == Ed25519 signature
b.append((uint16_t)ZT_ECC_SIGNATURE_LEN); // length of signature b.append((uint16_t)ZT_ECC_SIGNATURE_LEN); // length of signature
b.append(_custody[i].signature.data, ZT_ECC_SIGNATURE_LEN); b.append(_custody[i].signature.data, ZT_ECC_SIGNATURE_LEN);
} else { }
else {
b.append((unsigned char)0, ZT_ADDRESS_LENGTH); // zero 'to' terminates chain b.append((unsigned char)0, ZT_ADDRESS_LENGTH); // zero 'to' terminates chain
break; break;
} }
@ -419,8 +432,7 @@ public:
} }
} }
template<unsigned int C> template <unsigned int C> inline unsigned int deserialize(const Buffer<C>& b, unsigned int startAt = 0)
inline unsigned int deserialize(const Buffer<C> &b,unsigned int startAt = 0)
{ {
*this = Capability(); *this = Capability();
@ -464,7 +476,8 @@ public:
p += 2; p += 2;
memcpy(_custody[i].signature.data, b.field(p, ZT_ECC_SIGNATURE_LEN), ZT_ECC_SIGNATURE_LEN); memcpy(_custody[i].signature.data, b.field(p, ZT_ECC_SIGNATURE_LEN), ZT_ECC_SIGNATURE_LEN);
p += ZT_ECC_SIGNATURE_LEN; p += ZT_ECC_SIGNATURE_LEN;
} else { }
else {
p += 2 + b.template at<uint16_t>(p); p += 2 + b.template at<uint16_t>(p);
} }
} }
@ -478,10 +491,19 @@ public:
} }
// Provides natural sort order by ID // Provides natural sort order by ID
inline bool operator<(const Capability &c) const { return (_id < c._id); } inline bool operator<(const Capability& c) const
{
return (_id < c._id);
}
inline bool operator==(const Capability &c) const { return (memcmp(this,&c,sizeof(Capability)) == 0); } inline bool operator==(const Capability& c) const
inline bool operator!=(const Capability &c) const { return (memcmp(this,&c,sizeof(Capability)) != 0); } {
return (memcmp(this, &c, sizeof(Capability)) == 0);
}
inline bool operator!=(const Capability& c) const
{
return (memcmp(this, &c, sizeof(Capability)) != 0);
}
private: private:
uint64_t _nwid; uint64_t _nwid;

View file

@ -12,12 +12,13 @@
/****/ /****/
#include "CertificateOfMembership.hpp" #include "CertificateOfMembership.hpp"
#include "ECC.hpp" #include "ECC.hpp"
#include "RuntimeEnvironment.hpp"
#include "Topology.hpp"
#include "Switch.hpp"
#include "Network.hpp" #include "Network.hpp"
#include "Node.hpp" #include "Node.hpp"
#include "RuntimeEnvironment.hpp"
#include "Switch.hpp"
#include "Topology.hpp"
namespace ZeroTier { namespace ZeroTier {
@ -108,7 +109,8 @@ bool CertificateOfMembership::sign(const Identity &with)
_signature = with.sign(buf, ptr * sizeof(uint64_t)); _signature = with.sign(buf, ptr * sizeof(uint64_t));
_signedBy = with.address(); _signedBy = with.address();
return true; return true;
} catch ( ... ) { }
catch (...) {
_signedBy.zero(); _signedBy.zero();
return false; return false;
} }

View file

@ -14,21 +14,20 @@
#ifndef ZT_CERTIFICATEOFMEMBERSHIP_HPP #ifndef ZT_CERTIFICATEOFMEMBERSHIP_HPP
#define ZT_CERTIFICATEOFMEMBERSHIP_HPP #define ZT_CERTIFICATEOFMEMBERSHIP_HPP
#include <stdint.h> #include "Address.hpp"
#include <string.h> #include "Buffer.hpp"
#include <string>
#include <stdexcept>
#include <algorithm>
#include "Constants.hpp" #include "Constants.hpp"
#include "Credential.hpp" #include "Credential.hpp"
#include "Buffer.hpp"
#include "Address.hpp"
#include "ECC.hpp" #include "ECC.hpp"
#include "Identity.hpp" #include "Identity.hpp"
#include "Utils.hpp" #include "Utils.hpp"
#include <algorithm>
#include <stdexcept>
#include <stdint.h>
#include <string.h>
#include <string>
/** /**
* Maximum number of qualifiers allowed in a COM (absolute max: 65535) * Maximum number of qualifiers allowed in a COM (absolute max: 65535)
*/ */
@ -64,10 +63,12 @@ class RuntimeEnvironment;
* This is a memcpy()'able structure and is safe (in a crash sense) to modify * This is a memcpy()'able structure and is safe (in a crash sense) to modify
* without locks. * without locks.
*/ */
class CertificateOfMembership : public Credential class CertificateOfMembership : public Credential {
{
public: public:
static inline Credential::Type credentialType() { return Credential::CREDENTIAL_TYPE_COM; } static inline Credential::Type credentialType()
{
return Credential::CREDENTIAL_TYPE_COM;
}
/** /**
* Reserved qualifier IDs * Reserved qualifier IDs
@ -78,8 +79,7 @@ public:
* Addition of new required fields requires that code in hasRequiredFields * Addition of new required fields requires that code in hasRequiredFields
* be updated as well. * be updated as well.
*/ */
enum ReservedId enum ReservedId {
{
/** /**
* Timestamp of certificate * Timestamp of certificate
*/ */
@ -101,8 +101,9 @@ public:
/** /**
* Create an empty certificate of membership * Create an empty certificate of membership
*/ */
CertificateOfMembership() : CertificateOfMembership() : _qualifierCount(0)
_qualifierCount(0) {} {
}
/** /**
* Create from required fields common to all networks * Create from required fields common to all networks
@ -120,8 +121,7 @@ public:
* @param b Buffer to deserialize from * @param b Buffer to deserialize from
* @param startAt Position to start in buffer * @param startAt Position to start in buffer
*/ */
template<unsigned int C> template <unsigned int C> CertificateOfMembership(const Buffer<C>& b, unsigned int startAt = 0)
CertificateOfMembership(const Buffer<C> &b,unsigned int startAt = 0)
{ {
deserialize(b, startAt); deserialize(b, startAt);
} }
@ -129,12 +129,18 @@ public:
/** /**
* @return True if there's something here * @return True if there's something here
*/ */
inline operator bool() const { return (_qualifierCount != 0); } inline operator bool() const
{
return (_qualifierCount != 0);
}
/** /**
* @return Credential ID, always 0 for COMs * @return Credential ID, always 0 for COMs
*/ */
inline uint32_t id() const { return 0; } inline uint32_t id() const
{
return 0;
}
/** /**
* @return Timestamp for this cert and maximum delta for timestamp * @return Timestamp for this cert and maximum delta for timestamp
@ -211,15 +217,20 @@ public:
/** /**
* @return True if signed * @return True if signed
*/ */
inline bool isSigned() const { return (_signedBy); } inline bool isSigned() const
{
return (_signedBy);
}
/** /**
* @return Address that signed this certificate or null address if none * @return Address that signed this certificate or null address if none
*/ */
inline const Address &signedBy() const { return _signedBy; } inline const Address& signedBy() const
{
return _signedBy;
}
template<unsigned int C> template <unsigned int C> inline void serialize(Buffer<C>& b) const
inline void serialize(Buffer<C> &b) const
{ {
b.append((uint8_t)1); b.append((uint8_t)1);
b.append((uint16_t)_qualifierCount); b.append((uint16_t)_qualifierCount);
@ -234,8 +245,7 @@ public:
} }
} }
template<unsigned int C> template <unsigned int C> inline unsigned int deserialize(const Buffer<C>& b, unsigned int startAt = 0)
inline unsigned int deserialize(const Buffer<C> &b,unsigned int startAt = 0)
{ {
unsigned int p = startAt; unsigned int p = startAt;
@ -253,7 +263,8 @@ public:
const uint64_t qid = b.template at<uint64_t>(p); const uint64_t qid = b.template at<uint64_t>(p);
if (qid < lastId) { if (qid < lastId) {
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_BAD_ENCODING; throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_BAD_ENCODING;
} else { }
else {
lastId = qid; lastId = qid;
} }
if (_qualifierCount < ZT_NETWORK_COM_MAX_QUALIFIERS) { if (_qualifierCount < ZT_NETWORK_COM_MAX_QUALIFIERS) {
@ -262,7 +273,8 @@ public:
_qualifiers[_qualifierCount].maxDelta = b.template at<uint64_t>(p + 16); _qualifiers[_qualifierCount].maxDelta = b.template at<uint64_t>(p + 16);
p += 24; p += 24;
++_qualifierCount; ++_qualifierCount;
} else { }
else {
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW; throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW;
} }
} }
@ -295,16 +307,23 @@ public:
} }
return (memcmp(_signature.data, c._signature.data, ZT_ECC_SIGNATURE_LEN) == 0); return (memcmp(_signature.data, c._signature.data, ZT_ECC_SIGNATURE_LEN) == 0);
} }
inline bool operator!=(const CertificateOfMembership &c) const { return (!(*this == c)); } inline bool operator!=(const CertificateOfMembership& c) const
{
return (! (*this == c));
}
private: private:
struct _Qualifier struct _Qualifier {
_Qualifier() : id(0), value(0), maxDelta(0)
{ {
_Qualifier() : id(0),value(0),maxDelta(0) {} }
uint64_t id; uint64_t id;
uint64_t value; uint64_t value;
uint64_t maxDelta; uint64_t maxDelta;
inline bool operator<(const _Qualifier &q) const { return (id < q.id); } // sort order inline bool operator<(const _Qualifier& q) const
{
return (id < q.id);
} // sort order
}; };
Address _signedBy; Address _signedBy;

View file

@ -12,12 +12,13 @@
/****/ /****/
#include "CertificateOfOwnership.hpp" #include "CertificateOfOwnership.hpp"
#include "RuntimeEnvironment.hpp"
#include "Identity.hpp" #include "Identity.hpp"
#include "Topology.hpp"
#include "Switch.hpp"
#include "Network.hpp" #include "Network.hpp"
#include "Node.hpp" #include "Node.hpp"
#include "RuntimeEnvironment.hpp"
#include "Switch.hpp"
#include "Topology.hpp"
namespace ZeroTier { namespace ZeroTier {
@ -35,7 +36,8 @@ int CertificateOfOwnership::verify(const RuntimeEnvironment *RR,void *tPtr) cons
Buffer<(sizeof(CertificateOfOwnership) + 64)> tmp; Buffer<(sizeof(CertificateOfOwnership) + 64)> tmp;
this->serialize(tmp, true); this->serialize(tmp, true);
return (id.verify(tmp.data(), tmp.size(), _signature) ? 0 : -1); return (id.verify(tmp.data(), tmp.size(), _signature) ? 0 : -1);
} catch ( ... ) { }
catch (...) {
return -1; return -1;
} }
} }

View file

@ -14,20 +14,20 @@
#ifndef ZT_CERTIFICATEOFOWNERSHIP_HPP #ifndef ZT_CERTIFICATEOFOWNERSHIP_HPP
#define ZT_CERTIFICATEOFOWNERSHIP_HPP #define ZT_CERTIFICATEOFOWNERSHIP_HPP
#include "Address.hpp"
#include "Buffer.hpp"
#include "Constants.hpp"
#include "Credential.hpp"
#include "ECC.hpp"
#include "Identity.hpp"
#include "InetAddress.hpp"
#include "MAC.hpp"
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "Constants.hpp"
#include "Credential.hpp"
#include "ECC.hpp"
#include "Address.hpp"
#include "Identity.hpp"
#include "Buffer.hpp"
#include "InetAddress.hpp"
#include "MAC.hpp"
// Max things per CertificateOfOwnership // Max things per CertificateOfOwnership
#define ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS 16 #define ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS 16
@ -41,18 +41,14 @@ class RuntimeEnvironment;
/** /**
* Certificate indicating ownership of a network identifier * Certificate indicating ownership of a network identifier
*/ */
class CertificateOfOwnership : public Credential class CertificateOfOwnership : public Credential {
{
public: public:
static inline Credential::Type credentialType() { return Credential::CREDENTIAL_TYPE_COO; } static inline Credential::Type credentialType()
enum Thing
{ {
THING_NULL = 0, return Credential::CREDENTIAL_TYPE_COO;
THING_MAC_ADDRESS = 1, }
THING_IPV4_ADDRESS = 2,
THING_IPV6_ADDRESS = 3 enum Thing { THING_NULL = 0, THING_MAC_ADDRESS = 1, THING_IPV4_ADDRESS = 2, THING_IPV6_ADDRESS = 3 };
};
CertificateOfOwnership() CertificateOfOwnership()
{ {
@ -68,15 +64,36 @@ public:
_issuedTo = issuedTo; _issuedTo = issuedTo;
} }
inline uint64_t networkId() const { return _networkId; } inline uint64_t networkId() const
inline int64_t timestamp() const { return _ts; } {
inline uint32_t id() const { return _id; } return _networkId;
inline unsigned int thingCount() const { return (unsigned int)_thingCount; } }
inline int64_t timestamp() const
{
return _ts;
}
inline uint32_t id() const
{
return _id;
}
inline unsigned int thingCount() const
{
return (unsigned int)_thingCount;
}
inline Thing thingType(const unsigned int i) const { return (Thing)_thingTypes[i]; } inline Thing thingType(const unsigned int i) const
inline const uint8_t *thingValue(const unsigned int i) const { return _thingValues[i]; } {
return (Thing)_thingTypes[i];
}
inline const uint8_t* thingValue(const unsigned int i) const
{
return _thingValues[i];
}
inline const Address &issuedTo() const { return _issuedTo; } inline const Address& issuedTo() const
{
return _issuedTo;
}
inline bool owns(const InetAddress& ip) const inline bool owns(const InetAddress& ip) const
{ {
@ -105,7 +122,8 @@ public:
_thingTypes[_thingCount] = THING_IPV4_ADDRESS; _thingTypes[_thingCount] = THING_IPV4_ADDRESS;
memcpy(_thingValues[_thingCount], &(reinterpret_cast<const struct sockaddr_in*>(&ip)->sin_addr.s_addr), 4); memcpy(_thingValues[_thingCount], &(reinterpret_cast<const struct sockaddr_in*>(&ip)->sin_addr.s_addr), 4);
++_thingCount; ++_thingCount;
} else if (ip.ss_family == AF_INET6) { }
else if (ip.ss_family == AF_INET6) {
_thingTypes[_thingCount] = THING_IPV6_ADDRESS; _thingTypes[_thingCount] = THING_IPV6_ADDRESS;
memcpy(_thingValues[_thingCount], reinterpret_cast<const struct sockaddr_in6*>(&ip)->sin6_addr.s6_addr, 16); memcpy(_thingValues[_thingCount], reinterpret_cast<const struct sockaddr_in6*>(&ip)->sin6_addr.s6_addr, 16);
++_thingCount; ++_thingCount;
@ -145,8 +163,7 @@ public:
*/ */
int verify(const RuntimeEnvironment* RR, void* tPtr) const; int verify(const RuntimeEnvironment* RR, void* tPtr) const;
template<unsigned int C> template <unsigned int C> inline void serialize(Buffer<C>& b, const bool forSign = false) const
inline void serialize(Buffer<C> &b,const bool forSign = false) const
{ {
if (forSign) { if (forSign) {
b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL); b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
@ -177,8 +194,7 @@ public:
} }
} }
template<unsigned int C> template <unsigned int C> inline unsigned int deserialize(const Buffer<C>& b, unsigned int startAt = 0)
inline unsigned int deserialize(const Buffer<C> &b,unsigned int startAt = 0)
{ {
unsigned int p = startAt; unsigned int p = startAt;
@ -213,7 +229,8 @@ public:
p += 2; p += 2;
memcpy(_signature.data, b.field(p, ZT_ECC_SIGNATURE_LEN), ZT_ECC_SIGNATURE_LEN); memcpy(_signature.data, b.field(p, ZT_ECC_SIGNATURE_LEN), ZT_ECC_SIGNATURE_LEN);
p += ZT_ECC_SIGNATURE_LEN; p += ZT_ECC_SIGNATURE_LEN;
} else { }
else {
p += 2 + b.template at<uint16_t>(p); p += 2 + b.template at<uint16_t>(p);
} }
@ -226,10 +243,19 @@ public:
} }
// Provides natural sort order by ID // Provides natural sort order by ID
inline bool operator<(const CertificateOfOwnership &coo) const { return (_id < coo._id); } inline bool operator<(const CertificateOfOwnership& coo) const
{
return (_id < coo._id);
}
inline bool operator==(const CertificateOfOwnership &coo) const { return (memcmp(this,&coo,sizeof(CertificateOfOwnership)) == 0); } inline bool operator==(const CertificateOfOwnership& coo) const
inline bool operator!=(const CertificateOfOwnership &coo) const { return (memcmp(this,&coo,sizeof(CertificateOfOwnership)) != 0); } {
return (memcmp(this, &coo, sizeof(CertificateOfOwnership)) == 0);
}
inline bool operator!=(const CertificateOfOwnership& coo) const
{
return (memcmp(this, &coo, sizeof(CertificateOfOwnership)) != 0);
}
private: private:
bool _owns(const Thing& t, const void* v, unsigned int l) const; bool _owns(const Thing& t, const void* v, unsigned int l) const;

View file

@ -106,8 +106,8 @@
#pragma warning(disable : 4101) #pragma warning(disable : 4101)
#undef __UNIX_LIKE__ #undef __UNIX_LIKE__
#undef __BSD__ #undef __BSD__
#include <winsock2.h>
#include <windows.h> #include <windows.h>
#include <winsock2.h>
#endif #endif
#ifdef __NetBSD__ #ifdef __NetBSD__
@ -118,9 +118,9 @@
#if (defined(__amd64) || defined(__amd64__) || defined(__x86_64) || defined(__x86_64__) || defined(__AMD64) || defined(__AMD64__) || defined(_M_X64)) #if (defined(__amd64) || defined(__amd64__) || defined(__x86_64) || defined(__x86_64__) || defined(__AMD64) || defined(__AMD64__) || defined(_M_X64))
#define ZT_ARCH_X64 1 #define ZT_ARCH_X64 1
#include <xmmintrin.h>
#include <emmintrin.h> #include <emmintrin.h>
#include <immintrin.h> #include <immintrin.h>
#include <xmmintrin.h>
#endif #endif
#if (defined(__ARM_NEON) || defined(__ARM_NEON__) || defined(ZT_ARCH_ARM_HAS_NEON)) #if (defined(__ARM_NEON) || defined(__ARM_NEON__) || defined(ZT_ARCH_ARM_HAS_NEON))
@ -145,7 +145,8 @@
#endif #endif
// Define ZT_NO_TYPE_PUNNING to disable reckless casts on anything other than x86/x64. // Define ZT_NO_TYPE_PUNNING to disable reckless casts on anything other than x86/x64.
#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 1 #define ZT_NO_TYPE_PUNNING 1
#endif #endif
@ -632,7 +633,6 @@
*/ */
#define ZT_PEER_GENERAL_RATE_LIMIT 1000 #define ZT_PEER_GENERAL_RATE_LIMIT 1000
/** /**
* Minimum allowed amount of time between flow/path optimizations (anti-flapping) * Minimum allowed amount of time between flow/path optimizations (anti-flapping)
*/ */

View file

@ -19,14 +19,12 @@ namespace ZeroTier {
/** /**
* Base class for credentials * Base class for credentials
*/ */
class Credential class Credential {
{
public: public:
/** /**
* Do not change type code IDs -- these are used in Revocation objects and elsewhere * Do not change type code IDs -- these are used in Revocation objects and elsewhere
*/ */
enum Type enum Type {
{
CREDENTIAL_TYPE_NULL = 0, CREDENTIAL_TYPE_NULL = 0,
CREDENTIAL_TYPE_COM = 1, // CertificateOfMembership CREDENTIAL_TYPE_COM = 1, // CertificateOfMembership
CREDENTIAL_TYPE_CAPABILITY = 2, CREDENTIAL_TYPE_CAPABILITY = 2,

View file

@ -13,14 +13,14 @@
#ifndef ZT_DNS_HPP #ifndef ZT_DNS_HPP
#define ZT_DNS_HPP #define ZT_DNS_HPP
#include "../include/ZeroTierOne.h"
#include "Buffer.hpp"
#include "InetAddress.hpp"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "Buffer.hpp"
#include "InetAddress.hpp"
#include "../include/ZeroTierOne.h"
namespace ZeroTier { namespace ZeroTier {
/** /**
@ -28,8 +28,7 @@ namespace ZeroTier {
*/ */
class DNS { class DNS {
public: public:
template<unsigned int C> template <unsigned int C> static inline void serializeDNS(Buffer<C>& b, const ZT_VirtualNetworkDNS* dns)
static inline void serializeDNS(Buffer<C> &b, const ZT_VirtualNetworkDNS *dns)
{ {
b.append(dns->domain, 128); b.append(dns->domain, 128);
for (unsigned int j = 0; j < ZT_MAX_DNS_SERVERS; ++j) { for (unsigned int j = 0; j < ZT_MAX_DNS_SERVERS; ++j) {
@ -38,8 +37,7 @@ public:
} }
} }
template<unsigned int C> template <unsigned int C> static inline void deserializeDNS(const Buffer<C>& b, unsigned int& p, ZT_VirtualNetworkDNS* dns)
static inline void deserializeDNS(const Buffer<C> &b, unsigned int &p, ZT_VirtualNetworkDNS *dns)
{ {
char* d = (char*)b.data() + p; char* d = (char*)b.data() + p;
memset(dns, 0, sizeof(ZT_VirtualNetworkDNS)); memset(dns, 0, sizeof(ZT_VirtualNetworkDNS));
@ -52,6 +50,6 @@ public:
} }
}; };
} } // namespace ZeroTier
#endif // ZT_DNS_HPP #endif // ZT_DNS_HPP

View file

@ -14,10 +14,10 @@
#ifndef ZT_DICTIONARY_HPP #ifndef ZT_DICTIONARY_HPP
#define ZT_DICTIONARY_HPP #define ZT_DICTIONARY_HPP
#include "Address.hpp"
#include "Buffer.hpp"
#include "Constants.hpp" #include "Constants.hpp"
#include "Utils.hpp" #include "Utils.hpp"
#include "Buffer.hpp"
#include "Address.hpp"
#include <stdint.h> #include <stdint.h>
@ -45,28 +45,37 @@ namespace ZeroTier {
* *
* @tparam C Dictionary max capacity in bytes * @tparam C Dictionary max capacity in bytes
*/ */
template<unsigned int C> template <unsigned int C> class Dictionary {
class Dictionary
{
public: public:
Dictionary() { memset(_d,0,sizeof(_d)); } Dictionary()
Dictionary(const char *s) { this->load(s); } {
memset(_d, 0, sizeof(_d));
}
Dictionary(const char* s)
{
this->load(s);
}
Dictionary(const char* s, unsigned int len) Dictionary(const char* s, unsigned int len)
{ {
for (unsigned int i = 0; i < C; ++i) { for (unsigned int i = 0; i < C; ++i) {
if ((s) && (i < len)) { if ((s) && (i < len)) {
if (! (_d[i] = *s)) { if (! (_d[i] = *s)) {
s = (const char*)0; s = (const char*)0;
} else { }
else {
++s; ++s;
} }
} else { }
else {
_d[i] = (char)0; _d[i] = (char)0;
} }
} }
_d[C - 1] = (char)0; _d[C - 1] = (char)0;
} }
Dictionary(const Dictionary &d) { memcpy(_d,d._d,C); } Dictionary(const Dictionary& d)
{
memcpy(_d, d._d, C);
}
inline Dictionary& operator=(const Dictionary& d) inline Dictionary& operator=(const Dictionary& d)
{ {
@ -74,7 +83,10 @@ public:
return *this; return *this;
} }
inline operator bool() const { return (_d[0] != 0); } inline operator bool() const
{
return (_d[0] != 0);
}
/** /**
* Load a dictionary from a C-string * Load a dictionary from a C-string
@ -88,10 +100,12 @@ public:
if (s) { if (s) {
if (! (_d[i] = *s)) { if (! (_d[i] = *s)) {
s = (const char*)0; s = (const char*)0;
} else { }
else {
++s; ++s;
} }
} else { }
else {
_d[i] = (char)0; _d[i] = (char)0;
} }
} }
@ -195,9 +209,11 @@ public:
dest[j - 1] = (char)0; dest[j - 1] = (char)0;
return j - 1; return j - 1;
} }
} else if (*p == '\\') { }
else if (*p == '\\') {
esc = true; esc = true;
} else { }
else {
dest[j++] = *p; dest[j++] = *p;
if (j == (int)destlen) { if (j == (int)destlen) {
dest[j - 1] = (char)0; dest[j - 1] = (char)0;
@ -211,7 +227,8 @@ public:
} }
dest[j] = (char)0; dest[j] = (char)0;
return j; return j;
} else { }
else {
while ((*p) && (*p != 13) && (*p != 10)) { while ((*p) && (*p != 13) && (*p != 10)) {
if (++p == eof) { if (++p == eof) {
dest[0] = (char)0; dest[0] = (char)0;
@ -223,7 +240,8 @@ public:
dest[0] = (char)0; dest[0] = (char)0;
return -1; return -1;
} }
} else { }
else {
break; break;
} }
} }
@ -241,14 +259,14 @@ public:
* @return True if key was found (if false, dest will be empty) * @return True if key was found (if false, dest will be empty)
* @tparam BC Buffer capacity (usually inferred) * @tparam BC Buffer capacity (usually inferred)
*/ */
template<unsigned int BC> template <unsigned int BC> inline bool get(const char* key, Buffer<BC>& dest) const
inline bool get(const char *key,Buffer<BC> &dest) const
{ {
const int r = this->get(key, const_cast<char*>(reinterpret_cast<const char*>(dest.data())), BC); const int r = this->get(key, const_cast<char*>(reinterpret_cast<const char*>(dest.data())), BC);
if (r >= 0) { if (r >= 0) {
dest.setSize((unsigned int)r); dest.setSize((unsigned int)r);
return true; return true;
} else { }
else {
dest.clear(); dest.clear();
return false; return false;
} }
@ -426,7 +444,8 @@ public:
char tmp[32]; char tmp[32];
if (value >= 0) { if (value >= 0) {
return this->add(key, Utils::hex((uint64_t)value, tmp), -1); return this->add(key, Utils::hex((uint64_t)value, tmp), -1);
} else { }
else {
tmp[0] = '-'; tmp[0] = '-';
return this->add(key, Utils::hex((uint64_t)(value * -1), tmp + 1), -1); return this->add(key, Utils::hex((uint64_t)(value * -1), tmp + 1), -1);
} }
@ -446,8 +465,7 @@ public:
* *
* @tparam BC Buffer capacity (usually inferred) * @tparam BC Buffer capacity (usually inferred)
*/ */
template<unsigned int BC> template <unsigned int BC> inline bool add(const char* key, const Buffer<BC>& value)
inline bool add(const char *key,const Buffer<BC> &value)
{ {
return this->add(key, (const char*)value.data(), (int)value.size()); return this->add(key, (const char*)value.data(), (int)value.size());
} }
@ -465,10 +483,19 @@ public:
/** /**
* @return Value of C template parameter * @return Value of C template parameter
*/ */
inline unsigned int capacity() const { return C; } inline unsigned int capacity() const
{
return C;
}
inline const char *data() const { return _d; } inline const char* data() const
inline char *unsafeData() { return _d; } {
return _d;
}
inline char* unsafeData()
{
return _d;
}
private: private:
char _d[C]; char _d[C];

View file

@ -7,12 +7,13 @@ Derived from public domain code by D. J. Bernstein.
// Modified very slightly for ZeroTier One by Adam Ierymenko // Modified very slightly for ZeroTier One by Adam Ierymenko
// This code remains in the public domain. // This code remains in the public domain.
#include "ECC.hpp"
#include "SHA512.hpp"
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include "ECC.hpp"
#include "SHA512.hpp"
#ifdef __WINDOWS__ #ifdef __WINDOWS__
#pragma warning(disable : 4146) #pragma warning(disable : 4146)
#endif #endif
@ -36,7 +37,8 @@ typedef uint8_t u8;
typedef int32_t s32; typedef int32_t s32;
typedef int64_t limb; typedef int64_t limb;
static inline void fsum(limb *output, const limb *in) { static inline void fsum(limb* output, const limb* in)
{
unsigned i; unsigned i;
for (i = 0; i < 10; i += 2) { for (i = 0; i < 10; i += 2) {
output[0 + i] = output[0 + i] + in[0 + i]; output[0 + i] = output[0 + i] + in[0 + i];
@ -44,124 +46,56 @@ static inline void fsum(limb *output, const limb *in) {
} }
} }
static inline void fdifference(limb *output, const limb *in) { static inline void fdifference(limb* output, const limb* in)
{
unsigned i; unsigned i;
for (i = 0; i < 10; ++i) { for (i = 0; i < 10; ++i) {
output[i] = in[i] - output[i]; output[i] = in[i] - output[i];
} }
} }
static inline void fscalar_product(limb *output, const limb *in, const limb scalar) { static inline void fscalar_product(limb* output, const limb* in, const limb scalar)
{
unsigned i; unsigned i;
for (i = 0; i < 10; ++i) { for (i = 0; i < 10; ++i) {
output[i] = in[i] * scalar; output[i] = in[i] * scalar;
} }
} }
static inline void fproduct(limb *output, const limb *in2, const limb *in) { static inline void fproduct(limb* output, const limb* in2, const limb* in)
{
output[0] = ((limb)((s32)in2[0])) * ((s32)in[0]); output[0] = ((limb)((s32)in2[0])) * ((s32)in[0]);
output[1] = ((limb) ((s32) in2[0])) * ((s32) in[1]) + output[1] = ((limb)((s32)in2[0])) * ((s32)in[1]) + ((limb)((s32)in2[1])) * ((s32)in[0]);
((limb) ((s32) in2[1])) * ((s32) in[0]); output[2] = 2 * ((limb)((s32)in2[1])) * ((s32)in[1]) + ((limb)((s32)in2[0])) * ((s32)in[2]) + ((limb)((s32)in2[2])) * ((s32)in[0]);
output[2] = 2 * ((limb) ((s32) in2[1])) * ((s32) in[1]) + output[3] = ((limb)((s32)in2[1])) * ((s32)in[2]) + ((limb)((s32)in2[2])) * ((s32)in[1]) + ((limb)((s32)in2[0])) * ((s32)in[3]) + ((limb)((s32)in2[3])) * ((s32)in[0]);
((limb) ((s32) in2[0])) * ((s32) in[2]) + output[4] = ((limb)((s32)in2[2])) * ((s32)in[2]) + 2 * (((limb)((s32)in2[1])) * ((s32)in[3]) + ((limb)((s32)in2[3])) * ((s32)in[1])) + ((limb)((s32)in2[0])) * ((s32)in[4]) + ((limb)((s32)in2[4])) * ((s32)in[0]);
((limb) ((s32) in2[2])) * ((s32) in[0]); output[5] =
output[3] = ((limb) ((s32) in2[1])) * ((s32) in[2]) + ((limb)((s32)in2[2])) * ((s32)in[3]) + ((limb)((s32)in2[3])) * ((s32)in[2]) + ((limb)((s32)in2[1])) * ((s32)in[4]) + ((limb)((s32)in2[4])) * ((s32)in[1]) + ((limb)((s32)in2[0])) * ((s32)in[5]) + ((limb)((s32)in2[5])) * ((s32)in[0]);
((limb) ((s32) in2[2])) * ((s32) in[1]) + output[6] = 2 * (((limb)((s32)in2[3])) * ((s32)in[3]) + ((limb)((s32)in2[1])) * ((s32)in[5]) + ((limb)((s32)in2[5])) * ((s32)in[1])) + ((limb)((s32)in2[2])) * ((s32)in[4]) + ((limb)((s32)in2[4])) * ((s32)in[2])
((limb) ((s32) in2[0])) * ((s32) in[3]) + + ((limb)((s32)in2[0])) * ((s32)in[6]) + ((limb)((s32)in2[6])) * ((s32)in[0]);
((limb) ((s32) in2[3])) * ((s32) in[0]); output[7] = ((limb)((s32)in2[3])) * ((s32)in[4]) + ((limb)((s32)in2[4])) * ((s32)in[3]) + ((limb)((s32)in2[2])) * ((s32)in[5]) + ((limb)((s32)in2[5])) * ((s32)in[2]) + ((limb)((s32)in2[1])) * ((s32)in[6])
output[4] = ((limb) ((s32) in2[2])) * ((s32) in[2]) + + ((limb)((s32)in2[6])) * ((s32)in[1]) + ((limb)((s32)in2[0])) * ((s32)in[7]) + ((limb)((s32)in2[7])) * ((s32)in[0]);
2 * (((limb) ((s32) in2[1])) * ((s32) in[3]) + output[8] = ((limb)((s32)in2[4])) * ((s32)in[4]) + 2 * (((limb)((s32)in2[3])) * ((s32)in[5]) + ((limb)((s32)in2[5])) * ((s32)in[3]) + ((limb)((s32)in2[1])) * ((s32)in[7]) + ((limb)((s32)in2[7])) * ((s32)in[1]))
((limb) ((s32) in2[3])) * ((s32) in[1])) + + ((limb)((s32)in2[2])) * ((s32)in[6]) + ((limb)((s32)in2[6])) * ((s32)in[2]) + ((limb)((s32)in2[0])) * ((s32)in[8]) + ((limb)((s32)in2[8])) * ((s32)in[0]);
((limb) ((s32) in2[0])) * ((s32) in[4]) + output[9] = ((limb)((s32)in2[4])) * ((s32)in[5]) + ((limb)((s32)in2[5])) * ((s32)in[4]) + ((limb)((s32)in2[3])) * ((s32)in[6]) + ((limb)((s32)in2[6])) * ((s32)in[3]) + ((limb)((s32)in2[2])) * ((s32)in[7])
((limb) ((s32) in2[4])) * ((s32) in[0]); + ((limb)((s32)in2[7])) * ((s32)in[2]) + ((limb)((s32)in2[1])) * ((s32)in[8]) + ((limb)((s32)in2[8])) * ((s32)in[1]) + ((limb)((s32)in2[0])) * ((s32)in[9]) + ((limb)((s32)in2[9])) * ((s32)in[0]);
output[5] = ((limb) ((s32) in2[2])) * ((s32) in[3]) + output[10] = 2 * (((limb)((s32)in2[5])) * ((s32)in[5]) + ((limb)((s32)in2[3])) * ((s32)in[7]) + ((limb)((s32)in2[7])) * ((s32)in[3]) + ((limb)((s32)in2[1])) * ((s32)in[9]) + ((limb)((s32)in2[9])) * ((s32)in[1]))
((limb) ((s32) in2[3])) * ((s32) in[2]) + + ((limb)((s32)in2[4])) * ((s32)in[6]) + ((limb)((s32)in2[6])) * ((s32)in[4]) + ((limb)((s32)in2[2])) * ((s32)in[8]) + ((limb)((s32)in2[8])) * ((s32)in[2]);
((limb) ((s32) in2[1])) * ((s32) in[4]) + output[11] = ((limb)((s32)in2[5])) * ((s32)in[6]) + ((limb)((s32)in2[6])) * ((s32)in[5]) + ((limb)((s32)in2[4])) * ((s32)in[7]) + ((limb)((s32)in2[7])) * ((s32)in[4]) + ((limb)((s32)in2[3])) * ((s32)in[8])
((limb) ((s32) in2[4])) * ((s32) in[1]) + + ((limb)((s32)in2[8])) * ((s32)in[3]) + ((limb)((s32)in2[2])) * ((s32)in[9]) + ((limb)((s32)in2[9])) * ((s32)in[2]);
((limb) ((s32) in2[0])) * ((s32) in[5]) + output[12] = ((limb)((s32)in2[6])) * ((s32)in[6]) + 2 * (((limb)((s32)in2[5])) * ((s32)in[7]) + ((limb)((s32)in2[7])) * ((s32)in[5]) + ((limb)((s32)in2[3])) * ((s32)in[9]) + ((limb)((s32)in2[9])) * ((s32)in[3]))
((limb) ((s32) in2[5])) * ((s32) in[0]); + ((limb)((s32)in2[4])) * ((s32)in[8]) + ((limb)((s32)in2[8])) * ((s32)in[4]);
output[6] = 2 * (((limb) ((s32) in2[3])) * ((s32) in[3]) + output[13] =
((limb) ((s32) in2[1])) * ((s32) in[5]) + ((limb)((s32)in2[6])) * ((s32)in[7]) + ((limb)((s32)in2[7])) * ((s32)in[6]) + ((limb)((s32)in2[5])) * ((s32)in[8]) + ((limb)((s32)in2[8])) * ((s32)in[5]) + ((limb)((s32)in2[4])) * ((s32)in[9]) + ((limb)((s32)in2[9])) * ((s32)in[4]);
((limb) ((s32) in2[5])) * ((s32) in[1])) + output[14] = 2 * (((limb)((s32)in2[7])) * ((s32)in[7]) + ((limb)((s32)in2[5])) * ((s32)in[9]) + ((limb)((s32)in2[9])) * ((s32)in[5])) + ((limb)((s32)in2[6])) * ((s32)in[8]) + ((limb)((s32)in2[8])) * ((s32)in[6]);
((limb) ((s32) in2[2])) * ((s32) in[4]) + output[15] = ((limb)((s32)in2[7])) * ((s32)in[8]) + ((limb)((s32)in2[8])) * ((s32)in[7]) + ((limb)((s32)in2[6])) * ((s32)in[9]) + ((limb)((s32)in2[9])) * ((s32)in[6]);
((limb) ((s32) in2[4])) * ((s32) in[2]) + output[16] = ((limb)((s32)in2[8])) * ((s32)in[8]) + 2 * (((limb)((s32)in2[7])) * ((s32)in[9]) + ((limb)((s32)in2[9])) * ((s32)in[7]));
((limb) ((s32) in2[0])) * ((s32) in[6]) + output[17] = ((limb)((s32)in2[8])) * ((s32)in[9]) + ((limb)((s32)in2[9])) * ((s32)in[8]);
((limb) ((s32) in2[6])) * ((s32) in[0]);
output[7] = ((limb) ((s32) in2[3])) * ((s32) in[4]) +
((limb) ((s32) in2[4])) * ((s32) in[3]) +
((limb) ((s32) in2[2])) * ((s32) in[5]) +
((limb) ((s32) in2[5])) * ((s32) in[2]) +
((limb) ((s32) in2[1])) * ((s32) in[6]) +
((limb) ((s32) in2[6])) * ((s32) in[1]) +
((limb) ((s32) in2[0])) * ((s32) in[7]) +
((limb) ((s32) in2[7])) * ((s32) in[0]);
output[8] = ((limb) ((s32) in2[4])) * ((s32) in[4]) +
2 * (((limb) ((s32) in2[3])) * ((s32) in[5]) +
((limb) ((s32) in2[5])) * ((s32) in[3]) +
((limb) ((s32) in2[1])) * ((s32) in[7]) +
((limb) ((s32) in2[7])) * ((s32) in[1])) +
((limb) ((s32) in2[2])) * ((s32) in[6]) +
((limb) ((s32) in2[6])) * ((s32) in[2]) +
((limb) ((s32) in2[0])) * ((s32) in[8]) +
((limb) ((s32) in2[8])) * ((s32) in[0]);
output[9] = ((limb) ((s32) in2[4])) * ((s32) in[5]) +
((limb) ((s32) in2[5])) * ((s32) in[4]) +
((limb) ((s32) in2[3])) * ((s32) in[6]) +
((limb) ((s32) in2[6])) * ((s32) in[3]) +
((limb) ((s32) in2[2])) * ((s32) in[7]) +
((limb) ((s32) in2[7])) * ((s32) in[2]) +
((limb) ((s32) in2[1])) * ((s32) in[8]) +
((limb) ((s32) in2[8])) * ((s32) in[1]) +
((limb) ((s32) in2[0])) * ((s32) in[9]) +
((limb) ((s32) in2[9])) * ((s32) in[0]);
output[10] = 2 * (((limb) ((s32) in2[5])) * ((s32) in[5]) +
((limb) ((s32) in2[3])) * ((s32) in[7]) +
((limb) ((s32) in2[7])) * ((s32) in[3]) +
((limb) ((s32) in2[1])) * ((s32) in[9]) +
((limb) ((s32) in2[9])) * ((s32) in[1])) +
((limb) ((s32) in2[4])) * ((s32) in[6]) +
((limb) ((s32) in2[6])) * ((s32) in[4]) +
((limb) ((s32) in2[2])) * ((s32) in[8]) +
((limb) ((s32) in2[8])) * ((s32) in[2]);
output[11] = ((limb) ((s32) in2[5])) * ((s32) in[6]) +
((limb) ((s32) in2[6])) * ((s32) in[5]) +
((limb) ((s32) in2[4])) * ((s32) in[7]) +
((limb) ((s32) in2[7])) * ((s32) in[4]) +
((limb) ((s32) in2[3])) * ((s32) in[8]) +
((limb) ((s32) in2[8])) * ((s32) in[3]) +
((limb) ((s32) in2[2])) * ((s32) in[9]) +
((limb) ((s32) in2[9])) * ((s32) in[2]);
output[12] = ((limb) ((s32) in2[6])) * ((s32) in[6]) +
2 * (((limb) ((s32) in2[5])) * ((s32) in[7]) +
((limb) ((s32) in2[7])) * ((s32) in[5]) +
((limb) ((s32) in2[3])) * ((s32) in[9]) +
((limb) ((s32) in2[9])) * ((s32) in[3])) +
((limb) ((s32) in2[4])) * ((s32) in[8]) +
((limb) ((s32) in2[8])) * ((s32) in[4]);
output[13] = ((limb) ((s32) in2[6])) * ((s32) in[7]) +
((limb) ((s32) in2[7])) * ((s32) in[6]) +
((limb) ((s32) in2[5])) * ((s32) in[8]) +
((limb) ((s32) in2[8])) * ((s32) in[5]) +
((limb) ((s32) in2[4])) * ((s32) in[9]) +
((limb) ((s32) in2[9])) * ((s32) in[4]);
output[14] = 2 * (((limb) ((s32) in2[7])) * ((s32) in[7]) +
((limb) ((s32) in2[5])) * ((s32) in[9]) +
((limb) ((s32) in2[9])) * ((s32) in[5])) +
((limb) ((s32) in2[6])) * ((s32) in[8]) +
((limb) ((s32) in2[8])) * ((s32) in[6]);
output[15] = ((limb) ((s32) in2[7])) * ((s32) in[8]) +
((limb) ((s32) in2[8])) * ((s32) in[7]) +
((limb) ((s32) in2[6])) * ((s32) in[9]) +
((limb) ((s32) in2[9])) * ((s32) in[6]);
output[16] = ((limb) ((s32) in2[8])) * ((s32) in[8]) +
2 * (((limb) ((s32) in2[7])) * ((s32) in[9]) +
((limb) ((s32) in2[9])) * ((s32) in[7]));
output[17] = ((limb) ((s32) in2[8])) * ((s32) in[9]) +
((limb) ((s32) in2[9])) * ((s32) in[8]);
output[18] = 2 * ((limb)((s32)in2[9])) * ((s32)in[9]); output[18] = 2 * ((limb)((s32)in2[9])) * ((s32)in[9]);
} }
static inline void freduce_degree(limb *output) { static inline void freduce_degree(limb* output)
{
output[8] += output[18] << 4; output[8] += output[18] << 4;
output[8] += output[18] << 1; output[8] += output[18] << 1;
output[8] += output[18]; output[8] += output[18];
@ -219,7 +153,8 @@ static inline limb div_by_2_25(const limb v)
return (v + roundoff) >> 25; return (v + roundoff) >> 25;
} }
static inline void freduce_coefficients(limb *output) { static inline void freduce_coefficients(limb* output)
{
unsigned i; unsigned i;
output[10] = 0; output[10] = 0;
@ -262,7 +197,8 @@ static inline void freduce_coefficients(limb *output) {
* bound on |output[1]| is sufficient to meet our needs. */ * bound on |output[1]| is sufficient to meet our needs. */
} }
static inline void fmul(limb *output, const limb *in, const limb *in2) { static inline void fmul(limb* output, const limb* in, const limb* in2)
{
limb t[19]; limb t[19];
fproduct(t, in, in2); fproduct(t, in, in2);
/* |t[i]| < 14*2^54 */ /* |t[i]| < 14*2^54 */
@ -272,65 +208,31 @@ static inline void fmul(limb *output, const limb *in, const limb *in2) {
memcpy(output, t, sizeof(limb) * 10); memcpy(output, t, sizeof(limb) * 10);
} }
static inline void fsquare_inner(limb *output, const limb *in) { static inline void fsquare_inner(limb* output, const limb* in)
{
output[0] = ((limb)((s32)in[0])) * ((s32)in[0]); output[0] = ((limb)((s32)in[0])) * ((s32)in[0]);
output[1] = 2 * ((limb)((s32)in[0])) * ((s32)in[1]); output[1] = 2 * ((limb)((s32)in[0])) * ((s32)in[1]);
output[2] = 2 * (((limb) ((s32) in[1])) * ((s32) in[1]) + output[2] = 2 * (((limb)((s32)in[1])) * ((s32)in[1]) + ((limb)((s32)in[0])) * ((s32)in[2]));
((limb) ((s32) in[0])) * ((s32) in[2])); output[3] = 2 * (((limb)((s32)in[1])) * ((s32)in[2]) + ((limb)((s32)in[0])) * ((s32)in[3]));
output[3] = 2 * (((limb) ((s32) in[1])) * ((s32) in[2]) + output[4] = ((limb)((s32)in[2])) * ((s32)in[2]) + 4 * ((limb)((s32)in[1])) * ((s32)in[3]) + 2 * ((limb)((s32)in[0])) * ((s32)in[4]);
((limb) ((s32) in[0])) * ((s32) in[3])); output[5] = 2 * (((limb)((s32)in[2])) * ((s32)in[3]) + ((limb)((s32)in[1])) * ((s32)in[4]) + ((limb)((s32)in[0])) * ((s32)in[5]));
output[4] = ((limb) ((s32) in[2])) * ((s32) in[2]) + output[6] = 2 * (((limb)((s32)in[3])) * ((s32)in[3]) + ((limb)((s32)in[2])) * ((s32)in[4]) + ((limb)((s32)in[0])) * ((s32)in[6]) + 2 * ((limb)((s32)in[1])) * ((s32)in[5]));
4 * ((limb) ((s32) in[1])) * ((s32) in[3]) + output[7] = 2 * (((limb)((s32)in[3])) * ((s32)in[4]) + ((limb)((s32)in[2])) * ((s32)in[5]) + ((limb)((s32)in[1])) * ((s32)in[6]) + ((limb)((s32)in[0])) * ((s32)in[7]));
2 * ((limb) ((s32) in[0])) * ((s32) in[4]); output[8] = ((limb)((s32)in[4])) * ((s32)in[4]) + 2 * (((limb)((s32)in[2])) * ((s32)in[6]) + ((limb)((s32)in[0])) * ((s32)in[8]) + 2 * (((limb)((s32)in[1])) * ((s32)in[7]) + ((limb)((s32)in[3])) * ((s32)in[5])));
output[5] = 2 * (((limb) ((s32) in[2])) * ((s32) in[3]) + output[9] = 2 * (((limb)((s32)in[4])) * ((s32)in[5]) + ((limb)((s32)in[3])) * ((s32)in[6]) + ((limb)((s32)in[2])) * ((s32)in[7]) + ((limb)((s32)in[1])) * ((s32)in[8]) + ((limb)((s32)in[0])) * ((s32)in[9]));
((limb) ((s32) in[1])) * ((s32) in[4]) + output[10] = 2 * (((limb)((s32)in[5])) * ((s32)in[5]) + ((limb)((s32)in[4])) * ((s32)in[6]) + ((limb)((s32)in[2])) * ((s32)in[8]) + 2 * (((limb)((s32)in[3])) * ((s32)in[7]) + ((limb)((s32)in[1])) * ((s32)in[9])));
((limb) ((s32) in[0])) * ((s32) in[5])); output[11] = 2 * (((limb)((s32)in[5])) * ((s32)in[6]) + ((limb)((s32)in[4])) * ((s32)in[7]) + ((limb)((s32)in[3])) * ((s32)in[8]) + ((limb)((s32)in[2])) * ((s32)in[9]));
output[6] = 2 * (((limb) ((s32) in[3])) * ((s32) in[3]) + output[12] = ((limb)((s32)in[6])) * ((s32)in[6]) + 2 * (((limb)((s32)in[4])) * ((s32)in[8]) + 2 * (((limb)((s32)in[5])) * ((s32)in[7]) + ((limb)((s32)in[3])) * ((s32)in[9])));
((limb) ((s32) in[2])) * ((s32) in[4]) + output[13] = 2 * (((limb)((s32)in[6])) * ((s32)in[7]) + ((limb)((s32)in[5])) * ((s32)in[8]) + ((limb)((s32)in[4])) * ((s32)in[9]));
((limb) ((s32) in[0])) * ((s32) in[6]) + output[14] = 2 * (((limb)((s32)in[7])) * ((s32)in[7]) + ((limb)((s32)in[6])) * ((s32)in[8]) + 2 * ((limb)((s32)in[5])) * ((s32)in[9]));
2 * ((limb) ((s32) in[1])) * ((s32) in[5])); output[15] = 2 * (((limb)((s32)in[7])) * ((s32)in[8]) + ((limb)((s32)in[6])) * ((s32)in[9]));
output[7] = 2 * (((limb) ((s32) in[3])) * ((s32) in[4]) + output[16] = ((limb)((s32)in[8])) * ((s32)in[8]) + 4 * ((limb)((s32)in[7])) * ((s32)in[9]);
((limb) ((s32) in[2])) * ((s32) in[5]) +
((limb) ((s32) in[1])) * ((s32) in[6]) +
((limb) ((s32) in[0])) * ((s32) in[7]));
output[8] = ((limb) ((s32) in[4])) * ((s32) in[4]) +
2 * (((limb) ((s32) in[2])) * ((s32) in[6]) +
((limb) ((s32) in[0])) * ((s32) in[8]) +
2 * (((limb) ((s32) in[1])) * ((s32) in[7]) +
((limb) ((s32) in[3])) * ((s32) in[5])));
output[9] = 2 * (((limb) ((s32) in[4])) * ((s32) in[5]) +
((limb) ((s32) in[3])) * ((s32) in[6]) +
((limb) ((s32) in[2])) * ((s32) in[7]) +
((limb) ((s32) in[1])) * ((s32) in[8]) +
((limb) ((s32) in[0])) * ((s32) in[9]));
output[10] = 2 * (((limb) ((s32) in[5])) * ((s32) in[5]) +
((limb) ((s32) in[4])) * ((s32) in[6]) +
((limb) ((s32) in[2])) * ((s32) in[8]) +
2 * (((limb) ((s32) in[3])) * ((s32) in[7]) +
((limb) ((s32) in[1])) * ((s32) in[9])));
output[11] = 2 * (((limb) ((s32) in[5])) * ((s32) in[6]) +
((limb) ((s32) in[4])) * ((s32) in[7]) +
((limb) ((s32) in[3])) * ((s32) in[8]) +
((limb) ((s32) in[2])) * ((s32) in[9]));
output[12] = ((limb) ((s32) in[6])) * ((s32) in[6]) +
2 * (((limb) ((s32) in[4])) * ((s32) in[8]) +
2 * (((limb) ((s32) in[5])) * ((s32) in[7]) +
((limb) ((s32) in[3])) * ((s32) in[9])));
output[13] = 2 * (((limb) ((s32) in[6])) * ((s32) in[7]) +
((limb) ((s32) in[5])) * ((s32) in[8]) +
((limb) ((s32) in[4])) * ((s32) in[9]));
output[14] = 2 * (((limb) ((s32) in[7])) * ((s32) in[7]) +
((limb) ((s32) in[6])) * ((s32) in[8]) +
2 * ((limb) ((s32) in[5])) * ((s32) in[9]));
output[15] = 2 * (((limb) ((s32) in[7])) * ((s32) in[8]) +
((limb) ((s32) in[6])) * ((s32) in[9]));
output[16] = ((limb) ((s32) in[8])) * ((s32) in[8]) +
4 * ((limb) ((s32) in[7])) * ((s32) in[9]);
output[17] = 2 * ((limb)((s32)in[8])) * ((s32)in[9]); output[17] = 2 * ((limb)((s32)in[8])) * ((s32)in[9]);
output[18] = 2 * ((limb)((s32)in[9])) * ((s32)in[9]); output[18] = 2 * ((limb)((s32)in[9])) * ((s32)in[9]);
} }
static void fsquare(limb *output, const limb *in) { static void fsquare(limb* output, const limb* in)
{
limb t[19]; limb t[19];
fsquare_inner(t, in); fsquare_inner(t, in);
/* |t[i]| < 14*2^54 because the largest product of two limbs will be < /* |t[i]| < 14*2^54 because the largest product of two limbs will be <
@ -342,12 +244,9 @@ static void fsquare(limb *output, const limb *in) {
memcpy(output, t, sizeof(limb) * 10); memcpy(output, t, sizeof(limb) * 10);
} }
static inline void fexpand(limb *output, const u8 *input) { static inline void fexpand(limb* output, const u8* input)
#define F(n,start,shift,mask) \ {
output[n] = ((((limb) input[start + 0]) | \ #define F(n, start, shift, mask) output[n] = ((((limb)input[start + 0]) | ((limb)input[start + 1]) << 8 | ((limb)input[start + 2]) << 16 | ((limb)input[start + 3]) << 24) >> shift) & mask;
((limb) input[start + 1]) << 8 | \
((limb) input[start + 2]) << 16 | \
((limb) input[start + 3]) << 24) >> shift) & mask;
F(0, 0, 0, 0x3ffffff); F(0, 0, 0, 0x3ffffff);
F(1, 3, 2, 0x1ffffff); F(1, 3, 2, 0x1ffffff);
F(2, 6, 3, 0x3ffffff); F(2, 6, 3, 0x3ffffff);
@ -365,7 +264,8 @@ static inline void fexpand(limb *output, const u8 *input) {
#error "This code only works when >> does sign-extension on negative numbers" #error "This code only works when >> does sign-extension on negative numbers"
#endif #endif
static inline s32 s32_eq(s32 a, s32 b) { static inline s32 s32_eq(s32 a, s32 b)
{
a = ~(a ^ b); a = ~(a ^ b);
a &= a << 16; a &= a << 16;
a &= a << 8; a &= a << 8;
@ -375,13 +275,15 @@ static inline s32 s32_eq(s32 a, s32 b) {
return a >> 31; return a >> 31;
} }
static inline s32 s32_gte(s32 a, s32 b) { static inline s32 s32_gte(s32 a, s32 b)
{
a -= b; a -= b;
/* a >= 0 iff a >= b. */ /* a >= 0 iff a >= b. */
return ~(a >> 31); return ~(a >> 31);
} }
static inline void fcontract(u8 *output, limb *input_limbs) { static inline void fcontract(u8* output, limb* input_limbs)
{
int i; int i;
int j; int j;
s32 input[10]; s32 input[10];
@ -401,7 +303,8 @@ static inline void fcontract(u8 *output, limb *input_limbs) {
const s32 carry = -((input[i] & mask) >> 25); const s32 carry = -((input[i] & mask) >> 25);
input[i] = input[i] + (carry << 25); input[i] = input[i] + (carry << 25);
input[i + 1] = input[i + 1] - carry; input[i + 1] = input[i + 1] - carry;
} else { }
else {
const s32 mask = input[i] >> 31; const s32 mask = input[i] >> 31;
const s32 carry = -((input[i] & mask) >> 26); const s32 carry = -((input[i] & mask) >> 26);
input[i] = input[i] + (carry << 26); input[i] = input[i] + (carry << 26);
@ -450,7 +353,8 @@ static inline void fcontract(u8 *output, limb *input_limbs) {
const s32 carry = input[i] >> 25; const s32 carry = input[i] >> 25;
input[i] &= 0x1ffffff; input[i] &= 0x1ffffff;
input[i + 1] += carry; input[i + 1] += carry;
} else { }
else {
const s32 carry = input[i] >> 26; const s32 carry = input[i] >> 26;
input[i] &= 0x3ffffff; input[i] &= 0x3ffffff;
input[i + 1] += carry; input[i + 1] += carry;
@ -478,7 +382,8 @@ static inline void fcontract(u8 *output, limb *input_limbs) {
for (i = 1; i < 10; i++) { for (i = 1; i < 10; i++) {
if ((i & 1) == 1) { if ((i & 1) == 1) {
mask &= s32_eq(input[i], 0x1ffffff); mask &= s32_eq(input[i], 0x1ffffff);
} else { }
else {
mask &= s32_eq(input[i], 0x3ffffff); mask &= s32_eq(input[i], 0x3ffffff);
} }
} }
@ -490,7 +395,8 @@ static inline void fcontract(u8 *output, limb *input_limbs) {
for (i = 1; i < 10; i++) { for (i = 1; i < 10; i++) {
if ((i & 1) == 1) { if ((i & 1) == 1) {
input[i] -= mask & 0x1ffffff; input[i] -= mask & 0x1ffffff;
} else { }
else {
input[i] -= mask & 0x3ffffff; input[i] -= mask & 0x3ffffff;
} }
} }
@ -523,13 +429,18 @@ static inline void fcontract(u8 *output, limb *input_limbs) {
#undef F #undef F
} }
static inline void fmonty(limb *x2, limb *z2, /* output 2Q */ static inline void fmonty(
limb *x3, limb *z3, /* output Q + Q' */ limb* x2,
limb *x, limb *z, /* input Q */ limb* z2, /* output 2Q */
limb *xprime, limb *zprime, /* input Q' */ limb* x3,
const limb *qmqp /* input Q - Q' */) { limb* z3, /* output Q + Q' */
limb origx[10], origxprime[10], zzz[19], xx[19], zz[19], xxprime[19], limb* x,
zzprime[19], zzzprime[19], xxxprime[19]; limb* z, /* input Q */
limb* xprime,
limb* zprime, /* input Q' */
const limb* qmqp /* input Q - Q' */)
{
limb origx[10], origxprime[10], zzz[19], xx[19], zz[19], xxprime[19], zzprime[19], zzzprime[19], xxxprime[19];
memcpy(origx, x, 10 * sizeof(limb)); memcpy(origx, x, 10 * sizeof(limb));
fsum(x, z); fsum(x, z);
@ -598,7 +509,8 @@ static inline void fmonty(limb *x2, limb *z2, /* output 2Q */
/* |z2|i| < 2^26 */ /* |z2|i| < 2^26 */
} }
static inline void swap_conditional(limb a[19], limb b[19], limb iswap) { static inline void swap_conditional(limb a[19], limb b[19], limb iswap)
{
unsigned i; unsigned i;
const s32 swap = (s32)-iswap; const s32 swap = (s32)-iswap;
@ -609,7 +521,8 @@ static inline void swap_conditional(limb a[19], limb b[19], limb iswap) {
} }
} }
static inline void cmult(limb *resultx, limb *resultz, const u8 *n, const limb *q) { static inline void cmult(limb* resultx, limb* resultz, const u8* n, const limb* q)
{
limb a[19] = { 0 }, b[19] = { 1 }, c[19] = { 1 }, d[19] = { 0 }; limb a[19] = { 0 }, b[19] = { 1 }, c[19] = { 1 }, d[19] = { 0 };
limb *nqpqx = a, *nqpqz = b, *nqx = c, *nqz = d, *t; limb *nqpqx = a, *nqpqz = b, *nqx = c, *nqz = d, *t;
limb e[19] = { 0 }, f[19] = { 1 }, g[19] = { 0 }, h[19] = { 1 }; limb e[19] = { 0 }, f[19] = { 1 }, g[19] = { 0 }, h[19] = { 1 };
@ -626,11 +539,7 @@ static inline void cmult(limb *resultx, limb *resultz, const u8 *n, const limb *
swap_conditional(nqx, nqpqx, bit); swap_conditional(nqx, nqpqx, bit);
swap_conditional(nqz, nqpqz, bit); swap_conditional(nqz, nqpqz, bit);
fmonty(nqx2, nqz2, fmonty(nqx2, nqz2, nqpqx2, nqpqz2, nqx, nqz, nqpqx, nqpqz, q);
nqpqx2, nqpqz2,
nqx, nqz,
nqpqx, nqpqz,
q);
swap_conditional(nqx2, nqpqx2, bit); swap_conditional(nqx2, nqpqx2, bit);
swap_conditional(nqz2, nqpqz2, bit); swap_conditional(nqz2, nqpqz2, bit);
@ -655,7 +564,8 @@ static inline void cmult(limb *resultx, limb *resultz, const u8 *n, const limb *
memcpy(resultz, nqz, sizeof(limb) * 10); memcpy(resultz, nqz, sizeof(limb) * 10);
} }
static inline void crecip(limb *out, const limb *z) { static inline void crecip(limb* out, const limb* z)
{
limb z2[10]; limb z2[10];
limb z9[10]; limb z9[10];
limb z11[10]; limb z11[10];
@ -685,32 +595,50 @@ static inline void crecip(limb *out, const limb *z) {
/* 2^11 - 2^1 */ fsquare(t0, z2_10_0); /* 2^11 - 2^1 */ fsquare(t0, z2_10_0);
/* 2^12 - 2^2 */ fsquare(t1, t0); /* 2^12 - 2^2 */ fsquare(t1, t0);
/* 2^20 - 2^10 */ for (i = 2;i < 10;i += 2) { fsquare(t0,t1); fsquare(t1,t0); } /* 2^20 - 2^10 */ for (i = 2; i < 10; i += 2) {
fsquare(t0, t1);
fsquare(t1, t0);
}
/* 2^20 - 2^0 */ fmul(z2_20_0, t1, z2_10_0); /* 2^20 - 2^0 */ fmul(z2_20_0, t1, z2_10_0);
/* 2^21 - 2^1 */ fsquare(t0, z2_20_0); /* 2^21 - 2^1 */ fsquare(t0, z2_20_0);
/* 2^22 - 2^2 */ fsquare(t1, t0); /* 2^22 - 2^2 */ fsquare(t1, t0);
/* 2^40 - 2^20 */ for (i = 2;i < 20;i += 2) { fsquare(t0,t1); fsquare(t1,t0); } /* 2^40 - 2^20 */ for (i = 2; i < 20; i += 2) {
fsquare(t0, t1);
fsquare(t1, t0);
}
/* 2^40 - 2^0 */ fmul(t0, t1, z2_20_0); /* 2^40 - 2^0 */ fmul(t0, t1, z2_20_0);
/* 2^41 - 2^1 */ fsquare(t1, t0); /* 2^41 - 2^1 */ fsquare(t1, t0);
/* 2^42 - 2^2 */ fsquare(t0, t1); /* 2^42 - 2^2 */ fsquare(t0, t1);
/* 2^50 - 2^10 */ for (i = 2;i < 10;i += 2) { fsquare(t1,t0); fsquare(t0,t1); } /* 2^50 - 2^10 */ for (i = 2; i < 10; i += 2) {
fsquare(t1, t0);
fsquare(t0, t1);
}
/* 2^50 - 2^0 */ fmul(z2_50_0, t0, z2_10_0); /* 2^50 - 2^0 */ fmul(z2_50_0, t0, z2_10_0);
/* 2^51 - 2^1 */ fsquare(t0, z2_50_0); /* 2^51 - 2^1 */ fsquare(t0, z2_50_0);
/* 2^52 - 2^2 */ fsquare(t1, t0); /* 2^52 - 2^2 */ fsquare(t1, t0);
/* 2^100 - 2^50 */ for (i = 2;i < 50;i += 2) { fsquare(t0,t1); fsquare(t1,t0); } /* 2^100 - 2^50 */ for (i = 2; i < 50; i += 2) {
fsquare(t0, t1);
fsquare(t1, t0);
}
/* 2^100 - 2^0 */ fmul(z2_100_0, t1, z2_50_0); /* 2^100 - 2^0 */ fmul(z2_100_0, t1, z2_50_0);
/* 2^101 - 2^1 */ fsquare(t1, z2_100_0); /* 2^101 - 2^1 */ fsquare(t1, z2_100_0);
/* 2^102 - 2^2 */ fsquare(t0, t1); /* 2^102 - 2^2 */ fsquare(t0, t1);
/* 2^200 - 2^100 */ for (i = 2;i < 100;i += 2) { fsquare(t1,t0); fsquare(t0,t1); } /* 2^200 - 2^100 */ for (i = 2; i < 100; i += 2) {
fsquare(t1, t0);
fsquare(t0, t1);
}
/* 2^200 - 2^0 */ fmul(t1, t0, z2_100_0); /* 2^200 - 2^0 */ fmul(t1, t0, z2_100_0);
/* 2^201 - 2^1 */ fsquare(t0, t1); /* 2^201 - 2^1 */ fsquare(t0, t1);
/* 2^202 - 2^2 */ fsquare(t1, t0); /* 2^202 - 2^2 */ fsquare(t1, t0);
/* 2^250 - 2^50 */ for (i = 2;i < 50;i += 2) { fsquare(t0,t1); fsquare(t1,t0); } /* 2^250 - 2^50 */ for (i = 2; i < 50; i += 2) {
fsquare(t0, t1);
fsquare(t1, t0);
}
/* 2^250 - 2^0 */ fmul(t0, t1, z2_50_0); /* 2^250 - 2^0 */ fmul(t0, t1, z2_50_0);
/* 2^251 - 2^1 */ fsquare(t1, t0); /* 2^251 - 2^1 */ fsquare(t1, t0);
@ -721,7 +649,8 @@ static inline void crecip(limb *out, const limb *z) {
/* 2^255 - 21 */ fmul(out, t1, z11); /* 2^255 - 21 */ fmul(out, t1, z11);
} }
static void crypto_scalarmult(u8 *mypublic, const u8 *secret, const u8 *basepoint) { static void crypto_scalarmult(u8* mypublic, const u8* secret, const u8* basepoint)
{
limb bp[10], x[10], z[11], zmone[10]; limb bp[10], x[10], z[11], zmone[10];
uint8_t e[32]; uint8_t e[32];
int i; int i;
@ -751,26 +680,19 @@ static inline void crypto_scalarmult_base(unsigned char *q,const unsigned char *
// Ed25519 ref from: http://bench.cr.yp.to/supercop.html // Ed25519 ref from: http://bench.cr.yp.to/supercop.html
typedef struct typedef struct {
{
crypto_uint32 v[32]; crypto_uint32 v[32];
} } fe25519;
fe25519;
typedef struct typedef struct {
{
crypto_uint32 v[32]; crypto_uint32 v[32];
} } sc25519;
sc25519;
typedef struct typedef struct {
{
crypto_uint32 v[16]; crypto_uint32 v[16];
} } shortsc25519;
shortsc25519;
typedef struct typedef struct {
{
fe25519 x; fe25519 x;
fe25519 y; fe25519 y;
fe25519 z; fe25519 z;
@ -779,23 +701,20 @@ typedef struct
#define ge25519_p3 ge25519 #define ge25519_p3 ge25519
typedef struct typedef struct {
{
fe25519 x; fe25519 x;
fe25519 z; fe25519 z;
fe25519 y; fe25519 y;
fe25519 t; fe25519 t;
} ge25519_p1p1; } ge25519_p1p1;
typedef struct typedef struct {
{
fe25519 x; fe25519 x;
fe25519 y; fe25519 y;
fe25519 z; fe25519 z;
} ge25519_p2; } ge25519_p2;
typedef struct typedef struct {
{
fe25519 x; fe25519 x;
fe25519 y; fe25519 y;
} ge25519_aff; } ge25519_aff;
@ -1046,32 +965,50 @@ static inline void fe25519_invert(fe25519 *r, const fe25519 *x)
/* 2^11 - 2^1 */ fe25519_square(&t0, &z2_10_0); /* 2^11 - 2^1 */ fe25519_square(&t0, &z2_10_0);
/* 2^12 - 2^2 */ fe25519_square(&t1, &t0); /* 2^12 - 2^2 */ fe25519_square(&t1, &t0);
/* 2^20 - 2^10 */ for (i = 2;i < 10;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); } /* 2^20 - 2^10 */ for (i = 2; i < 10; i += 2) {
fe25519_square(&t0, &t1);
fe25519_square(&t1, &t0);
}
/* 2^20 - 2^0 */ fe25519_mul(&z2_20_0, &t1, &z2_10_0); /* 2^20 - 2^0 */ fe25519_mul(&z2_20_0, &t1, &z2_10_0);
/* 2^21 - 2^1 */ fe25519_square(&t0, &z2_20_0); /* 2^21 - 2^1 */ fe25519_square(&t0, &z2_20_0);
/* 2^22 - 2^2 */ fe25519_square(&t1, &t0); /* 2^22 - 2^2 */ fe25519_square(&t1, &t0);
/* 2^40 - 2^20 */ for (i = 2;i < 20;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); } /* 2^40 - 2^20 */ for (i = 2; i < 20; i += 2) {
fe25519_square(&t0, &t1);
fe25519_square(&t1, &t0);
}
/* 2^40 - 2^0 */ fe25519_mul(&t0, &t1, &z2_20_0); /* 2^40 - 2^0 */ fe25519_mul(&t0, &t1, &z2_20_0);
/* 2^41 - 2^1 */ fe25519_square(&t1, &t0); /* 2^41 - 2^1 */ fe25519_square(&t1, &t0);
/* 2^42 - 2^2 */ fe25519_square(&t0, &t1); /* 2^42 - 2^2 */ fe25519_square(&t0, &t1);
/* 2^50 - 2^10 */ for (i = 2;i < 10;i += 2) { fe25519_square(&t1,&t0); fe25519_square(&t0,&t1); } /* 2^50 - 2^10 */ for (i = 2; i < 10; i += 2) {
fe25519_square(&t1, &t0);
fe25519_square(&t0, &t1);
}
/* 2^50 - 2^0 */ fe25519_mul(&z2_50_0, &t0, &z2_10_0); /* 2^50 - 2^0 */ fe25519_mul(&z2_50_0, &t0, &z2_10_0);
/* 2^51 - 2^1 */ fe25519_square(&t0, &z2_50_0); /* 2^51 - 2^1 */ fe25519_square(&t0, &z2_50_0);
/* 2^52 - 2^2 */ fe25519_square(&t1, &t0); /* 2^52 - 2^2 */ fe25519_square(&t1, &t0);
/* 2^100 - 2^50 */ for (i = 2;i < 50;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); } /* 2^100 - 2^50 */ for (i = 2; i < 50; i += 2) {
fe25519_square(&t0, &t1);
fe25519_square(&t1, &t0);
}
/* 2^100 - 2^0 */ fe25519_mul(&z2_100_0, &t1, &z2_50_0); /* 2^100 - 2^0 */ fe25519_mul(&z2_100_0, &t1, &z2_50_0);
/* 2^101 - 2^1 */ fe25519_square(&t1, &z2_100_0); /* 2^101 - 2^1 */ fe25519_square(&t1, &z2_100_0);
/* 2^102 - 2^2 */ fe25519_square(&t0, &t1); /* 2^102 - 2^2 */ fe25519_square(&t0, &t1);
/* 2^200 - 2^100 */ for (i = 2;i < 100;i += 2) { fe25519_square(&t1,&t0); fe25519_square(&t0,&t1); } /* 2^200 - 2^100 */ for (i = 2; i < 100; i += 2) {
fe25519_square(&t1, &t0);
fe25519_square(&t0, &t1);
}
/* 2^200 - 2^0 */ fe25519_mul(&t1, &t0, &z2_100_0); /* 2^200 - 2^0 */ fe25519_mul(&t1, &t0, &z2_100_0);
/* 2^201 - 2^1 */ fe25519_square(&t0, &t1); /* 2^201 - 2^1 */ fe25519_square(&t0, &t1);
/* 2^202 - 2^2 */ fe25519_square(&t1, &t0); /* 2^202 - 2^2 */ fe25519_square(&t1, &t0);
/* 2^250 - 2^50 */ for (i = 2;i < 50;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); } /* 2^250 - 2^50 */ for (i = 2; i < 50; i += 2) {
fe25519_square(&t0, &t1);
fe25519_square(&t1, &t0);
}
/* 2^250 - 2^0 */ fe25519_mul(&t0, &t1, &z2_50_0); /* 2^250 - 2^0 */ fe25519_mul(&t0, &t1, &z2_50_0);
/* 2^251 - 2^1 */ fe25519_square(&t1, &t0); /* 2^251 - 2^1 */ fe25519_square(&t1, &t0);
@ -1350,24 +1287,17 @@ static inline void sc25519_2interleave2(unsigned char r[127], const sc25519 *s1,
} }
/* d */ /* d */
static const fe25519 ge25519_ecd = {{0xA3, 0x78, 0x59, 0x13, 0xCA, 0x4D, 0xEB, 0x75, 0xAB, 0xD8, 0x41, 0x41, 0x4D, 0x0A, 0x70, 0x00, static const fe25519 ge25519_ecd = { { 0xA3, 0x78, 0x59, 0x13, 0xCA, 0x4D, 0xEB, 0x75, 0xAB, 0xD8, 0x41, 0x41, 0x4D, 0x0A, 0x70, 0x00, 0x98, 0xE8, 0x79, 0x77, 0x79, 0x40, 0xC7, 0x8C, 0x73, 0xFE, 0x6F, 0x2B, 0xEE, 0x6C, 0x03, 0x52 } };
0x98, 0xE8, 0x79, 0x77, 0x79, 0x40, 0xC7, 0x8C, 0x73, 0xFE, 0x6F, 0x2B, 0xEE, 0x6C, 0x03, 0x52}};
/* 2*d */ /* 2*d */
static const fe25519 ge25519_ec2d = {{0x59, 0xF1, 0xB2, 0x26, 0x94, 0x9B, 0xD6, 0xEB, 0x56, 0xB1, 0x83, 0x82, 0x9A, 0x14, 0xE0, 0x00, static const fe25519 ge25519_ec2d = { { 0x59, 0xF1, 0xB2, 0x26, 0x94, 0x9B, 0xD6, 0xEB, 0x56, 0xB1, 0x83, 0x82, 0x9A, 0x14, 0xE0, 0x00, 0x30, 0xD1, 0xF3, 0xEE, 0xF2, 0x80, 0x8E, 0x19, 0xE7, 0xFC, 0xDF, 0x56, 0xDC, 0xD9, 0x06, 0x24 } };
0x30, 0xD1, 0xF3, 0xEE, 0xF2, 0x80, 0x8E, 0x19, 0xE7, 0xFC, 0xDF, 0x56, 0xDC, 0xD9, 0x06, 0x24}};
/* sqrt(-1) */ /* sqrt(-1) */
static const fe25519 ge25519_sqrtm1 = {{0xB0, 0xA0, 0x0E, 0x4A, 0x27, 0x1B, 0xEE, 0xC4, 0x78, 0xE4, 0x2F, 0xAD, 0x06, 0x18, 0x43, 0x2F, static const fe25519 ge25519_sqrtm1 = { { 0xB0, 0xA0, 0x0E, 0x4A, 0x27, 0x1B, 0xEE, 0xC4, 0x78, 0xE4, 0x2F, 0xAD, 0x06, 0x18, 0x43, 0x2F, 0xA7, 0xD7, 0xFB, 0x3D, 0x99, 0x00, 0x4D, 0x2B, 0x0B, 0xDF, 0xC1, 0x4F, 0x80, 0x24, 0x83, 0x2B } };
0xA7, 0xD7, 0xFB, 0x3D, 0x99, 0x00, 0x4D, 0x2B, 0x0B, 0xDF, 0xC1, 0x4F, 0x80, 0x24, 0x83, 0x2B}};
/* Packed coordinates of the base point */ /* Packed coordinates of the base point */
static const ge25519 ge25519_base = {{{0x1A, 0xD5, 0x25, 0x8F, 0x60, 0x2D, 0x56, 0xC9, 0xB2, 0xA7, 0x25, 0x95, 0x60, 0xC7, 0x2C, 0x69, static const ge25519 ge25519_base = { { { 0x1A, 0xD5, 0x25, 0x8F, 0x60, 0x2D, 0x56, 0xC9, 0xB2, 0xA7, 0x25, 0x95, 0x60, 0xC7, 0x2C, 0x69, 0x5C, 0xDC, 0xD6, 0xFD, 0x31, 0xE2, 0xA4, 0xC0, 0xFE, 0x53, 0x6E, 0xCD, 0xD3, 0x36, 0x69, 0x21 } },
0x5C, 0xDC, 0xD6, 0xFD, 0x31, 0xE2, 0xA4, 0xC0, 0xFE, 0x53, 0x6E, 0xCD, 0xD3, 0x36, 0x69, 0x21}}, { { 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66 } },
{{0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, { { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66}}, { { 0xA3, 0xDD, 0xB7, 0xA5, 0xB3, 0x8A, 0xDE, 0x6D, 0xF5, 0x52, 0x51, 0x77, 0x80, 0x9F, 0xF0, 0x20, 0x7D, 0xE3, 0xAB, 0x64, 0x8E, 0x4E, 0xEA, 0x66, 0x65, 0x76, 0x8B, 0xD7, 0x0F, 0x5F, 0x87, 0x67 } } };
{{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
{{0xA3, 0xDD, 0xB7, 0xA5, 0xB3, 0x8A, 0xDE, 0x6D, 0xF5, 0x52, 0x51, 0x77, 0x80, 0x9F, 0xF0, 0x20,
0x7D, 0xE3, 0xAB, 0x64, 0x8E, 0x4E, 0xEA, 0x66, 0x65, 0x76, 0x8B, 0xD7, 0x0F, 0x5F, 0x87, 0x67}}};
/* Multiples of the base point in affine representation */ /* Multiples of the base point in affine representation */
static const ge25519_aff ge25519_base_multiples_affine[425] = { static const ge25519_aff ge25519_base_multiples_affine[425] = {
@ -2424,20 +2354,33 @@ static inline void ge25519_double_scalarmult_vartime(ge25519_p3 *r, const ge2551
/* precomputation s2 s1 */ /* precomputation s2 s1 */
setneutral(pre); /* 00 00 */ setneutral(pre); /* 00 00 */
pre[1] = *p1; /* 00 01 */ pre[1] = *p1; /* 00 01 */
dbl_p1p1(&tp1p1,(ge25519_p2 *)p1); p1p1_to_p3( &pre[2], &tp1p1); /* 00 10 */ dbl_p1p1(&tp1p1, (ge25519_p2*)p1);
add_p1p1(&tp1p1,&pre[1], &pre[2]); p1p1_to_p3( &pre[3], &tp1p1); /* 00 11 */ p1p1_to_p3(&pre[2], &tp1p1); /* 00 10 */
add_p1p1(&tp1p1, &pre[1], &pre[2]);
p1p1_to_p3(&pre[3], &tp1p1); /* 00 11 */
pre[4] = *p2; /* 01 00 */ pre[4] = *p2; /* 01 00 */
add_p1p1(&tp1p1,&pre[1], &pre[4]); p1p1_to_p3( &pre[5], &tp1p1); /* 01 01 */ add_p1p1(&tp1p1, &pre[1], &pre[4]);
add_p1p1(&tp1p1,&pre[2], &pre[4]); p1p1_to_p3( &pre[6], &tp1p1); /* 01 10 */ p1p1_to_p3(&pre[5], &tp1p1); /* 01 01 */
add_p1p1(&tp1p1,&pre[3], &pre[4]); p1p1_to_p3( &pre[7], &tp1p1); /* 01 11 */ add_p1p1(&tp1p1, &pre[2], &pre[4]);
dbl_p1p1(&tp1p1,(ge25519_p2 *)p2); p1p1_to_p3( &pre[8], &tp1p1); /* 10 00 */ p1p1_to_p3(&pre[6], &tp1p1); /* 01 10 */
add_p1p1(&tp1p1,&pre[1], &pre[8]); p1p1_to_p3( &pre[9], &tp1p1); /* 10 01 */ add_p1p1(&tp1p1, &pre[3], &pre[4]);
dbl_p1p1(&tp1p1,(ge25519_p2 *)pre5); p1p1_to_p3(&pre[10], &tp1p1); /* 10 10 */ p1p1_to_p3(&pre[7], &tp1p1); /* 01 11 */
add_p1p1(&tp1p1,&pre[3], &pre[8]); p1p1_to_p3(&pre[11], &tp1p1); /* 10 11 */ dbl_p1p1(&tp1p1, (ge25519_p2*)p2);
add_p1p1(&tp1p1,&pre[4], &pre[8]); p1p1_to_p3(&pre[12], &tp1p1); /* 11 00 */ p1p1_to_p3(&pre[8], &tp1p1); /* 10 00 */
add_p1p1(&tp1p1,&pre[1],&pre[12]); p1p1_to_p3(&pre[13], &tp1p1); /* 11 01 */ add_p1p1(&tp1p1, &pre[1], &pre[8]);
add_p1p1(&tp1p1,&pre[2],&pre[12]); p1p1_to_p3(&pre[14], &tp1p1); /* 11 10 */ p1p1_to_p3(&pre[9], &tp1p1); /* 10 01 */
add_p1p1(&tp1p1,&pre[3],&pre[12]); p1p1_to_p3(&pre[15], &tp1p1); /* 11 11 */ dbl_p1p1(&tp1p1, (ge25519_p2*)pre5);
p1p1_to_p3(&pre[10], &tp1p1); /* 10 10 */
add_p1p1(&tp1p1, &pre[3], &pre[8]);
p1p1_to_p3(&pre[11], &tp1p1); /* 10 11 */
add_p1p1(&tp1p1, &pre[4], &pre[8]);
p1p1_to_p3(&pre[12], &tp1p1); /* 11 00 */
add_p1p1(&tp1p1, &pre[1], &pre[12]);
p1p1_to_p3(&pre[13], &tp1p1); /* 11 01 */
add_p1p1(&tp1p1, &pre[2], &pre[12]);
p1p1_to_p3(&pre[14], &tp1p1); /* 11 10 */
add_p1p1(&tp1p1, &pre[3], &pre[12]);
p1p1_to_p3(&pre[15], &tp1p1); /* 11 11 */
sc25519_2interleave2(b, s1, s2); sc25519_2interleave2(b, s1, s2);
@ -2453,7 +2396,8 @@ static inline void ge25519_double_scalarmult_vartime(ge25519_p3 *r, const ge2551
} }
if (i != 0) { if (i != 0) {
p1p1_to_p2((ge25519_p2*)r, &tp1p1); p1p1_to_p2((ge25519_p2*)r, &tp1p1);
} else { }
else {
p1p1_to_p3(r, &tp1p1); p1p1_to_p3(r, &tp1p1);
} }
} }

View file

@ -29,24 +29,32 @@
/* FIPS140/NIST ECC cryptography */ /* FIPS140/NIST ECC cryptography */
/* Note that to be FIPS we also need to link against a FIPS-certified library. */ /* Note that to be FIPS we also need to link against a FIPS-certified library. */
#include <openssl/evp.h> #include <openssl/bn.h>
#include <openssl/ec.h> #include <openssl/ec.h>
#include <openssl/err.h> #include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/pem.h> #include <openssl/pem.h>
#include <openssl/bn.h>
#define ZT_ECC_EPHEMERAL_PUBLIC_KEY_LEN 97 /* Single ECC P-384 key */ #define ZT_ECC_EPHEMERAL_PUBLIC_KEY_LEN 97 /* Single ECC P-384 key */
#define ZT_ECC_PUBLIC_KEY_SET_LEN (97 * 2) /* Two ECC P-384 keys */ #define ZT_ECC_PUBLIC_KEY_SET_LEN (97 * 2) /* Two ECC P-384 keys */
#define ZT_ECC_PRIVATE_KEY_SET_LEN (48 * 2) /* Two ECC P-384 secret keys */ #define ZT_ECC_PRIVATE_KEY_SET_LEN (48 * 2) /* Two ECC P-384 secret keys */
#define ZT_ECC_SIGNATURE_LEN 96 /* NIST P-384 ECDSA signature */ #define ZT_ECC_SIGNATURE_LEN 96 /* NIST P-384 ECDSA signature */
class ECC class ECC {
{
public: public:
struct Public { uint8_t data[ZT_ECC_PUBLIC_KEY_SET_LEN]; }; struct Public {
struct Private { uint8_t data[ZT_ECC_PRIVATE_KEY_SET_LEN]; }; uint8_t data[ZT_ECC_PUBLIC_KEY_SET_LEN];
struct Signature { uint8_t data[ZT_ECC_SIGNATURE_LEN]; }; };
struct Pair { Public pub; Private priv; }; struct Private {
uint8_t data[ZT_ECC_PRIVATE_KEY_SET_LEN];
};
struct Signature {
uint8_t data[ZT_ECC_SIGNATURE_LEN];
};
struct Pair {
Public pub;
Private priv;
};
}; };
#else // Curve25519 / Ed25519 #else // Curve25519 / Ed25519
@ -58,13 +66,21 @@ namespace ZeroTier {
#define ZT_ECC_PRIVATE_KEY_SET_LEN 64 /* C25519 and Ed25519 secret keys */ #define ZT_ECC_PRIVATE_KEY_SET_LEN 64 /* C25519 and Ed25519 secret keys */
#define ZT_ECC_SIGNATURE_LEN 96 /* Ed25519 signature plus (not necessary) hash */ #define ZT_ECC_SIGNATURE_LEN 96 /* Ed25519 signature plus (not necessary) hash */
class ECC class ECC {
{
public: public:
struct Public { uint8_t data[ZT_ECC_PUBLIC_KEY_SET_LEN]; }; struct Public {
struct Private { uint8_t data[ZT_ECC_PRIVATE_KEY_SET_LEN]; }; uint8_t data[ZT_ECC_PUBLIC_KEY_SET_LEN];
struct Signature { uint8_t data[ZT_ECC_SIGNATURE_LEN]; }; };
struct Pair { Public pub; Private priv; }; struct Private {
uint8_t data[ZT_ECC_PRIVATE_KEY_SET_LEN];
};
struct Signature {
uint8_t data[ZT_ECC_SIGNATURE_LEN];
};
struct Pair {
Public pub;
Private priv;
};
/** /**
* Generate an elliptic curve key pair * Generate an elliptic curve key pair
@ -91,8 +107,7 @@ public:
* @return Key pair where cond(kp) returns true * @return Key pair where cond(kp) returns true
* @tparam F Type of 'cond' * @tparam F Type of 'cond'
*/ */
template<typename F> template <typename F> static inline Pair generateSatisfying(F cond)
static inline Pair generateSatisfying(F cond)
{ {
Pair kp; Pair kp;
void* const priv = (void*)kp.priv.data; void* const priv = (void*)kp.priv.data;
@ -118,7 +133,10 @@ public:
* @param keylen Number of key bytes to generate * @param keylen Number of key bytes to generate
*/ */
static void agree(const Private& mine, const Public& their, void* keybuf, unsigned int keylen); static void agree(const Private& mine, const Public& their, void* keybuf, unsigned int keylen);
static inline void agree(const Pair &mine,const Public &their,void *keybuf,unsigned int keylen) { agree(mine.priv,their,keybuf,keylen); } static inline void agree(const Pair& mine, const Public& their, void* keybuf, unsigned int keylen)
{
agree(mine.priv, their, keybuf, keylen);
}
/** /**
* Sign a message with a sender's key pair * Sign a message with a sender's key pair
@ -140,7 +158,10 @@ public:
* @param signature Buffer to fill with signature -- MUST be 96 bytes in length * @param signature Buffer to fill with signature -- MUST be 96 bytes in length
*/ */
static void sign(const Private& myPrivate, const Public& myPublic, const void* msg, unsigned int len, void* signature); static void sign(const Private& myPrivate, const Public& myPublic, const void* msg, unsigned int len, void* signature);
static inline void sign(const Pair &mine,const void *msg,unsigned int len,void *signature) { sign(mine.priv,mine.pub,msg,len,signature); } static inline void sign(const Pair& mine, const void* msg, unsigned int len, void* signature)
{
sign(mine.priv, mine.pub, msg, len, signature);
}
/** /**
* Sign a message with a sender's key pair * Sign a message with a sender's key pair

View file

@ -16,30 +16,37 @@
#include "Constants.hpp" #include "Constants.hpp"
#include <algorithm>
#include <stdexcept>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdexcept>
#include <vector>
#include <utility> #include <utility>
#include <algorithm> #include <vector>
namespace ZeroTier { namespace ZeroTier {
/** /**
* A minimal hash table implementation for the ZeroTier core * A minimal hash table implementation for the ZeroTier core
*/ */
template<typename K,typename V> template <typename K, typename V> class Hashtable {
class Hashtable
{
private: private:
struct _Bucket struct _Bucket {
_Bucket(const K& k, const V& v) : k(k), v(v)
{ {
_Bucket(const K &k,const V &v) : k(k),v(v) {} }
_Bucket(const K &k) : k(k),v() {} _Bucket(const K& k) : k(k), v()
_Bucket(const _Bucket &b) : k(b.k),v(b.v) {} {
inline _Bucket &operator=(const _Bucket &b) { k = b.k; v = b.v; return *this; } }
_Bucket(const _Bucket& b) : k(b.k), v(b.v)
{
}
inline _Bucket& operator=(const _Bucket& b)
{
k = b.k;
v = b.v;
return *this;
}
K k; K k;
V v; V v;
_Bucket* next; // must be set manually for each _Bucket _Bucket* next; // must be set manually for each _Bucket
@ -53,16 +60,12 @@ public:
* may rehash and invalidate the iterator. Note the erasing the key will destroy * may rehash and invalidate the iterator. Note the erasing the key will destroy
* the targets of the pointers returned by next(). * the targets of the pointers returned by next().
*/ */
class Iterator class Iterator {
{
public: public:
/** /**
* @param ht Hash table to iterate over * @param ht Hash table to iterate over
*/ */
Iterator(Hashtable &ht) : Iterator(Hashtable& ht) : _idx(0), _ht(&ht), _b(ht._t[0])
_idx(0),
_ht(&ht),
_b(ht._t[0])
{ {
} }
@ -98,10 +101,7 @@ public:
/** /**
* @param bc Initial capacity in buckets (default: 64, must be nonzero) * @param bc Initial capacity in buckets (default: 64, must be nonzero)
*/ */
Hashtable(unsigned long bc = 64) : Hashtable(unsigned long bc = 64) : _t(reinterpret_cast<_Bucket**>(::malloc(sizeof(_Bucket*) * bc))), _bc(bc), _s(0)
_t(reinterpret_cast<_Bucket **>(::malloc(sizeof(_Bucket *) * bc))),
_bc(bc),
_s(0)
{ {
if (! _t) { if (! _t) {
throw ZT_EXCEPTION_OUT_OF_MEMORY; throw ZT_EXCEPTION_OUT_OF_MEMORY;
@ -111,10 +111,7 @@ public:
} }
} }
Hashtable(const Hashtable<K,V> &ht) : Hashtable(const Hashtable<K, V>& ht) : _t(reinterpret_cast<_Bucket**>(::malloc(sizeof(_Bucket*) * ht._bc))), _bc(ht._bc), _s(ht._s)
_t(reinterpret_cast<_Bucket **>(::malloc(sizeof(_Bucket *) * ht._bc))),
_bc(ht._bc),
_s(ht._s)
{ {
if (! _t) { if (! _t) {
throw ZT_EXCEPTION_OUT_OF_MEMORY; throw ZT_EXCEPTION_OUT_OF_MEMORY;
@ -198,8 +195,7 @@ public:
* @param v Vector, list, or other compliant container * @param v Vector, list, or other compliant container
* @tparam Type of V (generally inferred) * @tparam Type of V (generally inferred)
*/ */
template<typename C> template <typename C> inline void appendKeys(C& v) const
inline void appendKeys(C &v) const
{ {
if (_s) { if (_s) {
for (unsigned long i = 0; i < _bc; ++i) { for (unsigned long i = 0; i < _bc; ++i) {
@ -246,7 +242,10 @@ public:
} }
return (V*)0; return (V*)0;
} }
inline const V *get(const K &k) const { return const_cast<Hashtable *>(this)->get(k); } inline const V* get(const K& k) const
{
return const_cast<Hashtable*>(this)->get(k);
}
/** /**
* @param k Key * @param k Key
@ -295,7 +294,8 @@ public:
if (b->k == k) { if (b->k == k) {
if (lastb) { if (lastb) {
lastb->next = b->next; lastb->next = b->next;
} else { }
else {
_t[bidx] = b->next; _t[bidx] = b->next;
} }
delete b; delete b;
@ -371,16 +371,21 @@ public:
/** /**
* @return Number of entries * @return Number of entries
*/ */
inline unsigned long size() const { return _s; } inline unsigned long size() const
{
return _s;
}
/** /**
* @return True if table is empty * @return True if table is empty
*/ */
inline bool empty() const { return (_s == 0); } inline bool empty() const
{
return (_s == 0);
}
private: private:
template<typename O> template <typename O> static inline unsigned long _hc(const O& obj)
static inline unsigned long _hc(const O &obj)
{ {
return (unsigned long)obj.hashCode(); return (unsigned long)obj.hashCode();
} }

View file

@ -11,18 +11,19 @@
*/ */
/****/ /****/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "ECC.hpp"
#include "Constants.hpp"
#include "Identity.hpp" #include "Identity.hpp"
#include "Constants.hpp"
#include "ECC.hpp"
#include "SHA512.hpp" #include "SHA512.hpp"
#include "Salsa20.hpp" #include "Salsa20.hpp"
#include "Utils.hpp" #include "Utils.hpp"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// These can't be changed without a new identity type. They define the // These can't be changed without a new identity type. They define the
// parameters of the hashcash hashing/searching algorithm. // parameters of the hashcash hashing/searching algorithm.
@ -69,10 +70,13 @@ static inline void _computeMemoryHardHash(const void *publicKey,unsigned int pub
// Hashcash generation halting condition -- halt when first byte is less than // Hashcash generation halting condition -- halt when first byte is less than
// threshold value. // threshold value.
struct _Identity_generate_cond struct _Identity_generate_cond {
_Identity_generate_cond()
{ {
_Identity_generate_cond() {} }
_Identity_generate_cond(unsigned char *sb,char *gm) : digest(sb),genmem(gm) {} _Identity_generate_cond(unsigned char* sb, char* gm) : digest(sb), genmem(gm)
{
}
inline bool operator()(const ECC::Pair& kp) const inline bool operator()(const ECC::Pair& kp) const
{ {
_computeMemoryHardHash(kp.pub.data, ZT_ECC_PUBLIC_KEY_SET_LEN, digest, genmem); _computeMemoryHardHash(kp.pub.data, ZT_ECC_PUBLIC_KEY_SET_LEN, digest, genmem);
@ -116,13 +120,7 @@ bool Identity::locallyValidate() const
unsigned char addrb[5]; unsigned char addrb[5];
_address.copyTo(addrb, 5); _address.copyTo(addrb, 5);
return ( return ((digest[0] < ZT_IDENTITY_GEN_HASHCASH_FIRST_BYTE_LESS_THAN) && (digest[59] == addrb[0]) && (digest[60] == addrb[1]) && (digest[61] == addrb[2]) && (digest[62] == addrb[3]) && (digest[63] == addrb[4]));
(digest[0] < ZT_IDENTITY_GEN_HASHCASH_FIRST_BYTE_LESS_THAN)&&
(digest[59] == addrb[0])&&
(digest[60] == addrb[1])&&
(digest[61] == addrb[2])&&
(digest[62] == addrb[3])&&
(digest[63] == addrb[4]));
} }
char* Identity::toString(bool includePrivate, char buf[ZT_IDENTITY_STRING_BUFFER_LENGTH]) const char* Identity::toString(bool includePrivate, char buf[ZT_IDENTITY_STRING_BUFFER_LENGTH]) const

View file

@ -14,16 +14,16 @@
#ifndef ZT_IDENTITY_HPP #ifndef ZT_IDENTITY_HPP
#define ZT_IDENTITY_HPP #define ZT_IDENTITY_HPP
#include "Address.hpp"
#include "Buffer.hpp"
#include "Constants.hpp"
#include "ECC.hpp"
#include "SHA512.hpp"
#include "Utils.hpp"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "Constants.hpp"
#include "Utils.hpp"
#include "Address.hpp"
#include "ECC.hpp"
#include "Buffer.hpp"
#include "SHA512.hpp"
#define ZT_IDENTITY_STRING_BUFFER_LENGTH 384 #define ZT_IDENTITY_STRING_BUFFER_LENGTH 384
namespace ZeroTier { namespace ZeroTier {
@ -38,32 +38,24 @@ namespace ZeroTier {
* search for a different public key that duplicates an existing address. (See * search for a different public key that duplicates an existing address. (See
* code for deriveAddress() for this algorithm.) * code for deriveAddress() for this algorithm.)
*/ */
class Identity class Identity {
{
public: public:
Identity() : Identity() : _privateKey((ECC::Private*)0)
_privateKey((ECC::Private *)0)
{ {
} }
Identity(const Identity &id) : Identity(const Identity& id) : _address(id._address), _publicKey(id._publicKey), _privateKey((id._privateKey) ? new ECC::Private(*(id._privateKey)) : (ECC::Private*)0)
_address(id._address),
_publicKey(id._publicKey),
_privateKey((id._privateKey) ? new ECC::Private(*(id._privateKey)) : (ECC::Private *)0)
{ {
} }
Identity(const char *str) : Identity(const char* str) : _privateKey((ECC::Private*)0)
_privateKey((ECC::Private *)0)
{ {
if (! fromString(str)) { if (! fromString(str)) {
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_TYPE; throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_TYPE;
} }
} }
template<unsigned int C> template <unsigned int C> Identity(const Buffer<C>& b, unsigned int startAt = 0) : _privateKey((ECC::Private*)0)
Identity(const Buffer<C> &b,unsigned int startAt = 0) :
_privateKey((ECC::Private *)0)
{ {
deserialize(b, startAt); deserialize(b, startAt);
} }
@ -85,7 +77,8 @@ public:
_privateKey = new ECC::Private(); _privateKey = new ECC::Private();
} }
*_privateKey = *(id._privateKey); *_privateKey = *(id._privateKey);
} else { }
else {
delete _privateKey; delete _privateKey;
_privateKey = (ECC::Private*)0; _privateKey = (ECC::Private*)0;
} }
@ -109,7 +102,10 @@ public:
/** /**
* @return True if this identity contains a private key * @return True if this identity contains a private key
*/ */
inline bool hasPrivate() const { return (_privateKey != (ECC::Private *)0); } inline bool hasPrivate() const
{
return (_privateKey != (ECC::Private*)0);
}
/** /**
* Compute a SHA384 hash of this identity's address and public key(s). * Compute a SHA384 hash of this identity's address and public key(s).
@ -203,7 +199,10 @@ public:
/** /**
* @return This identity's address * @return This identity's address
*/ */
inline const Address &address() const { return _address; } inline const Address& address() const
{
return _address;
}
/** /**
* Serialize this identity (binary) * Serialize this identity (binary)
@ -212,8 +211,7 @@ public:
* @param includePrivate If true, include private key component (if present) (default: false) * @param includePrivate If true, include private key component (if present) (default: false)
* @throws std::out_of_range Buffer too small * @throws std::out_of_range Buffer too small
*/ */
template<unsigned int C> template <unsigned int C> inline void serialize(Buffer<C>& b, bool includePrivate = false) const
inline void serialize(Buffer<C> &b,bool includePrivate = false) const
{ {
_address.appendTo(b); _address.appendTo(b);
b.append((uint8_t)0); // C25519/Ed25519 identity type b.append((uint8_t)0); // C25519/Ed25519 identity type
@ -221,7 +219,8 @@ public:
if ((_privateKey) && (includePrivate)) { if ((_privateKey) && (includePrivate)) {
b.append((unsigned char)ZT_ECC_PRIVATE_KEY_SET_LEN); b.append((unsigned char)ZT_ECC_PRIVATE_KEY_SET_LEN);
b.append(_privateKey->data, ZT_ECC_PRIVATE_KEY_SET_LEN); b.append(_privateKey->data, ZT_ECC_PRIVATE_KEY_SET_LEN);
} else { }
else {
b.append((unsigned char)0); b.append((unsigned char)0);
} }
} }
@ -238,8 +237,7 @@ public:
* @throws std::out_of_range Serialized data invalid * @throws std::out_of_range Serialized data invalid
* @throws std::invalid_argument Serialized data invalid * @throws std::invalid_argument Serialized data invalid
*/ */
template<unsigned int C> template <unsigned int C> inline unsigned int deserialize(const Buffer<C>& b, unsigned int startAt = 0)
inline unsigned int deserialize(const Buffer<C> &b,unsigned int startAt = 0)
{ {
delete _privateKey; delete _privateKey;
_privateKey = (ECC::Private*)0; _privateKey = (ECC::Private*)0;
@ -292,7 +290,10 @@ public:
/** /**
* @return C25519 public key * @return C25519 public key
*/ */
inline const ECC::Public &publicKey() const { return _publicKey; } inline const ECC::Public& publicKey() const
{
return _publicKey;
}
/** /**
* @return C25519 key pair (only returns valid pair if private key is present in this Identity object) * @return C25519 key pair (only returns valid pair if private key is present in this Identity object)
@ -303,7 +304,8 @@ public:
pair.pub = _publicKey; pair.pub = _publicKey;
if (_privateKey) { if (_privateKey) {
pair.priv = *_privateKey; pair.priv = *_privateKey;
} else { }
else {
memset(pair.priv.data, 0, ZT_ECC_PRIVATE_KEY_SET_LEN); memset(pair.priv.data, 0, ZT_ECC_PRIVATE_KEY_SET_LEN);
} }
return pair; return pair;
@ -312,14 +314,35 @@ public:
/** /**
* @return True if this identity contains something * @return True if this identity contains something
*/ */
inline operator bool() const { return (_address); } inline operator bool() const
{
return (_address);
}
inline bool operator==(const Identity &id) const { return ((_address == id._address)&&(memcmp(_publicKey.data,id._publicKey.data,ZT_ECC_PUBLIC_KEY_SET_LEN) == 0)); } inline bool operator==(const Identity& id) const
inline bool operator<(const Identity &id) const { return ((_address < id._address)||((_address == id._address)&&(memcmp(_publicKey.data,id._publicKey.data,ZT_ECC_PUBLIC_KEY_SET_LEN) < 0))); } {
inline bool operator!=(const Identity &id) const { return !(*this == id); } return ((_address == id._address) && (memcmp(_publicKey.data, id._publicKey.data, ZT_ECC_PUBLIC_KEY_SET_LEN) == 0));
inline bool operator>(const Identity &id) const { return (id < *this); } }
inline bool operator<=(const Identity &id) const { return !(id < *this); } inline bool operator<(const Identity& id) const
inline bool operator>=(const Identity &id) const { return !(*this < id); } {
return ((_address < id._address) || ((_address == id._address) && (memcmp(_publicKey.data, id._publicKey.data, ZT_ECC_PUBLIC_KEY_SET_LEN) < 0)));
}
inline bool operator!=(const Identity& id) const
{
return ! (*this == id);
}
inline bool operator>(const Identity& id) const
{
return (id < *this);
}
inline bool operator<=(const Identity& id) const
{
return ! (id < *this);
}
inline bool operator>=(const Identity& id) const
{
return ! (*this < id);
}
private: private:
Address _address; Address _address;

View file

@ -11,34 +11,34 @@
*/ */
/****/ /****/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "../version.h"
#include "../include/ZeroTierOne.h"
#include "Constants.hpp"
#include "RuntimeEnvironment.hpp"
#include "IncomingPacket.hpp" #include "IncomingPacket.hpp"
#include "Topology.hpp"
#include "Switch.hpp" #include "../include/ZeroTierOne.h"
#include "Peer.hpp" #include "../version.h"
#include "NetworkController.hpp"
#include "SelfAwareness.hpp"
#include "Salsa20.hpp"
#include "SHA512.hpp"
#include "World.hpp"
#include "Node.hpp"
#include "CertificateOfMembership.hpp"
#include "Capability.hpp"
#include "Tag.hpp"
#include "Revocation.hpp"
#include "Trace.hpp"
#include "Path.hpp"
#include "Bond.hpp" #include "Bond.hpp"
#include "Capability.hpp"
#include "CertificateOfMembership.hpp"
#include "Constants.hpp"
#include "Metrics.hpp" #include "Metrics.hpp"
#include "NetworkController.hpp"
#include "Node.hpp"
#include "PacketMultiplexer.hpp" #include "PacketMultiplexer.hpp"
#include "Path.hpp"
#include "Peer.hpp"
#include "Revocation.hpp"
#include "RuntimeEnvironment.hpp"
#include "SHA512.hpp"
#include "Salsa20.hpp"
#include "SelfAwareness.hpp"
#include "Switch.hpp"
#include "Tag.hpp"
#include "Topology.hpp"
#include "Trace.hpp"
#include "World.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
namespace ZeroTier { namespace ZeroTier {
@ -56,11 +56,13 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR,void *tPtr,int32_t f
const uint64_t tpid = trustedPathId(); const uint64_t tpid = trustedPathId();
if (RR->topology->shouldInboundPathBeTrusted(_path->address(), tpid)) { if (RR->topology->shouldInboundPathBeTrusted(_path->address(), tpid)) {
_authenticated = true; _authenticated = true;
} else { }
else {
RR->t->incomingPacketMessageAuthenticationFailure(tPtr, _path, packetId(), sourceAddress, hops(), "path not trusted"); RR->t->incomingPacketMessageAuthenticationFailure(tPtr, _path, packetId(), sourceAddress, hops(), "path not trusted");
return true; return true;
} }
} else if ((c == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_NONE)&&(verb() == Packet::VERB_HELLO)) { }
else if ((c == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_NONE) && (verb() == Packet::VERB_HELLO)) {
// Only HELLO is allowed in the clear, but will still have a MAC // Only HELLO is allowed in the clear, but will still have a MAC
return _doHELLO(RR, tPtr, false); return _doHELLO(RR, tPtr, false);
} }
@ -156,11 +158,13 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR,void *tPtr,int32_t f
return true; return true;
} }
return false; return false;
} else { }
else {
RR->sw->requestWhois(tPtr, RR->node->now(), sourceAddress); RR->sw->requestWhois(tPtr, RR->node->now(), sourceAddress);
return false; return false;
} }
} catch ( ... ) { }
catch (...) {
RR->t->incomingPacketInvalid(tPtr, _path, packetId(), sourceAddress, hops(), verb(), "unexpected exception in tryDecode()"); RR->t->incomingPacketInvalid(tPtr, _path, packetId(), sourceAddress, hops(), verb(), "unexpected exception in tryDecode()");
return true; return true;
} }
@ -182,7 +186,6 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,void *tPtr,const Shar
* circumstances. */ * circumstances. */
switch (errorCode) { switch (errorCode) {
case Packet::ERROR_OBJ_NOT_FOUND: case Packet::ERROR_OBJ_NOT_FOUND:
// Object not found, currently only meaningful from network controllers. // Object not found, currently only meaningful from network controllers.
if (inReVerb == Packet::VERB_NETWORK_CONFIG_REQUEST) { if (inReVerb == Packet::VERB_NETWORK_CONFIG_REQUEST) {
@ -267,7 +270,8 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,void *tPtr,const Shar
authenticationURL[sizeof(authenticationURL) - 1] = 0; // ensure always zero terminated authenticationURL[sizeof(authenticationURL) - 1] = 0; // ensure always zero terminated
network->setAuthenticationRequired(tPtr, authenticationURL); network->setAuthenticationRequired(tPtr, authenticationURL);
} }
} else if (authVer == 1) { }
else if (authVer == 1) {
char issuerURL[2048] = { 0 }; char issuerURL[2048] = { 0 };
char centralAuthURL[2048] = { 0 }; char centralAuthURL[2048] = { 0 };
char ssoNonce[64] = { 0 }; char ssoNonce[64] = { 0 };
@ -292,14 +296,16 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,void *tPtr,const Shar
} }
if (authInfo.get(ZT_AUTHINFO_DICT_KEY_SSO_PROVIDER, ssoProvider, sizeof(ssoProvider)) > 0) { if (authInfo.get(ZT_AUTHINFO_DICT_KEY_SSO_PROVIDER, ssoProvider, sizeof(ssoProvider)) > 0) {
ssoProvider[sizeof(ssoProvider) - 1] = 0; ssoProvider[sizeof(ssoProvider) - 1] = 0;
} else { }
else {
strncpy(ssoProvider, "default", sizeof(ssoProvider)); strncpy(ssoProvider, "default", sizeof(ssoProvider));
} }
network->setAuthenticationRequired(tPtr, issuerURL, centralAuthURL, ssoClientID, ssoProvider, ssoNonce, ssoState); network->setAuthenticationRequired(tPtr, issuerURL, centralAuthURL, ssoClientID, ssoProvider, ssoNonce, ssoState);
} }
} }
} else { }
else {
network->setAuthenticationRequired(tPtr, ""); network->setAuthenticationRequired(tPtr, "");
} }
} }
@ -408,15 +414,18 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool
Metrics::pkt_error_out++; Metrics::pkt_error_out++;
Metrics::pkt_error_identity_collision_out++; Metrics::pkt_error_identity_collision_out++;
_path->send(RR, tPtr, outp.data(), outp.size(), RR->node->now()); _path->send(RR, tPtr, outp.data(), outp.size(), RR->node->now());
} else { }
else {
RR->t->incomingPacketMessageAuthenticationFailure(tPtr, _path, pid, fromAddress, hops(), "invalid MAC"); RR->t->incomingPacketMessageAuthenticationFailure(tPtr, _path, pid, fromAddress, hops(), "invalid MAC");
} }
} else { }
else {
RR->t->incomingPacketMessageAuthenticationFailure(tPtr, _path, pid, fromAddress, hops(), "invalid identity"); RR->t->incomingPacketMessageAuthenticationFailure(tPtr, _path, pid, fromAddress, hops(), "invalid identity");
} }
return true; return true;
} else { }
else {
// Identity is the same as the one we already have -- check packet integrity // Identity is the same as the one we already have -- check packet integrity
if (! dearmor(peer->key(), peer->aesKeysIfSupported(), RR->identity)) { if (! dearmor(peer->key(), peer->aesKeysIfSupported(), RR->identity)) {
@ -427,7 +436,8 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool
// Continue at // VALID // Continue at // VALID
} }
} // else if alreadyAuthenticated then continue at // VALID } // else if alreadyAuthenticated then continue at // VALID
} else { }
else {
// We don't already have an identity with this address -- validate and learn it // We don't already have an identity with this address -- validate and learn it
// Sanity check: this basically can't happen // Sanity check: this basically can't happen
@ -554,7 +564,6 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,void *tPtr,const SharedP
} }
switch (inReVerb) { switch (inReVerb) {
case Packet::VERB_HELLO: { case Packet::VERB_HELLO: {
const uint64_t latency = RR->node->now() - at<uint64_t>(ZT_PROTO_VERB_HELLO__OK__IDX_TIMESTAMP); const uint64_t latency = RR->node->now() - at<uint64_t>(ZT_PROTO_VERB_HELLO__OK__IDX_TIMESTAMP);
const unsigned int vProto = (*this)[ZT_PROTO_VERB_HELLO__OK__IDX_PROTOCOL_VERSION]; const unsigned int vProto = (*this)[ZT_PROTO_VERB_HELLO__OK__IDX_PROTOCOL_VERSION];
@ -584,7 +593,8 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,void *tPtr,const SharedP
ptr += w.deserialize(*this, ptr); ptr += w.deserialize(*this, ptr);
RR->topology->addWorld(tPtr, w, false); RR->topology->addWorld(tPtr, w, false);
} }
} else { }
else {
ptr += worldsLen; ptr += worldsLen;
} }
} }
@ -685,7 +695,8 @@ bool IncomingPacket::_doWHOIS(const RuntimeEnvironment *RR,void *tPtr,const Shar
if (id) { if (id) {
id.serialize(outp, false); id.serialize(outp, false);
++count; ++count;
} else { }
else {
// Request unknown WHOIS from upstream from us (if we have one) // Request unknown WHOIS from upstream from us (if we have one)
RR->sw->requestWhois(tPtr, RR->node->now(), addr); RR->sw->requestWhois(tPtr, RR->node->now(), addr);
} }
@ -840,7 +851,8 @@ bool IncomingPacket::_doFRAME(const RuntimeEnvironment *RR,void *tPtr,const Shar
RR->pm->putFrame(tPtr, nwid, network->userPtr(), sourceMac, network->mac(), etherType, 0, (const void*)frameData, frameLen, _flowId); RR->pm->putFrame(tPtr, nwid, network->userPtr(), sourceMac, network->mac(), etherType, 0, (const void*)frameData, frameLen, _flowId);
} }
} }
} else { }
else {
_sendErrorNeedCredentials(RR, tPtr, peer, nwid); _sendErrorNeedCredentials(RR, tPtr, peer, nwid);
return false; return false;
} }
@ -890,19 +902,22 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,void *tPtr,const
if (from != MAC(peer->address(), nwid)) { if (from != MAC(peer->address(), nwid)) {
if (network->config().permitsBridging(peer->address())) { if (network->config().permitsBridging(peer->address())) {
network->learnBridgeRoute(from, peer->address()); network->learnBridgeRoute(from, peer->address());
} else { }
else {
RR->t->incomingNetworkFrameDropped(tPtr, network, _path, packetId(), size(), peer->address(), Packet::VERB_EXT_FRAME, from, to, "bridging not allowed (remote)"); RR->t->incomingNetworkFrameDropped(tPtr, network, _path, packetId(), size(), peer->address(), Packet::VERB_EXT_FRAME, from, to, "bridging not allowed (remote)");
peer->received(tPtr, _path, hops(), packetId(), payloadLength(), Packet::VERB_EXT_FRAME, 0, Packet::VERB_NOP, true, nwid, flowId); // trustEstablished because COM is okay peer->received(tPtr, _path, hops(), packetId(), payloadLength(), Packet::VERB_EXT_FRAME, 0, Packet::VERB_NOP, true, nwid, flowId); // trustEstablished because COM is okay
return true; return true;
} }
} else if (to != network->mac()) { }
else if (to != network->mac()) {
if (to.isMulticast()) { if (to.isMulticast()) {
if (network->config().multicastLimit == 0) { if (network->config().multicastLimit == 0) {
RR->t->incomingNetworkFrameDropped(tPtr, network, _path, packetId(), size(), peer->address(), Packet::VERB_EXT_FRAME, from, to, "multicast disabled"); RR->t->incomingNetworkFrameDropped(tPtr, network, _path, packetId(), size(), peer->address(), Packet::VERB_EXT_FRAME, from, to, "multicast disabled");
peer->received(tPtr, _path, hops(), packetId(), payloadLength(), Packet::VERB_EXT_FRAME, 0, Packet::VERB_NOP, true, nwid, flowId); // trustEstablished because COM is okay peer->received(tPtr, _path, hops(), packetId(), payloadLength(), Packet::VERB_EXT_FRAME, 0, Packet::VERB_NOP, true, nwid, flowId); // trustEstablished because COM is okay
return true; return true;
} }
} else if (!network->config().permitsBridging(RR->identity.address())) { }
else if (! network->config().permitsBridging(RR->identity.address())) {
RR->t->incomingNetworkFrameDropped(tPtr, network, _path, packetId(), size(), peer->address(), Packet::VERB_EXT_FRAME, from, to, "bridging not allowed (local)"); RR->t->incomingNetworkFrameDropped(tPtr, network, _path, packetId(), size(), peer->address(), Packet::VERB_EXT_FRAME, from, to, "bridging not allowed (local)");
peer->received(tPtr, _path, hops(), packetId(), payloadLength(), Packet::VERB_EXT_FRAME, 0, Packet::VERB_NOP, true, nwid, flowId); // trustEstablished because COM is okay peer->received(tPtr, _path, hops(), packetId(), payloadLength(), Packet::VERB_EXT_FRAME, 0, Packet::VERB_NOP, true, nwid, flowId); // trustEstablished because COM is okay
return true; return true;
@ -928,7 +943,8 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,void *tPtr,const
} }
peer->received(tPtr, _path, hops(), packetId(), payloadLength(), Packet::VERB_EXT_FRAME, 0, Packet::VERB_NOP, true, nwid, flowId); peer->received(tPtr, _path, hops(), packetId(), payloadLength(), Packet::VERB_EXT_FRAME, 0, Packet::VERB_NOP, true, nwid, flowId);
} else { }
else {
peer->received(tPtr, _path, hops(), packetId(), payloadLength(), Packet::VERB_EXT_FRAME, 0, Packet::VERB_NOP, false, nwid, flowId); peer->received(tPtr, _path, hops(), packetId(), payloadLength(), Packet::VERB_EXT_FRAME, 0, Packet::VERB_NOP, false, nwid, flowId);
} }
@ -1140,7 +1156,8 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,void
const char* metaDataBytes = (metaDataLength != 0) ? (const char*)field(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT, metaDataLength) : (const char*)0; const char* metaDataBytes = (metaDataLength != 0) ? (const char*)field(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT, metaDataLength) : (const char*)0;
const Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> metaData(metaDataBytes, metaDataLength); const Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> metaData(metaDataBytes, metaDataLength);
RR->localNetworkController->request(nwid, (hopCount > 0) ? InetAddress() : _path->address(), requestPacketId, peer->identity(), metaData); RR->localNetworkController->request(nwid, (hopCount > 0) ? InetAddress() : _path->address(), requestPacketId, peer->identity(), metaData);
} else { }
else {
Packet outp(peer->address(), RR->identity.address(), Packet::VERB_ERROR); Packet outp(peer->address(), RR->identity.address(), Packet::VERB_ERROR);
outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST); outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
outp.append(requestPacketId); outp.append(requestPacketId);
@ -1199,7 +1216,9 @@ bool IncomingPacket::_doMULTICAST_GATHER(const RuntimeEnvironment *RR,void *tPtr
if ((com) && (network)) { if ((com) && (network)) {
network->addCredential(tPtr, com); network->addCredential(tPtr, com);
} }
} catch ( ... ) {} // discard invalid COMs }
catch (...) {
} // discard invalid COMs
} }
const bool trustEstablished = (network) ? network->gate(tPtr, peer) : false; const bool trustEstablished = (network) ? network->gate(tPtr, peer) : false;
@ -1260,7 +1279,8 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,void *tPtr,
if ((flags & 0x04) != 0) { if ((flags & 0x04) != 0) {
from.setTo(field(offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SOURCE_MAC, 6), 6); from.setTo(field(offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SOURCE_MAC, 6), 6);
offset += 6; offset += 6;
} else { }
else {
from.fromAddress(peer->address(), nwid); from.fromAddress(peer->address(), nwid);
} }
@ -1295,7 +1315,8 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,void *tPtr,
if (from != MAC(peer->address(), nwid)) { if (from != MAC(peer->address(), nwid)) {
if (network->config().permitsBridging(peer->address())) { if (network->config().permitsBridging(peer->address())) {
network->learnBridgeRoute(from, peer->address()); network->learnBridgeRoute(from, peer->address());
} else { }
else {
RR->t->incomingNetworkFrameDropped(tPtr, network, _path, packetId(), size(), peer->address(), Packet::VERB_MULTICAST_FRAME, from, to.mac(), "bridging not allowed (remote)"); RR->t->incomingNetworkFrameDropped(tPtr, network, _path, packetId(), size(), peer->address(), Packet::VERB_MULTICAST_FRAME, from, to.mac(), "bridging not allowed (remote)");
peer->received(tPtr, _path, hops(), packetId(), payloadLength(), Packet::VERB_MULTICAST_FRAME, 0, Packet::VERB_NOP, true, nwid, ZT_QOS_NO_FLOW); // trustEstablished because COM is okay peer->received(tPtr, _path, hops(), packetId(), payloadLength(), Packet::VERB_MULTICAST_FRAME, 0, Packet::VERB_NOP, true, nwid, ZT_QOS_NO_FLOW); // trustEstablished because COM is okay
return true; return true;
@ -1358,29 +1379,28 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,void *tPt
switch (addrType) { switch (addrType) {
case 4: { case 4: {
const InetAddress a(field(ptr, 4), 4, at<uint16_t>(ptr + 4)); const InetAddress a(field(ptr, 4), 4, at<uint16_t>(ptr + 4));
if ( if (((flags & ZT_PUSH_DIRECT_PATHS_FLAG_FORGET_PATH) == 0) && // not being told to forget
((flags & ZT_PUSH_DIRECT_PATHS_FLAG_FORGET_PATH) == 0) && // not being told to forget
(! (((flags & ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT) == 0) && (peer->hasActivePathTo(now, a)))) && // not already known (! (((flags & ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT) == 0) && (peer->hasActivePathTo(now, a)))) && // not already known
(RR->node->shouldUsePathForZeroTierTraffic(tPtr, peer->address(), _path->localSocket(), a))) // should use path (RR->node->shouldUsePathForZeroTierTraffic(tPtr, peer->address(), _path->localSocket(), a))) // should use path
{ {
if ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT) != 0) { if ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT) != 0) {
peer->clusterRedirect(tPtr, _path, a, now); peer->clusterRedirect(tPtr, _path, a, now);
} else if (++countPerScope[(int)a.ipScope()][0] <= ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY) { }
else if (++countPerScope[(int)a.ipScope()][0] <= ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY) {
peer->attemptToContactAt(tPtr, InetAddress(), a, now, false); peer->attemptToContactAt(tPtr, InetAddress(), a, now, false);
} }
} }
} break; } break;
case 6: { case 6: {
const InetAddress a(field(ptr, 16), 16, at<uint16_t>(ptr + 16)); const InetAddress a(field(ptr, 16), 16, at<uint16_t>(ptr + 16));
if ( if (((flags & ZT_PUSH_DIRECT_PATHS_FLAG_FORGET_PATH) == 0) && // not being told to forget
((flags & ZT_PUSH_DIRECT_PATHS_FLAG_FORGET_PATH) == 0) && // not being told to forget
(! (((flags & ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT) == 0) && (peer->hasActivePathTo(now, a)))) && // not already known (! (((flags & ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT) == 0) && (peer->hasActivePathTo(now, a)))) && // not already known
(RR->node->shouldUsePathForZeroTierTraffic(tPtr, peer->address(), _path->localSocket(), a))) // should use path (RR->node->shouldUsePathForZeroTierTraffic(tPtr, peer->address(), _path->localSocket(), a))) // should use path
{ {
if ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT) != 0) { if ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT) != 0) {
peer->clusterRedirect(tPtr, _path, a, now); peer->clusterRedirect(tPtr, _path, a, now);
} else if (++countPerScope[(int)a.ipScope()][1] <= ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY) { }
else if (++countPerScope[(int)a.ipScope()][1] <= ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY) {
peer->attemptToContactAt(tPtr, InetAddress(), a, now, false); peer->attemptToContactAt(tPtr, InetAddress(), a, now, false);
} }
} }
@ -1426,7 +1446,8 @@ bool IncomingPacket::_doREMOTE_TRACE(const RuntimeEnvironment *RR,void *tPtr,con
RR->node->postEvent(tPtr, ZT_EVENT_REMOTE_TRACE, &rt); RR->node->postEvent(tPtr, ZT_EVENT_REMOTE_TRACE, &rt);
} }
rt.data = const_cast<char*>(++ptr); // start of next string, if any rt.data = const_cast<char*>(++ptr); // start of next string, if any
} else { }
else {
++ptr; ++ptr;
} }
} }

View file

@ -14,13 +14,13 @@
#ifndef ZT_INCOMINGPACKET_HPP #ifndef ZT_INCOMINGPACKET_HPP
#define ZT_INCOMINGPACKET_HPP #define ZT_INCOMINGPACKET_HPP
#include <stdexcept> #include "MulticastGroup.hpp"
#include "Packet.hpp" #include "Packet.hpp"
#include "Path.hpp" #include "Path.hpp"
#include "Utils.hpp"
#include "MulticastGroup.hpp"
#include "Peer.hpp" #include "Peer.hpp"
#include "Utils.hpp"
#include <stdexcept>
/* /*
* The big picture: * The big picture:
@ -46,14 +46,9 @@ class Network;
/** /**
* Subclass of packet that handles the decoding of it * Subclass of packet that handles the decoding of it
*/ */
class IncomingPacket : public Packet class IncomingPacket : public Packet {
{
public: public:
IncomingPacket() : IncomingPacket() : Packet(), _receiveTime(0), _path(), _authenticated(false)
Packet(),
_receiveTime(0),
_path(),
_authenticated(false)
{ {
} }
@ -66,11 +61,7 @@ public:
* @param now Current time * @param now Current time
* @throws std::out_of_range Range error processing packet * @throws std::out_of_range Range error processing packet
*/ */
IncomingPacket(const void *data,unsigned int len,const SharedPtr<Path> &path,int64_t now) : IncomingPacket(const void* data, unsigned int len, const SharedPtr<Path>& path, int64_t now) : Packet(data, len), _receiveTime(now), _path(path), _authenticated(false)
Packet(data,len),
_receiveTime(now),
_path(path),
_authenticated(false)
{ {
} }
@ -109,7 +100,10 @@ public:
/** /**
* @return Time of packet receipt / start of decode * @return Time of packet receipt / start of decode
*/ */
inline uint64_t receiveTime() const { return _receiveTime; } inline uint64_t receiveTime() const
{
return _receiveTime;
}
private: private:
// These are called internally to handle packet contents once it has // These are called internally to handle packet contents once it has

View file

@ -11,16 +11,16 @@
*/ */
/****/ /****/
#include <stdio.h> #include "InetAddress.hpp"
#include <string.h>
#include <stdint.h>
#include <string>
#include "Constants.hpp" #include "Constants.hpp"
#include "InetAddress.hpp"
#include "Utils.hpp" #include "Utils.hpp"
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <string>
namespace ZeroTier { namespace ZeroTier {
const InetAddress InetAddress::LO4((const void*)("\x7f\x00\x00\x01"), 4, 0); const InetAddress InetAddress::LO4((const void*)("\x7f\x00\x00\x01"), 4, 0);
@ -29,7 +29,6 @@ const InetAddress InetAddress::LO6((const void *)("\x00\x00\x00\x00\x00\x00\x00\
InetAddress::IpScope InetAddress::ipScope() const InetAddress::IpScope InetAddress::ipScope() const
{ {
switch (ss_family) { switch (ss_family) {
case AF_INET: { case AF_INET: {
const uint32_t ip = Utils::ntoh((uint32_t)reinterpret_cast<const struct sockaddr_in*>(this)->sin_addr.s_addr); const uint32_t ip = Utils::ntoh((uint32_t)reinterpret_cast<const struct sockaddr_in*>(this)->sin_addr.s_addr);
switch (ip >> 24) { switch (ip >> 24) {
@ -124,7 +123,8 @@ InetAddress::IpScope InetAddress::ipScope() const
} }
if ((k == 15) && (ip[15] == 0x01)) { if ((k == 15) && (ip[15] == 0x01)) {
return IP_SCOPE_LOOPBACK; // fe80::1/128 return IP_SCOPE_LOOPBACK; // fe80::1/128
} else { }
else {
return IP_SCOPE_LINK_LOCAL; // fe80::/10 return IP_SCOPE_LINK_LOCAL; // fe80::/10
} }
} }
@ -159,7 +159,6 @@ InetAddress::IpScope InetAddress::ipScope() const
} }
return IP_SCOPE_GLOBAL; return IP_SCOPE_GLOBAL;
} break; } break;
} }
return IP_SCOPE_NONE; return IP_SCOPE_NONE;
@ -174,7 +173,8 @@ void InetAddress::set(const void *ipBytes,unsigned int ipLen,unsigned int port)
ss_family = AF_INET; ss_family = AF_INET;
reinterpret_cast<struct sockaddr_in*>(this)->sin_addr.s_addr = ipb[0]; reinterpret_cast<struct sockaddr_in*>(this)->sin_addr.s_addr = ipb[0];
reinterpret_cast<struct sockaddr_in*>(this)->sin_port = Utils::hton((uint16_t)port); reinterpret_cast<struct sockaddr_in*>(this)->sin_port = Utils::hton((uint16_t)port);
} else if (ipLen == 16) { }
else if (ipLen == 16) {
ss_family = AF_INET6; ss_family = AF_INET6;
memcpy(reinterpret_cast<struct sockaddr_in6*>(this)->sin6_addr.s6_addr, ipBytes, 16); memcpy(reinterpret_cast<struct sockaddr_in6*>(this)->sin6_addr.s6_addr, ipBytes, 16);
reinterpret_cast<struct sockaddr_in6*>(this)->sin6_port = Utils::hton((uint16_t)port); reinterpret_cast<struct sockaddr_in6*>(this)->sin6_port = Utils::hton((uint16_t)port);
@ -246,13 +246,15 @@ bool InetAddress::fromString(const char *ipSlashPort)
in6->sin6_family = AF_INET6; in6->sin6_family = AF_INET6;
in6->sin6_port = Utils::hton((uint16_t)port); in6->sin6_port = Utils::hton((uint16_t)port);
return true; return true;
} else if (strchr(buf,'.')) { }
else if (strchr(buf, '.')) {
struct sockaddr_in* const in = reinterpret_cast<struct sockaddr_in*>(this); struct sockaddr_in* const in = reinterpret_cast<struct sockaddr_in*>(this);
inet_pton(AF_INET, buf, &in->sin_addr.s_addr); inet_pton(AF_INET, buf, &in->sin_addr.s_addr);
in->sin_family = AF_INET; in->sin_family = AF_INET;
in->sin_port = Utils::hton((uint16_t)port); in->sin_port = Utils::hton((uint16_t)port);
return true; return true;
} else { }
else {
return false; return false;
} }
} }
@ -270,7 +272,8 @@ InetAddress InetAddress::netmask() const
if (bits) { if (bits) {
nm[0] = Utils::hton((uint64_t)((bits >= 64) ? 0xffffffffffffffffULL : (0xffffffffffffffffULL << (64 - bits)))); nm[0] = Utils::hton((uint64_t)((bits >= 64) ? 0xffffffffffffffffULL : (0xffffffffffffffffULL << (64 - bits))));
nm[1] = Utils::hton((uint64_t)((bits <= 64) ? 0ULL : (0xffffffffffffffffULL << (128 - bits)))); nm[1] = Utils::hton((uint64_t)((bits <= 64) ? 0ULL : (0xffffffffffffffffULL << (128 - bits))));
} else { }
else {
nm[0] = 0; nm[0] = 0;
nm[1] = 0; nm[1] = 0;
} }
@ -341,7 +344,8 @@ bool InetAddress::containsAddress(const InetAddress &addr) const
if (bits == 0) { if (bits == 0) {
return true; return true;
} }
return ( (Utils::ntoh((uint32_t)reinterpret_cast<const struct sockaddr_in *>(&addr)->sin_addr.s_addr) >> (32 - bits)) == (Utils::ntoh((uint32_t)reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr) >> (32 - bits)) ); return (
(Utils::ntoh((uint32_t)reinterpret_cast<const struct sockaddr_in*>(&addr)->sin_addr.s_addr) >> (32 - bits)) == (Utils::ntoh((uint32_t)reinterpret_cast<const struct sockaddr_in*>(this)->sin_addr.s_addr) >> (32 - bits)));
} }
case AF_INET6: { case AF_INET6: {
const InetAddress mask(netmask()); const InetAddress mask(netmask());
@ -404,15 +408,15 @@ bool InetAddress::operator==(const InetAddress &a) const
switch (ss_family) { switch (ss_family) {
case AF_INET: case AF_INET:
return ( return (
(reinterpret_cast<const struct sockaddr_in *>(this)->sin_port == reinterpret_cast<const struct sockaddr_in *>(&a)->sin_port)&& (reinterpret_cast<const struct sockaddr_in*>(this)->sin_port == reinterpret_cast<const struct sockaddr_in*>(&a)->sin_port)
(reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr == reinterpret_cast<const struct sockaddr_in *>(&a)->sin_addr.s_addr)); && (reinterpret_cast<const struct sockaddr_in*>(this)->sin_addr.s_addr == reinterpret_cast<const struct sockaddr_in*>(&a)->sin_addr.s_addr));
break; break;
case AF_INET6: case AF_INET6:
return ( return (
(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_port == reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_port)&& (reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_port == reinterpret_cast<const struct sockaddr_in6*>(&a)->sin6_port)
(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_flowinfo == reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_flowinfo)&& && (reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_flowinfo == reinterpret_cast<const struct sockaddr_in6*>(&a)->sin6_flowinfo)
(memcmp(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr,reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_addr.s6_addr,16) == 0)&& && (memcmp(reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_addr.s6_addr, reinterpret_cast<const struct sockaddr_in6*>(&a)->sin6_addr.s6_addr, 16) == 0)
(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_scope_id == reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_scope_id)); && (reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_scope_id == reinterpret_cast<const struct sockaddr_in6*>(&a)->sin6_scope_id));
break; break;
default: default:
return (memcmp(this, &a, sizeof(InetAddress)) == 0); return (memcmp(this, &a, sizeof(InetAddress)) == 0);
@ -425,12 +429,14 @@ bool InetAddress::operator<(const InetAddress &a) const
{ {
if (ss_family < a.ss_family) { if (ss_family < a.ss_family) {
return true; return true;
} else if (ss_family == a.ss_family) { }
else if (ss_family == a.ss_family) {
switch (ss_family) { switch (ss_family) {
case AF_INET: case AF_INET:
if (reinterpret_cast<const struct sockaddr_in*>(this)->sin_port < reinterpret_cast<const struct sockaddr_in*>(&a)->sin_port) { if (reinterpret_cast<const struct sockaddr_in*>(this)->sin_port < reinterpret_cast<const struct sockaddr_in*>(&a)->sin_port) {
return true; return true;
} else if (reinterpret_cast<const struct sockaddr_in *>(this)->sin_port == reinterpret_cast<const struct sockaddr_in *>(&a)->sin_port) { }
else if (reinterpret_cast<const struct sockaddr_in*>(this)->sin_port == reinterpret_cast<const struct sockaddr_in*>(&a)->sin_port) {
if (reinterpret_cast<const struct sockaddr_in*>(this)->sin_addr.s_addr < reinterpret_cast<const struct sockaddr_in*>(&a)->sin_addr.s_addr) { if (reinterpret_cast<const struct sockaddr_in*>(this)->sin_addr.s_addr < reinterpret_cast<const struct sockaddr_in*>(&a)->sin_addr.s_addr) {
return true; return true;
} }
@ -439,13 +445,16 @@ bool InetAddress::operator<(const InetAddress &a) const
case AF_INET6: case AF_INET6:
if (reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_port < reinterpret_cast<const struct sockaddr_in6*>(&a)->sin6_port) { if (reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_port < reinterpret_cast<const struct sockaddr_in6*>(&a)->sin6_port) {
return true; return true;
} else if (reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_port == reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_port) { }
else if (reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_port == reinterpret_cast<const struct sockaddr_in6*>(&a)->sin6_port) {
if (reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_flowinfo < reinterpret_cast<const struct sockaddr_in6*>(&a)->sin6_flowinfo) { if (reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_flowinfo < reinterpret_cast<const struct sockaddr_in6*>(&a)->sin6_flowinfo) {
return true; return true;
} else if (reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_flowinfo == reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_flowinfo) { }
else if (reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_flowinfo == reinterpret_cast<const struct sockaddr_in6*>(&a)->sin6_flowinfo) {
if (memcmp(reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_addr.s6_addr, reinterpret_cast<const struct sockaddr_in6*>(&a)->sin6_addr.s6_addr, 16) < 0) { if (memcmp(reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_addr.s6_addr, reinterpret_cast<const struct sockaddr_in6*>(&a)->sin6_addr.s6_addr, 16) < 0) {
return true; return true;
} else if (memcmp(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr,reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_addr.s6_addr,16) == 0) { }
else if (memcmp(reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_addr.s6_addr, reinterpret_cast<const struct sockaddr_in6*>(&a)->sin6_addr.s6_addr, 16) == 0) {
if (reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_scope_id < reinterpret_cast<const struct sockaddr_in6*>(&a)->sin6_scope_id) { if (reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_scope_id < reinterpret_cast<const struct sockaddr_in6*>(&a)->sin6_scope_id) {
return true; return true;
} }

View file

@ -14,15 +14,15 @@
#ifndef ZT_INETADDRESS_HPP #ifndef ZT_INETADDRESS_HPP
#define ZT_INETADDRESS_HPP #define ZT_INETADDRESS_HPP
#include "../include/ZeroTierOne.h"
#include "Buffer.hpp"
#include "Constants.hpp"
#include "MAC.hpp"
#include "Utils.hpp"
#include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdint.h>
#include "Constants.hpp"
#include "../include/ZeroTierOne.h"
#include "Utils.hpp"
#include "MAC.hpp"
#include "Buffer.hpp"
namespace ZeroTier { namespace ZeroTier {
@ -39,8 +39,7 @@ namespace ZeroTier {
* sockaddr_storage and used interchangeably. DO NOT change this by e.g. * sockaddr_storage and used interchangeably. DO NOT change this by e.g.
* adding non-static fields, since much code depends on this identity. * adding non-static fields, since much code depends on this identity.
*/ */
struct InetAddress : public sockaddr_storage struct InetAddress : public sockaddr_storage {
{
/** /**
* Loopback IPv4 address (no port) * Loopback IPv4 address (no port)
*/ */
@ -58,8 +57,7 @@ struct InetAddress : public sockaddr_storage
* MUST remain that way or Path must be changed to reflect. Also be sure * MUST remain that way or Path must be changed to reflect. Also be sure
* to change ZT_INETADDRESS_MAX_SCOPE if the max changes. * to change ZT_INETADDRESS_MAX_SCOPE if the max changes.
*/ */
enum IpScope enum IpScope {
{
IP_SCOPE_NONE = 0, // NULL or not an IP address IP_SCOPE_NONE = 0, // NULL or not an IP address
IP_SCOPE_MULTICAST = 1, // 224.0.0.0 and other V4/V6 multicast IPs IP_SCOPE_MULTICAST = 1, // 224.0.0.0 and other V4/V6 multicast IPs
IP_SCOPE_LOOPBACK = 2, // 127.0.0.1, ::1, etc. IP_SCOPE_LOOPBACK = 2, // 127.0.0.1, ::1, etc.
@ -72,25 +70,69 @@ struct InetAddress : public sockaddr_storage
// Can be used with the unordered maps and sets in c++11. We don't use C++11 in the core // Can be used with the unordered maps and sets in c++11. We don't use C++11 in the core
// but this is safe to put here. // but this is safe to put here.
struct Hasher struct Hasher {
inline std::size_t operator()(const InetAddress& a) const
{ {
inline std::size_t operator()(const InetAddress &a) const { return (std::size_t)a.hashCode(); } return (std::size_t)a.hashCode();
}
}; };
InetAddress() { memset(this,0,sizeof(InetAddress)); } InetAddress()
InetAddress(const InetAddress &a) { memcpy(this,&a,sizeof(InetAddress)); } {
InetAddress(const InetAddress *a) { memcpy(this,a,sizeof(InetAddress)); } memset(this, 0, sizeof(InetAddress));
InetAddress(const struct sockaddr_storage &ss) { *this = ss; } }
InetAddress(const struct sockaddr_storage *ss) { *this = ss; } InetAddress(const InetAddress& a)
InetAddress(const struct sockaddr &sa) { *this = sa; } {
InetAddress(const struct sockaddr *sa) { *this = sa; } memcpy(this, &a, sizeof(InetAddress));
InetAddress(const struct sockaddr_in &sa) { *this = sa; } }
InetAddress(const struct sockaddr_in *sa) { *this = sa; } InetAddress(const InetAddress* a)
InetAddress(const struct sockaddr_in6 &sa) { *this = sa; } {
InetAddress(const struct sockaddr_in6 *sa) { *this = sa; } memcpy(this, a, sizeof(InetAddress));
InetAddress(const void *ipBytes,unsigned int ipLen,unsigned int port) { this->set(ipBytes,ipLen,port); } }
InetAddress(const uint32_t ipv4,unsigned int port) { this->set(&ipv4,4,port); } InetAddress(const struct sockaddr_storage& ss)
InetAddress(const char *ipSlashPort) { this->fromString(ipSlashPort); } {
*this = ss;
}
InetAddress(const struct sockaddr_storage* ss)
{
*this = ss;
}
InetAddress(const struct sockaddr& sa)
{
*this = sa;
}
InetAddress(const struct sockaddr* sa)
{
*this = sa;
}
InetAddress(const struct sockaddr_in& sa)
{
*this = sa;
}
InetAddress(const struct sockaddr_in* sa)
{
*this = sa;
}
InetAddress(const struct sockaddr_in6& sa)
{
*this = sa;
}
InetAddress(const struct sockaddr_in6* sa)
{
*this = sa;
}
InetAddress(const void* ipBytes, unsigned int ipLen, unsigned int port)
{
this->set(ipBytes, ipLen, port);
}
InetAddress(const uint32_t ipv4, unsigned int port)
{
this->set(&ipv4, 4, port);
}
InetAddress(const char* ipSlashPort)
{
this->fromString(ipSlashPort);
}
inline InetAddress& operator=(const InetAddress& a) inline InetAddress& operator=(const InetAddress& a)
{ {
@ -283,7 +325,10 @@ struct InetAddress : public sockaddr_storage
* *
* @return Netmask bits * @return Netmask bits
*/ */
inline unsigned int netmaskBits() const { return port(); } inline unsigned int netmaskBits() const
{
return port();
}
/** /**
* @return True if netmask bits is valid for the address type * @return True if netmask bits is valid for the address type
@ -308,7 +353,10 @@ struct InetAddress : public sockaddr_storage
* *
* @return Gateway metric * @return Gateway metric
*/ */
inline unsigned int metric() const { return port(); } inline unsigned int metric() const
{
return port();
}
/** /**
* Construct a full netmask as an InetAddress * Construct a full netmask as an InetAddress
@ -353,12 +401,18 @@ struct InetAddress : public sockaddr_storage
/** /**
* @return True if this is an IPv4 address * @return True if this is an IPv4 address
*/ */
inline bool isV4() const { return (ss_family == AF_INET); } inline bool isV4() const
{
return (ss_family == AF_INET);
}
/** /**
* @return True if this is an IPv6 address * @return True if this is an IPv6 address
*/ */
inline bool isV6() const { return (ss_family == AF_INET6); } inline bool isV6() const
{
return (ss_family == AF_INET6);
}
/** /**
* @return pointer to raw address bytes or NULL if not available * @return pointer to raw address bytes or NULL if not available
@ -440,14 +494,16 @@ struct InetAddress : public sockaddr_storage
{ {
if (ss_family == AF_INET) { if (ss_family == AF_INET) {
return ((unsigned long)reinterpret_cast<const struct sockaddr_in*>(this)->sin_addr.s_addr + (unsigned long)reinterpret_cast<const struct sockaddr_in*>(this)->sin_port); return ((unsigned long)reinterpret_cast<const struct sockaddr_in*>(this)->sin_addr.s_addr + (unsigned long)reinterpret_cast<const struct sockaddr_in*>(this)->sin_port);
} else if (ss_family == AF_INET6) { }
else if (ss_family == AF_INET6) {
unsigned long tmp = reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_port; unsigned long tmp = reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_port;
const uint8_t* a = reinterpret_cast<const uint8_t*>(reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_addr.s6_addr); const uint8_t* a = reinterpret_cast<const uint8_t*>(reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_addr.s6_addr);
for (long i = 0; i < 16; ++i) { for (long i = 0; i < 16; ++i) {
reinterpret_cast<uint8_t*>(&tmp)[i % sizeof(tmp)] ^= a[i]; reinterpret_cast<uint8_t*>(&tmp)[i % sizeof(tmp)] ^= a[i];
} }
return tmp; return tmp;
} else { }
else {
unsigned long tmp = reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_port; unsigned long tmp = reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_port;
const uint8_t* a = reinterpret_cast<const uint8_t*>(this); const uint8_t* a = reinterpret_cast<const uint8_t*>(this);
for (long i = 0; i < (long)sizeof(InetAddress); ++i) { for (long i = 0; i < (long)sizeof(InetAddress); ++i) {
@ -460,7 +516,10 @@ struct InetAddress : public sockaddr_storage
/** /**
* Set to null/zero * Set to null/zero
*/ */
inline void zero() { memset(this,0,sizeof(InetAddress)); } inline void zero()
{
memset(this, 0, sizeof(InetAddress));
}
/** /**
* Check whether this is a network/route rather than an IP assignment * Check whether this is a network/route rather than an IP assignment
@ -500,7 +559,8 @@ struct InetAddress : public sockaddr_storage
for (unsigned int i = 0; i < 16; ++i) { for (unsigned int i = 0; i < 16; ++i) {
if (ip0[i] == ip1[i]) { if (ip0[i] == ip1[i]) {
c += 8; c += 8;
} else { }
else {
uint8_t ip0b = ip0[i]; uint8_t ip0b = ip0[i];
uint8_t ip1b = ip1[i]; uint8_t ip1b = ip1[i];
uint8_t bit = 0x80; uint8_t bit = 0x80;
@ -552,10 +612,12 @@ struct InetAddress : public sockaddr_storage
/** /**
* @return True if address family is non-zero * @return True if address family is non-zero
*/ */
inline operator bool() const { return (ss_family != 0); } inline operator bool() const
{
return (ss_family != 0);
}
template<unsigned int C> template <unsigned int C> inline void serialize(Buffer<C>& b) const
inline void serialize(Buffer<C> &b) const
{ {
// This is used in the protocol and must be the same as describe in places // This is used in the protocol and must be the same as describe in places
// like VERB_HELLO in Packet.hpp. // like VERB_HELLO in Packet.hpp.
@ -576,8 +638,7 @@ struct InetAddress : public sockaddr_storage
} }
} }
template<unsigned int C> template <unsigned int C> inline unsigned int deserialize(const Buffer<C>& b, unsigned int startAt = 0)
inline unsigned int deserialize(const Buffer<C> &b,unsigned int startAt = 0)
{ {
memset(this, 0, sizeof(InetAddress)); memset(this, 0, sizeof(InetAddress));
unsigned int p = startAt; unsigned int p = startAt;
@ -616,10 +677,22 @@ struct InetAddress : public sockaddr_storage
bool operator==(const InetAddress& a) const; bool operator==(const InetAddress& a) const;
bool operator<(const InetAddress& a) const; bool operator<(const InetAddress& a) const;
inline bool operator!=(const InetAddress &a) const { return !(*this == a); } inline bool operator!=(const InetAddress& a) const
inline bool operator>(const InetAddress &a) const { return (a < *this); } {
inline bool operator<=(const InetAddress &a) const { return !(a < *this); } return ! (*this == a);
inline bool operator>=(const InetAddress &a) const { return !(*this < a); } }
inline bool operator>(const InetAddress& a) const
{
return (a < *this);
}
inline bool operator<=(const InetAddress& a) const
{
return ! (a < *this);
}
inline bool operator>=(const InetAddress& a) const
{
return ! (*this < a);
}
/** /**
* @param mac MAC address seed * @param mac MAC address seed

View file

@ -14,51 +14,68 @@
#ifndef ZT_MAC_HPP #ifndef ZT_MAC_HPP
#define ZT_MAC_HPP #define ZT_MAC_HPP
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "Constants.hpp"
#include "Utils.hpp"
#include "Address.hpp" #include "Address.hpp"
#include "Buffer.hpp" #include "Buffer.hpp"
#include "Constants.hpp"
#include "Utils.hpp"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
namespace ZeroTier { namespace ZeroTier {
/** /**
* 48-byte Ethernet MAC address * 48-byte Ethernet MAC address
*/ */
class MAC class MAC {
{
public: public:
MAC() : _m(0ULL) {} MAC() : _m(0ULL)
MAC(const MAC &m) : _m(m._m) {} {
}
MAC(const MAC& m) : _m(m._m)
{
}
MAC(const unsigned char a,const unsigned char b,const unsigned char c,const unsigned char d,const unsigned char e,const unsigned char f) : MAC(const unsigned char a, const unsigned char b, const unsigned char c, const unsigned char d, const unsigned char e, const unsigned char f)
_m( ((((uint64_t)a) & 0xffULL) << 40) | : _m(((((uint64_t)a) & 0xffULL) << 40) | ((((uint64_t)b) & 0xffULL) << 32) | ((((uint64_t)c) & 0xffULL) << 24) | ((((uint64_t)d) & 0xffULL) << 16) | ((((uint64_t)e) & 0xffULL) << 8) | (((uint64_t)f) & 0xffULL))
((((uint64_t)b) & 0xffULL) << 32) | {
((((uint64_t)c) & 0xffULL) << 24) | }
((((uint64_t)d) & 0xffULL) << 16) | MAC(const void* bits, unsigned int len)
((((uint64_t)e) & 0xffULL) << 8) | {
(((uint64_t)f) & 0xffULL) ) {} setTo(bits, len);
MAC(const void *bits,unsigned int len) { setTo(bits,len); } }
MAC(const Address &ztaddr,uint64_t nwid) { fromAddress(ztaddr,nwid); } MAC(const Address& ztaddr, uint64_t nwid)
MAC(const uint64_t m) : _m(m & 0xffffffffffffULL) {} {
fromAddress(ztaddr, nwid);
}
MAC(const uint64_t m) : _m(m & 0xffffffffffffULL)
{
}
/** /**
* @return MAC in 64-bit integer * @return MAC in 64-bit integer
*/ */
inline uint64_t toInt() const { return _m; } inline uint64_t toInt() const
{
return _m;
}
/** /**
* Set MAC to zero * Set MAC to zero
*/ */
inline void zero() { _m = 0ULL; } inline void zero()
{
_m = 0ULL;
}
/** /**
* @return True if MAC is non-zero * @return True if MAC is non-zero
*/ */
inline operator bool() const { return (_m != 0ULL); } inline operator bool() const
{
return (_m != 0ULL);
}
/** /**
* @param bits Raw MAC in big-endian byte order * @param bits Raw MAC in big-endian byte order
@ -107,8 +124,7 @@ public:
* *
* @param b Buffer to append to * @param b Buffer to append to
*/ */
template<unsigned int C> template <unsigned int C> inline void appendTo(Buffer<C>& b) const
inline void appendTo(Buffer<C> &b) const
{ {
unsigned char* p = (unsigned char*)b.appendField(6); unsigned char* p = (unsigned char*)b.appendField(6);
*(p++) = (unsigned char)((_m >> 40) & 0xff); *(p++) = (unsigned char)((_m >> 40) & 0xff);
@ -122,17 +138,26 @@ public:
/** /**
* @return True if this is broadcast (all 0xff) * @return True if this is broadcast (all 0xff)
*/ */
inline bool isBroadcast() const { return (_m == 0xffffffffffffULL); } inline bool isBroadcast() const
{
return (_m == 0xffffffffffffULL);
}
/** /**
* @return True if this is a multicast MAC * @return True if this is a multicast MAC
*/ */
inline bool isMulticast() const { return ((_m & 0x010000000000ULL) != 0ULL); } inline bool isMulticast() const
{
return ((_m & 0x010000000000ULL) != 0ULL);
}
/** /**
* @param True if this is a locally-administered MAC * @param True if this is a locally-administered MAC
*/ */
inline bool isLocallyAdministered() const { return ((_m & 0x020000000000ULL) != 0ULL); } inline bool isLocallyAdministered() const
{
return ((_m & 0x020000000000ULL) != 0ULL);
}
/** /**
* Set this MAC to a MAC derived from an address and a network ID * Set this MAC to a MAC derived from an address and a network ID
@ -184,14 +209,23 @@ public:
* @param i Value from 0 to 5 (inclusive) * @param i Value from 0 to 5 (inclusive)
* @return Byte at said position (address interpreted in big-endian order) * @return Byte at said position (address interpreted in big-endian order)
*/ */
inline unsigned char operator[](unsigned int i) const { return (unsigned char)((_m >> (40 - (i * 8))) & 0xff); } inline unsigned char operator[](unsigned int i) const
{
return (unsigned char)((_m >> (40 - (i * 8))) & 0xff);
}
/** /**
* @return 6, which is the number of bytes in a MAC, for container compliance * @return 6, which is the number of bytes in a MAC, for container compliance
*/ */
inline unsigned int size() const { return 6; } inline unsigned int size() const
{
return 6;
}
inline unsigned long hashCode() const { return (unsigned long)_m; } inline unsigned long hashCode() const
{
return (unsigned long)_m;
}
inline char* toString(char buf[18]) const inline char* toString(char buf[18]) const
{ {
@ -227,12 +261,30 @@ public:
return *this; return *this;
} }
inline bool operator==(const MAC &m) const { return (_m == m._m); } inline bool operator==(const MAC& m) const
inline bool operator!=(const MAC &m) const { return (_m != m._m); } {
inline bool operator<(const MAC &m) const { return (_m < m._m); } return (_m == m._m);
inline bool operator<=(const MAC &m) const { return (_m <= m._m); } }
inline bool operator>(const MAC &m) const { return (_m > m._m); } inline bool operator!=(const MAC& m) const
inline bool operator>=(const MAC &m) const { return (_m >= m._m); } {
return (_m != m._m);
}
inline bool operator<(const MAC& m) const
{
return (_m < m._m);
}
inline bool operator<=(const MAC& m) const
{
return (_m <= m._m);
}
inline bool operator>(const MAC& m) const
{
return (_m > m._m);
}
inline bool operator>=(const MAC& m) const
{
return (_m >= m._m);
}
private: private:
uint64_t _m; uint64_t _m;

View file

@ -11,27 +11,21 @@
*/ */
/****/ /****/
#include <algorithm>
#include "Membership.hpp" #include "Membership.hpp"
#include "RuntimeEnvironment.hpp"
#include "Peer.hpp"
#include "Topology.hpp"
#include "Switch.hpp"
#include "Packet.hpp"
#include "Node.hpp" #include "Node.hpp"
#include "Packet.hpp"
#include "Peer.hpp"
#include "RuntimeEnvironment.hpp"
#include "Switch.hpp"
#include "Topology.hpp"
#include "Trace.hpp" #include "Trace.hpp"
#include <algorithm>
namespace ZeroTier { namespace ZeroTier {
Membership::Membership() : Membership::Membership() : _lastUpdatedMulticast(0), _comRevocationThreshold(0), _lastPushedCredentials(0), _revocations(4), _remoteTags(4), _remoteCaps(4), _remoteCoos(4)
_lastUpdatedMulticast(0),
_comRevocationThreshold(0),
_lastPushedCredentials(0),
_revocations(4),
_remoteTags(4),
_remoteCaps(4),
_remoteCoos(4)
{ {
} }
@ -172,9 +166,18 @@ static Membership::AddCredentialResult _addCredImpl(Hashtable<uint32_t,C> &remot
} }
} }
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const Tag &tag) { return _addCredImpl<Tag>(_remoteTags,_revocations,RR,tPtr,nconf,tag); } Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment* RR, void* tPtr, const NetworkConfig& nconf, const Tag& tag)
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const Capability &cap) { return _addCredImpl<Capability>(_remoteCaps,_revocations,RR,tPtr,nconf,cap); } {
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const CertificateOfOwnership &coo) { return _addCredImpl<CertificateOfOwnership>(_remoteCoos,_revocations,RR,tPtr,nconf,coo); } return _addCredImpl<Tag>(_remoteTags, _revocations, RR, tPtr, nconf, tag);
}
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment* RR, void* tPtr, const NetworkConfig& nconf, const Capability& cap)
{
return _addCredImpl<Capability>(_remoteCaps, _revocations, RR, tPtr, nconf, cap);
}
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment* RR, void* tPtr, const NetworkConfig& nconf, const CertificateOfOwnership& coo)
{
return _addCredImpl<CertificateOfOwnership>(_remoteCoos, _revocations, RR, tPtr, nconf, coo);
}
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment* RR, void* tPtr, const NetworkConfig& nconf, const Revocation& rev) Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment* RR, void* tPtr, const NetworkConfig& nconf, const Revocation& rev)
{ {

View file

@ -14,17 +14,17 @@
#ifndef ZT_MEMBERSHIP_HPP #ifndef ZT_MEMBERSHIP_HPP
#define ZT_MEMBERSHIP_HPP #define ZT_MEMBERSHIP_HPP
#include <stdint.h>
#include "Constants.hpp"
#include "../include/ZeroTierOne.h" #include "../include/ZeroTierOne.h"
#include "Capability.hpp"
#include "CertificateOfMembership.hpp"
#include "Constants.hpp"
#include "Credential.hpp" #include "Credential.hpp"
#include "Hashtable.hpp" #include "Hashtable.hpp"
#include "CertificateOfMembership.hpp"
#include "Capability.hpp"
#include "Tag.hpp"
#include "Revocation.hpp"
#include "NetworkConfig.hpp" #include "NetworkConfig.hpp"
#include "Revocation.hpp"
#include "Tag.hpp"
#include <stdint.h>
#define ZT_MEMBERSHIP_CRED_ID_UNUSED 0xffffffffffffffffULL #define ZT_MEMBERSHIP_CRED_ID_UNUSED 0xffffffffffffffffULL
@ -40,16 +40,9 @@ class Network;
* *
* This class is not thread safe. It must be locked externally. * This class is not thread safe. It must be locked externally.
*/ */
class Membership class Membership {
{
public: public:
enum AddCredentialResult enum AddCredentialResult { ADD_REJECTED, ADD_ACCEPTED_NEW, ADD_ACCEPTED_REDUNDANT, ADD_DEFERRED_FOR_WHOIS };
{
ADD_REJECTED,
ADD_ACCEPTED_NEW,
ADD_ACCEPTED_REDUNDANT,
ADD_DEFERRED_FOR_WHOIS
};
Membership(); Membership();
@ -64,9 +57,18 @@ public:
*/ */
void pushCredentials(const RuntimeEnvironment* RR, void* tPtr, const int64_t now, const Address& peerAddress, const NetworkConfig& nconf); void pushCredentials(const RuntimeEnvironment* RR, void* tPtr, const int64_t now, const Address& peerAddress, const NetworkConfig& nconf);
inline int64_t lastPushedCredentials() { return _lastPushedCredentials; } inline int64_t lastPushedCredentials()
inline int64_t comTimestamp() { return _com.timestamp(); } {
inline int64_t comRevocationThreshold() { return _comRevocationThreshold; } return _lastPushedCredentials;
}
inline int64_t comTimestamp()
{
return _com.timestamp();
}
inline int64_t comRevocationThreshold()
{
return _comRevocationThreshold;
}
/** /**
* Check whether we should push MULTICAST_LIKEs to this peer, and update last sent time if true * Check whether we should push MULTICAST_LIKEs to this peer, and update last sent time if true
@ -108,8 +110,7 @@ public:
* @param r Resource to check * @param r Resource to check
* @return True if this peer has a certificate of ownership for the given resource * @return True if this peer has a certificate of ownership for the given resource
*/ */
template<typename T> template <typename T> inline bool hasCertificateOfOwnershipFor(const NetworkConfig& nconf, const T& r) const
inline bool hasCertificateOfOwnershipFor(const NetworkConfig &nconf,const T &r) const
{ {
uint32_t* k = (uint32_t*)0; uint32_t* k = (uint32_t*)0;
CertificateOfOwnership* v = (CertificateOfOwnership*)0; CertificateOfOwnership* v = (CertificateOfOwnership*)0;
@ -171,10 +172,16 @@ public:
/** /**
* Generates a key for the internal use in indexing credentials by type and credential ID * Generates a key for the internal use in indexing credentials by type and credential ID
*/ */
static uint64_t credentialKey(const Credential::Type &t,const uint32_t i) { return (((uint64_t)t << 32) | (uint64_t)i); } static uint64_t credentialKey(const Credential::Type& t, const uint32_t i)
{
return (((uint64_t)t << 32) | (uint64_t)i);
}
private: private:
inline bool _isV6NDPEmulated(const NetworkConfig &nconf,const MAC &m) const { return false; } inline bool _isV6NDPEmulated(const NetworkConfig& nconf, const MAC& m) const
{
return false;
}
inline bool _isV6NDPEmulated(const NetworkConfig& nconf, const InetAddress& ip) const inline bool _isV6NDPEmulated(const NetworkConfig& nconf, const InetAddress& ip) const
{ {
if ((ip.isV6()) && (nconf.ndpEmulation())) { if ((ip.isV6()) && (nconf.ndpEmulation())) {
@ -215,8 +222,7 @@ private:
return false; return false;
} }
template<typename C> template <typename C> inline bool _isCredentialTimestampValid(const NetworkConfig& nconf, const C& remoteCredential) const
inline bool _isCredentialTimestampValid(const NetworkConfig &nconf,const C &remoteCredential) const
{ {
const int64_t ts = remoteCredential.timestamp(); const int64_t ts = remoteCredential.timestamp();
if (((ts >= nconf.timestamp) ? (ts - nconf.timestamp) : (nconf.timestamp - ts)) <= nconf.credentialTimeMaxDelta) { if (((ts >= nconf.timestamp) ? (ts - nconf.timestamp) : (nconf.timestamp - ts)) <= nconf.credentialTimeMaxDelta) {
@ -226,8 +232,7 @@ private:
return false; return false;
} }
template<typename C> template <typename C> inline void _cleanCredImpl(const NetworkConfig& nconf, Hashtable<uint32_t, C>& remoteCreds)
inline void _cleanCredImpl(const NetworkConfig &nconf,Hashtable<uint32_t,C> &remoteCreds)
{ {
uint32_t* k = (uint32_t*)0; uint32_t* k = (uint32_t*)0;
C* v = (C*)0; C* v = (C*)0;
@ -260,15 +265,9 @@ private:
Hashtable<uint32_t, CertificateOfOwnership> _remoteCoos; Hashtable<uint32_t, CertificateOfOwnership> _remoteCoos;
public: public:
class CapabilityIterator class CapabilityIterator {
{
public: public:
CapabilityIterator(Membership &m,const NetworkConfig &nconf) : CapabilityIterator(Membership& m, const NetworkConfig& nconf) : _hti(m._remoteCaps), _k((uint32_t*)0), _c((Capability*)0), _m(m), _nconf(nconf)
_hti(m._remoteCaps),
_k((uint32_t *)0),
_c((Capability *)0),
_m(m),
_nconf(nconf)
{ {
} }

View file

@ -10,263 +10,155 @@
* of this software will be governed by version 2.0 of the Apache License. * of this software will be governed by version 2.0 of the Apache License.
*/ */
#include <prometheus/simpleapi.h>
#include <prometheus/histogram.h> #include <prometheus/histogram.h>
#include <prometheus/simpleapi.h>
namespace prometheus { namespace prometheus {
namespace simpleapi { namespace simpleapi {
std::shared_ptr<Registry> registry_ptr = std::make_shared<Registry>(); std::shared_ptr<Registry> registry_ptr = std::make_shared<Registry>();
Registry& registry = *registry_ptr; Registry& registry = *registry_ptr;
SaveToFile saver; SaveToFile saver;
} } // namespace simpleapi
} } // namespace prometheus
namespace ZeroTier { namespace ZeroTier {
namespace Metrics { namespace Metrics {
// Packet Type Counts // Packet Type Counts
prometheus::simpleapi::counter_family_t packets prometheus::simpleapi::counter_family_t packets { "zt_packet", "ZeroTier packet type counts" };
{ "zt_packet", "ZeroTier packet type counts"};
// Incoming packets // Incoming packets
prometheus::simpleapi::counter_metric_t pkt_nop_in prometheus::simpleapi::counter_metric_t pkt_nop_in { packets.Add({ { "packet_type", "nop" }, { "direction", "rx" } }) };
{ packets.Add({{"packet_type", "nop"}, {"direction", "rx"}}) }; prometheus::simpleapi::counter_metric_t pkt_error_in { packets.Add({ { "packet_type", "error" }, { "direction", "rx" } }) };
prometheus::simpleapi::counter_metric_t pkt_error_in prometheus::simpleapi::counter_metric_t pkt_ack_in { packets.Add({ { "packet_type", "ack" }, { "direction", "rx" } }) };
{ packets.Add({{"packet_type", "error"}, {"direction", "rx"}}) }; prometheus::simpleapi::counter_metric_t pkt_qos_in { packets.Add({ { "packet_type", "qos" }, { "direction", "rx" } }) };
prometheus::simpleapi::counter_metric_t pkt_ack_in prometheus::simpleapi::counter_metric_t pkt_hello_in { packets.Add({ { "packet_type", "hello" }, { "direction", "rx" } }) };
{ packets.Add({{"packet_type", "ack"}, {"direction", "rx"}}) }; prometheus::simpleapi::counter_metric_t pkt_ok_in { packets.Add({ { "packet_type", "ok" }, { "direction", "rx" } }) };
prometheus::simpleapi::counter_metric_t pkt_qos_in prometheus::simpleapi::counter_metric_t pkt_whois_in { packets.Add({ { "packet_type", "whois" }, { "direction", "rx" } }) };
{ packets.Add({{"packet_type", "qos"}, {"direction", "rx"}}) }; prometheus::simpleapi::counter_metric_t pkt_rendezvous_in { packets.Add({ { "packet_type", "rendezvous" }, { "direction", "rx" } }) };
prometheus::simpleapi::counter_metric_t pkt_hello_in prometheus::simpleapi::counter_metric_t pkt_frame_in { packets.Add({ { "packet_type", "frame" }, { "direction", "rx" } }) };
{ packets.Add({{"packet_type", "hello"}, {"direction", "rx"}}) }; prometheus::simpleapi::counter_metric_t pkt_ext_frame_in { packets.Add({ { "packet_type", "ext_frame" }, { "direction", "rx" } }) };
prometheus::simpleapi::counter_metric_t pkt_ok_in prometheus::simpleapi::counter_metric_t pkt_echo_in { packets.Add({ { "packet_type", "echo" }, { "direction", "rx" } }) };
{ packets.Add({{"packet_type", "ok"}, {"direction", "rx"}}) }; prometheus::simpleapi::counter_metric_t pkt_multicast_like_in { packets.Add({ { "packet_type", "multicast_like" }, { "direction", "rx" } }) };
prometheus::simpleapi::counter_metric_t pkt_whois_in prometheus::simpleapi::counter_metric_t pkt_network_credentials_in { packets.Add({ { "packet_type", "network_credentials" }, { "direction", "rx" } }) };
{ packets.Add({{"packet_type", "whois"}, {"direction", "rx"}}) }; prometheus::simpleapi::counter_metric_t pkt_network_config_request_in { packets.Add({ { "packet_type", "network_config_request" }, { "direction", "rx" } }) };
prometheus::simpleapi::counter_metric_t pkt_rendezvous_in prometheus::simpleapi::counter_metric_t pkt_network_config_in { packets.Add({ { "packet_type", "network_config" }, { "direction", "rx" } }) };
{ packets.Add({{"packet_type", "rendezvous"}, {"direction", "rx"}}) }; prometheus::simpleapi::counter_metric_t pkt_multicast_gather_in { packets.Add({ { "packet_type", "multicast_gather" }, { "direction", "rx" } }) };
prometheus::simpleapi::counter_metric_t pkt_frame_in prometheus::simpleapi::counter_metric_t pkt_multicast_frame_in { packets.Add({ { "packet_type", "multicast_frame" }, { "direction", "rx" } }) };
{ packets.Add({{"packet_type", "frame"}, {"direction", "rx"}}) }; prometheus::simpleapi::counter_metric_t pkt_push_direct_paths_in { packets.Add({ { "packet_type", "push_direct_paths" }, { "direction", "rx" } }) };
prometheus::simpleapi::counter_metric_t pkt_ext_frame_in prometheus::simpleapi::counter_metric_t pkt_user_message_in { packets.Add({ { "packet_type", "user_message" }, { "direction", "rx" } }) };
{ packets.Add({{"packet_type", "ext_frame"}, {"direction", "rx"}}) }; prometheus::simpleapi::counter_metric_t pkt_remote_trace_in { packets.Add({ { "packet_type", "remote_trace" }, { "direction", "rx" } }) };
prometheus::simpleapi::counter_metric_t pkt_echo_in prometheus::simpleapi::counter_metric_t pkt_path_negotiation_request_in { packets.Add({ { "packet_type", "path_negotiation_request" }, { "direction", "rx" } }) };
{ packets.Add({{"packet_type", "echo"}, {"direction", "rx"}}) };
prometheus::simpleapi::counter_metric_t pkt_multicast_like_in
{ packets.Add({{"packet_type", "multicast_like"}, {"direction", "rx"}}) };
prometheus::simpleapi::counter_metric_t pkt_network_credentials_in
{ packets.Add({{"packet_type", "network_credentials"}, {"direction", "rx"}}) };
prometheus::simpleapi::counter_metric_t pkt_network_config_request_in
{ packets.Add({{"packet_type", "network_config_request"}, {"direction", "rx"}}) };
prometheus::simpleapi::counter_metric_t pkt_network_config_in
{ packets.Add({{"packet_type", "network_config"}, {"direction", "rx"}}) };
prometheus::simpleapi::counter_metric_t pkt_multicast_gather_in
{ packets.Add({{"packet_type", "multicast_gather"}, {"direction", "rx"}}) };
prometheus::simpleapi::counter_metric_t pkt_multicast_frame_in
{ packets.Add({{"packet_type", "multicast_frame"}, {"direction", "rx"}}) };
prometheus::simpleapi::counter_metric_t pkt_push_direct_paths_in
{ packets.Add({{"packet_type", "push_direct_paths"}, {"direction", "rx"}}) };
prometheus::simpleapi::counter_metric_t pkt_user_message_in
{ packets.Add({{"packet_type", "user_message"}, {"direction", "rx"}}) };
prometheus::simpleapi::counter_metric_t pkt_remote_trace_in
{ packets.Add({{"packet_type", "remote_trace"}, {"direction", "rx"}}) };
prometheus::simpleapi::counter_metric_t pkt_path_negotiation_request_in
{ packets.Add({{"packet_type", "path_negotiation_request"}, {"direction", "rx"}}) };
// Outgoing packets // Outgoing packets
prometheus::simpleapi::counter_metric_t pkt_nop_out prometheus::simpleapi::counter_metric_t pkt_nop_out { packets.Add({ { "packet_type", "nop" }, { "direction", "tx" } }) };
{ packets.Add({{"packet_type", "nop"}, {"direction", "tx"}}) }; prometheus::simpleapi::counter_metric_t pkt_error_out { packets.Add({ { "packet_type", "error" }, { "direction", "tx" } }) };
prometheus::simpleapi::counter_metric_t pkt_error_out prometheus::simpleapi::counter_metric_t pkt_ack_out { packets.Add({ { "packet_type", "ack" }, { "direction", "tx" } }) };
{ packets.Add({{"packet_type", "error"}, {"direction", "tx"}}) }; prometheus::simpleapi::counter_metric_t pkt_qos_out { packets.Add({ { "packet_type", "qos" }, { "direction", "tx" } }) };
prometheus::simpleapi::counter_metric_t pkt_ack_out prometheus::simpleapi::counter_metric_t pkt_hello_out { packets.Add({ { "packet_type", "hello" }, { "direction", "tx" } }) };
{ packets.Add({{"packet_type", "ack"}, {"direction", "tx"}}) }; prometheus::simpleapi::counter_metric_t pkt_ok_out { packets.Add({ { "packet_type", "ok" }, { "direction", "tx" } }) };
prometheus::simpleapi::counter_metric_t pkt_qos_out prometheus::simpleapi::counter_metric_t pkt_whois_out { packets.Add({ { "packet_type", "whois" }, { "direction", "tx" } }) };
{ packets.Add({{"packet_type", "qos"}, {"direction", "tx"}}) }; prometheus::simpleapi::counter_metric_t pkt_rendezvous_out { packets.Add({ { "packet_type", "rendezvous" }, { "direction", "tx" } }) };
prometheus::simpleapi::counter_metric_t pkt_hello_out prometheus::simpleapi::counter_metric_t pkt_frame_out { packets.Add({ { "packet_type", "frame" }, { "direction", "tx" } }) };
{ packets.Add({{"packet_type", "hello"}, {"direction", "tx"}}) }; prometheus::simpleapi::counter_metric_t pkt_ext_frame_out { packets.Add({ { "packet_type", "ext_frame" }, { "direction", "tx" } }) };
prometheus::simpleapi::counter_metric_t pkt_ok_out prometheus::simpleapi::counter_metric_t pkt_echo_out { packets.Add({ { "packet_type", "echo" }, { "direction", "tx" } }) };
{ packets.Add({{"packet_type", "ok"}, {"direction", "tx"}}) }; prometheus::simpleapi::counter_metric_t pkt_multicast_like_out { packets.Add({ { "packet_type", "multicast_like" }, { "direction", "tx" } }) };
prometheus::simpleapi::counter_metric_t pkt_whois_out prometheus::simpleapi::counter_metric_t pkt_network_credentials_out { packets.Add({ { "packet_type", "network_credentials" }, { "direction", "tx" } }) };
{ packets.Add({{"packet_type", "whois"}, {"direction", "tx"}}) }; prometheus::simpleapi::counter_metric_t pkt_network_config_request_out { packets.Add({ { "packet_type", "network_config_request" }, { "direction", "tx" } }) };
prometheus::simpleapi::counter_metric_t pkt_rendezvous_out prometheus::simpleapi::counter_metric_t pkt_network_config_out { packets.Add({ { "packet_type", "network_config" }, { "direction", "tx" } }) };
{ packets.Add({{"packet_type", "rendezvous"}, {"direction", "tx"}}) }; prometheus::simpleapi::counter_metric_t pkt_multicast_gather_out { packets.Add({ { "packet_type", "multicast_gather" }, { "direction", "tx" } }) };
prometheus::simpleapi::counter_metric_t pkt_frame_out prometheus::simpleapi::counter_metric_t pkt_multicast_frame_out { packets.Add({ { "packet_type", "multicast_frame" }, { "direction", "tx" } }) };
{ packets.Add({{"packet_type", "frame"}, {"direction", "tx"}}) }; prometheus::simpleapi::counter_metric_t pkt_push_direct_paths_out { packets.Add({ { "packet_type", "push_direct_paths" }, { "direction", "tx" } }) };
prometheus::simpleapi::counter_metric_t pkt_ext_frame_out prometheus::simpleapi::counter_metric_t pkt_user_message_out { packets.Add({ { "packet_type", "user_message" }, { "direction", "tx" } }) };
{ packets.Add({{"packet_type", "ext_frame"}, {"direction", "tx"}}) }; prometheus::simpleapi::counter_metric_t pkt_remote_trace_out { packets.Add({ { "packet_type", "remote_trace" }, { "direction", "tx" } }) };
prometheus::simpleapi::counter_metric_t pkt_echo_out prometheus::simpleapi::counter_metric_t pkt_path_negotiation_request_out { packets.Add({ { "packet_type", "path_negotiation_request" }, { "direction", "tx" } }) };
{ packets.Add({{"packet_type", "echo"}, {"direction", "tx"}}) };
prometheus::simpleapi::counter_metric_t pkt_multicast_like_out
{ packets.Add({{"packet_type", "multicast_like"}, {"direction", "tx"}}) };
prometheus::simpleapi::counter_metric_t pkt_network_credentials_out
{ packets.Add({{"packet_type", "network_credentials"}, {"direction", "tx"}}) };
prometheus::simpleapi::counter_metric_t pkt_network_config_request_out
{ packets.Add({{"packet_type", "network_config_request"}, {"direction", "tx"}}) };
prometheus::simpleapi::counter_metric_t pkt_network_config_out
{ packets.Add({{"packet_type", "network_config"}, {"direction", "tx"}}) };
prometheus::simpleapi::counter_metric_t pkt_multicast_gather_out
{ packets.Add({{"packet_type", "multicast_gather"}, {"direction", "tx"}}) };
prometheus::simpleapi::counter_metric_t pkt_multicast_frame_out
{ packets.Add({{"packet_type", "multicast_frame"}, {"direction", "tx"}}) };
prometheus::simpleapi::counter_metric_t pkt_push_direct_paths_out
{ packets.Add({{"packet_type", "push_direct_paths"}, {"direction", "tx"}}) };
prometheus::simpleapi::counter_metric_t pkt_user_message_out
{ packets.Add({{"packet_type", "user_message"}, {"direction", "tx"}}) };
prometheus::simpleapi::counter_metric_t pkt_remote_trace_out
{ packets.Add({{"packet_type", "remote_trace"}, {"direction", "tx"}}) };
prometheus::simpleapi::counter_metric_t pkt_path_negotiation_request_out
{ packets.Add({{"packet_type", "path_negotiation_request"}, {"direction", "tx"}}) };
// Packet Error Counts // Packet Error Counts
prometheus::simpleapi::counter_family_t packet_errors prometheus::simpleapi::counter_family_t packet_errors { "zt_packet_error", "ZeroTier packet errors" };
{ "zt_packet_error", "ZeroTier packet errors"};
// Incoming Error Counts // Incoming Error Counts
prometheus::simpleapi::counter_metric_t pkt_error_obj_not_found_in prometheus::simpleapi::counter_metric_t pkt_error_obj_not_found_in { packet_errors.Add({ { "error_type", "obj_not_found" }, { "direction", "rx" } }) };
{ packet_errors.Add({{"error_type", "obj_not_found"}, {"direction", "rx"}}) }; prometheus::simpleapi::counter_metric_t pkt_error_unsupported_op_in { packet_errors.Add({ { "error_type", "unsupported_operation" }, { "direction", "rx" } }) };
prometheus::simpleapi::counter_metric_t pkt_error_unsupported_op_in prometheus::simpleapi::counter_metric_t pkt_error_identity_collision_in { packet_errors.Add({ { "error_type", "identity_collision" }, { "direction", "rx" } }) };
{ packet_errors.Add({{"error_type", "unsupported_operation"}, {"direction", "rx"}}) }; prometheus::simpleapi::counter_metric_t pkt_error_need_membership_cert_in { packet_errors.Add({ { "error_type", "need_membership_certificate" }, { "direction", "rx" } }) };
prometheus::simpleapi::counter_metric_t pkt_error_identity_collision_in prometheus::simpleapi::counter_metric_t pkt_error_network_access_denied_in { packet_errors.Add({ { "error_type", "network_access_denied" }, { "direction", "rx" } }) };
{ packet_errors.Add({{"error_type", "identity_collision"}, {"direction", "rx"}}) }; prometheus::simpleapi::counter_metric_t pkt_error_unwanted_multicast_in { packet_errors.Add({ { "error_type", "unwanted_multicast" }, { "direction", "rx" } }) };
prometheus::simpleapi::counter_metric_t pkt_error_need_membership_cert_in prometheus::simpleapi::counter_metric_t pkt_error_authentication_required_in { packet_errors.Add({ { "error_type", "authentication_required" }, { "direction", "rx" } }) };
{ packet_errors.Add({{"error_type", "need_membership_certificate"}, {"direction", "rx"}}) }; prometheus::simpleapi::counter_metric_t pkt_error_internal_server_error_in { packet_errors.Add({ { "error_type", "internal_server_error" }, { "direction", "rx" } }) };
prometheus::simpleapi::counter_metric_t pkt_error_network_access_denied_in
{ packet_errors.Add({{"error_type", "network_access_denied"}, {"direction", "rx"}}) };
prometheus::simpleapi::counter_metric_t pkt_error_unwanted_multicast_in
{ packet_errors.Add({{"error_type", "unwanted_multicast"}, {"direction", "rx"}}) };
prometheus::simpleapi::counter_metric_t pkt_error_authentication_required_in
{ packet_errors.Add({{"error_type", "authentication_required"}, {"direction", "rx"}}) };
prometheus::simpleapi::counter_metric_t pkt_error_internal_server_error_in
{ packet_errors.Add({{"error_type", "internal_server_error"}, {"direction", "rx"}}) };
// Outgoing Error Counts // Outgoing Error Counts
prometheus::simpleapi::counter_metric_t pkt_error_obj_not_found_out prometheus::simpleapi::counter_metric_t pkt_error_obj_not_found_out { packet_errors.Add({ { "error_type", "obj_not_found" }, { "direction", "tx" } }) };
{ packet_errors.Add({{"error_type", "obj_not_found"}, {"direction", "tx"}}) }; prometheus::simpleapi::counter_metric_t pkt_error_unsupported_op_out { packet_errors.Add({ { "error_type", "unsupported_operation" }, { "direction", "tx" } }) };
prometheus::simpleapi::counter_metric_t pkt_error_unsupported_op_out prometheus::simpleapi::counter_metric_t pkt_error_identity_collision_out { packet_errors.Add({ { "error_type", "identity_collision" }, { "direction", "tx" } }) };
{ packet_errors.Add({{"error_type", "unsupported_operation"}, {"direction", "tx"}}) }; prometheus::simpleapi::counter_metric_t pkt_error_need_membership_cert_out { packet_errors.Add({ { "error_type", "need_membership_certificate" }, { "direction", "tx" } }) };
prometheus::simpleapi::counter_metric_t pkt_error_identity_collision_out prometheus::simpleapi::counter_metric_t pkt_error_network_access_denied_out { packet_errors.Add({ { "error_type", "network_access_denied" }, { "direction", "tx" } }) };
{ packet_errors.Add({{"error_type", "identity_collision"}, {"direction", "tx"}}) }; prometheus::simpleapi::counter_metric_t pkt_error_unwanted_multicast_out { packet_errors.Add({ { "error_type", "unwanted_multicast" }, { "direction", "tx" } }) };
prometheus::simpleapi::counter_metric_t pkt_error_need_membership_cert_out prometheus::simpleapi::counter_metric_t pkt_error_authentication_required_out { packet_errors.Add({ { "error_type", "authentication_required" }, { "direction", "tx" } }) };
{ packet_errors.Add({{"error_type", "need_membership_certificate"}, {"direction", "tx"}}) }; prometheus::simpleapi::counter_metric_t pkt_error_internal_server_error_out { packet_errors.Add({ { "error_type", "internal_server_error" }, { "direction", "tx" } }) };
prometheus::simpleapi::counter_metric_t pkt_error_network_access_denied_out
{ packet_errors.Add({{"error_type", "network_access_denied"}, {"direction", "tx"}}) };
prometheus::simpleapi::counter_metric_t pkt_error_unwanted_multicast_out
{ packet_errors.Add({{"error_type", "unwanted_multicast"}, {"direction", "tx"}}) };
prometheus::simpleapi::counter_metric_t pkt_error_authentication_required_out
{ packet_errors.Add({{"error_type", "authentication_required"}, {"direction", "tx"}}) };
prometheus::simpleapi::counter_metric_t pkt_error_internal_server_error_out
{ packet_errors.Add({{"error_type", "internal_server_error"}, {"direction", "tx"}}) };
// Data Sent/Received Metrics // Data Sent/Received Metrics
prometheus::simpleapi::counter_family_t data prometheus::simpleapi::counter_family_t data { "zt_data", "number of bytes ZeroTier has transmitted or received" };
{ "zt_data", "number of bytes ZeroTier has transmitted or received" }; prometheus::simpleapi::counter_metric_t udp_recv { data.Add({ { "protocol", "udp" }, { "direction", "rx" } }) };
prometheus::simpleapi::counter_metric_t udp_recv prometheus::simpleapi::counter_metric_t udp_send { data.Add({ { "protocol", "udp" }, { "direction", "tx" } }) };
{ data.Add({{"protocol","udp"},{"direction","rx"}}) }; prometheus::simpleapi::counter_metric_t tcp_send { data.Add({ { "protocol", "tcp" }, { "direction", "tx" } }) };
prometheus::simpleapi::counter_metric_t udp_send prometheus::simpleapi::counter_metric_t tcp_recv { data.Add({ { "protocol", "tcp" }, { "direction", "rx" } }) };
{ data.Add({{"protocol","udp"},{"direction","tx"}}) };
prometheus::simpleapi::counter_metric_t tcp_send
{ data.Add({{"protocol","tcp"},{"direction", "tx"}}) };
prometheus::simpleapi::counter_metric_t tcp_recv
{ data.Add({{"protocol","tcp"},{"direction", "rx"}}) };
// Network Metrics // Network Metrics
prometheus::simpleapi::gauge_metric_t network_num_joined prometheus::simpleapi::gauge_metric_t network_num_joined { "zt_num_networks", "number of networks this instance is joined to" };
{ "zt_num_networks", "number of networks this instance is joined to" }; prometheus::simpleapi::gauge_family_t network_num_multicast_groups { "zt_network_multicast_groups_subscribed", "number of multicast groups networks are subscribed to" };
prometheus::simpleapi::gauge_family_t network_num_multicast_groups prometheus::simpleapi::counter_family_t network_packets { "zt_network_packets", "number of incoming/outgoing packets per network" };
{ "zt_network_multicast_groups_subscribed", "number of multicast groups networks are subscribed to" };
prometheus::simpleapi::counter_family_t network_packets
{ "zt_network_packets", "number of incoming/outgoing packets per network" };
#ifndef ZT_NO_PEER_METRICS #ifndef ZT_NO_PEER_METRICS
// PeerMetrics // PeerMetrics
prometheus::CustomFamily<prometheus::Histogram<uint64_t>> &peer_latency = prometheus::CustomFamily<prometheus::Histogram<uint64_t> >& peer_latency = prometheus::Builder<prometheus::Histogram<uint64_t> >().Name("zt_peer_latency").Help("peer latency (ms)").Register(prometheus::simpleapi::registry);
prometheus::Builder<prometheus::Histogram<uint64_t>>()
.Name("zt_peer_latency")
.Help("peer latency (ms)")
.Register(prometheus::simpleapi::registry);
prometheus::simpleapi::gauge_family_t peer_path_count prometheus::simpleapi::gauge_family_t peer_path_count { "zt_peer_path_count", "number of paths to peer" };
{ "zt_peer_path_count", "number of paths to peer" }; prometheus::simpleapi::counter_family_t peer_packets { "zt_peer_packets", "number of packets to/from a peer" };
prometheus::simpleapi::counter_family_t peer_packets prometheus::simpleapi::counter_family_t peer_packet_errors { "zt_peer_packet_errors", "number of incoming packet errors from a peer" };
{ "zt_peer_packets", "number of packets to/from a peer" };
prometheus::simpleapi::counter_family_t peer_packet_errors
{ "zt_peer_packet_errors" , "number of incoming packet errors from a peer" };
#endif #endif
// General Controller Metrics // General Controller Metrics
prometheus::simpleapi::gauge_metric_t network_count prometheus::simpleapi::gauge_metric_t network_count { "controller_network_count", "number of networks the controller is serving" };
{"controller_network_count", "number of networks the controller is serving"}; prometheus::simpleapi::gauge_metric_t member_count { "controller_member_count", "number of network members the controller is serving" };
prometheus::simpleapi::gauge_metric_t member_count prometheus::simpleapi::counter_metric_t network_changes { "controller_network_change_count", "number of times a network configuration is changed" };
{"controller_member_count", "number of network members the controller is serving"}; prometheus::simpleapi::counter_metric_t member_changes { "controller_member_change_count", "number of times a network member configuration is changed" };
prometheus::simpleapi::counter_metric_t network_changes prometheus::simpleapi::counter_metric_t member_auths { "controller_member_auth_count", "number of network member auths" };
{"controller_network_change_count", "number of times a network configuration is changed"}; prometheus::simpleapi::counter_metric_t member_deauths { "controller_member_deauth_count", "number of network member deauths" };
prometheus::simpleapi::counter_metric_t member_changes
{"controller_member_change_count", "number of times a network member configuration is changed"};
prometheus::simpleapi::counter_metric_t member_auths
{"controller_member_auth_count", "number of network member auths"};
prometheus::simpleapi::counter_metric_t member_deauths
{"controller_member_deauth_count", "number of network member deauths"};
prometheus::simpleapi::gauge_metric_t network_config_request_queue_size prometheus::simpleapi::gauge_metric_t network_config_request_queue_size { "controller_network_config_request_queue", "number of entries in the request queue for network configurations" };
{ "controller_network_config_request_queue", "number of entries in the request queue for network configurations" };
prometheus::simpleapi::counter_metric_t sso_expiration_checks prometheus::simpleapi::counter_metric_t sso_expiration_checks { "controller_sso_expiration_checks", "number of sso expiration checks done" };
{ "controller_sso_expiration_checks", "number of sso expiration checks done" };
prometheus::simpleapi::counter_metric_t sso_member_deauth prometheus::simpleapi::counter_metric_t sso_member_deauth { "controller_sso_timeouts", "number of sso timeouts" };
{ "controller_sso_timeouts", "number of sso timeouts" };
prometheus::simpleapi::counter_metric_t network_config_request prometheus::simpleapi::counter_metric_t network_config_request { "controller_network_config_request", "count of config requests handled" };
{ "controller_network_config_request", "count of config requests handled" }; prometheus::simpleapi::gauge_metric_t network_config_request_threads { "controller_network_config_request_threads", "number of active network config handling threads" };
prometheus::simpleapi::gauge_metric_t network_config_request_threads prometheus::simpleapi::counter_metric_t db_get_network { "controller_db_get_network", "counter" };
{ "controller_network_config_request_threads", "number of active network config handling threads" }; prometheus::simpleapi::counter_metric_t db_get_network_and_member { "controller_db_get_network_and_member", "counter" };
prometheus::simpleapi::counter_metric_t db_get_network prometheus::simpleapi::counter_metric_t db_get_network_and_member_and_summary { "controller_db_get_networK_and_member_summary", "counter" };
{ "controller_db_get_network", "counter" }; prometheus::simpleapi::counter_metric_t db_get_member_list { "controller_db_get_member_list", "counter" };
prometheus::simpleapi::counter_metric_t db_get_network_and_member prometheus::simpleapi::counter_metric_t db_get_network_list { "controller_db_get_network_list", "counter" };
{ "controller_db_get_network_and_member", "counter" }; prometheus::simpleapi::counter_metric_t db_member_change { "controller_db_member_change", "counter" };
prometheus::simpleapi::counter_metric_t db_get_network_and_member_and_summary prometheus::simpleapi::counter_metric_t db_network_change { "controller_db_network_change", "counter" };
{ "controller_db_get_networK_and_member_summary", "counter" };
prometheus::simpleapi::counter_metric_t db_get_member_list
{ "controller_db_get_member_list", "counter" };
prometheus::simpleapi::counter_metric_t db_get_network_list
{ "controller_db_get_network_list", "counter" };
prometheus::simpleapi::counter_metric_t db_member_change
{ "controller_db_member_change", "counter" };
prometheus::simpleapi::counter_metric_t db_network_change
{ "controller_db_network_change", "counter" };
#ifdef ZT_CONTROLLER_USE_LIBPQ #ifdef ZT_CONTROLLER_USE_LIBPQ
// Central Controller Metrics // Central Controller Metrics
prometheus::simpleapi::counter_metric_t pgsql_mem_notification prometheus::simpleapi::counter_metric_t pgsql_mem_notification { "controller_pgsql_member_notifications_received", "number of member change notifications received via pgsql NOTIFY" };
{ "controller_pgsql_member_notifications_received", "number of member change notifications received via pgsql NOTIFY" }; prometheus::simpleapi::counter_metric_t pgsql_net_notification { "controller_pgsql_network_notifications_received", "number of network change notifications received via pgsql NOTIFY" };
prometheus::simpleapi::counter_metric_t pgsql_net_notification prometheus::simpleapi::counter_metric_t pgsql_node_checkin { "controller_pgsql_node_checkin_count", "number of node check-ins (pgsql)" };
{ "controller_pgsql_network_notifications_received", "number of network change notifications received via pgsql NOTIFY" }; prometheus::simpleapi::counter_metric_t pgsql_commit_ticks { "controller_pgsql_commit_ticks", "number of commit ticks run (pgsql)" };
prometheus::simpleapi::counter_metric_t pgsql_node_checkin prometheus::simpleapi::counter_metric_t db_get_sso_info { "controller_db_get_sso_info", "counter" };
{ "controller_pgsql_node_checkin_count", "number of node check-ins (pgsql)" };
prometheus::simpleapi::counter_metric_t pgsql_commit_ticks
{ "controller_pgsql_commit_ticks", "number of commit ticks run (pgsql)" };
prometheus::simpleapi::counter_metric_t db_get_sso_info
{ "controller_db_get_sso_info", "counter" };
prometheus::simpleapi::counter_metric_t redis_mem_notification prometheus::simpleapi::counter_metric_t redis_mem_notification { "controller_redis_member_notifications_received", "number of member change notifications received via redis" };
{ "controller_redis_member_notifications_received", "number of member change notifications received via redis" }; prometheus::simpleapi::counter_metric_t redis_net_notification { "controller_redis_network_notifications_received", "number of network change notifications received via redis" };
prometheus::simpleapi::counter_metric_t redis_net_notification prometheus::simpleapi::counter_metric_t redis_node_checkin { "controller_redis_node_checkin_count", "number of node check-ins (redis)" };
{ "controller_redis_network_notifications_received", "number of network change notifications received via redis" };
prometheus::simpleapi::counter_metric_t redis_node_checkin
{ "controller_redis_node_checkin_count", "number of node check-ins (redis)" };
// Central DB Pool Metrics // Central DB Pool Metrics
prometheus::simpleapi::counter_metric_t conn_counter prometheus::simpleapi::counter_metric_t conn_counter { "controller_pgsql_connections_created", "number of pgsql connections created" };
{ "controller_pgsql_connections_created", "number of pgsql connections created"}; prometheus::simpleapi::counter_metric_t max_pool_size { "controller_pgsql_max_conn_pool_size", "max connection pool size for postgres" };
prometheus::simpleapi::counter_metric_t max_pool_size prometheus::simpleapi::counter_metric_t min_pool_size { "controller_pgsql_min_conn_pool_size", "minimum connection pool size for postgres" };
{ "controller_pgsql_max_conn_pool_size", "max connection pool size for postgres"}; prometheus::simpleapi::gauge_metric_t pool_avail { "controller_pgsql_available_conns", "number of available postgres connections" };
prometheus::simpleapi::counter_metric_t min_pool_size prometheus::simpleapi::gauge_metric_t pool_in_use { "controller_pgsql_in_use_conns", "number of postgres database connections in use" };
{ "controller_pgsql_min_conn_pool_size", "minimum connection pool size for postgres" }; prometheus::simpleapi::counter_metric_t pool_errors { "controller_pgsql_connection_errors", "number of connection errors the connection pool has seen" };
prometheus::simpleapi::gauge_metric_t pool_avail
{ "controller_pgsql_available_conns", "number of available postgres connections" };
prometheus::simpleapi::gauge_metric_t pool_in_use
{ "controller_pgsql_in_use_conns", "number of postgres database connections in use" };
prometheus::simpleapi::counter_metric_t pool_errors
{ "controller_pgsql_connection_errors", "number of connection errors the connection pool has seen" };
#endif #endif
} } // namespace Metrics
} } // namespace ZeroTier

View file

@ -12,14 +12,14 @@
#ifndef METRICS_H_ #ifndef METRICS_H_
#define METRICS_H_ #define METRICS_H_
#include <prometheus/simpleapi.h>
#include <prometheus/histogram.h> #include <prometheus/histogram.h>
#include <prometheus/simpleapi.h>
namespace prometheus { namespace prometheus {
namespace simpleapi { namespace simpleapi {
extern std::shared_ptr<Registry> registry_ptr; extern std::shared_ptr<Registry> registry_ptr;
} }
} } // namespace prometheus
namespace ZeroTier { namespace ZeroTier {
namespace Metrics { namespace Metrics {
@ -137,7 +137,6 @@ namespace ZeroTier {
extern prometheus::simpleapi::counter_metric_t db_member_change; extern prometheus::simpleapi::counter_metric_t db_member_change;
extern prometheus::simpleapi::counter_metric_t db_network_change; extern prometheus::simpleapi::counter_metric_t db_network_change;
#ifdef ZT_CONTROLLER_USE_LIBPQ #ifdef ZT_CONTROLLER_USE_LIBPQ
// Central Controller Metrics // Central Controller Metrics
extern prometheus::simpleapi::counter_metric_t pgsql_mem_notification; extern prometheus::simpleapi::counter_metric_t pgsql_mem_notification;
@ -150,8 +149,6 @@ namespace ZeroTier {
extern prometheus::simpleapi::counter_metric_t redis_net_notification; extern prometheus::simpleapi::counter_metric_t redis_net_notification;
extern prometheus::simpleapi::counter_metric_t redis_node_checkin; extern prometheus::simpleapi::counter_metric_t redis_node_checkin;
// Central DB Pool Metrics // Central DB Pool Metrics
extern prometheus::simpleapi::counter_metric_t conn_counter; extern prometheus::simpleapi::counter_metric_t conn_counter;
extern prometheus::simpleapi::counter_metric_t max_pool_size; extern prometheus::simpleapi::counter_metric_t max_pool_size;

View file

@ -14,10 +14,10 @@
#ifndef ZT_MULTICASTGROUP_HPP #ifndef ZT_MULTICASTGROUP_HPP
#define ZT_MULTICASTGROUP_HPP #define ZT_MULTICASTGROUP_HPP
#include <stdint.h>
#include "MAC.hpp"
#include "InetAddress.hpp" #include "InetAddress.hpp"
#include "MAC.hpp"
#include <stdint.h>
namespace ZeroTier { namespace ZeroTier {
@ -36,18 +36,13 @@ namespace ZeroTier {
* *
* MulticastGroup behaves as an immutable value object. * MulticastGroup behaves as an immutable value object.
*/ */
class MulticastGroup class MulticastGroup {
{
public: public:
MulticastGroup() : MulticastGroup() : _mac(), _adi(0)
_mac(),
_adi(0)
{ {
} }
MulticastGroup(const MAC &m,uint32_t a) : MulticastGroup(const MAC& m, uint32_t a) : _mac(m), _adi(a)
_mac(m),
_adi(a)
{ {
} }
@ -65,7 +60,8 @@ public:
// ADI was added, as well as handling other things that want mindless // ADI was added, as well as handling other things that want mindless
// Ethernet broadcast to all. // Ethernet broadcast to all.
return MulticastGroup(MAC(0xffffffffffffULL), Utils::ntoh(*((const uint32_t*)ip.rawIpData()))); return MulticastGroup(MAC(0xffffffffffffULL), Utils::ntoh(*((const uint32_t*)ip.rawIpData())));
} else if (ip.isV6()) { }
else if (ip.isV6()) {
// IPv6 is better designed in this respect. We can compute the IPv6 // IPv6 is better designed in this respect. We can compute the IPv6
// multicast address directly from the IP address, and it gives us // multicast address directly from the IP address, and it gives us
// 24 bits of uniqueness. Collisions aren't likely to be common enough // 24 bits of uniqueness. Collisions aren't likely to be common enough
@ -79,29 +75,54 @@ public:
/** /**
* @return Multicast address * @return Multicast address
*/ */
inline const MAC &mac() const { return _mac; } inline const MAC& mac() const
{
return _mac;
}
/** /**
* @return Additional distinguishing information * @return Additional distinguishing information
*/ */
inline uint32_t adi() const { return _adi; } inline uint32_t adi() const
{
return _adi;
}
inline unsigned long hashCode() const { return (_mac.hashCode() ^ (unsigned long)_adi); } inline unsigned long hashCode() const
{
return (_mac.hashCode() ^ (unsigned long)_adi);
}
inline bool operator==(const MulticastGroup &g) const { return ((_mac == g._mac)&&(_adi == g._adi)); } inline bool operator==(const MulticastGroup& g) const
inline bool operator!=(const MulticastGroup &g) const { return ((_mac != g._mac)||(_adi != g._adi)); } {
return ((_mac == g._mac) && (_adi == g._adi));
}
inline bool operator!=(const MulticastGroup& g) const
{
return ((_mac != g._mac) || (_adi != g._adi));
}
inline bool operator<(const MulticastGroup& g) const inline bool operator<(const MulticastGroup& g) const
{ {
if (_mac < g._mac) { if (_mac < g._mac) {
return true; return true;
} else if (_mac == g._mac) { }
else if (_mac == g._mac) {
return (_adi < g._adi); return (_adi < g._adi);
} }
return false; return false;
} }
inline bool operator>(const MulticastGroup &g) const { return (g < *this); } inline bool operator>(const MulticastGroup& g) const
inline bool operator<=(const MulticastGroup &g) const { return !(g < *this); } {
inline bool operator>=(const MulticastGroup &g) const { return !(*this < g); } return (g < *this);
}
inline bool operator<=(const MulticastGroup& g) const
{
return ! (g < *this);
}
inline bool operator>=(const MulticastGroup& g) const
{
return ! (*this < g);
}
private: private:
MAC _mac; MAC _mac;

View file

@ -11,24 +11,23 @@
*/ */
/****/ /****/
#include <algorithm>
#include "Constants.hpp"
#include "RuntimeEnvironment.hpp"
#include "Multicaster.hpp" #include "Multicaster.hpp"
#include "Topology.hpp"
#include "Switch.hpp" #include "CertificateOfMembership.hpp"
#include "Constants.hpp"
#include "Network.hpp"
#include "Node.hpp"
#include "Packet.hpp" #include "Packet.hpp"
#include "Peer.hpp" #include "Peer.hpp"
#include "CertificateOfMembership.hpp" #include "RuntimeEnvironment.hpp"
#include "Node.hpp" #include "Switch.hpp"
#include "Network.hpp" #include "Topology.hpp"
#include <algorithm>
namespace ZeroTier { namespace ZeroTier {
Multicaster::Multicaster(const RuntimeEnvironment *renv) : Multicaster::Multicaster(const RuntimeEnvironment* renv) : RR(renv), _groups(32)
RR(renv),
_groups(32)
{ {
} }
@ -70,7 +69,8 @@ unsigned int Multicaster::gather(const Address &queryingPeer,uint64_t nwid,const
if (! limit) { if (! limit) {
return 0; return 0;
} else if (limit > 0xffff) { }
else if (limit > 0xffff) {
limit = 0xffff; limit = 0xffff;
} }
@ -145,16 +145,7 @@ std::vector<Address> Multicaster::getMembers(uint64_t nwid,const MulticastGroup
return ls; return ls;
} }
void Multicaster::send( void Multicaster::send(void* tPtr, int64_t now, const SharedPtr<Network>& network, const Address& origin, const MulticastGroup& mg, const MAC& src, unsigned int etherType, const void* data, unsigned int len)
void *tPtr,
int64_t now,
const SharedPtr<Network> &network,
const Address &origin,
const MulticastGroup &mg,
const MAC &src,
unsigned int etherType,
const void *data,
unsigned int len)
{ {
unsigned long idxbuf[4096]; unsigned long idxbuf[4096];
unsigned long* indexes = idxbuf; unsigned long* indexes = idxbuf;
@ -269,7 +260,8 @@ void Multicaster::send(
++count; ++count;
} }
} }
} else { }
else {
while (gs.txQueue.size() >= ZT_TX_QUEUE_SIZE) { while (gs.txQueue.size() >= ZT_TX_QUEUE_SIZE) {
gs.txQueue.pop_front(); gs.txQueue.pop_front();
} }
@ -341,18 +333,7 @@ void Multicaster::send(
gs.txQueue.push_back(OutboundMulticast()); gs.txQueue.push_back(OutboundMulticast());
OutboundMulticast& out = gs.txQueue.back(); OutboundMulticast& out = gs.txQueue.back();
out.init( out.init(RR, now, network->id(), network->config().disableCompression(), limit, gatherLimit, src, mg, etherType, data, len);
RR,
now,
network->id(),
network->config().disableCompression(),
limit,
gatherLimit,
src,
mg,
etherType,
data,
len);
if (origin) { if (origin) {
out.logAsSent(origin); out.logAsSent(origin);
@ -378,7 +359,9 @@ void Multicaster::send(
} }
} }
} }
} catch ( ... ) {} // this is a sanity check to catch any failures and make sure indexes[] still gets deleted }
catch (...) {
} // this is a sanity check to catch any failures and make sure indexes[] still gets deleted
// Free allocated memory buffer if any // Free allocated memory buffer if any
if (indexes != idxbuf) { if (indexes != idxbuf) {
@ -396,7 +379,8 @@ void Multicaster::clean(int64_t now)
for (std::list<OutboundMulticast>::iterator tx(s->txQueue.begin()); tx != s->txQueue.end();) { for (std::list<OutboundMulticast>::iterator tx(s->txQueue.begin()); tx != s->txQueue.end();) {
if ((tx->expired(now)) || (tx->atLimit())) { if ((tx->expired(now)) || (tx->atLimit())) {
s->txQueue.erase(tx++); s->txQueue.erase(tx++);
} else { }
else {
++tx; ++tx;
} }
} }
@ -417,9 +401,11 @@ void Multicaster::clean(int64_t now)
if (count) { if (count) {
s->members.resize(count); s->members.resize(count);
} else if (s->txQueue.empty()) { }
else if (s->txQueue.empty()) {
_groups.erase(*k); _groups.erase(*k);
} else { }
else {
s->members.clear(); s->members.clear();
} }
} }
@ -441,18 +427,21 @@ void Multicaster::_add(void *tPtr,int64_t now,uint64_t nwid,const MulticastGroup
return; return;
} }
gs.members.insert(m, MulticastGroupMember(member, now)); gs.members.insert(m, MulticastGroupMember(member, now));
} else { }
else {
gs.members.push_back(MulticastGroupMember(member, now)); gs.members.push_back(MulticastGroupMember(member, now));
} }
for (std::list<OutboundMulticast>::iterator tx(gs.txQueue.begin()); tx != gs.txQueue.end();) { for (std::list<OutboundMulticast>::iterator tx(gs.txQueue.begin()); tx != gs.txQueue.end();) {
if (tx->atLimit()) { if (tx->atLimit()) {
gs.txQueue.erase(tx++); gs.txQueue.erase(tx++);
} else { }
else {
tx->sendIfNew(RR, tPtr, member); tx->sendIfNew(RR, tPtr, member);
if (tx->atLimit()) { if (tx->atLimit()) {
gs.txQueue.erase(tx++); gs.txQueue.erase(tx++);
} else { }
else {
++tx; ++tx;
} }
} }

View file

@ -14,22 +14,21 @@
#ifndef ZT_MULTICASTER_HPP #ifndef ZT_MULTICASTER_HPP
#define ZT_MULTICASTER_HPP #define ZT_MULTICASTER_HPP
#include <stdint.h> #include "Address.hpp"
#include <string.h>
#include <map>
#include <vector>
#include <list>
#include "Constants.hpp" #include "Constants.hpp"
#include "Hashtable.hpp" #include "Hashtable.hpp"
#include "Address.hpp"
#include "MAC.hpp" #include "MAC.hpp"
#include "MulticastGroup.hpp" #include "MulticastGroup.hpp"
#include "OutboundMulticast.hpp"
#include "Utils.hpp"
#include "Mutex.hpp" #include "Mutex.hpp"
#include "OutboundMulticast.hpp"
#include "SharedPtr.hpp" #include "SharedPtr.hpp"
#include "Utils.hpp"
#include <list>
#include <map>
#include <stdint.h>
#include <string.h>
#include <vector>
namespace ZeroTier { namespace ZeroTier {
@ -41,8 +40,7 @@ class Network;
/** /**
* Database of known multicast peers within a network * Database of known multicast peers within a network
*/ */
class Multicaster class Multicaster {
{
public: public:
Multicaster(const RuntimeEnvironment* renv); Multicaster(const RuntimeEnvironment* renv);
~Multicaster(); ~Multicaster();
@ -126,16 +124,7 @@ public:
* @param data Packet data * @param data Packet data
* @param len Length of packet data * @param len Length of packet data
*/ */
void send( void send(void* tPtr, int64_t now, const SharedPtr<Network>& network, const Address& origin, const MulticastGroup& mg, const MAC& src, unsigned int etherType, const void* data, unsigned int len);
void *tPtr,
int64_t now,
const SharedPtr<Network> &network,
const Address &origin,
const MulticastGroup &mg,
const MAC &src,
unsigned int etherType,
const void *data,
unsigned int len);
/** /**
* Clean database * Clean database
@ -146,38 +135,72 @@ public:
void clean(int64_t now); void clean(int64_t now);
private: private:
struct Key struct Key {
Key() : nwid(0), mg()
{ {
Key() : nwid(0),mg() {} }
Key(uint64_t n,const MulticastGroup &g) : nwid(n),mg(g) {} Key(uint64_t n, const MulticastGroup& g) : nwid(n), mg(g)
{
}
uint64_t nwid; uint64_t nwid;
MulticastGroup mg; MulticastGroup mg;
inline bool operator==(const Key &k) const { return ((nwid == k.nwid)&&(mg == k.mg)); } inline bool operator==(const Key& k) const
inline bool operator!=(const Key &k) const { return ((nwid != k.nwid)||(mg != k.mg)); } {
inline unsigned long hashCode() const { return (mg.hashCode() ^ (unsigned long)(nwid ^ (nwid >> 32))); } return ((nwid == k.nwid) && (mg == k.mg));
}
inline bool operator!=(const Key& k) const
{
return ((nwid != k.nwid) || (mg != k.mg));
}
inline unsigned long hashCode() const
{
return (mg.hashCode() ^ (unsigned long)(nwid ^ (nwid >> 32)));
}
}; };
struct MulticastGroupMember struct MulticastGroupMember {
MulticastGroupMember()
{ {
MulticastGroupMember() {} }
MulticastGroupMember(const Address &a,uint64_t ts) : address(a),timestamp(ts) {} MulticastGroupMember(const Address& a, uint64_t ts) : address(a), timestamp(ts)
{
}
inline bool operator<(const MulticastGroupMember &a) const { return (address < a.address); } inline bool operator<(const MulticastGroupMember& a) const
inline bool operator==(const MulticastGroupMember &a) const { return (address == a.address); } {
inline bool operator!=(const MulticastGroupMember &a) const { return (address != a.address); } return (address < a.address);
inline bool operator<(const Address &a) const { return (address < a); } }
inline bool operator==(const Address &a) const { return (address == a); } inline bool operator==(const MulticastGroupMember& a) const
inline bool operator!=(const Address &a) const { return (address != a); } {
return (address == a.address);
}
inline bool operator!=(const MulticastGroupMember& a) const
{
return (address != a.address);
}
inline bool operator<(const Address& a) const
{
return (address < a);
}
inline bool operator==(const Address& a) const
{
return (address == a);
}
inline bool operator!=(const Address& a) const
{
return (address != a);
}
Address address; Address address;
int64_t timestamp; // time of last notification int64_t timestamp; // time of last notification
}; };
struct MulticastGroupStatus struct MulticastGroupStatus {
MulticastGroupStatus() : lastExplicitGather(0)
{ {
MulticastGroupStatus() : lastExplicitGather(0) {} }
int64_t lastExplicitGather; int64_t lastExplicitGather;
std::list<OutboundMulticast> txQueue; // pending outbound multicasts std::list<OutboundMulticast> txQueue; // pending outbound multicasts

View file

@ -18,15 +18,14 @@
#ifdef __UNIX_LIKE__ #ifdef __UNIX_LIKE__
#include <pthread.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <pthread.h>
namespace ZeroTier { namespace ZeroTier {
// libpthread based mutex lock // libpthread based mutex lock
class Mutex class Mutex {
{
public: public:
Mutex() Mutex()
{ {
@ -48,17 +47,14 @@ public:
pthread_mutex_unlock(&((const_cast<Mutex*>(this))->_mh)); pthread_mutex_unlock(&((const_cast<Mutex*>(this))->_mh));
} }
class Lock class Lock {
{
public: public:
Lock(Mutex &m) : Lock(Mutex& m) : _m(&m)
_m(&m)
{ {
m.lock(); m.lock();
} }
Lock(const Mutex &m) : Lock(const Mutex& m) : _m(const_cast<Mutex*>(&m))
_m(const_cast<Mutex *>(&m))
{ {
_m->lock(); _m->lock();
} }
@ -73,8 +69,13 @@ public:
}; };
private: private:
Mutex(const Mutex &) {} Mutex(const Mutex&)
const Mutex &operator=(const Mutex &) { return *this; } {
}
const Mutex& operator=(const Mutex&)
{
return *this;
}
pthread_mutex_t _mh; pthread_mutex_t _mh;
}; };
@ -91,8 +92,7 @@ private:
namespace ZeroTier { namespace ZeroTier {
// Windows critical section based lock // Windows critical section based lock
class Mutex class Mutex {
{
public: public:
Mutex() Mutex()
{ {
@ -124,17 +124,14 @@ public:
(const_cast<Mutex*>(this))->unlock(); (const_cast<Mutex*>(this))->unlock();
} }
class Lock class Lock {
{
public: public:
Lock(Mutex &m) : Lock(Mutex& m) : _m(&m)
_m(&m)
{ {
m.lock(); m.lock();
} }
Lock(const Mutex &m) : Lock(const Mutex& m) : _m(const_cast<Mutex*>(&m))
_m(const_cast<Mutex *>(&m))
{ {
_m->lock(); _m->lock();
} }
@ -149,8 +146,13 @@ public:
}; };
private: private:
Mutex(const Mutex &) {} Mutex(const Mutex&)
const Mutex &operator=(const Mutex &) { return *this; } {
}
const Mutex& operator=(const Mutex&)
{
return *this;
}
CRITICAL_SECTION _cs; CRITICAL_SECTION _cs;
}; };

View file

@ -11,31 +11,30 @@
*/ */
/****/ /****/
#include <stdio.h> #include "Network.hpp"
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include "../include/ZeroTierDebug.h" #include "../include/ZeroTierDebug.h"
#include "ECC.hpp"
#include "Constants.hpp"
#include "../version.h" #include "../version.h"
#include "Network.hpp"
#include "RuntimeEnvironment.hpp"
#include "MAC.hpp"
#include "Address.hpp" #include "Address.hpp"
#include "InetAddress.hpp"
#include "Switch.hpp"
#include "Buffer.hpp" #include "Buffer.hpp"
#include "Packet.hpp" #include "Constants.hpp"
#include "ECC.hpp"
#include "InetAddress.hpp"
#include "MAC.hpp"
#include "Metrics.hpp"
#include "NetworkController.hpp" #include "NetworkController.hpp"
#include "Node.hpp" #include "Node.hpp"
#include "Packet.hpp"
#include "Peer.hpp" #include "Peer.hpp"
#include "RuntimeEnvironment.hpp"
#include "Switch.hpp"
#include "Trace.hpp" #include "Trace.hpp"
#include "Metrics.hpp"
#include <math.h>
#include <set> #include <set>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
namespace ZeroTier { namespace ZeroTier {
@ -72,14 +71,7 @@ static inline bool _ipv6GetPayload(const uint8_t *frameData,unsigned int frameLe
return false; // overflow == invalid return false; // overflow == invalid
} }
enum _doZtFilterResult enum _doZtFilterResult { DOZTFILTER_NO_MATCH, DOZTFILTER_DROP, DOZTFILTER_REDIRECT, DOZTFILTER_ACCEPT, DOZTFILTER_SUPER_ACCEPT };
{
DOZTFILTER_NO_MATCH,
DOZTFILTER_DROP,
DOZTFILTER_REDIRECT,
DOZTFILTER_ACCEPT,
DOZTFILTER_SUPER_ACCEPT
};
static _doZtFilterResult _doZtFilter( static _doZtFilterResult _doZtFilter(
const RuntimeEnvironment* RR, const RuntimeEnvironment* RR,
@ -138,7 +130,8 @@ static _doZtFilterResult _doZtFilter(
#ifdef ZT_TRACE #ifdef ZT_TRACE
// fprintf(stderr, "\tskip Drop"); // fprintf(stderr, "\tskip Drop");
#endif #endif
skipDrop = 0; continue; skipDrop = 0;
continue;
} }
#ifdef ZT_TRACE #ifdef ZT_TRACE
// fprintf(stderr, "\tDrop\n"); // fprintf(stderr, "\tDrop\n");
@ -160,23 +153,29 @@ static _doZtFilterResult _doZtFilter(
const Address fwdAddr(rules[rn].v.fwd.address); const Address fwdAddr(rules[rn].v.fwd.address);
if (fwdAddr == ztSource) { if (fwdAddr == ztSource) {
// Skip as no-op since source is target // Skip as no-op since source is target
} else if (fwdAddr == RR->identity.address()) { }
else if (fwdAddr == RR->identity.address()) {
if (inbound) { if (inbound) {
return DOZTFILTER_SUPER_ACCEPT; return DOZTFILTER_SUPER_ACCEPT;
} else {
} }
} else if (fwdAddr == ztDest) { else {
} else { }
}
else if (fwdAddr == ztDest) {
}
else {
if (rt == ZT_NETWORK_RULE_ACTION_REDIRECT) { if (rt == ZT_NETWORK_RULE_ACTION_REDIRECT) {
ztDest = fwdAddr; ztDest = fwdAddr;
return DOZTFILTER_REDIRECT; return DOZTFILTER_REDIRECT;
} else { }
else {
cc = fwdAddr; cc = fwdAddr;
ccLength = (rules[rn].v.fwd.length != 0) ? ((frameLen < (unsigned int)rules[rn].v.fwd.length) ? frameLen : (unsigned int)rules[rn].v.fwd.length) : frameLen; ccLength = (rules[rn].v.fwd.length != 0) ? ((frameLen < (unsigned int)rules[rn].v.fwd.length) ? frameLen : (unsigned int)rules[rn].v.fwd.length) : frameLen;
ccWatch = (rt == ZT_NETWORK_RULE_ACTION_WATCH); ccWatch = (rt == ZT_NETWORK_RULE_ACTION_WATCH);
} }
} }
} continue; }
continue;
case ZT_NETWORK_RULE_ACTION_BREAK: case ZT_NETWORK_RULE_ACTION_BREAK:
return DOZTFILTER_NO_MATCH; return DOZTFILTER_NO_MATCH;
@ -185,7 +184,8 @@ static _doZtFilterResult _doZtFilter(
default: default:
continue; continue;
} }
} else { }
else {
// If this is an incoming packet and we are a TEE or REDIRECT target, we should // If this is an incoming packet and we are a TEE or REDIRECT target, we should
// super-accept if we accept at all. This will cause us to accept redirected or // super-accept if we accept at all. This will cause us to accept redirected or
// tee'd packets in spite of MAC and ZT addressing checks. // tee'd packets in spite of MAC and ZT addressing checks.
@ -248,28 +248,32 @@ static _doZtFilterResult _doZtFilter(
case ZT_NETWORK_RULE_MATCH_IPV4_SOURCE: case ZT_NETWORK_RULE_MATCH_IPV4_SOURCE:
if ((etherType == ZT_ETHERTYPE_IPV4) && (frameLen >= 20)) { if ((etherType == ZT_ETHERTYPE_IPV4) && (frameLen >= 20)) {
thisRuleMatches = (uint8_t)(InetAddress((const void*)&(rules[rn].v.ipv4.ip), 4, rules[rn].v.ipv4.mask).containsAddress(InetAddress((const void*)(frameData + 12), 4, 0))); thisRuleMatches = (uint8_t)(InetAddress((const void*)&(rules[rn].v.ipv4.ip), 4, rules[rn].v.ipv4.mask).containsAddress(InetAddress((const void*)(frameData + 12), 4, 0)));
} else { }
else {
thisRuleMatches = hardNo; thisRuleMatches = hardNo;
} }
break; break;
case ZT_NETWORK_RULE_MATCH_IPV4_DEST: case ZT_NETWORK_RULE_MATCH_IPV4_DEST:
if ((etherType == ZT_ETHERTYPE_IPV4) && (frameLen >= 20)) { if ((etherType == ZT_ETHERTYPE_IPV4) && (frameLen >= 20)) {
thisRuleMatches = (uint8_t)(InetAddress((const void*)&(rules[rn].v.ipv4.ip), 4, rules[rn].v.ipv4.mask).containsAddress(InetAddress((const void*)(frameData + 16), 4, 0))); thisRuleMatches = (uint8_t)(InetAddress((const void*)&(rules[rn].v.ipv4.ip), 4, rules[rn].v.ipv4.mask).containsAddress(InetAddress((const void*)(frameData + 16), 4, 0)));
} else { }
else {
thisRuleMatches = hardNo; thisRuleMatches = hardNo;
} }
break; break;
case ZT_NETWORK_RULE_MATCH_IPV6_SOURCE: case ZT_NETWORK_RULE_MATCH_IPV6_SOURCE:
if ((etherType == ZT_ETHERTYPE_IPV6) && (frameLen >= 40)) { if ((etherType == ZT_ETHERTYPE_IPV6) && (frameLen >= 40)) {
thisRuleMatches = (uint8_t)(InetAddress((const void*)rules[rn].v.ipv6.ip, 16, rules[rn].v.ipv6.mask).containsAddress(InetAddress((const void*)(frameData + 8), 16, 0))); thisRuleMatches = (uint8_t)(InetAddress((const void*)rules[rn].v.ipv6.ip, 16, rules[rn].v.ipv6.mask).containsAddress(InetAddress((const void*)(frameData + 8), 16, 0)));
} else { }
else {
thisRuleMatches = hardNo; thisRuleMatches = hardNo;
} }
break; break;
case ZT_NETWORK_RULE_MATCH_IPV6_DEST: case ZT_NETWORK_RULE_MATCH_IPV6_DEST:
if ((etherType == ZT_ETHERTYPE_IPV6) && (frameLen >= 40)) { if ((etherType == ZT_ETHERTYPE_IPV6) && (frameLen >= 40)) {
thisRuleMatches = (uint8_t)(InetAddress((const void*)rules[rn].v.ipv6.ip, 16, rules[rn].v.ipv6.mask).containsAddress(InetAddress((const void*)(frameData + 24), 16, 0))); thisRuleMatches = (uint8_t)(InetAddress((const void*)rules[rn].v.ipv6.ip, 16, rules[rn].v.ipv6.mask).containsAddress(InetAddress((const void*)(frameData + 24), 16, 0)));
} else { }
else {
thisRuleMatches = hardNo; thisRuleMatches = hardNo;
} }
break; break;
@ -277,24 +281,29 @@ static _doZtFilterResult _doZtFilter(
if ((etherType == ZT_ETHERTYPE_IPV4) && (frameLen >= 20)) { if ((etherType == ZT_ETHERTYPE_IPV4) && (frameLen >= 20)) {
const uint8_t tosMasked = frameData[1] & rules[rn].v.ipTos.mask; const uint8_t tosMasked = frameData[1] & rules[rn].v.ipTos.mask;
thisRuleMatches = (uint8_t)((tosMasked >= rules[rn].v.ipTos.value[0]) && (tosMasked <= rules[rn].v.ipTos.value[1])); thisRuleMatches = (uint8_t)((tosMasked >= rules[rn].v.ipTos.value[0]) && (tosMasked <= rules[rn].v.ipTos.value[1]));
} else if ((etherType == ZT_ETHERTYPE_IPV6)&&(frameLen >= 40)) { }
else if ((etherType == ZT_ETHERTYPE_IPV6) && (frameLen >= 40)) {
const uint8_t tosMasked = (((frameData[0] << 4) & 0xf0) | ((frameData[1] >> 4) & 0x0f)) & rules[rn].v.ipTos.mask; const uint8_t tosMasked = (((frameData[0] << 4) & 0xf0) | ((frameData[1] >> 4) & 0x0f)) & rules[rn].v.ipTos.mask;
thisRuleMatches = (uint8_t)((tosMasked >= rules[rn].v.ipTos.value[0]) && (tosMasked <= rules[rn].v.ipTos.value[1])); thisRuleMatches = (uint8_t)((tosMasked >= rules[rn].v.ipTos.value[0]) && (tosMasked <= rules[rn].v.ipTos.value[1]));
} else { }
else {
thisRuleMatches = hardNo; thisRuleMatches = hardNo;
} }
break; break;
case ZT_NETWORK_RULE_MATCH_IP_PROTOCOL: case ZT_NETWORK_RULE_MATCH_IP_PROTOCOL:
if ((etherType == ZT_ETHERTYPE_IPV4) && (frameLen >= 20)) { if ((etherType == ZT_ETHERTYPE_IPV4) && (frameLen >= 20)) {
thisRuleMatches = (uint8_t)(rules[rn].v.ipProtocol == frameData[9]); thisRuleMatches = (uint8_t)(rules[rn].v.ipProtocol == frameData[9]);
} else if (etherType == ZT_ETHERTYPE_IPV6) { }
else if (etherType == ZT_ETHERTYPE_IPV6) {
unsigned int pos = 0, proto = 0; unsigned int pos = 0, proto = 0;
if (_ipv6GetPayload(frameData, frameLen, pos, proto)) { if (_ipv6GetPayload(frameData, frameLen, pos, proto)) {
thisRuleMatches = (uint8_t)(rules[rn].v.ipProtocol == (uint8_t)proto); thisRuleMatches = (uint8_t)(rules[rn].v.ipProtocol == (uint8_t)proto);
} else { }
else {
thisRuleMatches = hardNo; thisRuleMatches = hardNo;
} }
} else { }
else {
thisRuleMatches = hardNo; thisRuleMatches = hardNo;
} }
break; break;
@ -309,38 +318,48 @@ static _doZtFilterResult _doZtFilter(
if (rules[rn].v.icmp.type == frameData[ihl]) { if (rules[rn].v.icmp.type == frameData[ihl]) {
if ((rules[rn].v.icmp.flags & 0x01) != 0) { if ((rules[rn].v.icmp.flags & 0x01) != 0) {
thisRuleMatches = (uint8_t)(frameData[ihl + 1] == rules[rn].v.icmp.code); thisRuleMatches = (uint8_t)(frameData[ihl + 1] == rules[rn].v.icmp.code);
} else { }
else {
thisRuleMatches = hardYes; thisRuleMatches = hardYes;
} }
} else { }
else {
thisRuleMatches = hardNo; thisRuleMatches = hardNo;
} }
} else { }
else {
thisRuleMatches = hardNo; thisRuleMatches = hardNo;
} }
} else { }
else {
thisRuleMatches = hardNo; thisRuleMatches = hardNo;
} }
} else if (etherType == ZT_ETHERTYPE_IPV6) { }
else if (etherType == ZT_ETHERTYPE_IPV6) {
unsigned int pos = 0, proto = 0; unsigned int pos = 0, proto = 0;
if (_ipv6GetPayload(frameData, frameLen, pos, proto)) { if (_ipv6GetPayload(frameData, frameLen, pos, proto)) {
if ((proto == 0x3a) && (frameLen >= (pos + 2))) { if ((proto == 0x3a) && (frameLen >= (pos + 2))) {
if (rules[rn].v.icmp.type == frameData[pos]) { if (rules[rn].v.icmp.type == frameData[pos]) {
if ((rules[rn].v.icmp.flags & 0x01) != 0) { if ((rules[rn].v.icmp.flags & 0x01) != 0) {
thisRuleMatches = (uint8_t)(frameData[pos + 1] == rules[rn].v.icmp.code); thisRuleMatches = (uint8_t)(frameData[pos + 1] == rules[rn].v.icmp.code);
} else { }
else {
thisRuleMatches = hardYes; thisRuleMatches = hardYes;
} }
} else { }
else {
thisRuleMatches = hardNo; thisRuleMatches = hardNo;
} }
} else { }
else {
thisRuleMatches = hardNo; thisRuleMatches = hardNo;
} }
} else { }
else {
thisRuleMatches = hardNo; thisRuleMatches = hardNo;
} }
} else { }
else {
thisRuleMatches = hardNo; thisRuleMatches = hardNo;
} }
break; break;
@ -364,7 +383,8 @@ static _doZtFilterResult _doZtFilter(
} }
thisRuleMatches = (p >= 0) ? (uint8_t)((p >= (int)rules[rn].v.port[0]) && (p <= (int)rules[rn].v.port[1])) : (uint8_t)0; thisRuleMatches = (p >= 0) ? (uint8_t)((p >= (int)rules[rn].v.port[0]) && (p <= (int)rules[rn].v.port[1])) : (uint8_t)0;
} else if (etherType == ZT_ETHERTYPE_IPV6) { }
else if (etherType == ZT_ETHERTYPE_IPV6) {
unsigned int pos = 0, proto = 0; unsigned int pos = 0, proto = 0;
if (_ipv6GetPayload(frameData, frameLen, pos, proto)) { if (_ipv6GetPayload(frameData, frameLen, pos, proto)) {
int p = -1; int p = -1;
@ -384,10 +404,12 @@ static _doZtFilterResult _doZtFilter(
break; break;
} }
thisRuleMatches = (p > 0) ? (uint8_t)((p >= (int)rules[rn].v.port[0]) && (p <= (int)rules[rn].v.port[1])) : (uint8_t)0; thisRuleMatches = (p > 0) ? (uint8_t)((p >= (int)rules[rn].v.port[0]) && (p <= (int)rules[rn].v.port[1])) : (uint8_t)0;
} else { }
else {
thisRuleMatches = hardNo; thisRuleMatches = hardNo;
} }
} else { }
else {
thisRuleMatches = hardNo; thisRuleMatches = hardNo;
} }
break; break;
@ -404,7 +426,8 @@ static _doZtFilterResult _doZtFilter(
InetAddress src; InetAddress src;
if ((etherType == ZT_ETHERTYPE_IPV4) && (frameLen >= 20)) { if ((etherType == ZT_ETHERTYPE_IPV4) && (frameLen >= 20)) {
src.set((const void*)(frameData + 12), 4, 0); src.set((const void*)(frameData + 12), 4, 0);
} else if ((etherType == ZT_ETHERTYPE_IPV6)&&(frameLen >= 40)) { }
else if ((etherType == ZT_ETHERTYPE_IPV6) && (frameLen >= 40)) {
// IPv6 NDP requires special handling, since the src and dest IPs in the packet are empty or link-local. // IPv6 NDP requires special handling, since the src and dest IPs in the packet are empty or link-local.
if ((frameLen >= (40 + 8 + 16)) && (frameData[6] == 0x3a) && ((frameData[40] == 0x87) || (frameData[40] == 0x88))) { if ((frameLen >= (40 + 8 + 16)) && (frameData[6] == 0x3a) && ((frameData[40] == 0x87) || (frameData[40] == 0x88))) {
if (frameData[40] == 0x87) { if (frameData[40] == 0x87) {
@ -412,15 +435,18 @@ static _doZtFilterResult _doZtFilter(
// hack by considering them authenticated. Otherwise you would pretty much have to do // hack by considering them authenticated. Otherwise you would pretty much have to do
// this manually in the rule set for IPv6 to work at all. // this manually in the rule set for IPv6 to work at all.
ownershipVerificationMask |= ZT_RULE_PACKET_CHARACTERISTICS_SENDER_IP_AUTHENTICATED; ownershipVerificationMask |= ZT_RULE_PACKET_CHARACTERISTICS_SENDER_IP_AUTHENTICATED;
} else { }
else {
// Neighbor advertisements on the other hand can absolutely be authenticated. // Neighbor advertisements on the other hand can absolutely be authenticated.
src.set((const void*)(frameData + 40 + 8), 16, 0); src.set((const void*)(frameData + 40 + 8), 16, 0);
} }
} else { }
else {
// Other IPv6 packets can be handled normally // Other IPv6 packets can be handled normally
src.set((const void*)(frameData + 8), 16, 0); src.set((const void*)(frameData + 8), 16, 0);
} }
} else if ((etherType == ZT_ETHERTYPE_ARP)&&(frameLen >= 28)) { }
else if ((etherType == ZT_ETHERTYPE_ARP) && (frameLen >= 28)) {
src.set((const void*)(frameData + 14), 4, 0); src.set((const void*)(frameData + 14), 4, 0);
} }
if (inbound) { if (inbound) {
@ -432,7 +458,8 @@ static _doZtFilterResult _doZtFilter(
ownershipVerificationMask |= ZT_RULE_PACKET_CHARACTERISTICS_SENDER_MAC_AUTHENTICATED; ownershipVerificationMask |= ZT_RULE_PACKET_CHARACTERISTICS_SENDER_MAC_AUTHENTICATED;
} }
} }
} else { }
else {
for (unsigned int i = 0; i < nconf.certificateOfOwnershipCount; ++i) { for (unsigned int i = 0; i < nconf.certificateOfOwnershipCount; ++i) {
if ((src) && (nconf.certificatesOfOwnership[i].owns(src))) { if ((src) && (nconf.certificatesOfOwnership[i].owns(src))) {
ownershipVerificationMask |= ZT_RULE_PACKET_CHARACTERISTICS_SENDER_IP_AUTHENTICATED; ownershipVerificationMask |= ZT_RULE_PACKET_CHARACTERISTICS_SENDER_IP_AUTHENTICATED;
@ -448,7 +475,8 @@ static _doZtFilterResult _doZtFilter(
const unsigned int headerLen = 4 * (frameData[0] & 0xf); const unsigned int headerLen = 4 * (frameData[0] & 0xf);
cf |= (uint64_t)frameData[headerLen + 13]; cf |= (uint64_t)frameData[headerLen + 13];
cf |= (((uint64_t)(frameData[headerLen + 12] & 0x0f)) << 8); cf |= (((uint64_t)(frameData[headerLen + 12] & 0x0f)) << 8);
} else if (etherType == ZT_ETHERTYPE_IPV6) { }
else if (etherType == ZT_ETHERTYPE_IPV6) {
unsigned int pos = 0, proto = 0; unsigned int pos = 0, proto = 0;
if (_ipv6GetPayload(frameData, frameLen, pos, proto)) { if (_ipv6GetPayload(frameData, frameLen, pos, proto)) {
if ((proto == 0x06) && (frameLen > (pos + 14))) { if ((proto == 0x06) && (frameLen > (pos + 14))) {
@ -487,24 +515,31 @@ static _doZtFilterResult _doZtFilter(
if (rt == ZT_NETWORK_RULE_MATCH_TAGS_DIFFERENCE) { if (rt == ZT_NETWORK_RULE_MATCH_TAGS_DIFFERENCE) {
const uint32_t diff = (ltv > rtv) ? (ltv - rtv) : (rtv - ltv); const uint32_t diff = (ltv > rtv) ? (ltv - rtv) : (rtv - ltv);
thisRuleMatches = (uint8_t)(diff <= rules[rn].v.tag.value); thisRuleMatches = (uint8_t)(diff <= rules[rn].v.tag.value);
} else if (rt == ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND) { }
else if (rt == ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND) {
thisRuleMatches = (uint8_t)((ltv & rtv) == rules[rn].v.tag.value); thisRuleMatches = (uint8_t)((ltv & rtv) == rules[rn].v.tag.value);
} else if (rt == ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR) { }
else if (rt == ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR) {
thisRuleMatches = (uint8_t)((ltv | rtv) == rules[rn].v.tag.value); thisRuleMatches = (uint8_t)((ltv | rtv) == rules[rn].v.tag.value);
} else if (rt == ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR) { }
else if (rt == ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR) {
thisRuleMatches = (uint8_t)((ltv ^ rtv) == rules[rn].v.tag.value); thisRuleMatches = (uint8_t)((ltv ^ rtv) == rules[rn].v.tag.value);
} else if (rt == ZT_NETWORK_RULE_MATCH_TAGS_EQUAL) { }
else if (rt == ZT_NETWORK_RULE_MATCH_TAGS_EQUAL) {
thisRuleMatches = (uint8_t)((ltv == rules[rn].v.tag.value) && (rtv == rules[rn].v.tag.value)); thisRuleMatches = (uint8_t)((ltv == rules[rn].v.tag.value) && (rtv == rules[rn].v.tag.value));
} else { // sanity check, can't really happen }
else { // sanity check, can't really happen
thisRuleMatches = hardNo; thisRuleMatches = hardNo;
} }
} else { }
else {
if ((inbound) && (! superAccept)) { if ((inbound) && (! superAccept)) {
thisRuleMatches = hardNo; thisRuleMatches = hardNo;
#ifdef ZT_TRACE #ifdef ZT_TRACE
// fprintf(stderr, "\tinbound "); // fprintf(stderr, "\tinbound ");
#endif #endif
} else { }
else {
// Outbound side is not strict since if we have to match both tags and // Outbound side is not strict since if we have to match both tags and
// we are sending a first packet to a recipient, we probably do not know // we are sending a first packet to a recipient, we probably do not know
// about their tags yet. They will filter on inbound and we will filter // about their tags yet. They will filter on inbound and we will filter
@ -517,7 +552,8 @@ static _doZtFilterResult _doZtFilter(
#endif #endif
} }
} }
} else { }
else {
thisRuleMatches = hardNo; thisRuleMatches = hardNo;
} }
} break; } break;
@ -536,24 +572,29 @@ static _doZtFilterResult _doZtFilter(
if (superAccept) { if (superAccept) {
skipDrop = 1; skipDrop = 1;
thisRuleMatches = hardYes; thisRuleMatches = hardYes;
} else if ( ((rt == ZT_NETWORK_RULE_MATCH_TAG_SENDER)&&(inbound)) || ((rt == ZT_NETWORK_RULE_MATCH_TAG_RECEIVER)&&(!inbound)) ) { }
else if (((rt == ZT_NETWORK_RULE_MATCH_TAG_SENDER) && (inbound)) || ((rt == ZT_NETWORK_RULE_MATCH_TAG_RECEIVER) && (! inbound))) {
const Tag* const remoteTag = ((membership) ? membership->getTag(nconf, rules[rn].v.tag.id) : (const Tag*)0); const Tag* const remoteTag = ((membership) ? membership->getTag(nconf, rules[rn].v.tag.id) : (const Tag*)0);
if (remoteTag) { if (remoteTag) {
thisRuleMatches = (uint8_t)(remoteTag->value() == rules[rn].v.tag.value); thisRuleMatches = (uint8_t)(remoteTag->value() == rules[rn].v.tag.value);
} else { }
else {
if (rt == ZT_NETWORK_RULE_MATCH_TAG_RECEIVER) { if (rt == ZT_NETWORK_RULE_MATCH_TAG_RECEIVER) {
// If we are checking the receiver and this is an outbound packet, we // If we are checking the receiver and this is an outbound packet, we
// can't be strict since we may not yet know the receiver's tag. // can't be strict since we may not yet know the receiver's tag.
skipDrop = 1; skipDrop = 1;
thisRuleMatches = hardYes; thisRuleMatches = hardYes;
} else { }
else {
thisRuleMatches = hardNo; thisRuleMatches = hardNo;
} }
} }
} else { // sender and outbound or receiver and inbound }
else { // sender and outbound or receiver and inbound
if ((localTag != &(nconf.tags[nconf.tagCount])) && (localTag->id() == rules[rn].v.tag.id)) { if ((localTag != &(nconf.tags[nconf.tagCount])) && (localTag->id() == rules[rn].v.tag.id)) {
thisRuleMatches = (uint8_t)(localTag->value() == rules[rn].v.tag.value); thisRuleMatches = (uint8_t)(localTag->value() == rules[rn].v.tag.value);
} else { }
else {
thisRuleMatches = hardNo; thisRuleMatches = hardNo;
} }
} }
@ -573,7 +614,8 @@ static _doZtFilterResult _doZtFilter(
} }
} }
integer &= 0xffffffffffffffffULL >> (64 - bits); integer &= 0xffffffffffffffffULL >> (64 - bits);
} else { }
else {
// Little-endian // Little-endian
unsigned int idx = rules[rn].v.intRange.idx; unsigned int idx = rules[rn].v.intRange.idx;
const unsigned int eof = idx + bytes; const unsigned int eof = idx + bytes;
@ -599,7 +641,8 @@ static _doZtFilterResult _doZtFilter(
if ((rules[rn].t & 0x40)) { if ((rules[rn].t & 0x40)) {
thisSetMatches |= (thisRuleMatches ^ ((rules[rn].t >> 7) & 1)); thisSetMatches |= (thisRuleMatches ^ ((rules[rn].t >> 7) & 1));
} else { }
else {
thisSetMatches &= (thisRuleMatches ^ ((rules[rn].t >> 7) & 1)); thisSetMatches &= (thisRuleMatches ^ ((rules[rn].t >> 7) & 1));
} }
} }
@ -611,23 +654,23 @@ static _doZtFilterResult _doZtFilter(
const ZeroTier::MulticastGroup Network::BROADCAST(ZeroTier::MAC(0xffffffffffffULL), 0); const ZeroTier::MulticastGroup Network::BROADCAST(ZeroTier::MAC(0xffffffffffffULL), 0);
Network::Network(const RuntimeEnvironment *renv,void *tPtr,uint64_t nwid,void *uptr,const NetworkConfig *nconf) : Network::Network(const RuntimeEnvironment* renv, void* tPtr, uint64_t nwid, void* uptr, const NetworkConfig* nconf)
RR(renv), : RR(renv)
_uPtr(uptr), , _uPtr(uptr)
_id(nwid), , _id(nwid)
_nwidStr(OSUtils::networkIDStr(nwid)), , _nwidStr(OSUtils::networkIDStr(nwid))
_lastAnnouncedMulticastGroupsUpstream(0), , _lastAnnouncedMulticastGroupsUpstream(0)
_mac(renv->identity.address(),nwid), , _mac(renv->identity.address(), nwid)
_portInitialized(false), , _portInitialized(false)
_lastConfigUpdate(0), , _lastConfigUpdate(0)
_destroyed(false), , _destroyed(false)
_netconfFailure(NETCONF_FAILURE_NONE), , _netconfFailure(NETCONF_FAILURE_NONE)
_portError(0), , _portError(0)
_num_multicast_groups{Metrics::network_num_multicast_groups.Add({{"network_id", _nwidStr}})}, , _num_multicast_groups { Metrics::network_num_multicast_groups.Add({ { "network_id", _nwidStr } }) }
_incoming_packets_accepted{Metrics::network_packets.Add({{"direction","rx"},{"network_id", _nwidStr},{"accepted","yes"}})}, , _incoming_packets_accepted { Metrics::network_packets.Add({ { "direction", "rx" }, { "network_id", _nwidStr }, { "accepted", "yes" } }) }
_incoming_packets_dropped{Metrics::network_packets.Add({{"direction","rx"},{"network_id", _nwidStr},{"accepted","no"}})}, , _incoming_packets_dropped { Metrics::network_packets.Add({ { "direction", "rx" }, { "network_id", _nwidStr }, { "accepted", "no" } }) }
_outgoing_packets_accepted{Metrics::network_packets.Add({{"direction","tx"},{"network_id", _nwidStr},{"accepted","yes"}})}, , _outgoing_packets_accepted { Metrics::network_packets.Add({ { "direction", "tx" }, { "network_id", _nwidStr }, { "accepted", "yes" } }) }
_outgoing_packets_dropped{Metrics::network_packets.Add({{"direction","tx"},{"network_id", _nwidStr},{"accepted","no"}})} , _outgoing_packets_dropped { Metrics::network_packets.Add({ { "direction", "tx" }, { "network_id", _nwidStr }, { "accepted", "no" } }) }
{ {
for (int i = 0; i < ZT_NETWORK_MAX_INCOMING_UPDATES; ++i) { for (int i = 0; i < ZT_NETWORK_MAX_INCOMING_UPDATES; ++i) {
_incomingConfigChunks[i].ts = 0; _incomingConfigChunks[i].ts = 0;
@ -636,7 +679,8 @@ Network::Network(const RuntimeEnvironment *renv,void *tPtr,uint64_t nwid,void *u
if (nconf) { if (nconf) {
this->setConfiguration(tPtr, *nconf, false); this->setConfiguration(tPtr, *nconf, false);
_lastConfigUpdate = 0; // still want to re-request since it's likely outdated _lastConfigUpdate = 0; // still want to re-request since it's likely outdated
} else { }
else {
uint64_t tmp[2]; uint64_t tmp[2];
tmp[0] = nwid; tmp[0] = nwid;
tmp[1] = 0; tmp[1] = 0;
@ -653,10 +697,14 @@ Network::Network(const RuntimeEnvironment *renv,void *tPtr,uint64_t nwid,void *u
_lastConfigUpdate = 0; // still want to re-request an update since it's likely outdated _lastConfigUpdate = 0; // still want to re-request an update since it's likely outdated
got = true; got = true;
} }
} catch ( ... ) {} }
catch (...) {
}
delete nconf; delete nconf;
} }
} catch ( ... ) {} }
catch (...) {
}
delete dict; delete dict;
if (! got) { if (! got) {
@ -683,7 +731,8 @@ Network::~Network()
if (_destroyed) { if (_destroyed) {
// This is done in Node::leave() so we can pass tPtr properly // This is done in Node::leave() so we can pass tPtr properly
// RR->node->configureVirtualNetworkPort((void *)0,_id,&_uPtr,ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY,&ctmp); // RR->node->configureVirtualNetworkPort((void *)0,_id,&_uPtr,ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY,&ctmp);
} else { }
else {
RR->node->configureVirtualNetworkPort((void*)0, _id, &_uPtr, ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DOWN, &ctmp); RR->node->configureVirtualNetworkPort((void*)0, _id, &_uPtr, ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DOWN, &ctmp);
} }
} }
@ -714,14 +763,32 @@ bool Network::filterOutgoingPacket(
Membership* const membership = (ztDest) ? _memberships.get(ztDest) : (Membership*)0; Membership* const membership = (ztDest) ? _memberships.get(ztDest) : (Membership*)0;
switch (_doZtFilter(RR, rrl, _config, membership, false, ztSource, ztFinalDest, macSource, macDest, frameData, frameLen, etherType, vlanId, _config.rules, _config.ruleCount, cc, ccLength, ccWatch, qosBucket)) { switch (_doZtFilter(RR, rrl, _config, membership, false, ztSource, ztFinalDest, macSource, macDest, frameData, frameLen, etherType, vlanId, _config.rules, _config.ruleCount, cc, ccLength, ccWatch, qosBucket)) {
case DOZTFILTER_NO_MATCH: { case DOZTFILTER_NO_MATCH: {
for (unsigned int c = 0; c < _config.capabilityCount; ++c) { for (unsigned int c = 0; c < _config.capabilityCount; ++c) {
ztFinalDest = ztDest; // sanity check, shouldn't be possible if there was no match ztFinalDest = ztDest; // sanity check, shouldn't be possible if there was no match
Address cc2; Address cc2;
unsigned int ccLength2 = 0; unsigned int ccLength2 = 0;
bool ccWatch2 = false; bool ccWatch2 = false;
switch (_doZtFilter(RR,crrl,_config,membership,false,ztSource,ztFinalDest,macSource,macDest,frameData,frameLen,etherType,vlanId,_config.capabilities[c].rules(),_config.capabilities[c].ruleCount(),cc2,ccLength2,ccWatch2,qosBucket)) { switch (_doZtFilter(
RR,
crrl,
_config,
membership,
false,
ztSource,
ztFinalDest,
macSource,
macDest,
frameData,
frameLen,
etherType,
vlanId,
_config.capabilities[c].rules(),
_config.capabilities[c].ruleCount(),
cc2,
ccLength2,
ccWatch2,
qosBucket)) {
case DOZTFILTER_NO_MATCH: case DOZTFILTER_NO_MATCH:
case DOZTFILTER_DROP: // explicit DROP in a capability just terminates its evaluation and is an anti-pattern case DOZTFILTER_DROP: // explicit DROP in a capability just terminates its evaluation and is an anti-pattern
break; break;
@ -794,19 +861,69 @@ bool Network::filterOutgoingPacket(
RR->sw->send(tPtr, outp, true); RR->sw->send(tPtr, outp, true);
if (_config.remoteTraceTarget) { if (_config.remoteTraceTarget) {
RR->t->networkFilter(tPtr,*this,rrl,(localCapabilityIndex >= 0) ? &crrl : (Trace::RuleResultLog *)0,(localCapabilityIndex >= 0) ? &(_config.capabilities[localCapabilityIndex]) : (Capability *)0,ztSource,ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,noTee,false,0); RR->t->networkFilter(
tPtr,
*this,
rrl,
(localCapabilityIndex >= 0) ? &crrl : (Trace::RuleResultLog*)0,
(localCapabilityIndex >= 0) ? &(_config.capabilities[localCapabilityIndex]) : (Capability*)0,
ztSource,
ztDest,
macSource,
macDest,
frameData,
frameLen,
etherType,
vlanId,
noTee,
false,
0);
} }
return false; // DROP locally, since we redirected return false; // DROP locally, since we redirected
} else { }
else {
if (_config.remoteTraceTarget) { if (_config.remoteTraceTarget) {
RR->t->networkFilter(tPtr,*this,rrl,(localCapabilityIndex >= 0) ? &crrl : (Trace::RuleResultLog *)0,(localCapabilityIndex >= 0) ? &(_config.capabilities[localCapabilityIndex]) : (Capability *)0,ztSource,ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,noTee,false,1); RR->t->networkFilter(
tPtr,
*this,
rrl,
(localCapabilityIndex >= 0) ? &crrl : (Trace::RuleResultLog*)0,
(localCapabilityIndex >= 0) ? &(_config.capabilities[localCapabilityIndex]) : (Capability*)0,
ztSource,
ztDest,
macSource,
macDest,
frameData,
frameLen,
etherType,
vlanId,
noTee,
false,
1);
} }
return true; return true;
} }
} else { }
else {
_outgoing_packets_dropped++; _outgoing_packets_dropped++;
if (_config.remoteTraceTarget) { if (_config.remoteTraceTarget) {
RR->t->networkFilter(tPtr,*this,rrl,(localCapabilityIndex >= 0) ? &crrl : (Trace::RuleResultLog *)0,(localCapabilityIndex >= 0) ? &(_config.capabilities[localCapabilityIndex]) : (Capability *)0,ztSource,ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,noTee,false,0); RR->t->networkFilter(
tPtr,
*this,
rrl,
(localCapabilityIndex >= 0) ? &crrl : (Trace::RuleResultLog*)0,
(localCapabilityIndex >= 0) ? &(_config.capabilities[localCapabilityIndex]) : (Capability*)0,
ztSource,
ztDest,
macSource,
macDest,
frameData,
frameLen,
etherType,
vlanId,
noTee,
false,
0);
} }
return false; return false;
} }
@ -838,7 +955,6 @@ int Network::filterIncomingPacket(
Membership& membership = _membership(sourcePeer->address()); Membership& membership = _membership(sourcePeer->address());
switch (_doZtFilter(RR, rrl, _config, &membership, true, sourcePeer->address(), ztFinalDest, macSource, macDest, frameData, frameLen, etherType, vlanId, _config.rules, _config.ruleCount, cc, ccLength, ccWatch, qosBucket)) { switch (_doZtFilter(RR, rrl, _config, &membership, true, sourcePeer->address(), ztFinalDest, macSource, macDest, frameData, frameLen, etherType, vlanId, _config.rules, _config.ruleCount, cc, ccLength, ccWatch, qosBucket)) {
case DOZTFILTER_NO_MATCH: { case DOZTFILTER_NO_MATCH: {
Membership::CapabilityIterator mci(membership, _config); Membership::CapabilityIterator mci(membership, _config);
while ((c = mci.next())) { while ((c = mci.next())) {
@ -921,7 +1037,8 @@ int Network::filterIncomingPacket(
} }
return 0; // DROP locally, since we redirected return 0; // DROP locally, since we redirected
} }
} else { }
else {
_incoming_packets_dropped++; _incoming_packets_dropped++;
} }
@ -936,7 +1053,8 @@ bool Network::subscribedToMulticastGroup(const MulticastGroup &mg,bool includeBr
Mutex::Lock _l(_lock); Mutex::Lock _l(_lock);
if (std::binary_search(_myMulticastGroups.begin(), _myMulticastGroups.end(), mg)) { if (std::binary_search(_myMulticastGroups.begin(), _myMulticastGroups.end(), mg)) {
return true; return true;
} else if (includeBridgedGroups) { }
else if (includeBridgedGroups) {
return _multicastGroupsBehindMe.contains(mg); return _multicastGroupsBehindMe.contains(mg);
} }
return false; return false;
@ -1018,7 +1136,8 @@ uint64_t Network::handleConfigChunk(void *tPtr,const uint64_t packetId,const Add
} }
break; break;
} else if ((!c)||(_incomingConfigChunks[i].ts < c->ts)) { }
else if ((! c) || (_incomingConfigChunks[i].ts < c->ts)) {
c = &(_incomingConfigChunks[i]); c = &(_incomingConfigChunks[i]);
} }
} }
@ -1045,7 +1164,8 @@ uint64_t Network::handleConfigChunk(void *tPtr,const uint64_t packetId,const Add
} }
} }
} }
} else if ((source == controller())||(!source)) { // since old chunks aren't signed, only accept from controller itself (or via cluster backplane) }
else if ((source == controller()) || (! source)) { // since old chunks aren't signed, only accept from controller itself (or via cluster backplane)
// Legacy support for OK(NETWORK_CONFIG_REQUEST) from older controllers // Legacy support for OK(NETWORK_CONFIG_REQUEST) from older controllers
chunkId = packetId; chunkId = packetId;
configUpdateId = chunkId; configUpdateId = chunkId;
@ -1061,7 +1181,8 @@ uint64_t Network::handleConfigChunk(void *tPtr,const uint64_t packetId,const Add
c = &(_incomingConfigChunks[i]); c = &(_incomingConfigChunks[i]);
} }
} }
} else { }
else {
// Single-chunk unsigned legacy configs are only allowed from the controller itself // Single-chunk unsigned legacy configs are only allowed from the controller itself
return 0; return 0;
} }
@ -1090,7 +1211,8 @@ uint64_t Network::handleConfigChunk(void *tPtr,const uint64_t packetId,const Add
delete nc; delete nc;
nc = (NetworkConfig*)0; nc = (NetworkConfig*)0;
} }
} catch ( ... ) { }
catch (...) {
delete nc; delete nc;
nc = (NetworkConfig*)0; nc = (NetworkConfig*)0;
} }
@ -1101,7 +1223,8 @@ uint64_t Network::handleConfigChunk(void *tPtr,const uint64_t packetId,const Add
this->setConfiguration(tPtr, *nc, true); this->setConfiguration(tPtr, *nc, true);
delete nc; delete nc;
return configUpdateId; return configUpdateId;
} else { }
else {
return 0; return 0;
} }
@ -1150,12 +1273,16 @@ int Network::setConfiguration(void *tPtr,const NetworkConfig &nconf,bool saveToD
tmp[1] = 0; tmp[1] = 0;
RR->node->stateObjectPut(tPtr, ZT_STATE_OBJECT_NETWORK_CONFIG, tmp, d->data(), d->sizeBytes()); RR->node->stateObjectPut(tPtr, ZT_STATE_OBJECT_NETWORK_CONFIG, tmp, d->data(), d->sizeBytes());
} }
} catch ( ... ) {} }
catch (...) {
}
delete d; delete d;
} }
return 2; // OK and configuration has changed return 2; // OK and configuration has changed
} catch ( ... ) {} // ignore invalid configs }
catch (...) {
} // ignore invalid configs
return 0; return 0;
} }
@ -1233,10 +1360,12 @@ void Network::requestConfiguration(void *tPtr)
this->setConfiguration(tPtr, *nconf, false); this->setConfiguration(tPtr, *nconf, false);
delete nconf; delete nconf;
} else { }
else {
this->setNotFound(tPtr); this->setNotFound(tPtr);
} }
} else if ((_id & 0xff) == 0x01) { }
else if ((_id & 0xff) == 0x01) {
// ffAAaaaaaaaaaa01 -- where AA is the IPv4 /8 to use and aaaaaaaaaa is the anchor node for multicast gather and replication // ffAAaaaaaaaaaa01 -- where AA is the IPv4 /8 to use and aaaaaaaaaa is the anchor node for multicast gather and replication
const uint64_t myAddress = RR->identity.address().toInt(); const uint64_t myAddress = RR->identity.address().toInt();
const uint64_t networkHub = (_id >> 8) & 0xffffffffffULL; const uint64_t networkHub = (_id >> 8) & 0xffffffffffULL;
@ -1321,7 +1450,8 @@ void Network::requestConfiguration(void *tPtr)
if (ctrl == RR->identity.address()) { if (ctrl == RR->identity.address()) {
if (RR->localNetworkController) { if (RR->localNetworkController) {
RR->localNetworkController->request(_id, InetAddress(), 0xffffffffffffffffULL, RR->identity, rmd); RR->localNetworkController->request(_id, InetAddress(), 0xffffffffffffffffULL, RR->identity, rmd);
} else { }
else {
this->setNotFound(tPtr); this->setNotFound(tPtr);
} }
return; return;
@ -1335,7 +1465,8 @@ void Network::requestConfiguration(void *tPtr)
if (_config) { if (_config) {
outp.append((uint64_t)_config.revision); outp.append((uint64_t)_config.revision);
outp.append((uint64_t)_config.timestamp); outp.append((uint64_t)_config.timestamp);
} else { }
else {
outp.append((unsigned char)0, 16); outp.append((unsigned char)0, 16);
} }
outp.compress(); outp.compress();
@ -1366,7 +1497,9 @@ bool Network::gate(void *tPtr,const SharedPtr<Peer> &peer)
return true; return true;
} }
} }
} catch ( ... ) {} }
catch (...) {
}
// printf("%.16llx %.10llx not allowed, COM ts %lld revocation %lld\n", _id, peer->address().toInt(), comTimestamp, comRevocationThreshold); fflush(stdout); // printf("%.16llx %.10llx not allowed, COM ts %lld revocation %lld\n", _id, peer->address().toInt(), comTimestamp, comRevocationThreshold); fflush(stdout);
return false; return false;
@ -1406,7 +1539,8 @@ void Network::clean()
while (i.next(a, m)) { while (i.next(a, m)) {
if (! RR->topology->getPeerNoCache(*a)) { if (! RR->topology->getPeerNoCache(*a)) {
_memberships.erase(*a); _memberships.erase(*a);
} else { }
else {
m->clean(now, _config); m->clean(now, _config);
} }
} }
@ -1535,7 +1669,8 @@ void Network::_externalConfig(ZT_VirtualNetworkConfig *ec) const
ec->mac = _mac.toInt(); ec->mac = _mac.toInt();
if (_config) { if (_config) {
Utils::scopy(ec->name, sizeof(ec->name), _config.name); Utils::scopy(ec->name, sizeof(ec->name), _config.name);
} else { }
else {
ec->name[0] = (char)0; ec->name[0] = (char)0;
} }
ec->status = _status(); ec->status = _status();
@ -1553,7 +1688,8 @@ void Network::_externalConfig(ZT_VirtualNetworkConfig *ec) const
if (i < _config.staticIpCount) { if (i < _config.staticIpCount) {
memcpy(&(ec->assignedAddresses[i]), &(_config.staticIps[i]), sizeof(struct sockaddr_storage)); memcpy(&(ec->assignedAddresses[i]), &(_config.staticIps[i]), sizeof(struct sockaddr_storage));
++ec->assignedAddressCount; ++ec->assignedAddressCount;
} else { }
else {
memset(&(ec->assignedAddresses[i]), 0, sizeof(struct sockaddr_storage)); memset(&(ec->assignedAddresses[i]), 0, sizeof(struct sockaddr_storage));
} }
} }
@ -1563,7 +1699,8 @@ void Network::_externalConfig(ZT_VirtualNetworkConfig *ec) const
if (i < _config.routeCount) { if (i < _config.routeCount) {
memcpy(&(ec->routes[i]), &(_config.routes[i]), sizeof(ZT_VirtualNetworkRoute)); memcpy(&(ec->routes[i]), &(_config.routes[i]), sizeof(ZT_VirtualNetworkRoute));
++ec->routeCount; ++ec->routeCount;
} else { }
else {
memset(&(ec->routes[i]), 0, sizeof(ZT_VirtualNetworkRoute)); memset(&(ec->routes[i]), 0, sizeof(ZT_VirtualNetworkRoute));
} }
} }
@ -1596,7 +1733,8 @@ void Network::_sendUpdatesToMembers(void *tPtr,const MulticastGroup *const newMu
std::vector<MulticastGroup> groups; std::vector<MulticastGroup> groups;
if (newMulticastGroup) { if (newMulticastGroup) {
groups.push_back(*newMulticastGroup); groups.push_back(*newMulticastGroup);
} else { }
else {
groups = _allMulticastGroups(); groups = _allMulticastGroups();
} }
@ -1715,7 +1853,8 @@ void Network::setAuthenticationRequired(void *tPtr, const char* issuerURL, const
_sendUpdateEvent(tPtr); _sendUpdateEvent(tPtr);
} }
void Network::_sendUpdateEvent(void *tPtr) { void Network::_sendUpdateEvent(void* tPtr)
{
ZT_VirtualNetworkConfig ctmp; ZT_VirtualNetworkConfig ctmp;
_externalConfig(&ctmp); _externalConfig(&ctmp);
RR->node->configureVirtualNetworkPort(tPtr, _id, &_uPtr, (_portInitialized) ? ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE : ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP, &ctmp); RR->node->configureVirtualNetworkPort(tPtr, _id, &_uPtr, (_portInitialized) ? ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE : ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP, &ctmp);

View file

@ -14,30 +14,28 @@
#ifndef ZT_NETWORK_HPP #ifndef ZT_NETWORK_HPP
#define ZT_NETWORK_HPP #define ZT_NETWORK_HPP
#include <stdint.h>
#include "../include/ZeroTierOne.h" #include "../include/ZeroTierOne.h"
#include <string>
#include <map>
#include <vector>
#include <algorithm>
#include <stdexcept>
#include "Constants.hpp"
#include "Hashtable.hpp"
#include "Address.hpp" #include "Address.hpp"
#include "Mutex.hpp"
#include "SharedPtr.hpp"
#include "AtomicCounter.hpp" #include "AtomicCounter.hpp"
#include "MulticastGroup.hpp"
#include "MAC.hpp"
#include "Dictionary.hpp"
#include "Multicaster.hpp"
#include "Membership.hpp"
#include "NetworkConfig.hpp"
#include "CertificateOfMembership.hpp" #include "CertificateOfMembership.hpp"
#include "Constants.hpp"
#include "Dictionary.hpp"
#include "Hashtable.hpp"
#include "MAC.hpp"
#include "Membership.hpp"
#include "Metrics.hpp" #include "Metrics.hpp"
#include "MulticastGroup.hpp"
#include "Multicaster.hpp"
#include "Mutex.hpp"
#include "NetworkConfig.hpp"
#include "SharedPtr.hpp"
#include <algorithm>
#include <map>
#include <stdexcept>
#include <stdint.h>
#include <string>
#include <vector>
#define ZT_NETWORK_MAX_INCOMING_UPDATES 3 #define ZT_NETWORK_MAX_INCOMING_UPDATES 3
#define ZT_NETWORK_MAX_UPDATE_CHUNKS ((ZT_NETWORKCONFIG_DICT_CAPACITY / 1024) + 1) #define ZT_NETWORK_MAX_UPDATE_CHUNKS ((ZT_NETWORKCONFIG_DICT_CAPACITY / 1024) + 1)
@ -50,8 +48,7 @@ class Peer;
/** /**
* A virtual LAN * A virtual LAN
*/ */
class Network class Network {
{
friend class SharedPtr<Network>; friend class SharedPtr<Network>;
public: public:
@ -63,7 +60,10 @@ public:
/** /**
* Compute primary controller device ID from network ID * Compute primary controller device ID from network ID
*/ */
static inline Address controllerFor(uint64_t nwid) { return Address(nwid >> 24); } static inline Address controllerFor(uint64_t nwid)
{
return Address(nwid >> 24);
}
/** /**
* Construct a new network * Construct a new network
@ -81,14 +81,39 @@ public:
~Network(); ~Network();
inline uint64_t id() const { return _id; } inline uint64_t id() const
inline Address controller() const { return Address(_id >> 24); } {
inline bool multicastEnabled() const { return (_config.multicastLimit > 0); } return _id;
inline bool hasConfig() const { return (_config); } }
inline uint64_t lastConfigUpdate() const { return _lastConfigUpdate; } inline Address controller() const
inline ZT_VirtualNetworkStatus status() const { Mutex::Lock _l(_lock); return _status(); } {
inline const NetworkConfig &config() const { return _config; } return Address(_id >> 24);
inline const MAC &mac() const { return _mac; } }
inline bool multicastEnabled() const
{
return (_config.multicastLimit > 0);
}
inline bool hasConfig() const
{
return (_config);
}
inline uint64_t lastConfigUpdate() const
{
return _lastConfigUpdate;
}
inline ZT_VirtualNetworkStatus status() const
{
Mutex::Lock _l(_lock);
return _status();
}
inline const NetworkConfig& config() const
{
return _config;
}
inline const MAC& mac() const
{
return _mac;
}
/** /**
* Apply filters to an outgoing packet * Apply filters to an outgoing packet
@ -304,7 +329,10 @@ public:
/** /**
* @return True if QoS is in effect for this network * @return True if QoS is in effect for this network
*/ */
inline bool qosEnabled() { return false; } inline bool qosEnabled()
{
return false;
}
/** /**
* Set a bridge route * Set a bridge route
@ -425,7 +453,10 @@ public:
/** /**
* @return Externally usable pointer-to-pointer exported via the core API * @return Externally usable pointer-to-pointer exported via the core API
*/ */
inline void **userPtr() { return &_uPtr; } inline void** userPtr()
{
return &_uPtr;
}
private: private:
ZT_VirtualNetworkStatus _status() const; ZT_VirtualNetworkStatus _status() const;
@ -452,9 +483,11 @@ private:
NetworkConfig _config; NetworkConfig _config;
int64_t _lastConfigUpdate; int64_t _lastConfigUpdate;
struct _IncomingConfigChunk struct _IncomingConfigChunk {
_IncomingConfigChunk()
{ {
_IncomingConfigChunk() { memset(this,0,sizeof(_IncomingConfigChunk)); } memset(this, 0, sizeof(_IncomingConfigChunk));
}
uint64_t ts; uint64_t ts;
uint64_t updateId; uint64_t updateId;
uint64_t haveChunkIds[ZT_NETWORK_MAX_UPDATE_CHUNKS]; uint64_t haveChunkIds[ZT_NETWORK_MAX_UPDATE_CHUNKS];
@ -466,13 +499,7 @@ private:
bool _destroyed; bool _destroyed;
enum { enum { NETCONF_FAILURE_NONE, NETCONF_FAILURE_ACCESS_DENIED, NETCONF_FAILURE_NOT_FOUND, NETCONF_FAILURE_INIT_FAILED, NETCONF_FAILURE_AUTHENTICATION_REQUIRED } _netconfFailure;
NETCONF_FAILURE_NONE,
NETCONF_FAILURE_ACCESS_DENIED,
NETCONF_FAILURE_NOT_FOUND,
NETCONF_FAILURE_INIT_FAILED,
NETCONF_FAILURE_AUTHENTICATION_REQUIRED
} _netconfFailure;
int _portError; // return value from port config callback int _portError; // return value from port config callback
std::string _authenticationURL; std::string _authenticationURL;

View file

@ -11,11 +11,10 @@
*/ */
/****/ /****/
#include <stdint.h> #include "NetworkConfig.hpp"
#include <algorithm> #include <algorithm>
#include <stdint.h>
#include "NetworkConfig.hpp"
namespace ZeroTier { namespace ZeroTier {
@ -129,7 +128,8 @@ bool NetworkConfig::toDictionary(Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d,b
ZT_VirtualNetworkRuleType rt = (ZT_VirtualNetworkRuleType)(rules[i].t & 0x7f); ZT_VirtualNetworkRuleType rt = (ZT_VirtualNetworkRuleType)(rules[i].t & 0x7f);
if (rt == ZT_NETWORK_RULE_MATCH_ETHERTYPE) { if (rt == ZT_NETWORK_RULE_MATCH_ETHERTYPE) {
et = rules[i].v.etherType; et = rules[i].v.etherType;
} else if (rt == ZT_NETWORK_RULE_ACTION_ACCEPT) { }
else if (rt == ZT_NETWORK_RULE_ACTION_ACCEPT) {
if (((int)lastrt < 32) || (lastrt == ZT_NETWORK_RULE_MATCH_ETHERTYPE)) { if (((int)lastrt < 32) || (lastrt == ZT_NETWORK_RULE_MATCH_ETHERTYPE)) {
if (ets.length() > 0) { if (ets.length() > 0) {
ets.push_back(','); ets.push_back(',');
@ -280,7 +280,8 @@ bool NetworkConfig::toDictionary(Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d,b
return false; return false;
} }
} }
} else if(this->ssoVersion == 1) { }
else if (this->ssoVersion == 1) {
if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_SSO_VERSION, this->ssoVersion)) { if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_SSO_VERSION, this->ssoVersion)) {
return false; return false;
} }
@ -309,7 +310,8 @@ bool NetworkConfig::toDictionary(Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d,b
} }
delete tmp; delete tmp;
} catch ( ... ) { }
catch (...) {
delete tmp; delete tmp;
throw; throw;
} }
@ -347,7 +349,8 @@ bool NetworkConfig::fromDictionary(const Dictionary<ZT_NETWORKCONFIG_DICT_CAPACI
this->mtu = (unsigned int)d.getUI(ZT_NETWORKCONFIG_DICT_KEY_MTU, ZT_DEFAULT_MTU); this->mtu = (unsigned int)d.getUI(ZT_NETWORKCONFIG_DICT_KEY_MTU, ZT_DEFAULT_MTU);
if (this->mtu < 1280) { if (this->mtu < 1280) {
this->mtu = 1280; // minimum MTU allowed by IPv6 standard and others this->mtu = 1280; // minimum MTU allowed by IPv6 standard and others
} else if (this->mtu > ZT_MAX_MTU) { }
else if (this->mtu > ZT_MAX_MTU) {
this->mtu = ZT_MAX_MTU; this->mtu = ZT_MAX_MTU;
} }
@ -405,7 +408,8 @@ bool NetworkConfig::fromDictionary(const Dictionary<ZT_NETWORKCONFIG_DICT_CAPACI
} }
this->rules[this->ruleCount++].t = (uint8_t)ZT_NETWORK_RULE_ACTION_ACCEPT; this->rules[this->ruleCount++].t = (uint8_t)ZT_NETWORK_RULE_ACTION_ACCEPT;
} }
} else { }
else {
this->rules[0].t = ZT_NETWORK_RULE_ACTION_ACCEPT; this->rules[0].t = ZT_NETWORK_RULE_ACTION_ACCEPT;
this->ruleCount = 1; this->ruleCount = 1;
} }
@ -420,7 +424,8 @@ bool NetworkConfig::fromDictionary(const Dictionary<ZT_NETWORKCONFIG_DICT_CAPACI
delete tmp; delete tmp;
return false; return false;
#endif // ZT_SUPPORT_OLD_STYLE_NETCONF #endif // ZT_SUPPORT_OLD_STYLE_NETCONF
} else { }
else {
// Otherwise we can use the new fields // Otherwise we can use the new fields
this->flags = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_FLAGS, 0); this->flags = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_FLAGS, 0);
this->type = (ZT_VirtualNetworkType)d.getUI(ZT_NETWORKCONFIG_DICT_KEY_TYPE, (uint64_t)ZT_NETWORK_TYPE_PRIVATE); this->type = (ZT_VirtualNetworkType)d.getUI(ZT_NETWORKCONFIG_DICT_KEY_TYPE, (uint64_t)ZT_NETWORK_TYPE_PRIVATE);
@ -437,7 +442,9 @@ bool NetworkConfig::fromDictionary(const Dictionary<ZT_NETWORKCONFIG_DICT_CAPACI
p += cap.deserialize(*tmp, p); p += cap.deserialize(*tmp, p);
this->capabilities[this->capabilityCount++] = cap; this->capabilities[this->capabilityCount++] = cap;
} }
} catch ( ... ) {} }
catch (...) {
}
std::sort(&(this->capabilities[0]), &(this->capabilities[this->capabilityCount])); std::sort(&(this->capabilities[0]), &(this->capabilities[this->capabilityCount]));
} }
@ -449,7 +456,9 @@ bool NetworkConfig::fromDictionary(const Dictionary<ZT_NETWORKCONFIG_DICT_CAPACI
p += tag.deserialize(*tmp, p); p += tag.deserialize(*tmp, p);
this->tags[this->tagCount++] = tag; this->tags[this->tagCount++] = tag;
} }
} catch ( ... ) {} }
catch (...) {
}
std::sort(&(this->tags[0]), &(this->tags[this->tagCount])); std::sort(&(this->tags[0]), &(this->tags[this->tagCount]));
} }
@ -458,7 +467,8 @@ bool NetworkConfig::fromDictionary(const Dictionary<ZT_NETWORKCONFIG_DICT_CAPACI
while (p < tmp->size()) { while (p < tmp->size()) {
if (certificateOfOwnershipCount < ZT_MAX_CERTIFICATES_OF_OWNERSHIP) { if (certificateOfOwnershipCount < ZT_MAX_CERTIFICATES_OF_OWNERSHIP) {
p += certificatesOfOwnership[certificateOfOwnershipCount++].deserialize(*tmp, p); p += certificatesOfOwnership[certificateOfOwnershipCount++].deserialize(*tmp, p);
} else { }
else {
CertificateOfOwnership foo; CertificateOfOwnership foo;
p += foo.deserialize(*tmp, p); p += foo.deserialize(*tmp, p);
} }
@ -514,15 +524,18 @@ bool NetworkConfig::fromDictionary(const Dictionary<ZT_NETWORKCONFIG_DICT_CAPACI
if (this->ssoEnabled) { if (this->ssoEnabled) {
if (d.get(ZT_NETWORKCONFIG_DICT_KEY_AUTHENTICATION_URL, this->authenticationURL, (unsigned int)sizeof(this->authenticationURL)) > 0) { if (d.get(ZT_NETWORKCONFIG_DICT_KEY_AUTHENTICATION_URL, this->authenticationURL, (unsigned int)sizeof(this->authenticationURL)) > 0) {
this->authenticationURL[sizeof(this->authenticationURL) - 1] = 0; // ensure null terminated this->authenticationURL[sizeof(this->authenticationURL) - 1] = 0; // ensure null terminated
} else { }
else {
this->authenticationURL[0] = 0; this->authenticationURL[0] = 0;
} }
this->authenticationExpiryTime = d.getI(ZT_NETWORKCONFIG_DICT_KEY_AUTHENTICATION_EXPIRY_TIME, 0); this->authenticationExpiryTime = d.getI(ZT_NETWORKCONFIG_DICT_KEY_AUTHENTICATION_EXPIRY_TIME, 0);
} else { }
else {
this->authenticationURL[0] = 0; this->authenticationURL[0] = 0;
this->authenticationExpiryTime = 0; this->authenticationExpiryTime = 0;
} }
} else if (this->ssoVersion == 1) { }
else if (this->ssoVersion == 1) {
// full flow // full flow
if (this->ssoEnabled) { if (this->ssoEnabled) {
if (d.get(ZT_NETWORKCONFIG_DICT_KEY_AUTHENTICATION_URL, this->authenticationURL, (unsigned int)sizeof(this->authenticationURL)) > 0) { if (d.get(ZT_NETWORKCONFIG_DICT_KEY_AUTHENTICATION_URL, this->authenticationURL, (unsigned int)sizeof(this->authenticationURL)) > 0) {
@ -545,11 +558,13 @@ bool NetworkConfig::fromDictionary(const Dictionary<ZT_NETWORKCONFIG_DICT_CAPACI
} }
if (d.get(ZT_NETWORKCONFIG_DICT_KEY_SSO_PROVIDER, this->ssoProvider, (unsigned int)(sizeof(this->ssoProvider))) > 0) { if (d.get(ZT_NETWORKCONFIG_DICT_KEY_SSO_PROVIDER, this->ssoProvider, (unsigned int)(sizeof(this->ssoProvider))) > 0) {
this->ssoProvider[sizeof(this->ssoProvider) - 1] = 0; this->ssoProvider[sizeof(this->ssoProvider) - 1] = 0;
} else { }
else {
strncpy(this->ssoProvider, "default", sizeof(this->ssoProvider)); strncpy(this->ssoProvider, "default", sizeof(this->ssoProvider));
this->ssoProvider[sizeof(this->ssoProvider) - 1] = 0; this->ssoProvider[sizeof(this->ssoProvider) - 1] = 0;
} }
} else { }
else {
this->authenticationURL[0] = 0; this->authenticationURL[0] = 0;
this->authenticationExpiryTime = 0; this->authenticationExpiryTime = 0;
this->centralAuthURL[0] = 0; this->centralAuthURL[0] = 0;
@ -568,7 +583,8 @@ bool NetworkConfig::fromDictionary(const Dictionary<ZT_NETWORKCONFIG_DICT_CAPACI
delete tmp; delete tmp;
return true; return true;
} catch ( ... ) { }
catch (...) {
delete tmp; delete tmp;
return false; return false;
} }

View file

@ -14,31 +14,29 @@
#ifndef ZT_NETWORKCONFIG_HPP #ifndef ZT_NETWORKCONFIG_HPP
#define ZT_NETWORKCONFIG_HPP #define ZT_NETWORKCONFIG_HPP
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <vector>
#include <stdexcept>
#include <algorithm>
#include "../include/ZeroTierOne.h" #include "../include/ZeroTierOne.h"
#include "Constants.hpp"
#include "Buffer.hpp"
#include "DNS.hpp"
#include "InetAddress.hpp"
#include "MulticastGroup.hpp"
#include "Address.hpp" #include "Address.hpp"
#include "Buffer.hpp"
#include "Capability.hpp"
#include "CertificateOfMembership.hpp" #include "CertificateOfMembership.hpp"
#include "CertificateOfOwnership.hpp" #include "CertificateOfOwnership.hpp"
#include "Capability.hpp" #include "Constants.hpp"
#include "Tag.hpp" #include "DNS.hpp"
#include "Dictionary.hpp" #include "Dictionary.hpp"
#include "Hashtable.hpp" #include "Hashtable.hpp"
#include "Identity.hpp" #include "Identity.hpp"
#include "Utils.hpp" #include "InetAddress.hpp"
#include "MulticastGroup.hpp"
#include "Tag.hpp"
#include "Trace.hpp" #include "Trace.hpp"
#include "Utils.hpp"
#include <algorithm>
#include <stdexcept>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <vector>
/** /**
* Default time delta for COMs, tags, and capabilities * Default time delta for COMs, tags, and capabilities
@ -93,7 +91,9 @@
namespace ZeroTier { namespace ZeroTier {
// Dictionary capacity needed for max size network config // Dictionary capacity needed for max size network config
#define ZT_NETWORKCONFIG_DICT_CAPACITY (4096 + (sizeof(ZT_VirtualNetworkConfig)) + (sizeof(ZT_VirtualNetworkRule) * ZT_MAX_NETWORK_RULES) + (sizeof(Capability) * ZT_MAX_NETWORK_CAPABILITIES) + (sizeof(Tag) * ZT_MAX_NETWORK_TAGS) + (sizeof(CertificateOfOwnership) * ZT_MAX_CERTIFICATES_OF_OWNERSHIP)) #define ZT_NETWORKCONFIG_DICT_CAPACITY \
(4096 + (sizeof(ZT_VirtualNetworkConfig)) + (sizeof(ZT_VirtualNetworkRule) * ZT_MAX_NETWORK_RULES) + (sizeof(Capability) * ZT_MAX_NETWORK_CAPABILITIES) + (sizeof(Tag) * ZT_MAX_NETWORK_TAGS) \
+ (sizeof(CertificateOfOwnership) * ZT_MAX_CERTIFICATES_OF_OWNERSHIP))
// Dictionary capacity needed for max size network meta-data // Dictionary capacity needed for max size network meta-data
#define ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY 1024 #define ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY 1024
@ -248,40 +248,39 @@ namespace ZeroTier {
* This is a memcpy()'able structure and is safe (in a crash sense) to modify * This is a memcpy()'able structure and is safe (in a crash sense) to modify
* without locks. * without locks.
*/ */
class NetworkConfig class NetworkConfig {
{
public: public:
NetworkConfig() : NetworkConfig()
networkId(0), : networkId(0)
timestamp(0), , timestamp(0)
credentialTimeMaxDelta(0), , credentialTimeMaxDelta(0)
revision(0), , revision(0)
issuedTo(), , issuedTo()
remoteTraceTarget(), , remoteTraceTarget()
flags(0), , flags(0)
remoteTraceLevel(Trace::LEVEL_NORMAL), , remoteTraceLevel(Trace::LEVEL_NORMAL)
mtu(0), , mtu(0)
multicastLimit(0), , multicastLimit(0)
specialistCount(0), , specialistCount(0)
routeCount(0), , routeCount(0)
staticIpCount(0), , staticIpCount(0)
ruleCount(0), , ruleCount(0)
capabilityCount(0), , capabilityCount(0)
tagCount(0), , tagCount(0)
certificateOfOwnershipCount(0), , certificateOfOwnershipCount(0)
capabilities(), , capabilities()
tags(), , tags()
certificatesOfOwnership(), , certificatesOfOwnership()
type(ZT_NETWORK_TYPE_PRIVATE), , type(ZT_NETWORK_TYPE_PRIVATE)
dnsCount(0), , dnsCount(0)
ssoEnabled(false), , ssoEnabled(false)
authenticationURL(), , authenticationURL()
authenticationExpiryTime(0), , authenticationExpiryTime(0)
issuerURL(), , issuerURL()
centralAuthURL(), , centralAuthURL()
ssoNonce(), , ssoNonce()
ssoState(), , ssoState()
ssoClientID() , ssoClientID()
{ {
name[0] = 0; name[0] = 0;
memset(specialists, 0, sizeof(uint64_t) * ZT_MAX_NETWORK_SPECIALISTS); memset(specialists, 0, sizeof(uint64_t) * ZT_MAX_NETWORK_SPECIALISTS);
@ -318,12 +317,18 @@ public:
/** /**
* @return True if broadcast (ff:ff:ff:ff:ff:ff) address should work on this network * @return True if broadcast (ff:ff:ff:ff:ff:ff) address should work on this network
*/ */
inline bool enableBroadcast() const { return ((this->flags & ZT_NETWORKCONFIG_FLAG_ENABLE_BROADCAST) != 0); } inline bool enableBroadcast() const
{
return ((this->flags & ZT_NETWORKCONFIG_FLAG_ENABLE_BROADCAST) != 0);
}
/** /**
* @return True if IPv6 NDP emulation should be allowed for certain "magic" IPv6 address patterns * @return True if IPv6 NDP emulation should be allowed for certain "magic" IPv6 address patterns
*/ */
inline bool ndpEmulation() const { return ((this->flags & ZT_NETWORKCONFIG_FLAG_ENABLE_IPV6_NDP_EMULATION) != 0); } inline bool ndpEmulation() const
{
return ((this->flags & ZT_NETWORKCONFIG_FLAG_ENABLE_IPV6_NDP_EMULATION) != 0);
}
/** /**
* @return True if frames should not be compressed * @return True if frames should not be compressed
@ -344,12 +349,18 @@ public:
/** /**
* @return Network type is public (no access control) * @return Network type is public (no access control)
*/ */
inline bool isPublic() const { return (this->type == ZT_NETWORK_TYPE_PUBLIC); } inline bool isPublic() const
{
return (this->type == ZT_NETWORK_TYPE_PUBLIC);
}
/** /**
* @return Network type is private (certificate access control) * @return Network type is private (certificate access control)
*/ */
inline bool isPrivate() const { return (this->type == ZT_NETWORK_TYPE_PRIVATE); } inline bool isPrivate() const
{
return (this->type == ZT_NETWORK_TYPE_PRIVATE);
}
/** /**
* @return ZeroTier addresses of devices on this network designated as active bridges * @return ZeroTier addresses of devices on this network designated as active bridges
@ -474,9 +485,18 @@ public:
return false; return false;
} }
inline operator bool() const { return (networkId != 0); } inline operator bool() const
inline bool operator==(const NetworkConfig &nc) const { return (memcmp(this,&nc,sizeof(NetworkConfig)) == 0); } {
inline bool operator!=(const NetworkConfig &nc) const { return (!(*this == nc)); } return (networkId != 0);
}
inline bool operator==(const NetworkConfig& nc) const
{
return (memcmp(this, &nc, sizeof(NetworkConfig)) == 0);
}
inline bool operator!=(const NetworkConfig& nc) const
{
return (! (*this == nc));
}
/** /**
* Add a specialist or mask flags if already present * Add a specialist or mask flags if already present

View file

@ -14,13 +14,13 @@
#ifndef ZT_NETWORKCONFIGMASTER_HPP #ifndef ZT_NETWORKCONFIGMASTER_HPP
#define ZT_NETWORKCONFIGMASTER_HPP #define ZT_NETWORKCONFIGMASTER_HPP
#include <stdint.h> #include "Address.hpp"
#include "Constants.hpp" #include "Constants.hpp"
#include "Dictionary.hpp" #include "Dictionary.hpp"
#include "NetworkConfig.hpp" #include "NetworkConfig.hpp"
#include "Revocation.hpp" #include "Revocation.hpp"
#include "Address.hpp"
#include <stdint.h>
namespace ZeroTier { namespace ZeroTier {
@ -30,23 +30,14 @@ struct InetAddress;
/** /**
* Interface for network controller implementations * Interface for network controller implementations
*/ */
class NetworkController class NetworkController {
{
public: public:
enum ErrorCode enum ErrorCode { NC_ERROR_NONE = 0, NC_ERROR_OBJECT_NOT_FOUND = 1, NC_ERROR_ACCESS_DENIED = 2, NC_ERROR_INTERNAL_SERVER_ERROR = 3, NC_ERROR_AUTHENTICATION_REQUIRED = 4 };
{
NC_ERROR_NONE = 0,
NC_ERROR_OBJECT_NOT_FOUND = 1,
NC_ERROR_ACCESS_DENIED = 2,
NC_ERROR_INTERNAL_SERVER_ERROR = 3,
NC_ERROR_AUTHENTICATION_REQUIRED = 4
};
/** /**
* Interface for sender used to send pushes and replies * Interface for sender used to send pushes and replies
*/ */
class Sender class Sender {
{
public: public:
/** /**
* Send a configuration to a remote peer * Send a configuration to a remote peer
@ -83,8 +74,12 @@ public:
virtual void ncSendError(uint64_t nwid, uint64_t requestPacketId, const Address& destination, NetworkController::ErrorCode errorCode, const void* errorData, unsigned int errorDataSize) = 0; virtual void ncSendError(uint64_t nwid, uint64_t requestPacketId, const Address& destination, NetworkController::ErrorCode errorCode, const void* errorData, unsigned int errorDataSize) = 0;
}; };
NetworkController() {} NetworkController()
virtual ~NetworkController() {} {
}
virtual ~NetworkController()
{
}
/** /**
* Called when this is added to a Node to initialize and supply info * Called when this is added to a Node to initialize and supply info
@ -104,12 +99,7 @@ public:
* @param metaData Meta-data bundled with request (if any) * @param metaData Meta-data bundled with request (if any)
* @return Returns NETCONF_QUERY_OK if result 'nc' is valid, or an error code on error * @return Returns NETCONF_QUERY_OK if result 'nc' is valid, or an error code on error
*/ */
virtual void request( virtual void request(uint64_t nwid, const InetAddress& fromAddr, uint64_t requestPacketId, const Identity& identity, const Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY>& metaData) = 0;
uint64_t nwid,
const InetAddress &fromAddr,
uint64_t requestPacketId,
const Identity &identity,
const Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> &metaData) = 0;
}; };
} // namespace ZeroTier } // namespace ZeroTier

View file

@ -11,32 +11,32 @@
*/ */
/****/ /****/
#include <stdio.h> #include "Node.hpp"
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <stdint.h>
#include "../version.h" #include "../version.h"
#include "ECC.hpp"
#include "Constants.hpp"
#include "SharedPtr.hpp"
#include "Node.hpp"
#include "RuntimeEnvironment.hpp"
#include "NetworkController.hpp"
#include "Switch.hpp"
#include "Multicaster.hpp"
#include "Topology.hpp"
#include "Buffer.hpp"
#include "Packet.hpp"
#include "Address.hpp" #include "Address.hpp"
#include "Buffer.hpp"
#include "Constants.hpp"
#include "ECC.hpp"
#include "Identity.hpp" #include "Identity.hpp"
#include "SelfAwareness.hpp"
#include "Network.hpp"
#include "Trace.hpp"
#include "Metrics.hpp" #include "Metrics.hpp"
#include "Multicaster.hpp"
#include "Network.hpp"
#include "NetworkController.hpp"
#include "Packet.hpp"
#include "PacketMultiplexer.hpp" #include "PacketMultiplexer.hpp"
#include "RuntimeEnvironment.hpp"
#include "SelfAwareness.hpp"
#include "SharedPtr.hpp"
#include "Switch.hpp"
#include "Topology.hpp"
#include "Trace.hpp"
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// FIXME: remove this suppression and actually fix warnings // FIXME: remove this suppression and actually fix warnings
#ifdef __GNUC__ #ifdef __GNUC__
@ -49,17 +49,17 @@ namespace ZeroTier {
/* Public Node interface (C++, exposed via CAPI bindings) */ /* Public Node interface (C++, exposed via CAPI bindings) */
/****************************************************************************/ /****************************************************************************/
Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,int64_t now) : Node::Node(void* uptr, void* tptr, const struct ZT_Node_Callbacks* callbacks, int64_t now)
_RR(this), : _RR(this)
RR(&_RR), , RR(&_RR)
_uPtr(uptr), , _uPtr(uptr)
_networks(8), , _networks(8)
_now(now), , _now(now)
_lastPingCheck(0), , _lastPingCheck(0)
_lastGratuitousPingCheck(0), , _lastGratuitousPingCheck(0)
_lastHousekeepingRun(0), , _lastHousekeepingRun(0)
_lastMemoizedTraceSettings(0), , _lastMemoizedTraceSettings(0)
_lowBandwidthMode(false) , _lowBandwidthMode(false)
{ {
if (callbacks->version != 0) { if (callbacks->version != 0) {
throw ZT_EXCEPTION_INVALID_ARGUMENT; throw ZT_EXCEPTION_INVALID_ARGUMENT;
@ -86,7 +86,8 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,int64
if (RR->identity.fromString(tmp)) { if (RR->identity.fromString(tmp)) {
RR->identity.toString(false, RR->publicIdentityStr); RR->identity.toString(false, RR->publicIdentityStr);
RR->identity.toString(true, RR->secretIdentityStr); RR->identity.toString(true, RR->secretIdentityStr);
} else { }
else {
throw ZT_EXCEPTION_INVALID_IDENTITY; throw ZT_EXCEPTION_INVALID_IDENTITY;
} }
@ -103,7 +104,8 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,int64
idtmp[1] = 0; idtmp[1] = 0;
stateObjectPut(tptr, ZT_STATE_OBJECT_IDENTITY_SECRET, idtmp, RR->secretIdentityStr, (unsigned int)strlen(RR->secretIdentityStr)); stateObjectPut(tptr, ZT_STATE_OBJECT_IDENTITY_SECRET, idtmp, RR->secretIdentityStr, (unsigned int)strlen(RR->secretIdentityStr));
stateObjectPut(tptr, ZT_STATE_OBJECT_IDENTITY_PUBLIC, idtmp, RR->publicIdentityStr, (unsigned int)strlen(RR->publicIdentityStr)); stateObjectPut(tptr, ZT_STATE_OBJECT_IDENTITY_PUBLIC, idtmp, RR->publicIdentityStr, (unsigned int)strlen(RR->publicIdentityStr));
} else { }
else {
idtmp[0] = RR->identity.address().toInt(); idtmp[0] = RR->identity.address().toInt();
idtmp[1] = 0; idtmp[1] = 0;
n = stateObjectGet(tptr, ZT_STATE_OBJECT_IDENTITY_PUBLIC, idtmp, tmp, sizeof(tmp) - 1); n = stateObjectGet(tptr, ZT_STATE_OBJECT_IDENTITY_PUBLIC, idtmp, tmp, sizeof(tmp) - 1);
@ -146,7 +148,8 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,int64
RR->bc = new (m) Bond(RR); RR->bc = new (m) Bond(RR);
m += bcs; m += bcs;
RR->pm = new (m) PacketMultiplexer(RR); RR->pm = new (m) PacketMultiplexer(RR);
} catch ( ... ) { }
catch (...) {
if (RR->sa) { if (RR->sa) {
RR->sa->~SelfAwareness(); RR->sa->~SelfAwareness();
} }
@ -205,14 +208,7 @@ Node::~Node()
::free(RR->rtmem); ::free(RR->rtmem);
} }
ZT_ResultCode Node::processWirePacket( ZT_ResultCode Node::processWirePacket(void* tptr, int64_t now, int64_t localSocket, const struct sockaddr_storage* remoteAddress, const void* packetData, unsigned int packetLength, volatile int64_t* nextBackgroundTaskDeadline)
void *tptr,
int64_t now,
int64_t localSocket,
const struct sockaddr_storage *remoteAddress,
const void *packetData,
unsigned int packetLength,
volatile int64_t *nextBackgroundTaskDeadline)
{ {
_now = now; _now = now;
RR->sw->onRemotePacket(tptr, localSocket, *(reinterpret_cast<const InetAddress*>(remoteAddress)), packetData, packetLength); RR->sw->onRemotePacket(tptr, localSocket, *(reinterpret_cast<const InetAddress*>(remoteAddress)), packetData, packetLength);
@ -236,7 +232,8 @@ ZT_ResultCode Node::processVirtualNetworkFrame(
if (nw) { if (nw) {
RR->sw->onLocalEthernet(tptr, nw, MAC(sourceMac), MAC(destMac), etherType, vlanId, frameData, frameLength); RR->sw->onLocalEthernet(tptr, nw, MAC(sourceMac), MAC(destMac), etherType, vlanId, frameData, frameLength);
return ZT_RESULT_OK; return ZT_RESULT_OK;
} else { }
else {
return ZT_RESULT_ERROR_NETWORK_NOT_FOUND; return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
} }
} }
@ -247,15 +244,14 @@ void Node::initMultithreading(unsigned int concurrency, bool cpuPinningEnabled)
} }
// Closure used to ping upstream and active/online peers // Closure used to ping upstream and active/online peers
class _PingPeersThatNeedPing class _PingPeersThatNeedPing {
{
public: public:
_PingPeersThatNeedPing(const RuntimeEnvironment *renv,void *tPtr,Hashtable< Address,std::vector<InetAddress> > &alwaysContact,int64_t now) : _PingPeersThatNeedPing(const RuntimeEnvironment* renv, void* tPtr, Hashtable<Address, std::vector<InetAddress> >& alwaysContact, int64_t now)
RR(renv), : RR(renv)
_tPtr(tPtr), , _tPtr(tPtr)
_alwaysContact(alwaysContact), , _alwaysContact(alwaysContact)
_now(now), , _now(now)
_bestCurrentUpstream(RR->topology->getUpstreamPeer()) , _bestCurrentUpstream(RR->topology->getUpstreamPeer())
{ {
} }
@ -263,7 +259,6 @@ public:
{ {
const std::vector<InetAddress>* const alwaysContactEndpoints = _alwaysContact.get(p->address()); const std::vector<InetAddress>* const alwaysContactEndpoints = _alwaysContact.get(p->address());
if (alwaysContactEndpoints) { if (alwaysContactEndpoints) {
ZT_PeerRole role = RR->topology->role(p->address()); ZT_PeerRole role = RR->topology->role(p->address());
// Contact upstream peers as infrequently as possible // Contact upstream peers as infrequently as possible
@ -310,7 +305,8 @@ public:
} }
_alwaysContact.erase(p->address()); // after this we'll WHOIS all upstreams that remain _alwaysContact.erase(p->address()); // after this we'll WHOIS all upstreams that remain
} else if (p->isActive(_now)) { }
else if (p->isActive(_now)) {
p->doPingAndKeepalive(_tPtr, _now); p->doPingAndKeepalive(_tPtr, _now);
} }
} }
@ -430,10 +426,12 @@ ZT_ResultCode Node::processBackgroundTasks(void *tptr,int64_t now,volatile int64
if (oldOnline != _online) { if (oldOnline != _online) {
postEvent(tptr, _online ? ZT_EVENT_ONLINE : ZT_EVENT_OFFLINE); postEvent(tptr, _online ? ZT_EVENT_ONLINE : ZT_EVENT_OFFLINE);
} }
} catch ( ... ) { }
catch (...) {
return ZT_RESULT_FATAL_ERROR_INTERNAL; return ZT_RESULT_FATAL_ERROR_INTERNAL;
} }
} else { }
else {
timeUntilNextPingCheck -= (unsigned long)timeSinceLastPingCheck; timeUntilNextPingCheck -= (unsigned long)timeSinceLastPingCheck;
} }
@ -448,14 +446,16 @@ ZT_ResultCode Node::processBackgroundTasks(void *tptr,int64_t now,volatile int64
RR->topology->doPeriodicTasks(tptr, now); RR->topology->doPeriodicTasks(tptr, now);
RR->sa->clean(now); RR->sa->clean(now);
RR->mc->clean(now); RR->mc->clean(now);
} catch ( ... ) { }
catch (...) {
return ZT_RESULT_FATAL_ERROR_INTERNAL; return ZT_RESULT_FATAL_ERROR_INTERNAL;
} }
} }
try { try {
*nextBackgroundTaskDeadline = now + (int64_t)std::max(std::min(bondCheckInterval, std::min(timeUntilNextPingCheck, RR->sw->doTimerTasks(tptr, now))), (unsigned long)ZT_CORE_TIMER_TASK_GRANULARITY); *nextBackgroundTaskDeadline = now + (int64_t)std::max(std::min(bondCheckInterval, std::min(timeUntilNextPingCheck, RR->sw->doTimerTasks(tptr, now))), (unsigned long)ZT_CORE_TIMER_TASK_GRANULARITY);
} catch ( ... ) { }
catch (...) {
return ZT_RESULT_FATAL_ERROR_INTERNAL; return ZT_RESULT_FATAL_ERROR_INTERNAL;
} }
@ -514,7 +514,8 @@ ZT_ResultCode Node::multicastSubscribe(void *tptr,uint64_t nwid,uint64_t multica
if (nw) { if (nw) {
nw->multicastSubscribe(tptr, MulticastGroup(MAC(multicastGroup), (uint32_t)(multicastAdi & 0xffffffff))); nw->multicastSubscribe(tptr, MulticastGroup(MAC(multicastGroup), (uint32_t)(multicastAdi & 0xffffffff)));
return ZT_RESULT_OK; return ZT_RESULT_OK;
} else { }
else {
return ZT_RESULT_ERROR_NETWORK_NOT_FOUND; return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
} }
} }
@ -525,7 +526,8 @@ ZT_ResultCode Node::multicastUnsubscribe(uint64_t nwid,uint64_t multicastGroup,u
if (nw) { if (nw) {
nw->multicastUnsubscribe(MulticastGroup(MAC(multicastGroup), (uint32_t)(multicastAdi & 0xffffffff))); nw->multicastUnsubscribe(MulticastGroup(MAC(multicastGroup), (uint32_t)(multicastAdi & 0xffffffff)));
return ZT_RESULT_OK; return ZT_RESULT_OK;
} else { }
else {
return ZT_RESULT_ERROR_NETWORK_NOT_FOUND; return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
} }
} }
@ -576,7 +578,8 @@ ZT_PeerList *Node::peers() const
p->versionMajor = pi->second->remoteVersionMajor(); p->versionMajor = pi->second->remoteVersionMajor();
p->versionMinor = pi->second->remoteVersionMinor(); p->versionMinor = pi->second->remoteVersionMinor();
p->versionRev = pi->second->remoteVersionRevision(); p->versionRev = pi->second->remoteVersionRevision();
} else { }
else {
p->versionMajor = -1; p->versionMajor = -1;
p->versionMinor = -1; p->versionMinor = -1;
p->versionRev = -1; p->versionRev = -1;
@ -699,7 +702,9 @@ int Node::sendUserMessage(void *tptr,uint64_t dest,uint64_t typeId,const void *d
RR->sw->send(tptr, outp, true); RR->sw->send(tptr, outp, true);
return 1; return 1;
} }
} catch ( ... ) {} }
catch (...) {
}
return 0; return 0;
} }
@ -784,7 +789,8 @@ void Node::ncSendConfig(uint64_t nwid,uint64_t requestPacketId,const Address &de
return; return;
} }
n->setConfiguration((void*)0, nc, true); n->setConfiguration((void*)0, nc, true);
} else { }
else {
Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY>* dconf = new Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY>(); Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY>* dconf = new Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY>();
try { try {
if (nc.toDictionary(*dconf, sendLegacyFormatConfig)) { if (nc.toDictionary(*dconf, sendLegacyFormatConfig)) {
@ -824,7 +830,8 @@ void Node::ncSendConfig(uint64_t nwid,uint64_t requestPacketId,const Address &de
} }
} }
delete dconf; delete dconf;
} catch ( ... ) { }
catch (...) {
delete dconf; delete dconf;
throw; throw;
} }
@ -839,7 +846,8 @@ void Node::ncSendRevocation(const Address &destination,const Revocation &rev)
return; return;
} }
n->addCredential((void*)0, RR->identity.address(), rev); n->addCredential((void*)0, RR->identity.address(), rev);
} else { }
else {
Packet outp(destination, RR->identity.address(), Packet::VERB_NETWORK_CREDENTIALS); Packet outp(destination, RR->identity.address(), Packet::VERB_NETWORK_CREDENTIALS);
outp.append((uint8_t)0x00); outp.append((uint8_t)0x00);
outp.append((uint16_t)0); outp.append((uint16_t)0);
@ -874,7 +882,8 @@ void Node::ncSendError(uint64_t nwid,uint64_t requestPacketId,const Address &des
default: default:
break; break;
} }
} else if (requestPacketId) { }
else if (requestPacketId) {
Packet outp(destination, RR->identity.address(), Packet::VERB_ERROR); Packet outp(destination, RR->identity.address(), Packet::VERB_ERROR);
outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST); outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
outp.append(requestPacketId); outp.append(requestPacketId);
@ -920,11 +929,14 @@ enum ZT_ResultCode ZT_Node_new(ZT_Node **node,void *uptr,void *tptr,const struct
try { try {
*node = reinterpret_cast<ZT_Node*>(new ZeroTier::Node(uptr, tptr, callbacks, now)); *node = reinterpret_cast<ZT_Node*>(new ZeroTier::Node(uptr, tptr, callbacks, now));
return ZT_RESULT_OK; return ZT_RESULT_OK;
} catch (std::bad_alloc &exc) { }
catch (std::bad_alloc& exc) {
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
} catch (std::runtime_error &exc) { }
catch (std::runtime_error& exc) {
return ZT_RESULT_FATAL_ERROR_DATA_STORE_FAILED; return ZT_RESULT_FATAL_ERROR_DATA_STORE_FAILED;
} catch ( ... ) { }
catch (...) {
return ZT_RESULT_FATAL_ERROR_INTERNAL; return ZT_RESULT_FATAL_ERROR_INTERNAL;
} }
} }
@ -933,24 +945,21 @@ void ZT_Node_delete(ZT_Node *node)
{ {
try { try {
delete (reinterpret_cast<ZeroTier::Node*>(node)); delete (reinterpret_cast<ZeroTier::Node*>(node));
} catch ( ... ) {} }
catch (...) {
}
} }
enum ZT_ResultCode ZT_Node_processWirePacket( enum ZT_ResultCode
ZT_Node *node, ZT_Node_processWirePacket(ZT_Node* node, void* tptr, int64_t now, int64_t localSocket, const struct sockaddr_storage* remoteAddress, const void* packetData, unsigned int packetLength, volatile int64_t* nextBackgroundTaskDeadline)
void *tptr,
int64_t now,
int64_t localSocket,
const struct sockaddr_storage *remoteAddress,
const void *packetData,
unsigned int packetLength,
volatile int64_t *nextBackgroundTaskDeadline)
{ {
try { try {
return reinterpret_cast<ZeroTier::Node*>(node)->processWirePacket(tptr, now, localSocket, remoteAddress, packetData, packetLength, nextBackgroundTaskDeadline); return reinterpret_cast<ZeroTier::Node*>(node)->processWirePacket(tptr, now, localSocket, remoteAddress, packetData, packetLength, nextBackgroundTaskDeadline);
} catch (std::bad_alloc &exc) { }
catch (std::bad_alloc& exc) {
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
} catch ( ... ) { }
catch (...) {
return ZT_RESULT_OK; // "OK" since invalid packets are simply dropped, but the system is still up return ZT_RESULT_OK; // "OK" since invalid packets are simply dropped, but the system is still up
} }
} }
@ -970,9 +979,11 @@ enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame(
{ {
try { try {
return reinterpret_cast<ZeroTier::Node*>(node)->processVirtualNetworkFrame(tptr, now, nwid, sourceMac, destMac, etherType, vlanId, frameData, frameLength, nextBackgroundTaskDeadline); return reinterpret_cast<ZeroTier::Node*>(node)->processVirtualNetworkFrame(tptr, now, nwid, sourceMac, destMac, etherType, vlanId, frameData, frameLength, nextBackgroundTaskDeadline);
} catch (std::bad_alloc &exc) { }
catch (std::bad_alloc& exc) {
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
} catch ( ... ) { }
catch (...) {
return ZT_RESULT_FATAL_ERROR_INTERNAL; return ZT_RESULT_FATAL_ERROR_INTERNAL;
} }
} }
@ -981,9 +992,11 @@ enum ZT_ResultCode ZT_Node_processBackgroundTasks(ZT_Node *node,void *tptr,int64
{ {
try { try {
return reinterpret_cast<ZeroTier::Node*>(node)->processBackgroundTasks(tptr, now, nextBackgroundTaskDeadline); return reinterpret_cast<ZeroTier::Node*>(node)->processBackgroundTasks(tptr, now, nextBackgroundTaskDeadline);
} catch (std::bad_alloc &exc) { }
catch (std::bad_alloc& exc) {
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
} catch ( ... ) { }
catch (...) {
return ZT_RESULT_FATAL_ERROR_INTERNAL; return ZT_RESULT_FATAL_ERROR_INTERNAL;
} }
} }
@ -992,9 +1005,11 @@ enum ZT_ResultCode ZT_Node_join(ZT_Node *node,uint64_t nwid,void *uptr,void *tpt
{ {
try { try {
return reinterpret_cast<ZeroTier::Node*>(node)->join(nwid, uptr, tptr); return reinterpret_cast<ZeroTier::Node*>(node)->join(nwid, uptr, tptr);
} catch (std::bad_alloc &exc) { }
catch (std::bad_alloc& exc) {
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
} catch ( ... ) { }
catch (...) {
return ZT_RESULT_FATAL_ERROR_INTERNAL; return ZT_RESULT_FATAL_ERROR_INTERNAL;
} }
} }
@ -1003,9 +1018,11 @@ enum ZT_ResultCode ZT_Node_leave(ZT_Node *node,uint64_t nwid,void **uptr,void *t
{ {
try { try {
return reinterpret_cast<ZeroTier::Node*>(node)->leave(nwid, uptr, tptr); return reinterpret_cast<ZeroTier::Node*>(node)->leave(nwid, uptr, tptr);
} catch (std::bad_alloc &exc) { }
catch (std::bad_alloc& exc) {
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
} catch ( ... ) { }
catch (...) {
return ZT_RESULT_FATAL_ERROR_INTERNAL; return ZT_RESULT_FATAL_ERROR_INTERNAL;
} }
} }
@ -1014,9 +1031,11 @@ enum ZT_ResultCode ZT_Node_multicastSubscribe(ZT_Node *node,void *tptr,uint64_t
{ {
try { try {
return reinterpret_cast<ZeroTier::Node*>(node)->multicastSubscribe(tptr, nwid, multicastGroup, multicastAdi); return reinterpret_cast<ZeroTier::Node*>(node)->multicastSubscribe(tptr, nwid, multicastGroup, multicastAdi);
} catch (std::bad_alloc &exc) { }
catch (std::bad_alloc& exc) {
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
} catch ( ... ) { }
catch (...) {
return ZT_RESULT_FATAL_ERROR_INTERNAL; return ZT_RESULT_FATAL_ERROR_INTERNAL;
} }
} }
@ -1025,9 +1044,11 @@ enum ZT_ResultCode ZT_Node_multicastUnsubscribe(ZT_Node *node,uint64_t nwid,uint
{ {
try { try {
return reinterpret_cast<ZeroTier::Node*>(node)->multicastUnsubscribe(nwid, multicastGroup, multicastAdi); return reinterpret_cast<ZeroTier::Node*>(node)->multicastUnsubscribe(nwid, multicastGroup, multicastAdi);
} catch (std::bad_alloc &exc) { }
catch (std::bad_alloc& exc) {
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
} catch ( ... ) { }
catch (...) {
return ZT_RESULT_FATAL_ERROR_INTERNAL; return ZT_RESULT_FATAL_ERROR_INTERNAL;
} }
} }
@ -1036,7 +1057,8 @@ enum ZT_ResultCode ZT_Node_orbit(ZT_Node *node,void *tptr,uint64_t moonWorldId,u
{ {
try { try {
return reinterpret_cast<ZeroTier::Node*>(node)->orbit(tptr, moonWorldId, moonSeed); return reinterpret_cast<ZeroTier::Node*>(node)->orbit(tptr, moonWorldId, moonSeed);
} catch ( ... ) { }
catch (...) {
return ZT_RESULT_FATAL_ERROR_INTERNAL; return ZT_RESULT_FATAL_ERROR_INTERNAL;
} }
} }
@ -1045,7 +1067,8 @@ enum ZT_ResultCode ZT_Node_deorbit(ZT_Node *node,void *tptr,uint64_t moonWorldId
{ {
try { try {
return reinterpret_cast<ZeroTier::Node*>(node)->deorbit(tptr, moonWorldId); return reinterpret_cast<ZeroTier::Node*>(node)->deorbit(tptr, moonWorldId);
} catch ( ... ) { }
catch (...) {
return ZT_RESULT_FATAL_ERROR_INTERNAL; return ZT_RESULT_FATAL_ERROR_INTERNAL;
} }
} }
@ -1059,14 +1082,17 @@ void ZT_Node_status(ZT_Node *node,ZT_NodeStatus *status)
{ {
try { try {
reinterpret_cast<ZeroTier::Node*>(node)->status(status); reinterpret_cast<ZeroTier::Node*>(node)->status(status);
} catch ( ... ) {} }
catch (...) {
}
} }
ZT_PeerList* ZT_Node_peers(ZT_Node* node) ZT_PeerList* ZT_Node_peers(ZT_Node* node)
{ {
try { try {
return reinterpret_cast<ZeroTier::Node*>(node)->peers(); return reinterpret_cast<ZeroTier::Node*>(node)->peers();
} catch ( ... ) { }
catch (...) {
return (ZT_PeerList*)0; return (ZT_PeerList*)0;
} }
} }
@ -1075,7 +1101,8 @@ ZT_VirtualNetworkConfig *ZT_Node_networkConfig(ZT_Node *node,uint64_t nwid)
{ {
try { try {
return reinterpret_cast<ZeroTier::Node*>(node)->networkConfig(nwid); return reinterpret_cast<ZeroTier::Node*>(node)->networkConfig(nwid);
} catch ( ... ) { }
catch (...) {
return (ZT_VirtualNetworkConfig*)0; return (ZT_VirtualNetworkConfig*)0;
} }
} }
@ -1084,7 +1111,8 @@ ZT_VirtualNetworkList *ZT_Node_networks(ZT_Node *node)
{ {
try { try {
return reinterpret_cast<ZeroTier::Node*>(node)->networks(); return reinterpret_cast<ZeroTier::Node*>(node)->networks();
} catch ( ... ) { }
catch (...) {
return (ZT_VirtualNetworkList*)0; return (ZT_VirtualNetworkList*)0;
} }
} }
@ -1093,14 +1121,17 @@ void ZT_Node_freeQueryResult(ZT_Node *node,void *qr)
{ {
try { try {
reinterpret_cast<ZeroTier::Node*>(node)->freeQueryResult(qr); reinterpret_cast<ZeroTier::Node*>(node)->freeQueryResult(qr);
} catch ( ... ) {} }
catch (...) {
}
} }
int ZT_Node_addLocalInterfaceAddress(ZT_Node* node, const struct sockaddr_storage* addr) int ZT_Node_addLocalInterfaceAddress(ZT_Node* node, const struct sockaddr_storage* addr)
{ {
try { try {
return reinterpret_cast<ZeroTier::Node*>(node)->addLocalInterfaceAddress(addr); return reinterpret_cast<ZeroTier::Node*>(node)->addLocalInterfaceAddress(addr);
} catch ( ... ) { }
catch (...) {
return 0; return 0;
} }
} }
@ -1109,14 +1140,17 @@ void ZT_Node_clearLocalInterfaceAddresses(ZT_Node *node)
{ {
try { try {
reinterpret_cast<ZeroTier::Node*>(node)->clearLocalInterfaceAddresses(); reinterpret_cast<ZeroTier::Node*>(node)->clearLocalInterfaceAddresses();
} catch ( ... ) {} }
catch (...) {
}
} }
int ZT_Node_sendUserMessage(ZT_Node* node, void* tptr, uint64_t dest, uint64_t typeId, const void* data, unsigned int len) int ZT_Node_sendUserMessage(ZT_Node* node, void* tptr, uint64_t dest, uint64_t typeId, const void* data, unsigned int len)
{ {
try { try {
return reinterpret_cast<ZeroTier::Node*>(node)->sendUserMessage(tptr, dest, typeId, data, len); return reinterpret_cast<ZeroTier::Node*>(node)->sendUserMessage(tptr, dest, typeId, data, len);
} catch ( ... ) { }
catch (...) {
return 0; return 0;
} }
} }
@ -1125,14 +1159,17 @@ void ZT_Node_setNetconfMaster(ZT_Node *node,void *networkControllerInstance)
{ {
try { try {
reinterpret_cast<ZeroTier::Node*>(node)->setNetconfMaster(networkControllerInstance); reinterpret_cast<ZeroTier::Node*>(node)->setNetconfMaster(networkControllerInstance);
} catch ( ... ) {} }
catch (...) {
}
} }
enum ZT_ResultCode ZT_Node_setPhysicalPathConfiguration(ZT_Node* node, const struct sockaddr_storage* pathNetwork, const ZT_PhysicalPathConfiguration* pathConfig) enum ZT_ResultCode ZT_Node_setPhysicalPathConfiguration(ZT_Node* node, const struct sockaddr_storage* pathNetwork, const ZT_PhysicalPathConfiguration* pathConfig)
{ {
try { try {
return reinterpret_cast<ZeroTier::Node*>(node)->setPhysicalPathConfiguration(pathNetwork, pathConfig); return reinterpret_cast<ZeroTier::Node*>(node)->setPhysicalPathConfiguration(pathNetwork, pathConfig);
} catch ( ... ) { }
catch (...) {
return ZT_RESULT_FATAL_ERROR_INTERNAL; return ZT_RESULT_FATAL_ERROR_INTERNAL;
} }
} }

View file

@ -14,29 +14,26 @@
#ifndef ZT_NODE_HPP #ifndef ZT_NODE_HPP
#define ZT_NODE_HPP #define ZT_NODE_HPP
#include "../include/ZeroTierOne.h"
#include "Bond.hpp"
#include "Constants.hpp"
#include "Hashtable.hpp"
#include "InetAddress.hpp"
#include "MAC.hpp"
#include "Mutex.hpp"
#include "Network.hpp"
#include "NetworkController.hpp"
#include "Path.hpp"
#include "RuntimeEnvironment.hpp"
#include "Salsa20.hpp"
#include "SelfAwareness.hpp"
#include <map>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <map>
#include <vector> #include <vector>
#include "Constants.hpp"
#include "../include/ZeroTierOne.h"
#include "RuntimeEnvironment.hpp"
#include "InetAddress.hpp"
#include "Mutex.hpp"
#include "MAC.hpp"
#include "Network.hpp"
#include "Path.hpp"
#include "Salsa20.hpp"
#include "NetworkController.hpp"
#include "Hashtable.hpp"
#include "Bond.hpp"
#include "SelfAwareness.hpp"
// Bit mask for "expecting reply" hash // Bit mask for "expecting reply" hash
#define ZT_EXPECTING_REPLIES_BUCKET_MASK1 255 #define ZT_EXPECTING_REPLIES_BUCKET_MASK1 255
#define ZT_EXPECTING_REPLIES_BUCKET_MASK2 31 #define ZT_EXPECTING_REPLIES_BUCKET_MASK2 31
@ -50,28 +47,26 @@ class World;
* *
* The pointer returned by ZT_Node_new() is an instance of this class. * The pointer returned by ZT_Node_new() is an instance of this class.
*/ */
class Node : public NetworkController::Sender class Node : public NetworkController::Sender {
{
public: public:
Node(void* uptr, void* tptr, const struct ZT_Node_Callbacks* callbacks, int64_t now); Node(void* uptr, void* tptr, const struct ZT_Node_Callbacks* callbacks, int64_t now);
virtual ~Node(); virtual ~Node();
// Get rid of alignment warnings on 32-bit Windows and possibly improve performance // Get rid of alignment warnings on 32-bit Windows and possibly improve performance
#ifdef __WINDOWS__ #ifdef __WINDOWS__
void * operator new(size_t i) { return _mm_malloc(i,16); } void* operator new(size_t i)
void operator delete(void* p) { _mm_free(p); } {
return _mm_malloc(i, 16);
}
void operator delete(void* p)
{
_mm_free(p);
}
#endif #endif
// Public API Functions ---------------------------------------------------- // Public API Functions ----------------------------------------------------
ZT_ResultCode processWirePacket( ZT_ResultCode processWirePacket(void* tptr, int64_t now, int64_t localSocket, const struct sockaddr_storage* remoteAddress, const void* packetData, unsigned int packetLength, volatile int64_t* nextBackgroundTaskDeadline);
void *tptr,
int64_t now,
int64_t localSocket,
const struct sockaddr_storage *remoteAddress,
const void *packetData,
unsigned int packetLength,
volatile int64_t *nextBackgroundTaskDeadline);
ZT_ResultCode processVirtualNetworkFrame( ZT_ResultCode processVirtualNetworkFrame(
void* tptr, void* tptr,
int64_t now, int64_t now,
@ -103,35 +98,19 @@ public:
// Internal functions ------------------------------------------------------ // Internal functions ------------------------------------------------------
inline int64_t now() const { return _now; } inline int64_t now() const
{
return _now;
}
inline bool putPacket(void* tPtr, const int64_t localSocket, const InetAddress& addr, const void* data, unsigned int len, unsigned int ttl = 0) inline bool putPacket(void* tPtr, const int64_t localSocket, const InetAddress& addr, const void* data, unsigned int len, unsigned int ttl = 0)
{ {
return (_cb.wirePacketSendFunction( return (_cb.wirePacketSendFunction(reinterpret_cast<ZT_Node*>(this), _uPtr, tPtr, localSocket, reinterpret_cast<const struct sockaddr_storage*>(&addr), data, len, ttl) == 0);
reinterpret_cast<ZT_Node *>(this),
_uPtr,
tPtr,
localSocket,
reinterpret_cast<const struct sockaddr_storage *>(&addr),
data,
len,
ttl) == 0);
} }
inline void putFrame(void* tPtr, uint64_t nwid, void** nuptr, const MAC& source, const MAC& dest, unsigned int etherType, unsigned int vlanId, const void* data, unsigned int len) inline void putFrame(void* tPtr, uint64_t nwid, void** nuptr, const MAC& source, const MAC& dest, unsigned int etherType, unsigned int vlanId, const void* data, unsigned int len)
{ {
_cb.virtualNetworkFrameFunction( _cb.virtualNetworkFrameFunction(reinterpret_cast<ZT_Node*>(this), _uPtr, tPtr, nwid, nuptr, source.toInt(), dest.toInt(), etherType, vlanId, data, len);
reinterpret_cast<ZT_Node *>(this),
_uPtr,
tPtr,
nwid,
nuptr,
source.toInt(),
dest.toInt(),
etherType,
vlanId,
data,
len);
} }
inline SharedPtr<Network> network(uint64_t nwid) const inline SharedPtr<Network> network(uint64_t nwid) const
@ -169,18 +148,39 @@ public:
return _directPaths; return _directPaths;
} }
inline void postEvent(void *tPtr,ZT_Event ev,const void *md = (const void *)0) { _cb.eventCallback(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,ev,md); } inline void postEvent(void* tPtr, ZT_Event ev, const void* md = (const void*)0)
{
_cb.eventCallback(reinterpret_cast<ZT_Node*>(this), _uPtr, tPtr, ev, md);
}
inline int configureVirtualNetworkPort(void *tPtr,uint64_t nwid,void **nuptr,ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nc) { return _cb.virtualNetworkConfigFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,nwid,nuptr,op,nc); } inline int configureVirtualNetworkPort(void* tPtr, uint64_t nwid, void** nuptr, ZT_VirtualNetworkConfigOperation op, const ZT_VirtualNetworkConfig* nc)
{
return _cb.virtualNetworkConfigFunction(reinterpret_cast<ZT_Node*>(this), _uPtr, tPtr, nwid, nuptr, op, nc);
}
inline bool online() const { return _online; } inline bool online() const
{
return _online;
}
inline int stateObjectGet(void *const tPtr,ZT_StateObjectType type,const uint64_t id[2],void *const data,const unsigned int maxlen) { return _cb.stateGetFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,type,id,data,maxlen); } inline int stateObjectGet(void* const tPtr, ZT_StateObjectType type, const uint64_t id[2], void* const data, const unsigned int maxlen)
inline void stateObjectPut(void *const tPtr,ZT_StateObjectType type,const uint64_t id[2],const void *const data,const unsigned int len) { _cb.statePutFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,type,id,data,(int)len); } {
inline void stateObjectDelete(void *const tPtr,ZT_StateObjectType type,const uint64_t id[2]) { _cb.statePutFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,type,id,(const void *)0,-1); } return _cb.stateGetFunction(reinterpret_cast<ZT_Node*>(this), _uPtr, tPtr, type, id, data, maxlen);
}
inline void stateObjectPut(void* const tPtr, ZT_StateObjectType type, const uint64_t id[2], const void* const data, const unsigned int len)
{
_cb.statePutFunction(reinterpret_cast<ZT_Node*>(this), _uPtr, tPtr, type, id, data, (int)len);
}
inline void stateObjectDelete(void* const tPtr, ZT_StateObjectType type, const uint64_t id[2])
{
_cb.statePutFunction(reinterpret_cast<ZT_Node*>(this), _uPtr, tPtr, type, id, (const void*)0, -1);
}
bool shouldUsePathForZeroTierTraffic(void* tPtr, const Address& ztaddr, const int64_t localSocket, const InetAddress& remoteAddress); bool shouldUsePathForZeroTierTraffic(void* tPtr, const Address& ztaddr, const int64_t localSocket, const InetAddress& remoteAddress);
inline bool externalPathLookup(void *tPtr,const Address &ztaddr,int family,InetAddress &addr) { return ( (_cb.pathLookupFunction) ? (_cb.pathLookupFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,ztaddr.toInt(),family,reinterpret_cast<struct sockaddr_storage *>(&addr)) != 0) : false ); } inline bool externalPathLookup(void* tPtr, const Address& ztaddr, int family, InetAddress& addr)
{
return ((_cb.pathLookupFunction) ? (_cb.pathLookupFunction(reinterpret_cast<ZT_Node*>(this), _uPtr, tPtr, ztaddr.toInt(), family, reinterpret_cast<struct sockaddr_storage*>(&addr)) != 0) : false);
}
uint64_t prng(); uint64_t prng();
ZT_ResultCode setPhysicalPathConfiguration(const struct sockaddr_storage* pathNetwork, const ZT_PhysicalPathConfiguration* pathConfig); ZT_ResultCode setPhysicalPathConfiguration(const struct sockaddr_storage* pathNetwork, const ZT_PhysicalPathConfiguration* pathConfig);
@ -188,11 +188,20 @@ public:
World planet() const; World planet() const;
std::vector<World> moons() const; std::vector<World> moons() const;
inline const Identity &identity() const { return _RR.identity; } inline const Identity& identity() const
{
return _RR.identity;
}
inline const std::vector<InetAddress> SurfaceAddresses() const { return _RR.sa->whoami(); } inline const std::vector<InetAddress> SurfaceAddresses() const
{
return _RR.sa->whoami();
}
inline Bond *bondController() const { return _RR.bc; } inline Bond* bondController() const
{
return _RR.bc;
}
/** /**
* Register that we are expecting a reply to a packet ID * Register that we are expecting a reply to a packet ID
@ -253,8 +262,14 @@ public:
virtual void ncSendRevocation(const Address& destination, const Revocation& rev); virtual void ncSendRevocation(const Address& destination, const Revocation& rev);
virtual void ncSendError(uint64_t nwid, uint64_t requestPacketId, const Address& destination, NetworkController::ErrorCode errorCode, const void* errorData, unsigned int errorDataSize); virtual void ncSendError(uint64_t nwid, uint64_t requestPacketId, const Address& destination, NetworkController::ErrorCode errorCode, const void* errorData, unsigned int errorDataSize);
inline const Address &remoteTraceTarget() const { return _remoteTraceTarget; } inline const Address& remoteTraceTarget() const
inline Trace::Level remoteTraceLevel() const { return _remoteTraceLevel; } {
return _remoteTraceTarget;
}
inline Trace::Level remoteTraceLevel() const
{
return _remoteTraceLevel;
}
inline bool localControllerHasAuthorized(const int64_t now, const uint64_t nwid, const Address& addr) const inline bool localControllerHasAuthorized(const int64_t now, const uint64_t nwid, const Address& addr) const
{ {
@ -285,7 +300,6 @@ public:
void initMultithreading(unsigned int concurrency, bool cpuPinningEnabled); void initMultithreading(unsigned int concurrency, bool cpuPinningEnabled);
public: public:
RuntimeEnvironment _RR; RuntimeEnvironment _RR;
RuntimeEnvironment* RR; RuntimeEnvironment* RR;
@ -304,13 +318,23 @@ public:
// Map that remembers if we have recently sent a network config to someone // Map that remembers if we have recently sent a network config to someone
// querying us as a controller. // querying us as a controller.
struct _LocalControllerAuth struct _LocalControllerAuth {
{
uint64_t nwid, address; uint64_t nwid, address;
_LocalControllerAuth(const uint64_t nwid_,const Address &address_) : nwid(nwid_),address(address_.toInt()) {} _LocalControllerAuth(const uint64_t nwid_, const Address& address_) : nwid(nwid_), address(address_.toInt())
inline unsigned long hashCode() const { return (unsigned long)(nwid ^ address); } {
inline bool operator==(const _LocalControllerAuth &a) const { return ((a.nwid == nwid)&&(a.address == address)); } }
inline bool operator!=(const _LocalControllerAuth &a) const { return ((a.nwid != nwid)||(a.address != address)); } inline unsigned long hashCode() const
{
return (unsigned long)(nwid ^ address);
}
inline bool operator==(const _LocalControllerAuth& a) const
{
return ((a.nwid == nwid) && (a.address == address));
}
inline bool operator!=(const _LocalControllerAuth& a) const
{
return ((a.nwid != nwid) || (a.address != address));
}
}; };
Hashtable<_LocalControllerAuth, int64_t> _localControllerAuthorizations; Hashtable<_LocalControllerAuth, int64_t> _localControllerAuthorizations;
Mutex _localControllerAuthorizations_m; Mutex _localControllerAuthorizations_m;

View file

@ -11,13 +11,14 @@
*/ */
/****/ /****/
#include "Constants.hpp"
#include "RuntimeEnvironment.hpp"
#include "OutboundMulticast.hpp" #include "OutboundMulticast.hpp"
#include "Switch.hpp"
#include "Constants.hpp"
#include "Network.hpp" #include "Network.hpp"
#include "Node.hpp" #include "Node.hpp"
#include "Peer.hpp" #include "Peer.hpp"
#include "RuntimeEnvironment.hpp"
#include "Switch.hpp"
#include "Topology.hpp" #include "Topology.hpp"
namespace ZeroTier { namespace ZeroTier {
@ -42,7 +43,8 @@ void OutboundMulticast::init(
if (src) { if (src) {
_macSrc = src; _macSrc = src;
flags |= 0x04; flags |= 0x04;
} else { }
else {
_macSrc.fromAddress(RR->identity.address(), nwid); _macSrc.fromAddress(RR->identity.address(), nwid);
} }
_macDest = dest.mac(); _macDest = dest.mac();

View file

@ -14,17 +14,16 @@
#ifndef ZT_OUTBOUNDMULTICAST_HPP #ifndef ZT_OUTBOUNDMULTICAST_HPP
#define ZT_OUTBOUNDMULTICAST_HPP #define ZT_OUTBOUNDMULTICAST_HPP
#include <stdint.h> #include "Address.hpp"
#include <vector>
#include <algorithm>
#include "Constants.hpp" #include "Constants.hpp"
#include "MAC.hpp" #include "MAC.hpp"
#include "MulticastGroup.hpp" #include "MulticastGroup.hpp"
#include "Address.hpp"
#include "Packet.hpp" #include "Packet.hpp"
#include <algorithm>
#include <stdint.h>
#include <vector>
namespace ZeroTier { namespace ZeroTier {
class CertificateOfMembership; class CertificateOfMembership;
@ -35,15 +34,16 @@ class RuntimeEnvironment;
* *
* This object isn't guarded by a mutex; caller must synchronize access. * This object isn't guarded by a mutex; caller must synchronize access.
*/ */
class OutboundMulticast class OutboundMulticast {
{
public: public:
/** /**
* Create an uninitialized outbound multicast * Create an uninitialized outbound multicast
* *
* It must be initialized with init(). * It must be initialized with init().
*/ */
OutboundMulticast() {} OutboundMulticast()
{
}
/** /**
* Initialize outbound multicast * Initialize outbound multicast
@ -77,18 +77,27 @@ public:
/** /**
* @return Multicast creation time * @return Multicast creation time
*/ */
inline uint64_t timestamp() const { return _timestamp; } inline uint64_t timestamp() const
{
return _timestamp;
}
/** /**
* @param now Current time * @param now Current time
* @return True if this multicast is expired (has exceeded transmit timeout) * @return True if this multicast is expired (has exceeded transmit timeout)
*/ */
inline bool expired(int64_t now) const { return ((now - _timestamp) >= ZT_MULTICAST_TRANSMIT_TIMEOUT); } inline bool expired(int64_t now) const
{
return ((now - _timestamp) >= ZT_MULTICAST_TRANSMIT_TIMEOUT);
}
/** /**
* @return True if this outbound multicast has been sent to enough peers * @return True if this outbound multicast has been sent to enough peers
*/ */
inline bool atLimit() const { return (_alreadySentTo.size() >= _limit); } inline bool atLimit() const
{
return (_alreadySentTo.size() >= _limit);
}
/** /**
* Just send without checking log * Just send without checking log
@ -135,7 +144,8 @@ public:
if (std::find(_alreadySentTo.begin(), _alreadySentTo.end(), toAddr) == _alreadySentTo.end()) { if (std::find(_alreadySentTo.begin(), _alreadySentTo.end(), toAddr) == _alreadySentTo.end()) {
sendAndLog(RR, tPtr, toAddr); sendAndLog(RR, tPtr, toAddr);
return true; return true;
} else { }
else {
return false; return false;
} }
} }

View file

@ -11,15 +11,16 @@
*/ */
/****/ /****/
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "Packet.hpp" #include "Packet.hpp"
#include "ECC.hpp" #include "ECC.hpp"
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(ZT_USE_X64_ASM_SALSA2012) && defined(ZT_ARCH_X64) #if defined(ZT_USE_X64_ASM_SALSA2012) && defined(ZT_ARCH_X64)
#include "../ext/x64-salsa2012-asm/salsa2012.h" #include "../ext/x64-salsa2012-asm/salsa2012.h"
#endif #endif
@ -50,10 +51,11 @@ namespace ZeroTier {
// ARM (32-bit) NEON crypto (must be detected) // ARM (32-bit) NEON crypto (must be detected)
#ifdef ZT_USE_ARM32_NEON_ASM_SALSA2012 #ifdef ZT_USE_ARM32_NEON_ASM_SALSA2012
class _FastCryptoChecker class _FastCryptoChecker {
{
public: public:
_FastCryptoChecker() : canHas(zt_arm_has_neon()) {} _FastCryptoChecker() : canHas(zt_arm_has_neon())
{
}
bool canHas; bool canHas;
}; };
static const _FastCryptoChecker _ZT_FAST_CRYPTO_CHECK; static const _FastCryptoChecker _ZT_FAST_CRYPTO_CHECK;
@ -64,7 +66,9 @@ static const _FastCryptoChecker _ZT_FAST_CRYPTO_CHECK;
// No fast crypto available // No fast crypto available
#ifndef ZT_HAS_FAST_CRYPTO #ifndef ZT_HAS_FAST_CRYPTO
#define ZT_HAS_FAST_CRYPTO() (false) #define ZT_HAS_FAST_CRYPTO() (false)
#define ZT_FAST_SINGLE_PASS_SALSA2012(b,l,n,k) {} #define ZT_FAST_SINGLE_PASS_SALSA2012(b, l, n, k) \
{ \
}
#endif #endif
/************************************************************************** */ /************************************************************************** */
@ -225,35 +229,78 @@ typedef uintptr_t reg_t;
static inline unsigned LZ4_isLittleEndian(void) static inline unsigned LZ4_isLittleEndian(void)
{ {
const union { U32 u; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */ const union {
U32 u;
BYTE c[4];
} one = { 1 }; /* don't use static : performance detrimental */
return one.c[0]; return one.c[0];
} }
#if defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_FORCE_MEMORY_ACCESS == 2) #if defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_FORCE_MEMORY_ACCESS == 2)
static U16 LZ4_read16(const void* memPtr) { return *(const U16*) memPtr; } static U16 LZ4_read16(const void* memPtr)
static U32 LZ4_read32(const void* memPtr) { return *(const U32*) memPtr; } {
static reg_t LZ4_read_ARCH(const void* memPtr) { return *(const reg_t*) memPtr; } return *(const U16*)memPtr;
static void LZ4_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; } }
static void LZ4_write32(void* memPtr, U32 value) { *(U32*)memPtr = value; } static U32 LZ4_read32(const void* memPtr)
{
return *(const U32*)memPtr;
}
static reg_t LZ4_read_ARCH(const void* memPtr)
{
return *(const reg_t*)memPtr;
}
static void LZ4_write16(void* memPtr, U16 value)
{
*(U16*)memPtr = value;
}
static void LZ4_write32(void* memPtr, U32 value)
{
*(U32*)memPtr = value;
}
#elif defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_FORCE_MEMORY_ACCESS == 1) #elif defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_FORCE_MEMORY_ACCESS == 1)
typedef union { U16 u16; U32 u32; reg_t uArch; } __attribute__((packed)) unalign; typedef union {
static U16 LZ4_read16(const void* ptr) { return ((const unalign*)ptr)->u16; } U16 u16;
static U32 LZ4_read32(const void* ptr) { return ((const unalign*)ptr)->u32; } U32 u32;
static reg_t LZ4_read_ARCH(const void* ptr) { return ((const unalign*)ptr)->uArch; } reg_t uArch;
static void LZ4_write16(void* memPtr, U16 value) { ((unalign*)memPtr)->u16 = value; } } __attribute__((packed)) unalign;
static void LZ4_write32(void* memPtr, U32 value) { ((unalign*)memPtr)->u32 = value; } static U16 LZ4_read16(const void* ptr)
{
return ((const unalign*)ptr)->u16;
}
static U32 LZ4_read32(const void* ptr)
{
return ((const unalign*)ptr)->u32;
}
static reg_t LZ4_read_ARCH(const void* ptr)
{
return ((const unalign*)ptr)->uArch;
}
static void LZ4_write16(void* memPtr, U16 value)
{
((unalign*)memPtr)->u16 = value;
}
static void LZ4_write32(void* memPtr, U32 value)
{
((unalign*)memPtr)->u32 = value;
}
#else /* safe and portable access through memcpy() */ #else /* safe and portable access through memcpy() */
static inline U16 LZ4_read16(const void* memPtr) static inline U16 LZ4_read16(const void* memPtr)
{ {
U16 val; memcpy(&val, memPtr, sizeof(val)); return val; U16 val;
memcpy(&val, memPtr, sizeof(val));
return val;
} }
static inline U32 LZ4_read32(const void* memPtr) static inline U32 LZ4_read32(const void* memPtr)
{ {
U32 val; memcpy(&val, memPtr, sizeof(val)); return val; U32 val;
memcpy(&val, memPtr, sizeof(val));
return val;
} }
static inline reg_t LZ4_read_ARCH(const void* memPtr) static inline reg_t LZ4_read_ARCH(const void* memPtr)
{ {
reg_t val; memcpy(&val, memPtr, sizeof(val)); return val; reg_t val;
memcpy(&val, memPtr, sizeof(val));
return val;
} }
static inline void LZ4_write16(void* memPtr, U16 value) static inline void LZ4_write16(void* memPtr, U16 value)
{ {
@ -269,7 +316,8 @@ static inline U16 LZ4_readLE16(const void* memPtr)
{ {
if (LZ4_isLittleEndian()) { if (LZ4_isLittleEndian()) {
return LZ4_read16(memPtr); return LZ4_read16(memPtr);
} else { }
else {
const BYTE* p = (const BYTE*)memPtr; const BYTE* p = (const BYTE*)memPtr;
return (U16)((U16)p[0] + (p[1] << 8)); return (U16)((U16)p[0] + (p[1] << 8));
} }
@ -279,7 +327,8 @@ static inline void LZ4_writeLE16(void* memPtr, U16 value)
{ {
if (LZ4_isLittleEndian()) { if (LZ4_isLittleEndian()) {
LZ4_write16(memPtr, value); LZ4_write16(memPtr, value);
} else { }
else {
BYTE* p = (BYTE*)memPtr; BYTE* p = (BYTE*)memPtr;
p[0] = (BYTE)value; p[0] = (BYTE)value;
p[1] = (BYTE)(value >> 8); p[1] = (BYTE)(value >> 8);
@ -322,7 +371,10 @@ static const int LZ4_minLength = (MFLIMIT+1);
#define RUN_BITS (8 - ML_BITS) #define RUN_BITS (8 - ML_BITS)
#define RUN_MASK ((1U << RUN_BITS) - 1) #define RUN_MASK ((1U << RUN_BITS) - 1)
#define LZ4_STATIC_ASSERT(c) { enum { LZ4_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */ #define LZ4_STATIC_ASSERT(c) \
{ \
enum { LZ4_static_assert = 1 / (int)(! ! (c)) }; \
} /* use only *after* variable declarations */
static inline unsigned LZ4_NbCommonBytes(reg_t val) static inline unsigned LZ4_NbCommonBytes(reg_t val)
{ {
@ -335,10 +387,12 @@ static inline unsigned LZ4_NbCommonBytes (reg_t val)
#elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 3))) && ! defined(LZ4_FORCE_SW_BITCOUNT) #elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 3))) && ! defined(LZ4_FORCE_SW_BITCOUNT)
return (__builtin_ctzll((U64)val) >> 3); return (__builtin_ctzll((U64)val) >> 3);
#else #else
static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 }; static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7,
7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 };
return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58]; return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58];
#endif #endif
} else /* 32 bits */ { }
else /* 32 bits */ {
#if defined(_MSC_VER) && ! defined(LZ4_FORCE_SW_BITCOUNT) #if defined(_MSC_VER) && ! defined(LZ4_FORCE_SW_BITCOUNT)
unsigned long r; unsigned long r;
_BitScanForward(&r, (U32)val); _BitScanForward(&r, (U32)val);
@ -350,7 +404,8 @@ static inline unsigned LZ4_NbCommonBytes (reg_t val)
return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27]; return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27];
#endif #endif
} }
} else /* Big Endian CPU */ { }
else /* Big Endian CPU */ {
if (sizeof(val) == 8) { if (sizeof(val) == 8) {
#if defined(_MSC_VER) && defined(_WIN64) && ! defined(LZ4_FORCE_SW_BITCOUNT) #if defined(_MSC_VER) && defined(_WIN64) && ! defined(LZ4_FORCE_SW_BITCOUNT)
unsigned long r = 0; unsigned long r = 0;
@ -362,20 +417,23 @@ static inline unsigned LZ4_NbCommonBytes (reg_t val)
unsigned r; unsigned r;
if (! (val >> 32)) { if (! (val >> 32)) {
r = 4; r = 4;
} else { }
else {
r = 0; r = 0;
val >>= 32; val >>= 32;
} }
if (! (val >> 16)) { if (! (val >> 16)) {
r += 2; r += 2;
val >>= 8; val >>= 8;
} else { }
else {
val >>= 24; val >>= 24;
} }
r += (! val); r += (! val);
return r; return r;
#endif #endif
} else /* 32 bits */ { }
else /* 32 bits */ {
#if defined(_MSC_VER) && ! defined(LZ4_FORCE_SW_BITCOUNT) #if defined(_MSC_VER) && ! defined(LZ4_FORCE_SW_BITCOUNT)
unsigned long r = 0; unsigned long r = 0;
_BitScanReverse(&r, (unsigned long)val); _BitScanReverse(&r, (unsigned long)val);
@ -387,7 +445,8 @@ static inline unsigned LZ4_NbCommonBytes (reg_t val)
if (! (val >> 16)) { if (! (val >> 16)) {
r = 2; r = 2;
val >>= 8; val >>= 8;
} else { }
else {
r = 0; r = 0;
val >>= 24; val >>= 24;
} }
@ -407,17 +466,20 @@ static inline unsigned LZ4_count(const BYTE* pIn, const BYTE* pMatch, const BYTE
reg_t const diff = LZ4_read_ARCH(pMatch) ^ LZ4_read_ARCH(pIn); reg_t const diff = LZ4_read_ARCH(pMatch) ^ LZ4_read_ARCH(pIn);
if (! diff) { if (! diff) {
pIn += STEPSIZE; pIn += STEPSIZE;
pMatch+=STEPSIZE; continue; pMatch += STEPSIZE;
continue;
} }
pIn += LZ4_NbCommonBytes(diff); pIn += LZ4_NbCommonBytes(diff);
return (unsigned)(pIn - pStart); return (unsigned)(pIn - pStart);
} }
if ((STEPSIZE == 8) && (pIn < (pInLimit - 3)) && (LZ4_read32(pMatch) == LZ4_read32(pIn))) { if ((STEPSIZE == 8) && (pIn < (pInLimit - 3)) && (LZ4_read32(pMatch) == LZ4_read32(pIn))) {
pIn+=4; pMatch+=4; pIn += 4;
pMatch += 4;
} }
if ((pIn < (pInLimit - 1)) && (LZ4_read16(pMatch) == LZ4_read16(pIn))) { if ((pIn < (pInLimit - 1)) && (LZ4_read16(pMatch) == LZ4_read16(pIn))) {
pIn+=2; pMatch+=2; pIn += 2;
pMatch += 2;
} }
if ((pIn < pInLimit) && (*pMatch == *pIn)) { if ((pIn < pInLimit) && (*pMatch == *pIn)) {
pIn++; pIn++;
@ -437,13 +499,17 @@ typedef enum { noDictIssue = 0, dictSmall } dictIssue_directive;
typedef enum { endOnOutputSize = 0, endOnInputSize = 1 } endCondition_directive; typedef enum { endOnOutputSize = 0, endOnInputSize = 1 } endCondition_directive;
typedef enum { full = 0, partial = 1 } earlyEnd_directive; typedef enum { full = 0, partial = 1 } earlyEnd_directive;
static inline int LZ4_compressBound(int isize) { return LZ4_COMPRESSBOUND(isize); } static inline int LZ4_compressBound(int isize)
{
return LZ4_COMPRESSBOUND(isize);
}
static inline U32 LZ4_hash4(U32 sequence, tableType_t const tableType) static inline U32 LZ4_hash4(U32 sequence, tableType_t const tableType)
{ {
if (tableType == byU16) { if (tableType == byU16) {
return ((sequence * 2654435761U) >> ((MINMATCH * 8) - (LZ4_HASHLOG + 1))); return ((sequence * 2654435761U) >> ((MINMATCH * 8) - (LZ4_HASHLOG + 1)));
} else { }
else {
return ((sequence * 2654435761U) >> ((MINMATCH * 8) - LZ4_HASHLOG)); return ((sequence * 2654435761U) >> ((MINMATCH * 8) - LZ4_HASHLOG));
} }
} }
@ -455,7 +521,8 @@ static inline U32 LZ4_hash5(U64 sequence, tableType_t const tableType)
const U32 hashLog = (tableType == byU16) ? LZ4_HASHLOG + 1 : LZ4_HASHLOG; const U32 hashLog = (tableType == byU16) ? LZ4_HASHLOG + 1 : LZ4_HASHLOG;
if (LZ4_isLittleEndian()) { if (LZ4_isLittleEndian()) {
return (U32)(((sequence << 24) * prime5bytes) >> (64 - hashLog)); return (U32)(((sequence << 24) * prime5bytes) >> (64 - hashLog));
} else { }
else {
return (U32)(((sequence >> 24) * prime8bytes) >> (64 - hashLog)); return (U32)(((sequence >> 24) * prime8bytes) >> (64 - hashLog));
} }
} }
@ -472,15 +539,18 @@ static inline void LZ4_putPositionOnHash(const BYTE* p, U32 h, void* tableBase,
{ {
switch (tableType) { switch (tableType) {
case byPtr: { case byPtr: {
const BYTE** hashTable = (const BYTE**)tableBase; hashTable[h] = p; const BYTE** hashTable = (const BYTE**)tableBase;
hashTable[h] = p;
return; return;
} }
case byU32: { case byU32: {
U32* hashTable = (U32*) tableBase; hashTable[h] = (U32)(p-srcBase); U32* hashTable = (U32*)tableBase;
hashTable[h] = (U32)(p - srcBase);
return; return;
} }
case byU16: { case byU16: {
U16* hashTable = (U16*) tableBase; hashTable[h] = (U16)(p-srcBase); U16* hashTable = (U16*)tableBase;
hashTable[h] = (U16)(p - srcBase);
return; return;
} }
} }
@ -600,7 +670,8 @@ FORCE_INLINE int LZ4_compress_generic(
if (match < (const BYTE*)source) { if (match < (const BYTE*)source) {
refDelta = dictDelta; refDelta = dictDelta;
lowLimit = dictionary; lowLimit = dictionary;
} else { }
else {
refDelta = 0; refDelta = 0;
lowLimit = (const BYTE*)source; lowLimit = (const BYTE*)source;
} }
@ -608,9 +679,7 @@ FORCE_INLINE int LZ4_compress_generic(
forwardH = LZ4_hashPosition(forwardIp, tableType); forwardH = LZ4_hashPosition(forwardIp, tableType);
LZ4_putPositionOnHash(ip, h, cctx->hashTable, tableType, base); LZ4_putPositionOnHash(ip, h, cctx->hashTable, tableType, base);
} while ( ((dictIssue==dictSmall) ? (match < lowRefLimit) : 0) } while (((dictIssue == dictSmall) ? (match < lowRefLimit) : 0) || ((tableType == byU16) ? 0 : (match + MAX_DISTANCE < ip)) || (LZ4_read32(match + refDelta) != LZ4_read32(ip)));
|| ((tableType==byU16) ? 0 : (match + MAX_DISTANCE < ip))
|| (LZ4_read32(match+refDelta) != LZ4_read32(ip)) );
} }
/* Catch up */ /* Catch up */
@ -634,7 +703,8 @@ FORCE_INLINE int LZ4_compress_generic(
*op++ = 255; *op++ = 255;
} }
*op++ = (BYTE)len; *op++ = (BYTE)len;
} else { }
else {
*token = (BYTE)(litLength << ML_BITS); *token = (BYTE)(litLength << ML_BITS);
} }
@ -666,7 +736,8 @@ _next_match:
matchCode += more; matchCode += more;
ip += more; ip += more;
} }
} else { }
else {
matchCode = LZ4_count(ip + MINMATCH, match + MINMATCH, matchlimit); matchCode = LZ4_count(ip + MINMATCH, match + MINMATCH, matchlimit);
ip += MINMATCH + matchCode; ip += MINMATCH + matchCode;
} }
@ -686,7 +757,8 @@ _next_match:
} }
op += matchCode / 255; op += matchCode / 255;
*op++ = (BYTE)(matchCode % 255); *op++ = (BYTE)(matchCode % 255);
} else { }
else {
*token += (BYTE)(matchCode); *token += (BYTE)(matchCode);
} }
} }
@ -707,15 +779,14 @@ _next_match:
if (match < (const BYTE*)source) { if (match < (const BYTE*)source) {
refDelta = dictDelta; refDelta = dictDelta;
lowLimit = dictionary; lowLimit = dictionary;
} else { }
else {
refDelta = 0; refDelta = 0;
lowLimit = (const BYTE*)source; lowLimit = (const BYTE*)source;
} }
} }
LZ4_putPosition(ip, cctx->hashTable, tableType, base); LZ4_putPosition(ip, cctx->hashTable, tableType, base);
if ( ((dictIssue==dictSmall) ? (match>=lowRefLimit) : 1) if (((dictIssue == dictSmall) ? (match >= lowRefLimit) : 1) && (match + MAX_DISTANCE >= ip) && (LZ4_read32(match + refDelta) == LZ4_read32(ip))) {
&& (match+MAX_DISTANCE>=ip)
&& (LZ4_read32(match+refDelta)==LZ4_read32(ip)) ) {
token = op++; token = op++;
*token = 0; *token = 0;
goto _next_match; goto _next_match;
@ -740,7 +811,8 @@ _last_literals:
*op++ = 255; *op++ = 255;
} }
*op++ = (BYTE)accumulator; *op++ = (BYTE)accumulator;
} else { }
else {
*op++ = (BYTE)(lastRun << ML_BITS); *op++ = (BYTE)(lastRun << ML_BITS);
} }
memcpy(op, anchor, lastRun); memcpy(op, anchor, lastRun);
@ -760,13 +832,16 @@ static inline int LZ4_compress_fast_extState(void* state, const char* source, ch
if (maxOutputSize >= LZ4_compressBound(inputSize)) { if (maxOutputSize >= LZ4_compressBound(inputSize)) {
if (inputSize < LZ4_64Klimit) { if (inputSize < LZ4_64Klimit) {
return LZ4_compress_generic(ctx, source, dest, inputSize, 0, notLimited, byU16, noDict, noDictIssue, acceleration); return LZ4_compress_generic(ctx, source, dest, inputSize, 0, notLimited, byU16, noDict, noDictIssue, acceleration);
} else { }
else {
return LZ4_compress_generic(ctx, source, dest, inputSize, 0, notLimited, (sizeof(void*) == 8) ? byU32 : byPtr, noDict, noDictIssue, acceleration); return LZ4_compress_generic(ctx, source, dest, inputSize, 0, notLimited, (sizeof(void*) == 8) ? byU32 : byPtr, noDict, noDictIssue, acceleration);
} }
} else { }
else {
if (inputSize < LZ4_64Klimit) { if (inputSize < LZ4_64Klimit) {
return LZ4_compress_generic(ctx, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration); return LZ4_compress_generic(ctx, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration);
} else { }
else {
return LZ4_compress_generic(ctx, source, dest, inputSize, maxOutputSize, limitedOutput, (sizeof(void*) == 8) ? byU32 : byPtr, noDict, noDictIssue, acceleration); return LZ4_compress_generic(ctx, source, dest, inputSize, maxOutputSize, limitedOutput, (sizeof(void*) == 8) ? byU32 : byPtr, noDict, noDictIssue, acceleration);
} }
} }
@ -826,7 +901,6 @@ FORCE_INLINE int LZ4_decompress_generic(
const int safeDecode = (endOnInput == endOnInputSize); const int safeDecode = (endOnInput == endOnInputSize);
const int checkOffset = ((safeDecode) && (dictSize < (int)(64 KB))); const int checkOffset = ((safeDecode) && (dictSize < (int)(64 KB)));
/* Special cases */ /* Special cases */
if ((partialDecoding) && (oexit > oend - MFLIMIT)) { if ((partialDecoding) && (oexit > oend - MFLIMIT)) {
oexit = oend - MFLIMIT; /* targetOutputSize too high => decode everything */ oexit = oend - MFLIMIT; /* targetOutputSize too high => decode everything */
@ -862,8 +936,7 @@ FORCE_INLINE int LZ4_decompress_generic(
/* copy literals */ /* copy literals */
cpy = op + length; cpy = op + length;
if ( ((endOnInput) && ((cpy>(partialDecoding?oexit:oend-MFLIMIT)) || (ip+length>iend-(2+1+LASTLITERALS))) ) if (((endOnInput) && ((cpy > (partialDecoding ? oexit : oend - MFLIMIT)) || (ip + length > iend - (2 + 1 + LASTLITERALS)))) || ((! endOnInput) && (cpy > oend - WILDCOPYLENGTH))) {
|| ((!endOnInput) && (cpy>oend-WILDCOPYLENGTH)) ) {
if (partialDecoding) { if (partialDecoding) {
if (cpy > oend) { if (cpy > oend) {
goto _output_error; /* Error : write attempt beyond end of output buffer */ goto _output_error; /* Error : write attempt beyond end of output buffer */
@ -871,7 +944,8 @@ FORCE_INLINE int LZ4_decompress_generic(
if ((endOnInput) && (ip + length > iend)) { if ((endOnInput) && (ip + length > iend)) {
goto _output_error; /* Error : read attempt beyond end of input buffer */ goto _output_error; /* Error : read attempt beyond end of input buffer */
} }
} else { }
else {
if ((! endOnInput) && (cpy != oend)) { if ((! endOnInput) && (cpy != oend)) {
goto _output_error; /* Error : block decoding must stop exactly there */ goto _output_error; /* Error : block decoding must stop exactly there */
} }
@ -924,7 +998,8 @@ FORCE_INLINE int LZ4_decompress_generic(
/* match can be copied as a single segment from external dictionary */ /* match can be copied as a single segment from external dictionary */
memmove(op, dictEnd - (lowPrefix - match), length); memmove(op, dictEnd - (lowPrefix - match), length);
op += length; op += length;
} else { }
else {
/* match encompass external dictionary and current block */ /* match encompass external dictionary and current block */
size_t const copySize = (size_t)(lowPrefix - match); size_t const copySize = (size_t)(lowPrefix - match);
size_t const restSize = length - copySize; size_t const restSize = length - copySize;
@ -936,7 +1011,8 @@ FORCE_INLINE int LZ4_decompress_generic(
while (op < endOfMatch) { while (op < endOfMatch) {
*op++ = *copyFrom++; *op++ = *copyFrom++;
} }
} else { }
else {
memcpy(op, lowPrefix, restSize); memcpy(op, lowPrefix, restSize);
op += restSize; op += restSize;
} }
@ -955,7 +1031,8 @@ FORCE_INLINE int LZ4_decompress_generic(
match += dec32table[offset]; match += dec32table[offset];
memcpy(op + 4, match, 4); memcpy(op + 4, match, 4);
match -= dec64; match -= dec64;
} else { }
else {
LZ4_copy8(op, match); LZ4_copy8(op, match);
match += 8; match += 8;
} }
@ -974,7 +1051,8 @@ FORCE_INLINE int LZ4_decompress_generic(
while (op < cpy) { while (op < cpy) {
*op++ = *match++; *op++ = *match++;
} }
} else { }
else {
LZ4_copy8(op, match); LZ4_copy8(op, match);
if (length > 16) { if (length > 16) {
LZ4_wildCopy(op + 8, match + 8, cpy); LZ4_wildCopy(op + 8, match + 8, cpy);
@ -986,7 +1064,8 @@ FORCE_INLINE int LZ4_decompress_generic(
/* end of decoding */ /* end of decoding */
if (endOnInput) { if (endOnInput) {
return (int)(((char*)op) - dest); /* Nb of output bytes decoded */ return (int)(((char*)op) - dest); /* Nb of output bytes decoded */
} else { }
else {
return (int)(((const char*)ip) - source); /* Nb of input bytes read */ return (int)(((const char*)ip) - source); /* Nb of input bytes read */
} }
/* Overflow error detected */ /* Overflow error detected */
@ -1033,7 +1112,8 @@ void Packet::armor(const void *key,bool encryptPayload,bool extendedArmor,const
*reinterpret_cast<uint64_t*>(data + ZT_PACKET_IDX_IV) = tag[0]; *reinterpret_cast<uint64_t*>(data + ZT_PACKET_IDX_IV) = tag[0];
*reinterpret_cast<uint64_t*>(data + ZT_PACKET_IDX_MAC) = tag[1]; *reinterpret_cast<uint64_t*>(data + ZT_PACKET_IDX_MAC) = tag[1];
#endif #endif
} else { }
else {
setCipher(encryptPayload ? ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012 : ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_NONE); setCipher(encryptPayload ? ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012 : ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_NONE);
uint8_t mangledKey[32]; uint8_t mangledKey[32];
@ -1053,7 +1133,8 @@ void Packet::armor(const void *key,bool encryptPayload,bool extendedArmor,const
#else #else
(*reinterpret_cast<uint64_t*>(data + ZT_PACKET_IDX_MAC)) = mac[0]; (*reinterpret_cast<uint64_t*>(data + ZT_PACKET_IDX_MAC)) = mac[0];
#endif #endif
} else { }
else {
uint64_t macKey[4]; uint64_t macKey[4];
uint64_t mac[2]; uint64_t mac[2];
@ -1136,7 +1217,8 @@ bool Packet::dearmor(const void *key,const AES aesKeys[2],const Identity &identi
dec.update(payload, payloadLen); dec.update(payload, payloadLen);
return dec.finish(); return dec.finish();
} }
} else if ((cs == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_NONE)||(cs == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012)) { }
else if ((cs == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_NONE) || (cs == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012)) {
uint8_t mangledKey[32]; uint8_t mangledKey[32];
_salsa20MangleKey((const unsigned char*)key, mangledKey); _salsa20MangleKey((const unsigned char*)key, mangledKey);
if (ZT_HAS_FAST_CRYPTO()) { if (ZT_HAS_FAST_CRYPTO()) {
@ -1156,7 +1238,8 @@ bool Packet::dearmor(const void *key,const AES aesKeys[2],const Identity &identi
if (cs == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012) { if (cs == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012) {
Salsa20::memxor(data + ZT_PACKET_IDX_VERB, reinterpret_cast<const uint8_t*>(keyStream + 8), payloadLen); Salsa20::memxor(data + ZT_PACKET_IDX_VERB, reinterpret_cast<const uint8_t*>(keyStream + 8), payloadLen);
} }
} else { }
else {
Salsa20 s20(mangledKey, data + ZT_PACKET_IDX_IV); Salsa20 s20(mangledKey, data + ZT_PACKET_IDX_IV);
uint64_t macKey[4]; uint64_t macKey[4];
s20.crypt12(ZERO_KEY, macKey, sizeof(macKey)); s20.crypt12(ZERO_KEY, macKey, sizeof(macKey));
@ -1225,7 +1308,8 @@ bool Packet::uncompress()
if ((ucl > 0) && (ucl <= (int)(capacity() - ZT_PACKET_IDX_PAYLOAD))) { if ((ucl > 0) && (ucl <= (int)(capacity() - ZT_PACKET_IDX_PAYLOAD))) {
setSize((unsigned int)ucl + ZT_PACKET_IDX_PAYLOAD); setSize((unsigned int)ucl + ZT_PACKET_IDX_PAYLOAD);
memcpy(data + ZT_PACKET_IDX_PAYLOAD, buf, ucl); memcpy(data + ZT_PACKET_IDX_PAYLOAD, buf, ucl);
} else { }
else {
return false; return false;
} }
} }

View file

@ -14,22 +14,20 @@
#ifndef ZT_N_PACKET_HPP #ifndef ZT_N_PACKET_HPP
#define ZT_N_PACKET_HPP #define ZT_N_PACKET_HPP
#include <stdint.h> #include "AES.hpp"
#include <string.h>
#include <stdio.h>
#include <string>
#include <iostream>
#include "Constants.hpp"
#include "Address.hpp" #include "Address.hpp"
#include "Buffer.hpp"
#include "Constants.hpp"
#include "Identity.hpp"
#include "Poly1305.hpp" #include "Poly1305.hpp"
#include "Salsa20.hpp" #include "Salsa20.hpp"
#include "AES.hpp"
#include "Utils.hpp" #include "Utils.hpp"
#include "Buffer.hpp"
#include "Identity.hpp" #include <iostream>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <string>
/** /**
* Protocol version -- incremented only for major changes * Protocol version -- incremented only for major changes
@ -345,8 +343,7 @@ namespace ZeroTier {
* For unencrypted packets, MAC is computed on plaintext. Only HELLO is ever * For unencrypted packets, MAC is computed on plaintext. Only HELLO is ever
* sent in the clear, as it's the "here is my public key" message. * sent in the clear, as it's the "here is my public key" message.
*/ */
class Packet : public Buffer<ZT_PROTO_MAX_PACKET_LENGTH> class Packet : public Buffer<ZT_PROTO_MAX_PACKET_LENGTH> {
{
public: public:
/** /**
* A packet fragment * A packet fragment
@ -374,22 +371,17 @@ public:
* receipt to authenticate and decrypt; there is no per-fragment MAC. (But if * receipt to authenticate and decrypt; there is no per-fragment MAC. (But if
* fragments are corrupt, the MAC will fail for the whole assembled packet.) * fragments are corrupt, the MAC will fail for the whole assembled packet.)
*/ */
class Fragment : public Buffer<ZT_PROTO_MAX_PACKET_LENGTH> class Fragment : public Buffer<ZT_PROTO_MAX_PACKET_LENGTH> {
{
public: public:
Fragment() : Fragment() : Buffer<ZT_PROTO_MAX_PACKET_LENGTH>()
Buffer<ZT_PROTO_MAX_PACKET_LENGTH>()
{ {
} }
template<unsigned int C2> template <unsigned int C2> Fragment(const Buffer<C2>& b) : Buffer<ZT_PROTO_MAX_PACKET_LENGTH>(b)
Fragment(const Buffer<C2> &b) :
Buffer<ZT_PROTO_MAX_PACKET_LENGTH>(b)
{ {
} }
Fragment(const void *data,unsigned int len) : Fragment(const void* data, unsigned int len) : Buffer<ZT_PROTO_MAX_PACKET_LENGTH>(data, len)
Buffer<ZT_PROTO_MAX_PACKET_LENGTH>(data,len)
{ {
} }
@ -438,32 +430,50 @@ public:
* *
* @return Destination ZT address * @return Destination ZT address
*/ */
inline Address destination() const { return Address(field(ZT_PACKET_FRAGMENT_IDX_DEST,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); } inline Address destination() const
{
return Address(field(ZT_PACKET_FRAGMENT_IDX_DEST, ZT_ADDRESS_LENGTH), ZT_ADDRESS_LENGTH);
}
/** /**
* @return True if fragment is of a valid length * @return True if fragment is of a valid length
*/ */
inline bool lengthValid() const { return (size() >= ZT_PACKET_FRAGMENT_IDX_PAYLOAD); } inline bool lengthValid() const
{
return (size() >= ZT_PACKET_FRAGMENT_IDX_PAYLOAD);
}
/** /**
* @return ID of packet this is a fragment of * @return ID of packet this is a fragment of
*/ */
inline uint64_t packetId() const { return at<uint64_t>(ZT_PACKET_FRAGMENT_IDX_PACKET_ID); } inline uint64_t packetId() const
{
return at<uint64_t>(ZT_PACKET_FRAGMENT_IDX_PACKET_ID);
}
/** /**
* @return Total number of fragments in packet * @return Total number of fragments in packet
*/ */
inline unsigned int totalFragments() const { return (((unsigned int)((*this)[ZT_PACKET_FRAGMENT_IDX_FRAGMENT_NO]) >> 4) & 0xf); } inline unsigned int totalFragments() const
{
return (((unsigned int)((*this)[ZT_PACKET_FRAGMENT_IDX_FRAGMENT_NO]) >> 4) & 0xf);
}
/** /**
* @return Fragment number of this fragment * @return Fragment number of this fragment
*/ */
inline unsigned int fragmentNumber() const { return ((unsigned int)((*this)[ZT_PACKET_FRAGMENT_IDX_FRAGMENT_NO]) & 0xf); } inline unsigned int fragmentNumber() const
{
return ((unsigned int)((*this)[ZT_PACKET_FRAGMENT_IDX_FRAGMENT_NO]) & 0xf);
}
/** /**
* @return Fragment ZT hop count * @return Fragment ZT hop count
*/ */
inline unsigned int hops() const { return (unsigned int)((*this)[ZT_PACKET_FRAGMENT_IDX_HOPS]); } inline unsigned int hops() const
{
return (unsigned int)((*this)[ZT_PACKET_FRAGMENT_IDX_HOPS]);
}
/** /**
* Increment this packet's hop count * Increment this packet's hop count
@ -476,7 +486,10 @@ public:
/** /**
* @return Length of payload in bytes * @return Length of payload in bytes
*/ */
inline unsigned int payloadLength() const { return ((size() > ZT_PACKET_FRAGMENT_IDX_PAYLOAD) ? (size() - ZT_PACKET_FRAGMENT_IDX_PAYLOAD) : 0); } inline unsigned int payloadLength() const
{
return ((size() > ZT_PACKET_FRAGMENT_IDX_PAYLOAD) ? (size() - ZT_PACKET_FRAGMENT_IDX_PAYLOAD) : 0);
}
/** /**
* @return Raw packet payload * @return Raw packet payload
@ -1013,8 +1026,7 @@ public:
/** /**
* Error codes for VERB_ERROR * Error codes for VERB_ERROR
*/ */
enum ErrorCode enum ErrorCode {
{
/* No error, not actually used in transit */ /* No error, not actually used in transit */
ERROR_NONE = 0x00, ERROR_NONE = 0x00,
@ -1046,14 +1058,11 @@ public:
ERROR_NETWORK_AUTHENTICATION_REQUIRED = 0x09 ERROR_NETWORK_AUTHENTICATION_REQUIRED = 0x09
}; };
template<unsigned int C2> template <unsigned int C2> Packet(const Buffer<C2>& b) : Buffer<ZT_PROTO_MAX_PACKET_LENGTH>(b)
Packet(const Buffer<C2> &b) :
Buffer<ZT_PROTO_MAX_PACKET_LENGTH>(b)
{ {
} }
Packet(const void *data,unsigned int len) : Packet(const void* data, unsigned int len) : Buffer<ZT_PROTO_MAX_PACKET_LENGTH>(data, len)
Buffer<ZT_PROTO_MAX_PACKET_LENGTH>(data,len)
{ {
} }
@ -1064,8 +1073,7 @@ public:
* Use the header access methods (setDestination() and friends) to fill out * Use the header access methods (setDestination() and friends) to fill out
* the header. Payload should be appended; initial size is header size. * the header. Payload should be appended; initial size is header size.
*/ */
Packet() : Packet() : Buffer<ZT_PROTO_MAX_PACKET_LENGTH>(ZT_PROTO_MIN_PACKET_LENGTH)
Buffer<ZT_PROTO_MAX_PACKET_LENGTH>(ZT_PROTO_MIN_PACKET_LENGTH)
{ {
Utils::getSecureRandom(field(ZT_PACKET_IDX_IV, 8), 8); Utils::getSecureRandom(field(ZT_PACKET_IDX_IV, 8), 8);
(*this)[ZT_PACKET_IDX_FLAGS] = 0; // zero flags, cipher ID, and hops (*this)[ZT_PACKET_IDX_FLAGS] = 0; // zero flags, cipher ID, and hops
@ -1080,8 +1088,7 @@ public:
* @param prototype Prototype packet * @param prototype Prototype packet
* @param dest Destination ZeroTier address for new packet * @param dest Destination ZeroTier address for new packet
*/ */
Packet(const Packet &prototype,const Address &dest) : Packet(const Packet& prototype, const Address& dest) : Buffer<ZT_PROTO_MAX_PACKET_LENGTH>(prototype)
Buffer<ZT_PROTO_MAX_PACKET_LENGTH>(prototype)
{ {
Utils::getSecureRandom(field(ZT_PACKET_IDX_IV, 8), 8); Utils::getSecureRandom(field(ZT_PACKET_IDX_IV, 8), 8);
setDestination(dest); setDestination(dest);
@ -1094,8 +1101,7 @@ public:
* @param source Source ZT address * @param source Source ZT address
* @param v Verb * @param v Verb
*/ */
Packet(const Address &dest,const Address &source,const Verb v) : Packet(const Address& dest, const Address& source, const Verb v) : Buffer<ZT_PROTO_MAX_PACKET_LENGTH>(ZT_PROTO_MIN_PACKET_LENGTH)
Buffer<ZT_PROTO_MAX_PACKET_LENGTH>(ZT_PROTO_MIN_PACKET_LENGTH)
{ {
Utils::getSecureRandom(field(ZT_PACKET_IDX_IV, 8), 8); Utils::getSecureRandom(field(ZT_PACKET_IDX_IV, 8), 8);
setDestination(dest); setDestination(dest);
@ -1128,45 +1134,66 @@ public:
* technically different but otherwise identical copies of the same * technically different but otherwise identical copies of the same
* packet. * packet.
*/ */
inline void newInitializationVector() { Utils::getSecureRandom(field(ZT_PACKET_IDX_IV,8),8); } inline void newInitializationVector()
{
Utils::getSecureRandom(field(ZT_PACKET_IDX_IV, 8), 8);
}
/** /**
* Set this packet's destination * Set this packet's destination
* *
* @param dest ZeroTier address of destination * @param dest ZeroTier address of destination
*/ */
inline void setDestination(const Address &dest) { dest.copyTo(field(ZT_PACKET_IDX_DEST,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); } inline void setDestination(const Address& dest)
{
dest.copyTo(field(ZT_PACKET_IDX_DEST, ZT_ADDRESS_LENGTH), ZT_ADDRESS_LENGTH);
}
/** /**
* Set this packet's source * Set this packet's source
* *
* @param source ZeroTier address of source * @param source ZeroTier address of source
*/ */
inline void setSource(const Address &source) { source.copyTo(field(ZT_PACKET_IDX_SOURCE,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); } inline void setSource(const Address& source)
{
source.copyTo(field(ZT_PACKET_IDX_SOURCE, ZT_ADDRESS_LENGTH), ZT_ADDRESS_LENGTH);
}
/** /**
* Get this packet's destination * Get this packet's destination
* *
* @return Destination ZT address * @return Destination ZT address
*/ */
inline Address destination() const { return Address(field(ZT_PACKET_IDX_DEST,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); } inline Address destination() const
{
return Address(field(ZT_PACKET_IDX_DEST, ZT_ADDRESS_LENGTH), ZT_ADDRESS_LENGTH);
}
/** /**
* Get this packet's source * Get this packet's source
* *
* @return Source ZT address * @return Source ZT address
*/ */
inline Address source() const { return Address(field(ZT_PACKET_IDX_SOURCE,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); } inline Address source() const
{
return Address(field(ZT_PACKET_IDX_SOURCE, ZT_ADDRESS_LENGTH), ZT_ADDRESS_LENGTH);
}
/** /**
* @return True if packet is of valid length * @return True if packet is of valid length
*/ */
inline bool lengthValid() const { return (size() >= ZT_PROTO_MIN_PACKET_LENGTH); } inline bool lengthValid() const
{
return (size() >= ZT_PROTO_MIN_PACKET_LENGTH);
}
/** /**
* @return True if packet is fragmented (expect fragments) * @return True if packet is fragmented (expect fragments)
*/ */
inline bool fragmented() const { return (((unsigned char)(*this)[ZT_PACKET_IDX_FLAGS] & ZT_PROTO_FLAG_FRAGMENTED) != 0); } inline bool fragmented() const
{
return (((unsigned char)(*this)[ZT_PACKET_IDX_FLAGS] & ZT_PROTO_FLAG_FRAGMENTED) != 0);
}
/** /**
* Set this packet's fragmented flag * Set this packet's fragmented flag
@ -1177,7 +1204,8 @@ public:
{ {
if (f) { if (f) {
(*this)[ZT_PACKET_IDX_FLAGS] |= (char)ZT_PROTO_FLAG_FRAGMENTED; (*this)[ZT_PACKET_IDX_FLAGS] |= (char)ZT_PROTO_FLAG_FRAGMENTED;
} else { }
else {
(*this)[ZT_PACKET_IDX_FLAGS] &= (char)(~ZT_PROTO_FLAG_FRAGMENTED); (*this)[ZT_PACKET_IDX_FLAGS] &= (char)(~ZT_PROTO_FLAG_FRAGMENTED);
} }
} }
@ -1185,7 +1213,10 @@ public:
/** /**
* @return True if packet is encrypted with an extra ephemeral key * @return True if packet is encrypted with an extra ephemeral key
*/ */
inline bool extendedArmor() const { return (((unsigned char)(*this)[ZT_PACKET_IDX_FLAGS] & ZT_PROTO_FLAG_EXTENDED_ARMOR) != 0); } inline bool extendedArmor() const
{
return (((unsigned char)(*this)[ZT_PACKET_IDX_FLAGS] & ZT_PROTO_FLAG_EXTENDED_ARMOR) != 0);
}
/** /**
* Set this packet's extended armor flag * Set this packet's extended armor flag
@ -1196,7 +1227,8 @@ public:
{ {
if (f) { if (f) {
(*this)[ZT_PACKET_IDX_FLAGS] |= (char)ZT_PROTO_FLAG_EXTENDED_ARMOR; (*this)[ZT_PACKET_IDX_FLAGS] |= (char)ZT_PROTO_FLAG_EXTENDED_ARMOR;
} else { }
else {
(*this)[ZT_PACKET_IDX_FLAGS] &= (char)(~ZT_PROTO_FLAG_EXTENDED_ARMOR); (*this)[ZT_PACKET_IDX_FLAGS] &= (char)(~ZT_PROTO_FLAG_EXTENDED_ARMOR);
} }
} }
@ -1204,12 +1236,18 @@ public:
/** /**
* @return True if compressed (result only valid if unencrypted) * @return True if compressed (result only valid if unencrypted)
*/ */
inline bool compressed() const { return (((unsigned char)(*this)[ZT_PACKET_IDX_VERB] & ZT_PROTO_VERB_FLAG_COMPRESSED) != 0); } inline bool compressed() const
{
return (((unsigned char)(*this)[ZT_PACKET_IDX_VERB] & ZT_PROTO_VERB_FLAG_COMPRESSED) != 0);
}
/** /**
* @return ZeroTier forwarding hops (0 to 7) * @return ZeroTier forwarding hops (0 to 7)
*/ */
inline unsigned int hops() const { return ((unsigned int)(*this)[ZT_PACKET_IDX_FLAGS] & 0x07); } inline unsigned int hops() const
{
return ((unsigned int)(*this)[ZT_PACKET_IDX_FLAGS] & 0x07);
}
/** /**
* Increment this packet's hop count * Increment this packet's hop count
@ -1250,7 +1288,10 @@ public:
* *
* @return Trusted path ID (from MAC field) * @return Trusted path ID (from MAC field)
*/ */
inline uint64_t trustedPathId() const { return at<uint64_t>(ZT_PACKET_IDX_MAC); } inline uint64_t trustedPathId() const
{
return at<uint64_t>(ZT_PACKET_IDX_MAC);
}
/** /**
* Set this packet's trusted path ID and set the cipher spec to trusted path * Set this packet's trusted path ID and set the cipher spec to trusted path
@ -1274,7 +1315,10 @@ public:
* *
* @return Packet ID * @return Packet ID
*/ */
inline uint64_t packetId() const { return at<uint64_t>(ZT_PACKET_IDX_IV); } inline uint64_t packetId() const
{
return at<uint64_t>(ZT_PACKET_IDX_IV);
}
/** /**
* Set packet verb * Set packet verb
@ -1284,22 +1328,34 @@ public:
* *
* @param v New packet verb * @param v New packet verb
*/ */
inline void setVerb(Verb v) { (*this)[ZT_PACKET_IDX_VERB] = (char)v; } inline void setVerb(Verb v)
{
(*this)[ZT_PACKET_IDX_VERB] = (char)v;
}
/** /**
* @return Packet verb (not including flag bits) * @return Packet verb (not including flag bits)
*/ */
inline Verb verb() const { return (Verb)((*this)[ZT_PACKET_IDX_VERB] & 0x1f); } inline Verb verb() const
{
return (Verb)((*this)[ZT_PACKET_IDX_VERB] & 0x1f);
}
/** /**
* @return Length of packet payload * @return Length of packet payload
*/ */
inline unsigned int payloadLength() const { return ((size() < ZT_PROTO_MIN_PACKET_LENGTH) ? 0 : (size() - ZT_PROTO_MIN_PACKET_LENGTH)); } inline unsigned int payloadLength() const
{
return ((size() < ZT_PROTO_MIN_PACKET_LENGTH) ? 0 : (size() - ZT_PROTO_MIN_PACKET_LENGTH));
}
/** /**
* @return Raw packet payload * @return Raw packet payload
*/ */
inline const unsigned char *payload() const { return field(ZT_PACKET_IDX_PAYLOAD,size() - ZT_PACKET_IDX_PAYLOAD); } inline const unsigned char* payload() const
{
return field(ZT_PACKET_IDX_PAYLOAD, size() - ZT_PACKET_IDX_PAYLOAD);
}
/** /**
* Armor packet for transport * Armor packet for transport

View file

@ -13,9 +13,9 @@
#include "PacketMultiplexer.hpp" #include "PacketMultiplexer.hpp"
#include "Constants.hpp"
#include "Node.hpp" #include "Node.hpp"
#include "RuntimeEnvironment.hpp" #include "RuntimeEnvironment.hpp"
#include "Constants.hpp"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>

View file

@ -12,8 +12,9 @@
/****/ /****/
#include "Path.hpp" #include "Path.hpp"
#include "RuntimeEnvironment.hpp"
#include "Node.hpp" #include "Node.hpp"
#include "RuntimeEnvironment.hpp"
namespace ZeroTier { namespace ZeroTier {

View file

@ -14,20 +14,19 @@
#ifndef ZT_PATH_HPP #ifndef ZT_PATH_HPP
#define ZT_PATH_HPP #define ZT_PATH_HPP
#include <stdint.h> #include "AtomicCounter.hpp"
#include <string.h>
#include <stdlib.h>
#include <stdexcept>
#include <algorithm>
#include "Constants.hpp" #include "Constants.hpp"
#include "InetAddress.hpp" #include "InetAddress.hpp"
#include "SharedPtr.hpp"
#include "AtomicCounter.hpp"
#include "Utils.hpp"
#include "Packet.hpp" #include "Packet.hpp"
#include "RingBuffer.hpp" #include "RingBuffer.hpp"
#include "SharedPtr.hpp"
#include "Utils.hpp"
#include <algorithm>
#include <stdexcept>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
/** /**
* Maximum return value of preferenceRank() * Maximum return value of preferenceRank()
@ -41,8 +40,7 @@ class RuntimeEnvironment;
/** /**
* A path across the physical network * A path across the physical network
*/ */
class Path class Path {
{
friend class SharedPtr<Path>; friend class SharedPtr<Path>;
friend class Bond; friend class Bond;
@ -50,10 +48,11 @@ public:
/** /**
* Efficient unique key for paths in a Hashtable * Efficient unique key for paths in a Hashtable
*/ */
class HashKey class HashKey {
{
public: public:
HashKey() {} HashKey()
{
}
HashKey(const int64_t l, const InetAddress& r) HashKey(const int64_t l, const InetAddress& r)
{ {
@ -61,69 +60,82 @@ public:
_k[0] = (uint64_t)reinterpret_cast<const struct sockaddr_in*>(&r)->sin_addr.s_addr; _k[0] = (uint64_t)reinterpret_cast<const struct sockaddr_in*>(&r)->sin_addr.s_addr;
_k[1] = (uint64_t)reinterpret_cast<const struct sockaddr_in*>(&r)->sin_port; _k[1] = (uint64_t)reinterpret_cast<const struct sockaddr_in*>(&r)->sin_port;
_k[2] = (uint64_t)l; _k[2] = (uint64_t)l;
} else if (r.ss_family == AF_INET6) { }
else if (r.ss_family == AF_INET6) {
memcpy(_k, reinterpret_cast<const struct sockaddr_in6*>(&r)->sin6_addr.s6_addr, 16); memcpy(_k, reinterpret_cast<const struct sockaddr_in6*>(&r)->sin6_addr.s6_addr, 16);
_k[2] = ((uint64_t)reinterpret_cast<const struct sockaddr_in6*>(&r)->sin6_port << 32) ^ (uint64_t)l; _k[2] = ((uint64_t)reinterpret_cast<const struct sockaddr_in6*>(&r)->sin6_port << 32) ^ (uint64_t)l;
} else { }
else {
memcpy(_k, &r, std::min(sizeof(_k), sizeof(InetAddress))); memcpy(_k, &r, std::min(sizeof(_k), sizeof(InetAddress)));
_k[2] += (uint64_t)l; _k[2] += (uint64_t)l;
} }
} }
inline unsigned long hashCode() const { return (unsigned long)(_k[0] + _k[1] + _k[2]); } inline unsigned long hashCode() const
{
return (unsigned long)(_k[0] + _k[1] + _k[2]);
}
inline bool operator==(const HashKey &k) const { return ( (_k[0] == k._k[0]) && (_k[1] == k._k[1]) && (_k[2] == k._k[2]) ); } inline bool operator==(const HashKey& k) const
inline bool operator!=(const HashKey &k) const { return (!(*this == k)); } {
return ((_k[0] == k._k[0]) && (_k[1] == k._k[1]) && (_k[2] == k._k[2]));
}
inline bool operator!=(const HashKey& k) const
{
return (! (*this == k));
}
private: private:
uint64_t _k[3]; uint64_t _k[3];
}; };
Path() : Path()
_lastOut(0), : _lastOut(0)
_lastIn(0), , _lastIn(0)
_lastTrustEstablishedPacketReceived(0), , _lastTrustEstablishedPacketReceived(0)
_lastEchoRequestReceived(0), , _lastEchoRequestReceived(0)
_localPort(0), , _localPort(0)
_localSocket(-1), , _localSocket(-1)
_latencyMean(0.0), , _latencyMean(0.0)
_latencyVariance(0.0), , _latencyVariance(0.0)
_packetLossRatio(0.0), , _packetLossRatio(0.0)
_packetErrorRatio(0.0), , _packetErrorRatio(0.0)
_assignedFlowCount(0), , _assignedFlowCount(0)
_valid(true), , _valid(true)
_eligible(false), , _eligible(false)
_bonded(false), , _bonded(false)
_mtu(0), , _mtu(0)
_givenLinkSpeed(0), , _givenLinkSpeed(0)
_relativeQuality(0), , _relativeQuality(0)
_latency(0xffff), , _latency(0xffff)
_addr(), , _addr()
_ipScope(InetAddress::IP_SCOPE_NONE) , _ipScope(InetAddress::IP_SCOPE_NONE)
{} {
}
Path(const int64_t localSocket,const InetAddress &addr) : Path(const int64_t localSocket, const InetAddress& addr)
_lastOut(0), : _lastOut(0)
_lastIn(0), , _lastIn(0)
_lastTrustEstablishedPacketReceived(0), , _lastTrustEstablishedPacketReceived(0)
_lastEchoRequestReceived(0), , _lastEchoRequestReceived(0)
_localPort(0), , _localPort(0)
_localSocket(localSocket), , _localSocket(localSocket)
_latencyMean(0.0), , _latencyMean(0.0)
_latencyVariance(0.0), , _latencyVariance(0.0)
_packetLossRatio(0.0), , _packetLossRatio(0.0)
_packetErrorRatio(0.0), , _packetErrorRatio(0.0)
_assignedFlowCount(0), , _assignedFlowCount(0)
_valid(true), , _valid(true)
_eligible(false), , _eligible(false)
_bonded(false), , _bonded(false)
_mtu(0), , _mtu(0)
_givenLinkSpeed(0), , _givenLinkSpeed(0)
_relativeQuality(0), , _relativeQuality(0)
_latency(0xffff), , _latency(0xffff)
_addr(addr), , _addr(addr)
_ipScope(addr.ipScope()) , _ipScope(addr.ipScope())
{} {
}
/** /**
* Called when a packet is received from this remote path, regardless of content * Called when a packet is received from this remote path, regardless of content
@ -138,7 +150,10 @@ public:
/** /**
* Set time last trusted packet was received (done in Peer::received()) * Set time last trusted packet was received (done in Peer::received())
*/ */
inline void trustedPacketReceived(const uint64_t t) { _lastTrustEstablishedPacketReceived = t; } inline void trustedPacketReceived(const uint64_t t)
{
_lastTrustEstablishedPacketReceived = t;
}
/** /**
* Send a packet via this path (last out time is also updated) * Send a packet via this path (last out time is also updated)
@ -157,7 +172,10 @@ public:
* *
* @param t Time of send * @param t Time of send
*/ */
inline void sent(const int64_t t) { _lastOut = t; } inline void sent(const int64_t t)
{
_lastOut = t;
}
/** /**
* Update path latency with a new measurement * Update path latency with a new measurement
@ -169,7 +187,8 @@ public:
unsigned int pl = _latency; unsigned int pl = _latency;
if (pl < 0xffff) { if (pl < 0xffff) {
_latency = (pl + l) / 2; _latency = (pl + l) / 2;
} else { }
else {
_latency = l; _latency = l;
} }
} }
@ -177,27 +196,42 @@ public:
/** /**
* @return Local socket as specified by external code * @return Local socket as specified by external code
*/ */
inline int64_t localSocket() const { return _localSocket; } inline int64_t localSocket() const
{
return _localSocket;
}
/** /**
* @return Local port corresponding to the localSocket * @return Local port corresponding to the localSocket
*/ */
inline int64_t localPort() const { return _localPort; } inline int64_t localPort() const
{
return _localPort;
}
/** /**
* @return Physical address * @return Physical address
*/ */
inline const InetAddress &address() const { return _addr; } inline const InetAddress& address() const
{
return _addr;
}
/** /**
* @return IP scope -- faster shortcut for address().ipScope() * @return IP scope -- faster shortcut for address().ipScope()
*/ */
inline InetAddress::IpScope ipScope() const { return _ipScope; } inline InetAddress::IpScope ipScope() const
{
return _ipScope;
}
/** /**
* @return True if path has received a trust established packet (e.g. common network membership) in the past ZT_TRUST_EXPIRATION ms * @return True if path has received a trust established packet (e.g. common network membership) in the past ZT_TRUST_EXPIRATION ms
*/ */
inline bool trustEstablished(const int64_t now) const { return ((now - _lastTrustEstablishedPacketReceived) < ZT_TRUST_EXPIRATION); } inline bool trustEstablished(const int64_t now) const
{
return ((now - _lastTrustEstablishedPacketReceived) < ZT_TRUST_EXPIRATION);
}
/** /**
* @return Preference rank, higher == better * @return Preference rank, higher == better
@ -253,7 +287,10 @@ public:
/** /**
* @return Latency or 0xffff if unknown * @return Latency or 0xffff if unknown
*/ */
inline unsigned int latency() const { return _latency; } inline unsigned int latency() const
{
return _latency;
}
/** /**
* @return Path quality -- lower is better * @return Path quality -- lower is better
@ -268,34 +305,50 @@ public:
/** /**
* @return True if this path is alive (receiving heartbeats) * @return True if this path is alive (receiving heartbeats)
*/ */
inline bool alive(const int64_t now) const { inline bool alive(const int64_t now) const
{
return (now - _lastIn) < (ZT_PATH_HEARTBEAT_PERIOD + 5000); return (now - _lastIn) < (ZT_PATH_HEARTBEAT_PERIOD + 5000);
} }
/** /**
* @return True if this path needs a heartbeat * @return True if this path needs a heartbeat
*/ */
inline bool needsHeartbeat(const int64_t now) const { return ((now - _lastOut) >= ZT_PATH_HEARTBEAT_PERIOD); } inline bool needsHeartbeat(const int64_t now) const
{
return ((now - _lastOut) >= ZT_PATH_HEARTBEAT_PERIOD);
}
/** /**
* @return Last time we sent something * @return Last time we sent something
*/ */
inline int64_t lastOut() const { return _lastOut; } inline int64_t lastOut() const
{
return _lastOut;
}
/** /**
* @return Last time we received anything * @return Last time we received anything
*/ */
inline int64_t lastIn() const { return _lastIn; } inline int64_t lastIn() const
{
return _lastIn;
}
/** /**
* @return the age of the path in terms of receiving packets * @return the age of the path in terms of receiving packets
*/ */
inline int64_t age(int64_t now) { return (now - _lastIn); } inline int64_t age(int64_t now)
{
return (now - _lastIn);
}
/** /**
* @return Time last trust-established packet was received * @return Time last trust-established packet was received
*/ */
inline int64_t lastTrustEstablishedPacketReceived() const { return _lastTrustEstablishedPacketReceived; } inline int64_t lastTrustEstablishedPacketReceived() const
{
return _lastTrustEstablishedPacketReceived;
}
/** /**
* Rate limit gate for inbound ECHO requests * Rate limit gate for inbound ECHO requests
@ -312,68 +365,101 @@ public:
/** /**
* @return Mean latency as reported by the bonding layer * @return Mean latency as reported by the bonding layer
*/ */
inline float latencyMean() const { return _latencyMean; } inline float latencyMean() const
{
return _latencyMean;
}
/** /**
* @return Latency variance as reported by the bonding layer * @return Latency variance as reported by the bonding layer
*/ */
inline float latencyVariance() const { return _latencyVariance; } inline float latencyVariance() const
{
return _latencyVariance;
}
/** /**
* @return Packet Loss Ratio as reported by the bonding layer * @return Packet Loss Ratio as reported by the bonding layer
*/ */
inline float packetLossRatio() const { return _packetLossRatio; } inline float packetLossRatio() const
{
return _packetLossRatio;
}
/** /**
* @return Packet Error Ratio as reported by the bonding layer * @return Packet Error Ratio as reported by the bonding layer
*/ */
inline float packetErrorRatio() const { return _packetErrorRatio; } inline float packetErrorRatio() const
{
return _packetErrorRatio;
}
/** /**
* @return Number of flows assigned to this path * @return Number of flows assigned to this path
*/ */
inline unsigned int assignedFlowCount() const { return _assignedFlowCount; } inline unsigned int assignedFlowCount() const
{
return _assignedFlowCount;
}
/** /**
* @return Whether this path is valid as reported by the bonding layer. The bonding layer * @return Whether this path is valid as reported by the bonding layer. The bonding layer
* actually checks with Phy to see if the interface is still up * actually checks with Phy to see if the interface is still up
*/ */
inline bool valid() const { return _valid; } inline bool valid() const
{
return _valid;
}
/** /**
* @return Whether this path is eligible for use in a bond as reported by the bonding layer * @return Whether this path is eligible for use in a bond as reported by the bonding layer
*/ */
inline bool eligible() const { return _eligible; } inline bool eligible() const
{
return _eligible;
}
/** /**
* @return Whether this path is bonded as reported by the bonding layer * @return Whether this path is bonded as reported by the bonding layer
*/ */
inline bool bonded() const { return _bonded; } inline bool bonded() const
{
return _bonded;
}
/** /**
* @return Whether the user-specified MTU for this path (determined by MTU for parent link) * @return Whether the user-specified MTU for this path (determined by MTU for parent link)
*/ */
inline uint16_t mtu() const { return _mtu; } inline uint16_t mtu() const
{
return _mtu;
}
/** /**
* @return Given link capacity as reported by the bonding layer * @return Given link capacity as reported by the bonding layer
*/ */
inline uint32_t givenLinkSpeed() const { return _givenLinkSpeed; } inline uint32_t givenLinkSpeed() const
{
return _givenLinkSpeed;
}
/** /**
* @return Path's quality as reported by the bonding layer * @return Path's quality as reported by the bonding layer
*/ */
inline float relativeQuality() const { return _relativeQuality; } inline float relativeQuality() const
{
return _relativeQuality;
}
/** /**
* @return Physical interface name that this path lives on * @return Physical interface name that this path lives on
*/ */
char *ifname() { char* ifname()
{
return _ifname; return _ifname;
} }
private: private:
char _ifname[ZT_MAX_PHYSIFNAME] = {}; char _ifname[ZT_MAX_PHYSIFNAME] = {};
volatile int64_t _lastOut; volatile int64_t _lastOut;

View file

@ -11,19 +11,20 @@
*/ */
/****/ /****/
#include "Peer.hpp"
#include "../version.h" #include "../version.h"
#include "Constants.hpp" #include "Constants.hpp"
#include "Peer.hpp"
#include "Identity.hpp" #include "Identity.hpp"
#include "Switch.hpp"
#include "Network.hpp"
#include "SelfAwareness.hpp"
#include "Packet.hpp"
#include "Trace.hpp"
#include "InetAddress.hpp" #include "InetAddress.hpp"
#include "RingBuffer.hpp"
#include "Utils.hpp"
#include "Metrics.hpp" #include "Metrics.hpp"
#include "Network.hpp"
#include "Packet.hpp"
#include "RingBuffer.hpp"
#include "SelfAwareness.hpp"
#include "Switch.hpp"
#include "Trace.hpp"
#include "Utils.hpp"
namespace ZeroTier { namespace ZeroTier {
@ -129,7 +130,8 @@ void Peer::received(
break; break;
} }
} }
} else { }
else {
break; break;
} }
} }
@ -158,7 +160,8 @@ void Peer::received(
} }
} }
} }
} else { }
else {
replacePath = i; replacePath = i;
break; break;
} }
@ -176,17 +179,20 @@ void Peer::received(
_bond->nominatePathToBond(_paths[replacePath].p, now); _bond->nominatePathToBond(_paths[replacePath].p, now);
} }
} }
} else { }
else {
Mutex::Lock ltl(_lastTriedPath_m); Mutex::Lock ltl(_lastTriedPath_m);
bool triedTooRecently = false; bool triedTooRecently = false;
for (std::list<std::pair<Path*, int64_t> >::iterator i(_lastTriedPath.begin()); i != _lastTriedPath.end();) { for (std::list<std::pair<Path*, int64_t> >::iterator i(_lastTriedPath.begin()); i != _lastTriedPath.end();) {
if ((now - i->second) > 1000) { if ((now - i->second) > 1000) {
_lastTriedPath.erase(i++); _lastTriedPath.erase(i++);
} else if (i->first == path.ptr()) { }
else if (i->first == path.ptr()) {
++i; ++i;
triedTooRecently = true; triedTooRecently = true;
} else { }
else {
++i; ++i;
} }
} }
@ -279,7 +285,8 @@ SharedPtr<Path> Peer::getAppropriatePath(int64_t now, bool includeExpired, int32
bestPath = i; bestPath = i;
} }
} }
} else { }
else {
break; break;
} }
} }
@ -330,7 +337,8 @@ void Peer::introduce(void *const tPtr,const int64_t now,const SharedPtr<Peer> &o
} }
break; break;
} }
} else { }
else {
break; break;
} }
} }
@ -355,7 +363,8 @@ void Peer::introduce(void *const tPtr,const int64_t now,const SharedPtr<Peer> &o
} }
break; break;
} }
} else { }
else {
break; break;
} }
} }
@ -388,14 +397,16 @@ void Peer::introduce(void *const tPtr,const int64_t now,const SharedPtr<Peer> &o
if (other->_paths[theirs].p->address().ss_family == AF_INET6) { if (other->_paths[theirs].p->address().ss_family == AF_INET6) {
outp.append((uint8_t)16); outp.append((uint8_t)16);
outp.append(other->_paths[theirs].p->address().rawIpData(), 16); outp.append(other->_paths[theirs].p->address().rawIpData(), 16);
} else { }
else {
outp.append((uint8_t)4); outp.append((uint8_t)4);
outp.append(other->_paths[theirs].p->address().rawIpData(), 4); outp.append(other->_paths[theirs].p->address().rawIpData(), 4);
} }
outp.armor(_key, true, false, aesKeysIfSupported(), _id); outp.armor(_key, true, false, aesKeysIfSupported(), _id);
Metrics::pkt_rendezvous_out++; Metrics::pkt_rendezvous_out++;
_paths[mine].p->send(RR, tPtr, outp.data(), outp.size(), now); _paths[mine].p->send(RR, tPtr, outp.data(), outp.size(), now);
} else { }
else {
Packet outp(other->_id.address(), RR->identity.address(), Packet::VERB_RENDEZVOUS); Packet outp(other->_id.address(), RR->identity.address(), Packet::VERB_RENDEZVOUS);
outp.append((uint8_t)0); outp.append((uint8_t)0);
_id.address().appendTo(outp); _id.address().appendTo(outp);
@ -403,7 +414,8 @@ void Peer::introduce(void *const tPtr,const int64_t now,const SharedPtr<Peer> &o
if (_paths[mine].p->address().ss_family == AF_INET6) { if (_paths[mine].p->address().ss_family == AF_INET6) {
outp.append((uint8_t)16); outp.append((uint8_t)16);
outp.append(_paths[mine].p->address().rawIpData(), 16); outp.append(_paths[mine].p->address().rawIpData(), 16);
} else { }
else {
outp.append((uint8_t)4); outp.append((uint8_t)4);
outp.append(_paths[mine].p->address().rawIpData(), 4); outp.append(_paths[mine].p->address().rawIpData(), 4);
} }
@ -456,7 +468,8 @@ void Peer::sendHELLO(void *tPtr,const int64_t localSocket,const InetAddress &atA
outp.armor(_key, false, false, nullptr, _id); outp.armor(_key, false, false, nullptr, _id);
RR->node->expectReplyTo(outp.packetId()); RR->node->expectReplyTo(outp.packetId());
RR->node->putPacket(tPtr, RR->node->lowBandwidthModeEnabled() ? localSocket : -1, atAddress, outp.data(), outp.size()); RR->node->putPacket(tPtr, RR->node->lowBandwidthModeEnabled() ? localSocket : -1, atAddress, outp.data(), outp.size());
} else { }
else {
RR->node->expectReplyTo(outp.packetId()); RR->node->expectReplyTo(outp.packetId());
RR->sw->send(tPtr, outp, true); RR->sw->send(tPtr, outp, true);
} }
@ -470,7 +483,8 @@ void Peer::attemptToContactAt(void *tPtr,const int64_t localSocket,const InetAdd
Metrics::pkt_echo_out++; Metrics::pkt_echo_out++;
RR->node->expectReplyTo(outp.packetId()); RR->node->expectReplyTo(outp.packetId());
RR->node->putPacket(tPtr, localSocket, atAddress, outp.data(), outp.size()); RR->node->putPacket(tPtr, localSocket, atAddress, outp.data(), outp.size());
} else { }
else {
sendHELLO(tPtr, localSocket, atAddress, now); sendHELLO(tPtr, localSocket, atAddress, now);
} }
} }
@ -551,7 +565,8 @@ unsigned int Peer::doPingAndKeepalive(void *tPtr,int64_t now)
for (unsigned int i = 0; i < ZT_MAX_PEER_NETWORK_PATHS; ++i) { for (unsigned int i = 0; i < ZT_MAX_PEER_NETWORK_PATHS; ++i) {
if (_paths[i].p) { if (_paths[i].p) {
maxPriority = std::max(_paths[i].priority, maxPriority); maxPriority = std::max(_paths[i].priority, maxPriority);
} else { }
else {
break; break;
} }
} }
@ -566,7 +581,8 @@ unsigned int Peer::doPingAndKeepalive(void *tPtr,int64_t now)
_paths[i].p->sent(now); _paths[i].p->sent(now);
sent |= (_paths[i].p->address().ss_family == AF_INET) ? 0x1 : 0x2; sent |= (_paths[i].p->address().ss_family == AF_INET) ? 0x1 : 0x2;
} }
} else { }
else {
_paths[i] = _PeerPath(); _paths[i] = _PeerPath();
deletionOccurred = true; deletionOccurred = true;
} }
@ -622,7 +638,8 @@ void Peer::clusterRedirect(void *tPtr,const SharedPtr<Path> &originatingPath,con
newPriority = _paths[i].priority; newPriority = _paths[i].priority;
break; break;
} }
} else { }
else {
break; break;
} }
} }
@ -666,14 +683,14 @@ void Peer::resetWithinScope(void *tPtr,InetAddress::IpScope scope,int inetAddres
_paths[i].p->sent(now); _paths[i].p->sent(now);
_paths[i].lr = 0; // path will not be used unless it speaks again _paths[i].lr = 0; // path will not be used unless it speaks again
} }
} else { }
else {
break; break;
} }
} }
} }
void Peer::recordOutgoingPacket(const SharedPtr<Path> &path, const uint64_t packetId, void Peer::recordOutgoingPacket(const SharedPtr<Path>& path, const uint64_t packetId, uint16_t payloadLength, const Packet::Verb verb, const int32_t flowId, int64_t now)
uint16_t payloadLength, const Packet::Verb verb, const int32_t flowId, int64_t now)
{ {
#ifndef ZT_NO_PEER_METRICS #ifndef ZT_NO_PEER_METRICS
_outgoing_packet++; _outgoing_packet++;
@ -693,8 +710,7 @@ void Peer::recordIncomingInvalidPacket(const SharedPtr<Path>& path)
} }
} }
void Peer::recordIncomingPacket(const SharedPtr<Path> &path, const uint64_t packetId, void Peer::recordIncomingPacket(const SharedPtr<Path>& path, const uint64_t packetId, uint16_t payloadLength, const Packet::Verb verb, const int32_t flowId, int64_t now)
uint16_t payloadLength, const Packet::Verb verb, const int32_t flowId, int64_t now)
{ {
if (_localMultipathSupported && _bond) { if (_localMultipathSupported && _bond) {
_bond->recordIncomingPacket(path, packetId, payloadLength, verb, flowId, now); _bond->recordIncomingPacket(path, packetId, payloadLength, verb, flowId, now);

View file

@ -14,27 +14,26 @@
#ifndef ZT_PEER_HPP #ifndef ZT_PEER_HPP
#define ZT_PEER_HPP #define ZT_PEER_HPP
#include <vector>
#include <list>
#include "../include/ZeroTierOne.h" #include "../include/ZeroTierOne.h"
#include "AES.hpp"
#include "Constants.hpp"
#include "RuntimeEnvironment.hpp"
#include "Node.hpp"
#include "Path.hpp"
#include "Address.hpp" #include "Address.hpp"
#include "Utils.hpp" #include "AtomicCounter.hpp"
#include "Bond.hpp"
#include "Constants.hpp"
#include "Hashtable.hpp"
#include "Identity.hpp" #include "Identity.hpp"
#include "InetAddress.hpp" #include "InetAddress.hpp"
#include "Packet.hpp"
#include "SharedPtr.hpp"
#include "AtomicCounter.hpp"
#include "Hashtable.hpp"
#include "Mutex.hpp"
#include "Bond.hpp"
#include "AES.hpp"
#include "Metrics.hpp" #include "Metrics.hpp"
#include "Mutex.hpp"
#include "Node.hpp"
#include "Packet.hpp"
#include "Path.hpp"
#include "RuntimeEnvironment.hpp"
#include "SharedPtr.hpp"
#include "Utils.hpp"
#include <list>
#include <vector>
#define ZT_PEER_MAX_SERIALIZED_STATE_SIZE (sizeof(Peer) + 32 + (sizeof(Path) * 2)) #define ZT_PEER_MAX_SERIALIZED_STATE_SIZE (sizeof(Peer) + 32 + (sizeof(Path) * 2))
@ -43,8 +42,7 @@ namespace ZeroTier {
/** /**
* Peer on P2P Network (virtual layer 1) * Peer on P2P Network (virtual layer 1)
*/ */
class Peer class Peer {
{
friend class SharedPtr<Peer>; friend class SharedPtr<Peer>;
friend class SharedPtr<Bond>; friend class SharedPtr<Bond>;
friend class Switch; friend class Switch;
@ -54,7 +52,8 @@ private:
Peer() = delete; // disabled to prevent bugs -- should not be constructed uninitialized Peer() = delete; // disabled to prevent bugs -- should not be constructed uninitialized
public: public:
~Peer() { ~Peer()
{
Utils::burn(_key, sizeof(_key)); Utils::burn(_key, sizeof(_key));
} }
@ -71,12 +70,18 @@ public:
/** /**
* @return This peer's ZT address (short for identity().address()) * @return This peer's ZT address (short for identity().address())
*/ */
inline const Address &address() const { return _id.address(); } inline const Address& address() const
{
return _id.address();
}
/** /**
* @return This peer's identity * @return This peer's identity
*/ */
inline const Identity &identity() const { return _id; } inline const Identity& identity() const
{
return _id;
}
/** /**
* Log receipt of an authenticated packet * Log receipt of an authenticated packet
@ -122,7 +127,8 @@ public:
if (((now - _paths[i].lr) < ZT_PEER_PATH_EXPIRATION) && (_paths[i].p->address() == addr)) { if (((now - _paths[i].lr) < ZT_PEER_PATH_EXPIRATION) && (_paths[i].p->address() == addr)) {
return true; return true;
} }
} else { }
else {
break; break;
} }
} }
@ -159,8 +165,7 @@ public:
* @param flowId Flow ID * @param flowId Flow ID
* @param now Current time * @param now Current time
*/ */
void recordIncomingPacket(const SharedPtr<Path> &path, const uint64_t packetId, void recordIncomingPacket(const SharedPtr<Path>& path, const uint64_t packetId, uint16_t payloadLength, const Packet::Verb verb, const int32_t flowId, int64_t now);
uint16_t payloadLength, const Packet::Verb verb, const int32_t flowId, int64_t now);
/** /**
* *
@ -171,8 +176,7 @@ public:
* @param flowId Flow ID * @param flowId Flow ID
* @param now Current time * @param now Current time
*/ */
void recordOutgoingPacket(const SharedPtr<Path> &path, const uint64_t packetId, void recordOutgoingPacket(const SharedPtr<Path>& path, const uint64_t packetId, uint16_t payloadLength, const Packet::Verb verb, const int32_t flowId, int64_t now);
uint16_t payloadLength, const Packet::Verb verb, const int32_t flowId, int64_t now);
/** /**
* Record an invalid incoming packet. This packet failed * Record an invalid incoming packet. This packet failed
@ -296,19 +300,31 @@ public:
/** /**
* @return Time of last receive of anything, whether direct or relayed * @return Time of last receive of anything, whether direct or relayed
*/ */
inline int64_t lastReceive() const { return _lastReceive; } inline int64_t lastReceive() const
{
return _lastReceive;
}
/** /**
* @return True if we've heard from this peer in less than ZT_PEER_ACTIVITY_TIMEOUT * @return True if we've heard from this peer in less than ZT_PEER_ACTIVITY_TIMEOUT
*/ */
inline bool isAlive(const int64_t now) const { return ((now - _lastReceive) < ZT_PEER_ACTIVITY_TIMEOUT); } inline bool isAlive(const int64_t now) const
{
return ((now - _lastReceive) < ZT_PEER_ACTIVITY_TIMEOUT);
}
/** /**
* @return True if this peer has sent us real network traffic recently * @return True if this peer has sent us real network traffic recently
*/ */
inline int64_t isActive(int64_t now) const { return ((now - _lastNontrivialReceive) < ZT_PEER_ACTIVITY_TIMEOUT); } inline int64_t isActive(int64_t now) const
{
return ((now - _lastNontrivialReceive) < ZT_PEER_ACTIVITY_TIMEOUT);
}
inline int64_t lastSentFullHello() { return _lastSentFullHello; } inline int64_t lastSentFullHello()
{
return _lastSentFullHello;
}
/** /**
* @return Latency in milliseconds of best/aggregate path or 0xffff if unknown / no paths * @return Latency in milliseconds of best/aggregate path or 0xffff if unknown / no paths
@ -317,7 +333,8 @@ public:
{ {
if (_localMultipathSupported) { if (_localMultipathSupported) {
return (int)_lastComputedAggregateMeanLatency; return (int)_lastComputedAggregateMeanLatency;
} else { }
else {
SharedPtr<Path> bp(getAppropriatePath(now, false)); SharedPtr<Path> bp(getAppropriatePath(now, false));
if (bp) { if (bp) {
return (unsigned int)bp->latency(); return (unsigned int)bp->latency();
@ -353,7 +370,10 @@ public:
/** /**
* @return 256-bit secret symmetric encryption key * @return 256-bit secret symmetric encryption key
*/ */
inline const unsigned char *key() const { return _key; } inline const unsigned char* key() const
{
return _key;
}
/** /**
* Set the currently known remote version of this peer's client * Set the currently known remote version of this peer's client
@ -371,17 +391,35 @@ public:
_vRevision = (uint16_t)vrev; _vRevision = (uint16_t)vrev;
} }
inline unsigned int remoteVersionProtocol() const { return _vProto; } inline unsigned int remoteVersionProtocol() const
inline unsigned int remoteVersionMajor() const { return _vMajor; } {
inline unsigned int remoteVersionMinor() const { return _vMinor; } return _vProto;
inline unsigned int remoteVersionRevision() const { return _vRevision; } }
inline unsigned int remoteVersionMajor() const
{
return _vMajor;
}
inline unsigned int remoteVersionMinor() const
{
return _vMinor;
}
inline unsigned int remoteVersionRevision() const
{
return _vRevision;
}
inline bool remoteVersionKnown() const { return ((_vMajor > 0)||(_vMinor > 0)||(_vRevision > 0)); } inline bool remoteVersionKnown() const
{
return ((_vMajor > 0) || (_vMinor > 0) || (_vRevision > 0));
}
/** /**
* @return True if peer has received a trust established packet (e.g. common network membership) in the past ZT_TRUST_EXPIRATION ms * @return True if peer has received a trust established packet (e.g. common network membership) in the past ZT_TRUST_EXPIRATION ms
*/ */
inline bool trustEstablished(const int64_t now) const { return ((now - _lastTrustEstablishedPacketReceived) < ZT_TRUST_EXPIRATION); } inline bool trustEstablished(const int64_t now) const
{
return ((now - _lastTrustEstablishedPacketReceived) < ZT_TRUST_EXPIRATION);
}
/** /**
* Rate limit gate for VERB_PUSH_DIRECT_PATHS * Rate limit gate for VERB_PUSH_DIRECT_PATHS
@ -390,7 +428,8 @@ public:
{ {
if ((now - _lastDirectPathPushReceive) <= ZT_PUSH_DIRECT_PATHS_CUTOFF_TIME) { if ((now - _lastDirectPathPushReceive) <= ZT_PUSH_DIRECT_PATHS_CUTOFF_TIME) {
++_directPathPushCutoffCount; ++_directPathPushCutoffCount;
} else { }
else {
_directPathPushCutoffCount = 0; _directPathPushCutoffCount = 0;
} }
_lastDirectPathPushReceive = now; _lastDirectPathPushReceive = now;
@ -496,8 +535,7 @@ public:
* *
* This does not serialize everything, just non-ephemeral information. * This does not serialize everything, just non-ephemeral information.
*/ */
template<unsigned int C> template <unsigned int C> inline void serializeForCache(Buffer<C>& b) const
inline void serializeForCache(Buffer<C> &b) const
{ {
b.append((uint8_t)2); b.append((uint8_t)2);
@ -514,7 +552,8 @@ public:
for (unsigned int i = 0; i < ZT_MAX_PEER_NETWORK_PATHS; ++i) { for (unsigned int i = 0; i < ZT_MAX_PEER_NETWORK_PATHS; ++i) {
if (_paths[i].p) { if (_paths[i].p) {
++pc; ++pc;
} else { }
else {
break; break;
} }
} }
@ -525,8 +564,7 @@ public:
} }
} }
template<unsigned int C> template <unsigned int C> inline static SharedPtr<Peer> deserializeFromCache(int64_t now, void* tPtr, Buffer<C>& b, const RuntimeEnvironment* renv)
inline static SharedPtr<Peer> deserializeFromCache(int64_t now,void *tPtr,Buffer<C> &b,const RuntimeEnvironment *renv)
{ {
try { try {
unsigned int ptr = 0; unsigned int ptr = 0;
@ -563,13 +601,15 @@ public:
if (inaddr) { if (inaddr) {
p->attemptToContactAt(tPtr, -1, inaddr, now, true); p->attemptToContactAt(tPtr, -1, inaddr, now, true);
} }
} catch ( ... ) { }
catch (...) {
break; break;
} }
} }
return p; return p;
} catch ( ... ) { }
catch (...) {
return SharedPtr<Peer>(); return SharedPtr<Peer>();
} }
} }
@ -577,12 +617,16 @@ public:
/** /**
* @return The bonding policy used to reach this peer * @return The bonding policy used to reach this peer
*/ */
SharedPtr<Bond> bond() { return _bond; } SharedPtr<Bond> bond()
{
return _bond;
}
/** /**
* @return The bonding policy used to reach this peer * @return The bonding policy used to reach this peer
*/ */
inline int8_t bondingPolicy() { inline int8_t bondingPolicy()
{
Mutex::Lock _l(_bond_m); Mutex::Lock _l(_bond_m);
if (_bond) { if (_bond) {
return _bond->policy(); return _bond->policy();
@ -593,7 +637,8 @@ public:
/** /**
* @return the number of links in this bond which are considered alive * @return the number of links in this bond which are considered alive
*/ */
inline uint8_t getNumAliveLinks() { inline uint8_t getNumAliveLinks()
{
Mutex::Lock _l(_paths_m); Mutex::Lock _l(_paths_m);
if (_bond) { if (_bond) {
return _bond->getNumAliveLinks(); return _bond->getNumAliveLinks();
@ -604,7 +649,8 @@ public:
/** /**
* @return the number of links in this bond * @return the number of links in this bond
*/ */
inline uint8_t getNumTotalLinks() { inline uint8_t getNumTotalLinks()
{
Mutex::Lock _l(_paths_m); Mutex::Lock _l(_paths_m);
if (_bond) { if (_bond) {
return _bond->getNumTotalLinks(); return _bond->getNumTotalLinks();
@ -616,15 +662,20 @@ public:
//{ return (const AES *)0; } //{ return (const AES *)0; }
inline const AES* aesKeysIfSupported() const inline const AES* aesKeysIfSupported() const
{ return (_vProto >= 12) ? _aesKeys : (const AES *)0; } {
return (_vProto >= 12) ? _aesKeys : (const AES*)0;
}
inline const AES* aesKeys() const inline const AES* aesKeys() const
{ return _aesKeys; } {
return _aesKeys;
}
private: private:
struct _PeerPath struct _PeerPath {
_PeerPath() : lr(0), p(), priority(1)
{ {
_PeerPath() : lr(0),p(),priority(1) {} }
int64_t lr; // time of last valid ZeroTier packet int64_t lr; // time of last valid ZeroTier packet
SharedPtr<Path> p; SharedPtr<Path> p;
long priority; // >= 1, higher is better long priority; // >= 1, higher is better
@ -692,11 +743,10 @@ private:
// Add a swap() for shared ptr's to peers to speed up peer sorts // Add a swap() for shared ptr's to peers to speed up peer sorts
namespace std { namespace std {
template<> template <> inline void swap(ZeroTier::SharedPtr<ZeroTier::Peer>& a, ZeroTier::SharedPtr<ZeroTier::Peer>& b)
inline void swap(ZeroTier::SharedPtr<ZeroTier::Peer> &a,ZeroTier::SharedPtr<ZeroTier::Peer> &b)
{ {
a.swap(b); a.swap(b);
} }
} } // namespace std
#endif #endif

View file

@ -4,11 +4,12 @@ D. J. Bernstein
Public domain. Public domain.
*/ */
#include "Constants.hpp"
#include "Poly1305.hpp" #include "Poly1305.hpp"
#include <stdio.h> #include "Constants.hpp"
#include <stdint.h> #include <stdint.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -39,8 +40,18 @@ typedef struct poly1305_context {
} uint128_t; } uint128_t;
#define MUL(out, x, y) out.lo = _umul128((x), (y), &out.hi) #define MUL(out, x, y) out.lo = _umul128((x), (y), &out.hi)
#define ADD(out, in) { unsigned long long t = out.lo; out.lo += in.lo; out.hi += (out.lo < t) + in.hi; } #define ADD(out, in) \
#define ADDLO(out, in) { unsigned long long t = out.lo; out.lo += in; out.hi += (out.lo < t); } { \
unsigned long long t = out.lo; \
out.lo += in.lo; \
out.hi += (out.lo < t) + in.hi; \
}
#define ADDLO(out, in) \
{ \
unsigned long long t = out.lo; \
out.lo += in; \
out.hi += (out.lo < t); \
}
#define SHR(in, shift) (__shiftright128(in.lo, in.hi, (shift))) #define SHR(in, shift) (__shiftright128(in.lo, in.hi, (shift)))
#define LO(in) (in.lo) #define LO(in) (in.lo)
@ -76,15 +87,9 @@ typedef struct poly1305_state_internal_t {
#if defined(ZT_NO_TYPE_PUNNING) || (__BYTE_ORDER != __LITTLE_ENDIAN) #if defined(ZT_NO_TYPE_PUNNING) || (__BYTE_ORDER != __LITTLE_ENDIAN)
static inline unsigned long long U8TO64(const unsigned char* p) static inline unsigned long long U8TO64(const unsigned char* p)
{ {
return return (
(((unsigned long long)(p[0] & 0xff) ) | ((unsigned long long)(p[0] & 0xff)) | ((unsigned long long)(p[1] & 0xff) << 8) | ((unsigned long long)(p[2] & 0xff) << 16) | ((unsigned long long)(p[3] & 0xff) << 24) | ((unsigned long long)(p[4] & 0xff) << 32)
((unsigned long long)(p[1] & 0xff) << 8) | | ((unsigned long long)(p[5] & 0xff) << 40) | ((unsigned long long)(p[6] & 0xff) << 48) | ((unsigned long long)(p[7] & 0xff) << 56));
((unsigned long long)(p[2] & 0xff) << 16) |
((unsigned long long)(p[3] & 0xff) << 24) |
((unsigned long long)(p[4] & 0xff) << 32) |
((unsigned long long)(p[5] & 0xff) << 40) |
((unsigned long long)(p[6] & 0xff) << 48) |
((unsigned long long)(p[7] & 0xff) << 56));
} }
#else #else
#define U8TO64(p) (*reinterpret_cast<const unsigned long long*>(p)) #define U8TO64(p) (*reinterpret_cast<const unsigned long long*>(p))
@ -106,7 +111,8 @@ static inline void U64TO8(unsigned char *p, unsigned long long v)
#define U64TO8(p, v) ((*reinterpret_cast<unsigned long long*>(p)) = (v)) #define U64TO8(p, v) ((*reinterpret_cast<unsigned long long*>(p)) = (v))
#endif #endif
static inline void poly1305_init(poly1305_context *ctx, const unsigned char key[32]) { static inline void poly1305_init(poly1305_context* ctx, const unsigned char key[32])
{
poly1305_state_internal_t* st = (poly1305_state_internal_t*)ctx; poly1305_state_internal_t* st = (poly1305_state_internal_t*)ctx;
unsigned long long t0, t1; unsigned long long t0, t1;
@ -131,7 +137,8 @@ static inline void poly1305_init(poly1305_context *ctx, const unsigned char key[
st->final = 0; st->final = 0;
} }
static inline void poly1305_blocks(poly1305_state_internal_t *st, const unsigned char *m, size_t bytes) { static inline void poly1305_blocks(poly1305_state_internal_t* st, const unsigned char* m, size_t bytes)
{
const unsigned long long hibit = (st->final) ? 0 : ((unsigned long long)1 << 40); /* 1 << 128 */ const unsigned long long hibit = (st->final) ? 0 : ((unsigned long long)1 << 40); /* 1 << 128 */
unsigned long long r0, r1, r2; unsigned long long r0, r1, r2;
unsigned long long s1, s2; unsigned long long s1, s2;
@ -162,15 +169,34 @@ static inline void poly1305_blocks(poly1305_state_internal_t *st, const unsigned
h2 += (((t1 >> 24)) & 0x3ffffffffff) | hibit; h2 += (((t1 >> 24)) & 0x3ffffffffff) | hibit;
/* h *= r */ /* h *= r */
MUL(d0, h0, r0); MUL(d, h1, s2); ADD(d0, d); MUL(d, h2, s1); ADD(d0, d); MUL(d0, h0, r0);
MUL(d1, h0, r1); MUL(d, h1, r0); ADD(d1, d); MUL(d, h2, s2); ADD(d1, d); MUL(d, h1, s2);
MUL(d2, h0, r2); MUL(d, h1, r1); ADD(d2, d); MUL(d, h2, r0); ADD(d2, d); ADD(d0, d);
MUL(d, h2, s1);
ADD(d0, d);
MUL(d1, h0, r1);
MUL(d, h1, r0);
ADD(d1, d);
MUL(d, h2, s2);
ADD(d1, d);
MUL(d2, h0, r2);
MUL(d, h1, r1);
ADD(d2, d);
MUL(d, h2, r0);
ADD(d2, d);
/* (partial) h %= p */ /* (partial) h %= p */
c = SHR(d0, 44); h0 = LO(d0) & 0xfffffffffff; c = SHR(d0, 44);
ADDLO(d1, c); c = SHR(d1, 44); h1 = LO(d1) & 0xfffffffffff; h0 = LO(d0) & 0xfffffffffff;
ADDLO(d2, c); c = SHR(d2, 42); h2 = LO(d2) & 0x3ffffffffff; ADDLO(d1, c);
h0 += c * 5; c = (h0 >> 44); h0 = h0 & 0xfffffffffff; c = SHR(d1, 44);
h1 = LO(d1) & 0xfffffffffff;
ADDLO(d2, c);
c = SHR(d2, 42);
h2 = LO(d2) & 0x3ffffffffff;
h0 += c * 5;
c = (h0 >> 44);
h0 = h0 & 0xfffffffffff;
h1 += c; h1 += c;
m += poly1305_block_size; m += poly1305_block_size;
@ -182,7 +208,8 @@ static inline void poly1305_blocks(poly1305_state_internal_t *st, const unsigned
st->h[2] = h2; st->h[2] = h2;
} }
static inline void poly1305_finish(poly1305_context *ctx, unsigned char mac[16]) { static inline void poly1305_finish(poly1305_context* ctx, unsigned char mac[16])
{
poly1305_state_internal_t* st = (poly1305_state_internal_t*)ctx; poly1305_state_internal_t* st = (poly1305_state_internal_t*)ctx;
unsigned long long h0, h1, h2, c; unsigned long long h0, h1, h2, c;
unsigned long long g0, g1, g2; unsigned long long g0, g1, g2;
@ -204,17 +231,32 @@ static inline void poly1305_finish(poly1305_context *ctx, unsigned char mac[16])
h1 = st->h[1]; h1 = st->h[1];
h2 = st->h[2]; h2 = st->h[2];
c = (h1 >> 44); h1 &= 0xfffffffffff; c = (h1 >> 44);
h2 += c; c = (h2 >> 42); h2 &= 0x3ffffffffff; h1 &= 0xfffffffffff;
h0 += c * 5; c = (h0 >> 44); h0 &= 0xfffffffffff; h2 += c;
h1 += c; c = (h1 >> 44); h1 &= 0xfffffffffff; c = (h2 >> 42);
h2 += c; c = (h2 >> 42); h2 &= 0x3ffffffffff; h2 &= 0x3ffffffffff;
h0 += c * 5; c = (h0 >> 44); h0 &= 0xfffffffffff; h0 += c * 5;
c = (h0 >> 44);
h0 &= 0xfffffffffff;
h1 += c;
c = (h1 >> 44);
h1 &= 0xfffffffffff;
h2 += c;
c = (h2 >> 42);
h2 &= 0x3ffffffffff;
h0 += c * 5;
c = (h0 >> 44);
h0 &= 0xfffffffffff;
h1 += c; h1 += c;
/* compute h + -p */ /* compute h + -p */
g0 = h0 + 5; c = (g0 >> 44); g0 &= 0xfffffffffff; g0 = h0 + 5;
g1 = h1 + c; c = (g1 >> 44); g1 &= 0xfffffffffff; c = (g0 >> 44);
g0 &= 0xfffffffffff;
g1 = h1 + c;
c = (g1 >> 44);
g1 &= 0xfffffffffff;
g2 = h2 + c - ((unsigned long long)1 << 42); g2 = h2 + c - ((unsigned long long)1 << 42);
/* select h if h < p, or h + -p if h >= p */ /* select h if h < p, or h + -p if h >= p */
@ -231,9 +273,14 @@ static inline void poly1305_finish(poly1305_context *ctx, unsigned char mac[16])
t0 = st->pad[0]; t0 = st->pad[0];
t1 = st->pad[1]; t1 = st->pad[1];
h0 += (( t0 ) & 0xfffffffffff) ; c = (h0 >> 44); h0 &= 0xfffffffffff; h0 += ((t0) & 0xfffffffffff);
h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff) + c; c = (h1 >> 44); h1 &= 0xfffffffffff; c = (h0 >> 44);
h2 += (((t1 >> 24) ) & 0x3ffffffffff) + c; h2 &= 0x3ffffffffff; h0 &= 0xfffffffffff;
h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff) + c;
c = (h1 >> 44);
h1 &= 0xfffffffffff;
h2 += (((t1 >> 24)) & 0x3ffffffffff) + c;
h2 &= 0x3ffffffffff;
/* mac = h % (2^128) */ /* mac = h % (2^128) */
h0 = ((h0) | (h1 << 44)); h0 = ((h0) | (h1 << 44));
@ -273,26 +320,22 @@ typedef struct poly1305_state_internal_t {
} poly1305_state_internal_t; } poly1305_state_internal_t;
/* interpret four 8 bit unsigned integers as a 32 bit unsigned integer in little endian */ /* interpret four 8 bit unsigned integers as a 32 bit unsigned integer in little endian */
static unsigned long static unsigned long U8TO32(const unsigned char* p)
U8TO32(const unsigned char *p) { {
return return (((unsigned long)(p[0] & 0xff)) | ((unsigned long)(p[1] & 0xff) << 8) | ((unsigned long)(p[2] & 0xff) << 16) | ((unsigned long)(p[3] & 0xff) << 24));
(((unsigned long)(p[0] & 0xff) ) |
((unsigned long)(p[1] & 0xff) << 8) |
((unsigned long)(p[2] & 0xff) << 16) |
((unsigned long)(p[3] & 0xff) << 24));
} }
/* store a 32 bit unsigned integer as four 8 bit unsigned integers in little endian */ /* store a 32 bit unsigned integer as four 8 bit unsigned integers in little endian */
static void static void U32TO8(unsigned char* p, unsigned long v)
U32TO8(unsigned char *p, unsigned long v) { {
p[0] = (v) & 0xff; p[0] = (v) & 0xff;
p[1] = (v >> 8) & 0xff; p[1] = (v >> 8) & 0xff;
p[2] = (v >> 16) & 0xff; p[2] = (v >> 16) & 0xff;
p[3] = (v >> 24) & 0xff; p[3] = (v >> 24) & 0xff;
} }
static inline void static inline void poly1305_init(poly1305_context* ctx, const unsigned char key[32])
poly1305_init(poly1305_context *ctx, const unsigned char key[32]) { {
poly1305_state_internal_t* st = (poly1305_state_internal_t*)ctx; poly1305_state_internal_t* st = (poly1305_state_internal_t*)ctx;
/* r &= 0xffffffc0ffffffc0ffffffc0fffffff */ /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
@ -319,8 +362,8 @@ poly1305_init(poly1305_context *ctx, const unsigned char key[32]) {
st->final = 0; st->final = 0;
} }
static inline void static inline void poly1305_blocks(poly1305_state_internal_t* st, const unsigned char* m, size_t bytes)
poly1305_blocks(poly1305_state_internal_t *st, const unsigned char *m, size_t bytes) { {
const unsigned long hibit = (st->final) ? 0 : (1 << 24); /* 1 << 128 */ const unsigned long hibit = (st->final) ? 0 : (1 << 24); /* 1 << 128 */
unsigned long r0, r1, r2, r3, r4; unsigned long r0, r1, r2, r3, r4;
unsigned long s1, s2, s3, s4; unsigned long s1, s2, s3, s4;
@ -361,12 +404,23 @@ poly1305_blocks(poly1305_state_internal_t *st, const unsigned char *m, size_t by
d4 = ((unsigned long long)h0 * r4) + ((unsigned long long)h1 * r3) + ((unsigned long long)h2 * r2) + ((unsigned long long)h3 * r1) + ((unsigned long long)h4 * r0); d4 = ((unsigned long long)h0 * r4) + ((unsigned long long)h1 * r3) + ((unsigned long long)h2 * r2) + ((unsigned long long)h3 * r1) + ((unsigned long long)h4 * r0);
/* (partial) h %= p */ /* (partial) h %= p */
c = (unsigned long)(d0 >> 26); h0 = (unsigned long)d0 & 0x3ffffff; c = (unsigned long)(d0 >> 26);
d1 += c; c = (unsigned long)(d1 >> 26); h1 = (unsigned long)d1 & 0x3ffffff; h0 = (unsigned long)d0 & 0x3ffffff;
d2 += c; c = (unsigned long)(d2 >> 26); h2 = (unsigned long)d2 & 0x3ffffff; d1 += c;
d3 += c; c = (unsigned long)(d3 >> 26); h3 = (unsigned long)d3 & 0x3ffffff; c = (unsigned long)(d1 >> 26);
d4 += c; c = (unsigned long)(d4 >> 26); h4 = (unsigned long)d4 & 0x3ffffff; h1 = (unsigned long)d1 & 0x3ffffff;
h0 += c * 5; c = (h0 >> 26); h0 = h0 & 0x3ffffff; d2 += c;
c = (unsigned long)(d2 >> 26);
h2 = (unsigned long)d2 & 0x3ffffff;
d3 += c;
c = (unsigned long)(d3 >> 26);
h3 = (unsigned long)d3 & 0x3ffffff;
d4 += c;
c = (unsigned long)(d4 >> 26);
h4 = (unsigned long)d4 & 0x3ffffff;
h0 += c * 5;
c = (h0 >> 26);
h0 = h0 & 0x3ffffff;
h1 += c; h1 += c;
m += poly1305_block_size; m += poly1305_block_size;
@ -380,8 +434,8 @@ poly1305_blocks(poly1305_state_internal_t *st, const unsigned char *m, size_t by
st->h[4] = h4; st->h[4] = h4;
} }
static inline void static inline void poly1305_finish(poly1305_context* ctx, unsigned char mac[16])
poly1305_finish(poly1305_context *ctx, unsigned char mac[16]) { {
poly1305_state_internal_t* st = (poly1305_state_internal_t*)ctx; poly1305_state_internal_t* st = (poly1305_state_internal_t*)ctx;
unsigned long h0, h1, h2, h3, h4, c; unsigned long h0, h1, h2, h3, h4, c;
unsigned long g0, g1, g2, g3, g4; unsigned long g0, g1, g2, g3, g4;
@ -406,18 +460,35 @@ poly1305_finish(poly1305_context *ctx, unsigned char mac[16]) {
h3 = st->h[3]; h3 = st->h[3];
h4 = st->h[4]; h4 = st->h[4];
c = h1 >> 26; h1 = h1 & 0x3ffffff; c = h1 >> 26;
h2 += c; c = h2 >> 26; h2 = h2 & 0x3ffffff; h1 = h1 & 0x3ffffff;
h3 += c; c = h3 >> 26; h3 = h3 & 0x3ffffff; h2 += c;
h4 += c; c = h4 >> 26; h4 = h4 & 0x3ffffff; c = h2 >> 26;
h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff; h2 = h2 & 0x3ffffff;
h3 += c;
c = h3 >> 26;
h3 = h3 & 0x3ffffff;
h4 += c;
c = h4 >> 26;
h4 = h4 & 0x3ffffff;
h0 += c * 5;
c = h0 >> 26;
h0 = h0 & 0x3ffffff;
h1 += c; h1 += c;
/* compute h + -p */ /* compute h + -p */
g0 = h0 + 5; c = g0 >> 26; g0 &= 0x3ffffff; g0 = h0 + 5;
g1 = h1 + c; c = g1 >> 26; g1 &= 0x3ffffff; c = g0 >> 26;
g2 = h2 + c; c = g2 >> 26; g2 &= 0x3ffffff; g0 &= 0x3ffffff;
g3 = h3 + c; c = g3 >> 26; g3 &= 0x3ffffff; g1 = h1 + c;
c = g1 >> 26;
g1 &= 0x3ffffff;
g2 = h2 + c;
c = g2 >> 26;
g2 &= 0x3ffffff;
g3 = h3 + c;
c = g3 >> 26;
g3 &= 0x3ffffff;
g4 = h4 + c - (1 << 26); g4 = h4 + c - (1 << 26);
/* select h if h < p, or h + -p if h >= p */ /* select h if h < p, or h + -p if h >= p */
@ -441,10 +512,14 @@ poly1305_finish(poly1305_context *ctx, unsigned char mac[16]) {
h3 = ((h3 >> 18) | (h4 << 8)) & 0xffffffff; h3 = ((h3 >> 18) | (h4 << 8)) & 0xffffffff;
/* mac = (h + pad) % (2^128) */ /* mac = (h + pad) % (2^128) */
f = (unsigned long long)h0 + st->pad[0] ; h0 = (unsigned long)f; f = (unsigned long long)h0 + st->pad[0];
f = (unsigned long long)h1 + st->pad[1] + (f >> 32); h1 = (unsigned long)f; h0 = (unsigned long)f;
f = (unsigned long long)h2 + st->pad[2] + (f >> 32); h2 = (unsigned long)f; f = (unsigned long long)h1 + st->pad[1] + (f >> 32);
f = (unsigned long long)h3 + st->pad[3] + (f >> 32); h3 = (unsigned long)f; h1 = (unsigned long)f;
f = (unsigned long long)h2 + st->pad[2] + (f >> 32);
h2 = (unsigned long)f;
f = (unsigned long long)h3 + st->pad[3] + (f >> 32);
h3 = (unsigned long)f;
U32TO8(mac + 0, h0); U32TO8(mac + 0, h0);
U32TO8(mac + 4, h1); U32TO8(mac + 4, h1);
@ -472,7 +547,8 @@ poly1305_finish(poly1305_context *ctx, unsigned char mac[16]) {
#endif // MSC/GCC or not #endif // MSC/GCC or not
static inline void poly1305_update(poly1305_context *ctx, const unsigned char *m, size_t bytes) { static inline void poly1305_update(poly1305_context* ctx, const unsigned char* m, size_t bytes)
{
poly1305_state_internal_t* st = (poly1305_state_internal_t*)ctx; poly1305_state_internal_t* st = (poly1305_state_internal_t*)ctx;
size_t i; size_t i;

View file

@ -30,8 +30,7 @@ namespace ZeroTier {
* keystream as a one-time-use key. These 32 bytes are then discarded and * keystream as a one-time-use key. These 32 bytes are then discarded and
* the packet is encrypted with the next N bytes. * the packet is encrypted with the next N bytes.
*/ */
class Poly1305 class Poly1305 {
{
public: public:
/** /**
* Compute a one-time authentication code * Compute a one-time authentication code

View file

@ -12,12 +12,13 @@
/****/ /****/
#include "Revocation.hpp" #include "Revocation.hpp"
#include "RuntimeEnvironment.hpp"
#include "Identity.hpp" #include "Identity.hpp"
#include "Topology.hpp"
#include "Switch.hpp"
#include "Network.hpp" #include "Network.hpp"
#include "Node.hpp" #include "Node.hpp"
#include "RuntimeEnvironment.hpp"
#include "Switch.hpp"
#include "Topology.hpp"
namespace ZeroTier { namespace ZeroTier {
@ -35,7 +36,8 @@ int Revocation::verify(const RuntimeEnvironment *RR,void *tPtr) const
Buffer<sizeof(Revocation) + 64> tmp; Buffer<sizeof(Revocation) + 64> tmp;
this->serialize(tmp, true); this->serialize(tmp, true);
return (id.verify(tmp.data(), tmp.size(), _signature) ? 0 : -1); return (id.verify(tmp.data(), tmp.size(), _signature) ? 0 : -1);
} catch ( ... ) { }
catch (...) {
return -1; return -1;
} }
} }

View file

@ -14,19 +14,19 @@
#ifndef ZT_REVOCATION_HPP #ifndef ZT_REVOCATION_HPP
#define ZT_REVOCATION_HPP #define ZT_REVOCATION_HPP
#include "../include/ZeroTierOne.h"
#include "Address.hpp"
#include "Buffer.hpp"
#include "Constants.hpp"
#include "Credential.hpp"
#include "ECC.hpp"
#include "Identity.hpp"
#include "Utils.hpp"
#include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdint.h>
#include "Constants.hpp"
#include "../include/ZeroTierOne.h"
#include "Credential.hpp"
#include "Address.hpp"
#include "ECC.hpp"
#include "Utils.hpp"
#include "Buffer.hpp"
#include "Identity.hpp"
/** /**
* Flag: fast propagation via rumor mill algorithm * Flag: fast propagation via rumor mill algorithm
@ -40,20 +40,14 @@ class RuntimeEnvironment;
/** /**
* Revocation certificate to instantaneously revoke a COM, capability, or tag * Revocation certificate to instantaneously revoke a COM, capability, or tag
*/ */
class Revocation : public Credential class Revocation : public Credential {
{
public: public:
static inline Credential::Type credentialType() { return Credential::CREDENTIAL_TYPE_REVOCATION; } static inline Credential::Type credentialType()
{
return Credential::CREDENTIAL_TYPE_REVOCATION;
}
Revocation() : Revocation() : _id(0), _credentialId(0), _networkId(0), _threshold(0), _flags(0), _target(), _signedBy(), _type(Credential::CREDENTIAL_TYPE_NULL)
_id(0),
_credentialId(0),
_networkId(0),
_threshold(0),
_flags(0),
_target(),
_signedBy(),
_type(Credential::CREDENTIAL_TYPE_NULL)
{ {
memset(_signature.data, 0, sizeof(_signature.data)); memset(_signature.data, 0, sizeof(_signature.data));
} }
@ -67,28 +61,52 @@ public:
* @param tgt Target node whose credential(s) are being revoked * @param tgt Target node whose credential(s) are being revoked
* @param ct Credential type being revoked * @param ct Credential type being revoked
*/ */
Revocation(const uint32_t i,const uint64_t nwid,const uint32_t cid,const int64_t thr,const uint64_t fl,const Address &tgt,const Credential::Type ct) : Revocation(const uint32_t i, const uint64_t nwid, const uint32_t cid, const int64_t thr, const uint64_t fl, const Address& tgt, const Credential::Type ct)
_id(i), : _id(i)
_credentialId(cid), , _credentialId(cid)
_networkId(nwid), , _networkId(nwid)
_threshold(thr), , _threshold(thr)
_flags(fl), , _flags(fl)
_target(tgt), , _target(tgt)
_signedBy(), , _signedBy()
_type(ct) , _type(ct)
{ {
memset(_signature.data, 0, sizeof(_signature.data)); memset(_signature.data, 0, sizeof(_signature.data));
} }
inline uint32_t id() const { return _id; } inline uint32_t id() const
inline uint32_t credentialId() const { return _credentialId; } {
inline uint64_t networkId() const { return _networkId; } return _id;
inline int64_t threshold() const { return _threshold; } }
inline const Address &target() const { return _target; } inline uint32_t credentialId() const
inline const Address &signer() const { return _signedBy; } {
inline Credential::Type type() const { return _type; } return _credentialId;
}
inline uint64_t networkId() const
{
return _networkId;
}
inline int64_t threshold() const
{
return _threshold;
}
inline const Address& target() const
{
return _target;
}
inline const Address& signer() const
{
return _signedBy;
}
inline Credential::Type type() const
{
return _type;
}
inline bool fastPropagate() const { return ((_flags & ZT_REVOCATION_FLAG_FAST_PROPAGATE) != 0); } inline bool fastPropagate() const
{
return ((_flags & ZT_REVOCATION_FLAG_FAST_PROPAGATE) != 0);
}
/** /**
* @param signer Signing identity, must have private key * @param signer Signing identity, must have private key
@ -115,8 +133,7 @@ public:
*/ */
int verify(const RuntimeEnvironment* RR, void* tPtr) const; int verify(const RuntimeEnvironment* RR, void* tPtr) const;
template<unsigned int C> template <unsigned int C> inline void serialize(Buffer<C>& b, const bool forSign = false) const
inline void serialize(Buffer<C> &b,const bool forSign = false) const
{ {
if (forSign) { if (forSign) {
b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL); b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
@ -147,8 +164,7 @@ public:
} }
} }
template<unsigned int C> template <unsigned int C> inline unsigned int deserialize(const Buffer<C>& b, unsigned int startAt = 0)
inline unsigned int deserialize(const Buffer<C> &b,unsigned int startAt = 0)
{ {
*this = Revocation(); *this = Revocation();
@ -177,10 +193,12 @@ public:
p += 2; p += 2;
memcpy(_signature.data, b.field(p, ZT_ECC_SIGNATURE_LEN), ZT_ECC_SIGNATURE_LEN); memcpy(_signature.data, b.field(p, ZT_ECC_SIGNATURE_LEN), ZT_ECC_SIGNATURE_LEN);
p += ZT_ECC_SIGNATURE_LEN; p += ZT_ECC_SIGNATURE_LEN;
} else { }
else {
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN; throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN;
} }
} else { }
else {
p += 2 + b.template at<uint16_t>(p); p += 2 + b.template at<uint16_t>(p);
} }

View file

@ -14,12 +14,12 @@
#ifndef ZT_RINGBUFFER_H #ifndef ZT_RINGBUFFER_H
#define ZT_RINGBUFFER_H #define ZT_RINGBUFFER_H
#include <typeinfo>
#include <cstdint>
#include <stdlib.h>
#include <memory.h>
#include <algorithm> #include <algorithm>
#include <cstdint>
#include <math.h> #include <math.h>
#include <memory.h>
#include <stdlib.h>
#include <typeinfo>
namespace ZeroTier { namespace ZeroTier {
@ -34,9 +34,7 @@ namespace ZeroTier {
* to reduce the complexity of code needed to interact with this type of buffer. * to reduce the complexity of code needed to interact with this type of buffer.
*/ */
template <class T,size_t S> template <class T, size_t S> class RingBuffer {
class RingBuffer
{
private: private:
T buf[S]; T buf[S];
size_t begin; size_t begin;
@ -44,10 +42,7 @@ private:
bool wrap; bool wrap;
public: public:
RingBuffer() : RingBuffer() : begin(0), end(0), wrap(false)
begin(0),
end(0),
wrap(false)
{ {
memset(buf, 0, sizeof(T) * S); memset(buf, 0, sizeof(T) * S);
} }
@ -87,7 +82,10 @@ public:
* Fast erase, O(1). * Fast erase, O(1).
* Merely reset the buffer pointer, doesn't erase contents * Merely reset the buffer pointer, doesn't erase contents
*/ */
inline void reset() { consume(count()); } inline void reset()
{
consume(count());
}
/** /**
* adjust buffer index pointer as if we copied data out * adjust buffer index pointer as if we copied data out
@ -157,7 +155,10 @@ public:
/** /**
* @return The most recently pushed element on the buffer * @return The most recently pushed element on the buffer
*/ */
inline T get_most_recent() { return *(buf + end); } inline T get_most_recent()
{
return *(buf + end);
}
/** /**
* @param dest Destination buffer * @param dest Destination buffer
@ -193,9 +194,11 @@ public:
{ {
if (end == begin) { if (end == begin) {
return wrap ? S : 0; return wrap ? S : 0;
} else if (end > begin) { }
else if (end > begin) {
return end - begin; return end - begin;
} else { }
else {
return S + end - begin; return S + end - begin;
} }
} }
@ -203,7 +206,10 @@ public:
/** /**
* @return The number of slots that are unused in the buffer * @return The number of slots that are unused in the buffer
*/ */
inline size_t getFree() { return S - count(); } inline size_t getFree()
{
return S - count();
}
/** /**
* @return The arithmetic mean of the contents of the buffer * @return The arithmetic mean of the contents of the buffer
@ -254,7 +260,10 @@ public:
/** /**
* @return The sample standard deviation of element values * @return The sample standard deviation of element values
*/ */
inline float stddev() { return sqrt(variance()); } inline float stddev()
{
return sqrt(variance());
}
/** /**
* @return The variance of element values * @return The variance of element values

View file

@ -14,11 +14,11 @@
#ifndef ZT_RUNTIMEENVIRONMENT_HPP #ifndef ZT_RUNTIMEENVIRONMENT_HPP
#define ZT_RUNTIMEENVIRONMENT_HPP #define ZT_RUNTIMEENVIRONMENT_HPP
#include <string.h>
#include "Constants.hpp" #include "Constants.hpp"
#include "Utils.hpp"
#include "Identity.hpp" #include "Identity.hpp"
#include "Utils.hpp"
#include <string.h>
namespace ZeroTier { namespace ZeroTier {
@ -36,17 +36,9 @@ class PacketMultiplexer;
/** /**
* Holds global state for an instance of ZeroTier::Node * Holds global state for an instance of ZeroTier::Node
*/ */
class RuntimeEnvironment class RuntimeEnvironment {
{
public: public:
RuntimeEnvironment(Node *n) : RuntimeEnvironment(Node* n) : node(n), localNetworkController((NetworkController*)0), rtmem((void*)0), sw((Switch*)0), mc((Multicaster*)0), topology((Topology*)0), sa((SelfAwareness*)0)
node(n)
,localNetworkController((NetworkController *)0)
,rtmem((void *)0)
,sw((Switch *)0)
,mc((Multicaster *)0)
,topology((Topology *)0)
,sa((SelfAwareness *)0)
{ {
publicIdentityStr[0] = (char)0; publicIdentityStr[0] = (char)0;
secretIdentityStr[0] = (char)0; secretIdentityStr[0] = (char)0;

View file

@ -1,10 +1,11 @@
// This code is public domain, taken from a PD crypto source file on GitHub. // This code is public domain, taken from a PD crypto source file on GitHub.
#include <algorithm>
#include "SHA512.hpp" #include "SHA512.hpp"
#include "Utils.hpp" #include "Utils.hpp"
#include <algorithm>
namespace ZeroTier { namespace ZeroTier {
#ifndef ZT_HAVE_NATIVE_SHA512 #ifndef ZT_HAVE_NATIVE_SHA512
@ -17,28 +18,15 @@ struct sha512_state {
uint8_t buf[128]; uint8_t buf[128];
}; };
static const uint64_t K[80] = { static const uint64_t K[80] = { 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL,
0x428a2f98d728ae22ULL,0x7137449123ef65cdULL,0xb5c0fbcfec4d3b2fULL,0xe9b5dba58189dbbcULL, 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
0x3956c25bf348b538ULL,0x59f111f1b605d019ULL,0x923f82a4af194f9bULL,0xab1c5ed5da6d8118ULL, 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL,
0xd807aa98a3030242ULL,0x12835b0145706fbeULL,0x243185be4ee4b28cULL,0x550c7dc3d5ffb4e2ULL, 0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
0x72be5d74f27b896fULL,0x80deb1fe3b1696b1ULL,0x9bdc06a725c71235ULL,0xc19bf174cf692694ULL, 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL,
0xe49b69c19ef14ad2ULL,0xefbe4786384f25e3ULL,0x0fc19dc68b8cd5b5ULL,0x240ca1cc77ac9c65ULL, 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
0x2de92c6f592b0275ULL,0x4a7484aa6ea6e483ULL,0x5cb0a9dcbd41fbd4ULL,0x76f988da831153b5ULL, 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL,
0x983e5152ee66dfabULL,0xa831c66d2db43210ULL,0xb00327c898fb213fULL,0xbf597fc7beef0ee4ULL, 0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
0xc6e00bf33da88fc2ULL,0xd5a79147930aa725ULL,0x06ca6351e003826fULL,0x142929670a0e6e70ULL, 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL };
0x27b70a8546d22ffcULL,0x2e1b21385c26c926ULL,0x4d2c6dfc5ac42aedULL,0x53380d139d95b3dfULL,
0x650a73548baf63deULL,0x766a0abb3c77b2a8ULL,0x81c2c92e47edaee6ULL,0x92722c851482353bULL,
0xa2bfe8a14cf10364ULL,0xa81a664bbc423001ULL,0xc24b8b70d0f89791ULL,0xc76c51a30654be30ULL,
0xd192e819d6ef5218ULL,0xd69906245565a910ULL,0xf40e35855771202aULL,0x106aa07032bbd1b8ULL,
0x19a4c116b8d2d0c8ULL,0x1e376c085141ab53ULL,0x2748774cdf8eeb99ULL,0x34b0bcb5e19b48a8ULL,
0x391c0cb3c5c95a63ULL,0x4ed8aa4ae3418acbULL,0x5b9cca4f7763e373ULL,0x682e6ff3d6b2b8a3ULL,
0x748f82ee5defb2fcULL,0x78a5636f43172f60ULL,0x84c87814a1f0ab72ULL,0x8cc702081a6439ecULL,
0x90befffa23631e28ULL,0xa4506cebde82bde9ULL,0xbef9a3f7b2c67915ULL,0xc67178f2e372532bULL,
0xca273eceea26619cULL,0xd186b8c721c0c207ULL,0xeada7dd6cde0eb1eULL,0xf57d4f7fee6ed178ULL,
0x06f067aa72176fbaULL,0x0a637dc5a2c898a6ULL,0x113f9804bef90daeULL,0x1b710b35131c471bULL,
0x28db77f523047d84ULL,0x32caab7b40c72493ULL,0x3c9ebe0a15c9bebcULL,0x431d67c49c100d4cULL,
0x4cc5d4becb3e42b6ULL,0x597f299cfc657e2aULL,0x5fcb6fab3ad6faecULL,0x6c44198c4a475817ULL
};
#define STORE64H(x, y) Utils::storeBigEndian<uint64_t>(y, x) #define STORE64H(x, y) Utils::storeBigEndian<uint64_t>(y, x)
#define LOAD64H(x, y) x = Utils::loadBigEndian<uint64_t>(y) #define LOAD64H(x, y) x = Utils::loadBigEndian<uint64_t>(y)
@ -126,7 +114,8 @@ static void sha512_process(sha512_state *const md,const uint8_t *in,unsigned lon
md->length += 128 * 8; md->length += 128 * 8;
in += 128; in += 128;
inlen -= 128; inlen -= 128;
} else { }
else {
unsigned long n = std::min(inlen, (128 - md->curlen)); unsigned long n = std::min(inlen, (128 - md->curlen));
Utils::copy(md->buf + md->curlen, in, n); Utils::copy(md->buf + md->curlen, in, n);
md->curlen += n; md->curlen += n;
@ -282,4 +271,6 @@ void KBKDFHMACSHA384(const uint8_t key[ZT_SYMMETRIC_KEY_SIZE],const char label,c
// Internally re-export to included C code, which includes some fast crypto code ported in on some platforms. // Internally re-export to included C code, which includes some fast crypto code ported in on some platforms.
// This eliminates the need to link against a third party SHA512() from this code // This eliminates the need to link against a third party SHA512() from this code
extern "C" void ZT_sha512internal(void* digest, const void* data, unsigned int len) extern "C" void ZT_sha512internal(void* digest, const void* data, unsigned int len)
{ ZeroTier::SHA512(digest,data,len); } {
ZeroTier::SHA512(digest, data, len);
}

View file

@ -7,9 +7,10 @@
* Since the original was public domain, this is too. * Since the original was public domain, this is too.
*/ */
#include "Constants.hpp"
#include "Salsa20.hpp" #include "Salsa20.hpp"
#include "Constants.hpp"
#define ROTATE(v, c) (((v) << (c)) | ((v) >> (32 - (c)))) #define ROTATE(v, c) (((v) << (c)) | ((v) >> (32 - (c))))
#define XOR(v, w) ((v) ^ (w)) #define XOR(v, w) ((v) ^ (w))
#define PLUS(v, w) ((uint32_t)((v) + (w))) #define PLUS(v, w) ((uint32_t)((v) + (w)))
@ -22,7 +23,13 @@
#ifdef ZT_NO_TYPE_PUNNING #ifdef ZT_NO_TYPE_PUNNING
// Slower version that does not use type punning // Slower version that does not use type punning
#define U8TO32_LITTLE(p) (((uint32_t)(p)[0]) | ((uint32_t)(p)[1] << 8) | ((uint32_t)(p)[2] << 16) | ((uint32_t)(p)[3] << 24)) #define U8TO32_LITTLE(p) (((uint32_t)(p)[0]) | ((uint32_t)(p)[1] << 8) | ((uint32_t)(p)[2] << 16) | ((uint32_t)(p)[3] << 24))
static inline void U32TO8_LITTLE(uint8_t *const c,const uint32_t v) { c[0] = (uint8_t)v; c[1] = (uint8_t)(v >> 8); c[2] = (uint8_t)(v >> 16); c[3] = (uint8_t)(v >> 24); } static inline void U32TO8_LITTLE(uint8_t* const c, const uint32_t v)
{
c[0] = (uint8_t)v;
c[1] = (uint8_t)(v >> 8);
c[2] = (uint8_t)(v >> 16);
c[3] = (uint8_t)(v >> 24);
}
#else #else
// Fast version that just does 32-bit load/store // Fast version that just does 32-bit load/store
#define U8TO32_LITTLE(p) (*((const uint32_t*)((const void*)(p)))) #define U8TO32_LITTLE(p) (*((const uint32_t*)((const void*)(p))))
@ -41,7 +48,13 @@ static inline void U32TO8_LITTLE(uint8_t *const c,const uint32_t v) { c[0] = (ui
// Otherwise do it the slow, manual way on BE machines // Otherwise do it the slow, manual way on BE machines
#define U8TO32_LITTLE(p) (((uint32_t)(p)[0]) | ((uint32_t)(p)[1] << 8) | ((uint32_t)(p)[2] << 16) | ((uint32_t)(p)[3] << 24)) #define U8TO32_LITTLE(p) (((uint32_t)(p)[0]) | ((uint32_t)(p)[1] << 8) | ((uint32_t)(p)[2] << 16) | ((uint32_t)(p)[3] << 24))
static inline void U32TO8_LITTLE(uint8_t *const c,const uint32_t v) { c[0] = (uint8_t)v; c[1] = (uint8_t)(v >> 8); c[2] = (uint8_t)(v >> 16); c[3] = (uint8_t)(v >> 24); } static inline void U32TO8_LITTLE(uint8_t* const c, const uint32_t v)
{
c[0] = (uint8_t)v;
c[1] = (uint8_t)(v >> 8);
c[2] = (uint8_t)(v >> 16);
c[3] = (uint8_t)(v >> 24);
}
#endif // __GNUC__ or not #endif // __GNUC__ or not
@ -51,8 +64,7 @@ static inline void U32TO8_LITTLE(uint8_t *const c,const uint32_t v) { c[0] = (ui
// Statically compute and define SSE constants // Statically compute and define SSE constants
#ifdef ZT_SALSA20_SSE #ifdef ZT_SALSA20_SSE
class _s20sseconsts class _s20sseconsts {
{
public: public:
_s20sseconsts() _s20sseconsts()
{ {

View file

@ -7,14 +7,14 @@
#ifndef ZT_SALSA20_HPP #ifndef ZT_SALSA20_HPP
#define ZT_SALSA20_HPP #define ZT_SALSA20_HPP
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "Constants.hpp" #include "Constants.hpp"
#include "Utils.hpp" #include "Utils.hpp"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if (! defined(ZT_SALSA20_SSE)) && (defined(__SSE2__) || (defined(__WINDOWS__) && ! defined(__MINGW32__) && ! defined(_M_ARM64))) #if (! defined(ZT_SALSA20_SSE)) && (defined(__SSE2__) || (defined(__WINDOWS__) && ! defined(__MINGW32__) && ! defined(_M_ARM64)))
#define ZT_SALSA20_SSE 1 #define ZT_SALSA20_SSE 1
#endif #endif
@ -28,11 +28,15 @@ namespace ZeroTier {
/** /**
* Salsa20 stream cipher * Salsa20 stream cipher
*/ */
class Salsa20 class Salsa20 {
{
public: public:
Salsa20() {} Salsa20()
~Salsa20() { Utils::burn(&_state,sizeof(_state)); } {
}
~Salsa20()
{
Utils::burn(&_state, sizeof(_state));
}
/** /**
* XOR d with s * XOR d with s

View file

@ -11,38 +11,38 @@
*/ */
/****/ /****/
#include "SelfAwareness.hpp"
#include "Constants.hpp"
#include "Node.hpp"
#include "Packet.hpp"
#include "Peer.hpp"
#include "RuntimeEnvironment.hpp"
#include "Switch.hpp"
#include "Topology.hpp"
#include "Trace.hpp"
#include <set>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <set>
#include <vector> #include <vector>
#include "Constants.hpp"
#include "SelfAwareness.hpp"
#include "RuntimeEnvironment.hpp"
#include "Node.hpp"
#include "Topology.hpp"
#include "Packet.hpp"
#include "Peer.hpp"
#include "Switch.hpp"
#include "Trace.hpp"
// Entry timeout -- make it fairly long since this is just to prevent stale buildup // Entry timeout -- make it fairly long since this is just to prevent stale buildup
#define ZT_SELFAWARENESS_ENTRY_TIMEOUT 600000 #define ZT_SELFAWARENESS_ENTRY_TIMEOUT 600000
namespace ZeroTier { namespace ZeroTier {
class _ResetWithinScope class _ResetWithinScope {
{
public: public:
_ResetWithinScope(void *tPtr,int64_t now,int inetAddressFamily,InetAddress::IpScope scope) : _ResetWithinScope(void* tPtr, int64_t now, int inetAddressFamily, InetAddress::IpScope scope) : _now(now), _tPtr(tPtr), _family(inetAddressFamily), _scope(scope)
_now(now), {
_tPtr(tPtr), }
_family(inetAddressFamily),
_scope(scope) {}
inline void operator()(Topology &t,const SharedPtr<Peer> &p) { p->resetWithinScope(_tPtr,_scope,_family,_now); } inline void operator()(Topology& t, const SharedPtr<Peer>& p)
{
p->resetWithinScope(_tPtr, _scope, _family, _now);
}
private: private:
uint64_t _now; uint64_t _now;
@ -51,9 +51,7 @@ private:
InetAddress::IpScope _scope; InetAddress::IpScope _scope;
}; };
SelfAwareness::SelfAwareness(const RuntimeEnvironment *renv) : SelfAwareness::SelfAwareness(const RuntimeEnvironment* renv) : RR(renv), _phy(128)
RR(renv),
_phy(128)
{ {
} }
@ -93,7 +91,8 @@ void SelfAwareness::iam(void *tPtr,const Address &reporter,const int64_t receive
// Reset all paths within this scope and address family // Reset all paths within this scope and address family
_ResetWithinScope rset(tPtr, now, myPhysicalAddress.ss_family, (InetAddress::IpScope)scope); _ResetWithinScope rset(tPtr, now, myPhysicalAddress.ss_family, (InetAddress::IpScope)scope);
RR->topology->eachPeer<_ResetWithinScope&>(rset); RR->topology->eachPeer<_ResetWithinScope&>(rset);
} else { }
else {
// Otherwise just update DB to use to determine external surface info // Otherwise just update DB to use to determine external surface info
entry.mySurface = myPhysicalAddress; entry.mySurface = myPhysicalAddress;
entry.ts = now; entry.ts = now;

View file

@ -14,10 +14,10 @@
#ifndef ZT_SELFAWARENESS_HPP #ifndef ZT_SELFAWARENESS_HPP
#define ZT_SELFAWARENESS_HPP #define ZT_SELFAWARENESS_HPP
#include "Constants.hpp"
#include "InetAddress.hpp"
#include "Hashtable.hpp"
#include "Address.hpp" #include "Address.hpp"
#include "Constants.hpp"
#include "Hashtable.hpp"
#include "InetAddress.hpp"
#include "Mutex.hpp" #include "Mutex.hpp"
namespace ZeroTier { namespace ZeroTier {
@ -27,8 +27,7 @@ class RuntimeEnvironment;
/** /**
* Tracks changes to this peer's real world addresses * Tracks changes to this peer's real world addresses
*/ */
class SelfAwareness class SelfAwareness {
{
public: public:
SelfAwareness(const RuntimeEnvironment* renv); SelfAwareness(const RuntimeEnvironment* renv);
@ -59,27 +58,39 @@ public:
void clean(int64_t now); void clean(int64_t now);
private: private:
struct PhySurfaceKey struct PhySurfaceKey {
{
Address reporter; Address reporter;
int64_t receivedOnLocalSocket; int64_t receivedOnLocalSocket;
InetAddress reporterPhysicalAddress; InetAddress reporterPhysicalAddress;
InetAddress::IpScope scope; InetAddress::IpScope scope;
PhySurfaceKey() : reporter(),scope(InetAddress::IP_SCOPE_NONE) {} PhySurfaceKey() : reporter(), scope(InetAddress::IP_SCOPE_NONE)
PhySurfaceKey(const Address &r,const int64_t rol,const InetAddress &ra,InetAddress::IpScope s) : reporter(r),receivedOnLocalSocket(rol),reporterPhysicalAddress(ra),scope(s) {}
inline unsigned long hashCode() const { return ((unsigned long)reporter.toInt() + (unsigned long)scope); }
inline bool operator==(const PhySurfaceKey &k) const { return ((reporter == k.reporter)&&(receivedOnLocalSocket == k.receivedOnLocalSocket)&&(reporterPhysicalAddress == k.reporterPhysicalAddress)&&(scope == k.scope)); }
};
struct PhySurfaceEntry
{ {
}
PhySurfaceKey(const Address& r, const int64_t rol, const InetAddress& ra, InetAddress::IpScope s) : reporter(r), receivedOnLocalSocket(rol), reporterPhysicalAddress(ra), scope(s)
{
}
inline unsigned long hashCode() const
{
return ((unsigned long)reporter.toInt() + (unsigned long)scope);
}
inline bool operator==(const PhySurfaceKey& k) const
{
return ((reporter == k.reporter) && (receivedOnLocalSocket == k.receivedOnLocalSocket) && (reporterPhysicalAddress == k.reporterPhysicalAddress) && (scope == k.scope));
}
};
struct PhySurfaceEntry {
InetAddress mySurface; InetAddress mySurface;
uint64_t ts; uint64_t ts;
bool trusted; bool trusted;
PhySurfaceEntry() : mySurface(),ts(0),trusted(false) {} PhySurfaceEntry() : mySurface(), ts(0), trusted(false)
PhySurfaceEntry(const InetAddress &a,const uint64_t t) : mySurface(a),ts(t),trusted(false) {} {
}
PhySurfaceEntry(const InetAddress& a, const uint64_t t) : mySurface(a), ts(t), trusted(false)
{
}
}; };
const RuntimeEnvironment* RR; const RuntimeEnvironment* RR;

View file

@ -14,8 +14,8 @@
#ifndef ZT_SHAREDPTR_HPP #ifndef ZT_SHAREDPTR_HPP
#define ZT_SHAREDPTR_HPP #define ZT_SHAREDPTR_HPP
#include "Mutex.hpp"
#include "AtomicCounter.hpp" #include "AtomicCounter.hpp"
#include "Mutex.hpp"
namespace ZeroTier { namespace ZeroTier {
@ -26,13 +26,18 @@ namespace ZeroTier {
* counted must list this as a 'friend' and must have a private instance of * counted must list this as a 'friend' and must have a private instance of
* AtomicCounter called __refCount. * AtomicCounter called __refCount.
*/ */
template<typename T> template <typename T> class SharedPtr {
class SharedPtr
{
public: public:
SharedPtr() : _ptr((T *)0) {} SharedPtr() : _ptr((T*)0)
SharedPtr(T *obj) : _ptr(obj) { ++obj->__refCount; } {
SharedPtr(const SharedPtr &sp) : _ptr(sp._getAndInc()) {} }
SharedPtr(T* obj) : _ptr(obj)
{
++obj->__refCount;
}
SharedPtr(const SharedPtr& sp) : _ptr(sp._getAndInc())
{
}
~SharedPtr() ~SharedPtr()
{ {
@ -84,14 +89,26 @@ public:
with._ptr = tmp; with._ptr = tmp;
} }
inline operator bool() const { return (_ptr != (T *)0); } inline operator bool() const
inline T &operator*() const { return *_ptr; } {
inline T *operator->() const { return _ptr; } return (_ptr != (T*)0);
}
inline T& operator*() const
{
return *_ptr;
}
inline T* operator->() const
{
return _ptr;
}
/** /**
* @return Raw pointer to held object * @return Raw pointer to held object
*/ */
inline T *ptr() const { return _ptr; } inline T* ptr() const
{
return _ptr;
}
/** /**
* Set this pointer to NULL * Set this pointer to NULL
@ -117,12 +134,30 @@ public:
return 0; return 0;
} }
inline bool operator==(const SharedPtr &sp) const { return (_ptr == sp._ptr); } inline bool operator==(const SharedPtr& sp) const
inline bool operator!=(const SharedPtr &sp) const { return (_ptr != sp._ptr); } {
inline bool operator>(const SharedPtr &sp) const { return (_ptr > sp._ptr); } return (_ptr == sp._ptr);
inline bool operator<(const SharedPtr &sp) const { return (_ptr < sp._ptr); } }
inline bool operator>=(const SharedPtr &sp) const { return (_ptr >= sp._ptr); } inline bool operator!=(const SharedPtr& sp) const
inline bool operator<=(const SharedPtr &sp) const { return (_ptr <= sp._ptr); } {
return (_ptr != sp._ptr);
}
inline bool operator>(const SharedPtr& sp) const
{
return (_ptr > sp._ptr);
}
inline bool operator<(const SharedPtr& sp) const
{
return (_ptr < sp._ptr);
}
inline bool operator>=(const SharedPtr& sp) const
{
return (_ptr >= sp._ptr);
}
inline bool operator<=(const SharedPtr& sp) const
{
return (_ptr <= sp._ptr);
}
private: private:
inline T* _getAndInc() const inline T* _getAndInc() const

View file

@ -11,35 +11,30 @@
*/ */
/****/ /****/
#include <stdio.h> #include "Switch.hpp"
#include <stdlib.h>
#include "../include/ZeroTierOne.h"
#include "../version.h"
#include "Constants.hpp"
#include "InetAddress.hpp"
#include "Metrics.hpp"
#include "Node.hpp"
#include "Packet.hpp"
#include "Peer.hpp"
#include "RuntimeEnvironment.hpp"
#include "SelfAwareness.hpp"
#include "Topology.hpp"
#include "Trace.hpp"
#include <algorithm> #include <algorithm>
#include <utility>
#include <stdexcept> #include <stdexcept>
#include <stdio.h>
#include "../version.h" #include <stdlib.h>
#include "../include/ZeroTierOne.h" #include <utility>
#include "Constants.hpp"
#include "RuntimeEnvironment.hpp"
#include "Switch.hpp"
#include "Node.hpp"
#include "InetAddress.hpp"
#include "Topology.hpp"
#include "Peer.hpp"
#include "SelfAwareness.hpp"
#include "Packet.hpp"
#include "Trace.hpp"
#include "Metrics.hpp"
namespace ZeroTier { namespace ZeroTier {
Switch::Switch(const RuntimeEnvironment *renv) : Switch::Switch(const RuntimeEnvironment* renv) : RR(renv), _lastBeaconResponse(0), _lastCheckedQueues(0), _lastUniteAttempt(8) // only really used on root servers and upstreams, and it'll grow there just fine
RR(renv),
_lastBeaconResponse(0),
_lastCheckedQueues(0),
_lastUniteAttempt(8) // only really used on root servers and upstreams, and it'll grow there just fine
{ {
} }
@ -109,7 +104,8 @@ void Switch::onRemotePacket(void *tPtr,const int64_t localSocket,const InetAddre
} }
} }
} }
} else { }
else {
// Fragment looks like ours // Fragment looks like ours
const uint64_t fragmentPacketId = fragment.packetId(); const uint64_t fragmentPacketId = fragment.packetId();
const unsigned int fragmentNumber = fragment.fragmentNumber(); const unsigned int fragmentNumber = fragment.fragmentNumber();
@ -133,7 +129,8 @@ void Switch::onRemotePacket(void *tPtr,const int64_t localSocket,const InetAddre
rq->totalFragments = totalFragments; // total fragment count is known rq->totalFragments = totalFragments; // total fragment count is known
rq->haveFragments = 1 << fragmentNumber; // we have only this fragment rq->haveFragments = 1 << fragmentNumber; // we have only this fragment
rq->complete = false; rq->complete = false;
} else if (!(rq->haveFragments & (1 << fragmentNumber))) { }
else if (! (rq->haveFragments & (1 << fragmentNumber))) {
// We have other fragments and maybe the head, so add this one and check // We have other fragments and maybe the head, so add this one and check
rq->frags[fragmentNumber - 1] = fragment; rq->frags[fragmentNumber - 1] = fragment;
@ -148,7 +145,8 @@ void Switch::onRemotePacket(void *tPtr,const int64_t localSocket,const InetAddre
if (rq->frag0.tryDecode(RR, tPtr, flowId)) { if (rq->frag0.tryDecode(RR, tPtr, flowId)) {
rq->timestamp = 0; // packet decoded, free entry rq->timestamp = 0; // packet decoded, free entry
} else { }
else {
rq->complete = true; // set complete flag but leave entry since it probably needs WHOIS or something rq->complete = true; // set complete flag but leave entry since it probably needs WHOIS or something
} }
} }
@ -157,7 +155,8 @@ void Switch::onRemotePacket(void *tPtr,const int64_t localSocket,const InetAddre
} }
// -------------------------------------------------------------------- // --------------------------------------------------------------------
} else if (len >= ZT_PROTO_MIN_PACKET_LENGTH) { // min length check is important! }
else if (len >= ZT_PROTO_MIN_PACKET_LENGTH) { // min length check is important!
// Handle packet head ------------------------------------------------- // Handle packet head -------------------------------------------------
const Address destination(reinterpret_cast<const uint8_t*>(data) + 8, ZT_ADDRESS_LENGTH); const Address destination(reinterpret_cast<const uint8_t*>(data) + 8, ZT_ADDRESS_LENGTH);
@ -184,7 +183,8 @@ void Switch::onRemotePacket(void *tPtr,const int64_t localSocket,const InetAddre
relayTo->introduce(tPtr, now, sourcePeer); relayTo->introduce(tPtr, now, sourcePeer);
} }
} }
} else { }
else {
relayTo = RR->topology->getUpstreamPeer(); relayTo = RR->topology->getUpstreamPeer();
if ((relayTo) && (relayTo->address() != source)) { if ((relayTo) && (relayTo->address() != source)) {
if (relayTo->sendDirect(tPtr, packet.data(), packet.size(), now, true)) { if (relayTo->sendDirect(tPtr, packet.data(), packet.size(), now, true)) {
@ -196,19 +196,14 @@ void Switch::onRemotePacket(void *tPtr,const int64_t localSocket,const InetAddre
} }
} }
} }
} else if ((reinterpret_cast<const uint8_t *>(data)[ZT_PACKET_IDX_FLAGS] & ZT_PROTO_FLAG_FRAGMENTED) != 0) { }
else if ((reinterpret_cast<const uint8_t*>(data)[ZT_PACKET_IDX_FLAGS] & ZT_PROTO_FLAG_FRAGMENTED) != 0) {
// Packet is the head of a fragmented packet series // Packet is the head of a fragmented packet series
const uint64_t packetId = ( const uint64_t packetId =
(((uint64_t)reinterpret_cast<const uint8_t *>(data)[0]) << 56) | ((((uint64_t)reinterpret_cast<const uint8_t*>(data)[0]) << 56) | (((uint64_t)reinterpret_cast<const uint8_t*>(data)[1]) << 48) | (((uint64_t)reinterpret_cast<const uint8_t*>(data)[2]) << 40)
(((uint64_t)reinterpret_cast<const uint8_t *>(data)[1]) << 48) | | (((uint64_t)reinterpret_cast<const uint8_t*>(data)[3]) << 32) | (((uint64_t)reinterpret_cast<const uint8_t*>(data)[4]) << 24) | (((uint64_t)reinterpret_cast<const uint8_t*>(data)[5]) << 16)
(((uint64_t)reinterpret_cast<const uint8_t *>(data)[2]) << 40) | | (((uint64_t)reinterpret_cast<const uint8_t*>(data)[6]) << 8) | ((uint64_t)reinterpret_cast<const uint8_t*>(data)[7]));
(((uint64_t)reinterpret_cast<const uint8_t *>(data)[3]) << 32) |
(((uint64_t)reinterpret_cast<const uint8_t *>(data)[4]) << 24) |
(((uint64_t)reinterpret_cast<const uint8_t *>(data)[5]) << 16) |
(((uint64_t)reinterpret_cast<const uint8_t *>(data)[6]) << 8) |
((uint64_t)reinterpret_cast<const uint8_t *>(data)[7])
);
RXQueueEntry* const rq = _findRXQueueEntry(packetId); RXQueueEntry* const rq = _findRXQueueEntry(packetId);
Mutex::Lock rql(rq->lock); Mutex::Lock rql(rq->lock);
@ -222,7 +217,8 @@ void Switch::onRemotePacket(void *tPtr,const int64_t localSocket,const InetAddre
rq->totalFragments = 0; rq->totalFragments = 0;
rq->haveFragments = 1; rq->haveFragments = 1;
rq->complete = false; rq->complete = false;
} else if (!(rq->haveFragments & 1)) { }
else if (! (rq->haveFragments & 1)) {
// If we have other fragments but no head, see if we are complete with the head // If we have other fragments but no head, see if we are complete with the head
if ((rq->totalFragments > 1) && (Utils::countBits(rq->haveFragments |= 1) == rq->totalFragments)) { if ((rq->totalFragments > 1) && (Utils::countBits(rq->haveFragments |= 1) == rq->totalFragments)) {
@ -235,15 +231,18 @@ void Switch::onRemotePacket(void *tPtr,const int64_t localSocket,const InetAddre
if (rq->frag0.tryDecode(RR, tPtr, flowId)) { if (rq->frag0.tryDecode(RR, tPtr, flowId)) {
rq->timestamp = 0; // packet decoded, free entry rq->timestamp = 0; // packet decoded, free entry
} else { }
else {
rq->complete = true; // set complete flag but leave entry since it probably needs WHOIS or something rq->complete = true; // set complete flag but leave entry since it probably needs WHOIS or something
} }
} else { }
else {
// Still waiting on more fragments, but keep the head // Still waiting on more fragments, but keep the head
rq->frag0.init(data, len, path, now); rq->frag0.init(data, len, path, now);
} }
} // else this is a duplicate head, ignore } // else this is a duplicate head, ignore
} else { }
else {
// Packet is unfragmented, so just process it // Packet is unfragmented, so just process it
IncomingPacket packet(data, len, path, now); IncomingPacket packet(data, len, path, now);
if (! packet.tryDecode(RR, tPtr, flowId)) { if (! packet.tryDecode(RR, tPtr, flowId)) {
@ -262,7 +261,9 @@ void Switch::onRemotePacket(void *tPtr,const int64_t localSocket,const InetAddre
// -------------------------------------------------------------------- // --------------------------------------------------------------------
} }
} }
} catch ( ... ) {} // sanity check, should be caught elsewhere }
catch (...) {
} // sanity check, should be caught elsewhere
} }
void Switch::onLocalEthernet(void* tPtr, const SharedPtr<Network>& network, const MAC& from, const MAC& to, unsigned int etherType, unsigned int vlanId, const void* data, unsigned int len) void Switch::onLocalEthernet(void* tPtr, const SharedPtr<Network>& network, const MAC& from, const MAC& to, unsigned int etherType, unsigned int vlanId, const void* data, unsigned int len)
@ -354,7 +355,8 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr<Network> &network,const
MulticastGroup multicastGroup(to, 0); MulticastGroup multicastGroup(to, 0);
if (to.isBroadcast()) { if (to.isBroadcast()) {
if ( (etherType == ZT_ETHERTYPE_ARP) && (len >= 28) && ((((const uint8_t *)data)[2] == 0x08)&&(((const uint8_t *)data)[3] == 0x00)&&(((const uint8_t *)data)[4] == 6)&&(((const uint8_t *)data)[5] == 4)&&(((const uint8_t *)data)[7] == 0x01)) ) { if ((etherType == ZT_ETHERTYPE_ARP) && (len >= 28)
&& ((((const uint8_t*)data)[2] == 0x08) && (((const uint8_t*)data)[3] == 0x00) && (((const uint8_t*)data)[4] == 6) && (((const uint8_t*)data)[5] == 4) && (((const uint8_t*)data)[7] == 0x01))) {
/* IPv4 ARP is one of the few special cases that we impose upon what is /* IPv4 ARP is one of the few special cases that we impose upon what is
* otherwise a straightforward Ethernet switch emulation. Vanilla ARP * otherwise a straightforward Ethernet switch emulation. Vanilla ARP
* is dumb old broadcast and simply doesn't scale. ZeroTier multicast * is dumb old broadcast and simply doesn't scale. ZeroTier multicast
@ -365,12 +367,14 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr<Network> &network,const
* the 32-bit ADI field. In practice this uses our multicast pub/sub * the 32-bit ADI field. In practice this uses our multicast pub/sub
* system to implement a kind of extended/distributed ARP table. */ * system to implement a kind of extended/distributed ARP table. */
multicastGroup = MulticastGroup::deriveMulticastGroupForAddressResolution(InetAddress(((const unsigned char*)data) + 24, 4, 0)); multicastGroup = MulticastGroup::deriveMulticastGroupForAddressResolution(InetAddress(((const unsigned char*)data) + 24, 4, 0));
} else if (!network->config().enableBroadcast()) { }
else if (! network->config().enableBroadcast()) {
// Don't transmit broadcasts if this network doesn't want them // Don't transmit broadcasts if this network doesn't want them
RR->t->outgoingNetworkFrameDropped(tPtr, network, from, to, etherType, vlanId, len, "broadcast disabled"); RR->t->outgoingNetworkFrameDropped(tPtr, network, from, to, etherType, vlanId, len, "broadcast disabled");
return; return;
} }
} else if ((etherType == ZT_ETHERTYPE_IPV6)&&(len >= (40 + 8 + 16))) { }
else if ((etherType == ZT_ETHERTYPE_IPV6) && (len >= (40 + 8 + 16))) {
// IPv6 NDP emulation for certain very special patterns of private IPv6 addresses -- if enabled // IPv6 NDP emulation for certain very special patterns of private IPv6 addresses -- if enabled
if ((network->config().ndpEmulation()) && (reinterpret_cast<const uint8_t*>(data)[6] == 0x3a) && (reinterpret_cast<const uint8_t*>(data)[40] == 0x87)) { // ICMPv6 neighbor solicitation if ((network->config().ndpEmulation()) && (reinterpret_cast<const uint8_t*>(data)[6] == 0x3a) && (reinterpret_cast<const uint8_t*>(data)[40] == 0x87)) { // ICMPv6 neighbor solicitation
Address v6EmbeddedAddress; Address v6EmbeddedAddress;
@ -401,7 +405,8 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr<Network> &network,const
v6EmbeddedAddress.setTo(pkt6 + ptr, 5); v6EmbeddedAddress.setTo(pkt6 + ptr, 5);
break; break;
} }
} else if (sipNetmaskBits == 40) { // ZT-6PLANE /40 ??? }
else if (sipNetmaskBits == 40) { // ZT-6PLANE /40 ???
const uint32_t nwid32 = (uint32_t)((network->id() ^ (network->id() >> 32)) & 0xffffffff); const uint32_t nwid32 = (uint32_t)((network->id() ^ (network->id() >> 32)) & 0xffffffff);
if ((my6[0] == 0xfc) && (my6[1] == (uint8_t)((nwid32 >> 24) & 0xff)) && (my6[2] == (uint8_t)((nwid32 >> 16) & 0xff)) && (my6[3] == (uint8_t)((nwid32 >> 8) & 0xff)) && (my6[4] == (uint8_t)(nwid32 & 0xff))) { if ((my6[0] == 0xfc) && (my6[1] == (uint8_t)((nwid32 >> 24) & 0xff)) && (my6[2] == (uint8_t)((nwid32 >> 16) & 0xff)) && (my6[3] == (uint8_t)((nwid32 >> 8) & 0xff)) && (my6[4] == (uint8_t)(nwid32 & 0xff))) {
unsigned int ptr = 0; unsigned int ptr = 0;
@ -491,9 +496,7 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr<Network> &network,const
// //
std::thread([=]() { std::thread([=]() {
RR->node->putFrame(tPtr, network->id(), network->userPtr(), peerMac, from, ZT_ETHERTYPE_IPV6, 0, adv, 72); RR->node->putFrame(tPtr, network->id(), network->userPtr(), peerMac, from, ZT_ETHERTYPE_IPV6, 0, adv, 72);
}).detach(); }).detach();
return; // NDP emulation done. We have forged a "fake" reply, so no need to send actual NDP query. return; // NDP emulation done. We have forged a "fake" reply, so no need to send actual NDP query.
@ -521,30 +524,19 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr<Network> &network,const
return; return;
} }
RR->mc->send( RR->mc->send(tPtr, RR->node->now(), network, Address(), multicastGroup, (fromBridged) ? from : MAC(), etherType, data, len);
tPtr, }
RR->node->now(), else if (to == network->mac()) {
network,
Address(),
multicastGroup,
(fromBridged) ? from : MAC(),
etherType,
data,
len);
} else if (to == network->mac()) {
// Destination is this node, so just reinject it // Destination is this node, so just reinject it
// //
// same pattern as putFrame call above // same pattern as putFrame call above
// //
std::thread([=]() { std::thread([=]() {
RR->node->putFrame(tPtr, network->id(), network->userPtr(), from, to, etherType, vlanId, data, len); RR->node->putFrame(tPtr, network->id(), network->userPtr(), from, to, etherType, vlanId, data, len);
}).detach(); }).detach();
}
} else if (to[0] == MAC::firstOctetForNetwork(network->id())) { else if (to[0] == MAC::firstOctetForNetwork(network->id())) {
// Destination is another ZeroTier peer on the same network // Destination is another ZeroTier peer on the same network
Address toZT(to.toAddress(network->id())); // since in-network MACs are derived from addresses and network IDs, we can reverse this Address toZT(to.toAddress(network->id())); // since in-network MACs are derived from addresses and network IDs, we can reverse this
@ -566,7 +558,8 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr<Network> &network,const
// if (!network->config().disableCompression()) // if (!network->config().disableCompression())
// outp.compress(); // outp.compress();
aqm_enqueue(tPtr, network, outp, true, qosBucket, flowId); aqm_enqueue(tPtr, network, outp, true, qosBucket, flowId);
} else { }
else {
Packet outp(toZT, RR->identity.address(), Packet::VERB_EXT_FRAME); Packet outp(toZT, RR->identity.address(), Packet::VERB_EXT_FRAME);
outp.append(network->id()); outp.append(network->id());
outp.append((unsigned char)0x00); outp.append((unsigned char)0x00);
@ -579,7 +572,8 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr<Network> &network,const
// outp.compress(); // outp.compress();
aqm_enqueue(tPtr, network, outp, true, qosBucket, flowId); aqm_enqueue(tPtr, network, outp, true, qosBucket, flowId);
} }
} else { }
else {
// Destination is bridged behind a remote peer // Destination is bridged behind a remote peer
// We filter with a NULL destination ZeroTier address first. Filtrations // We filter with a NULL destination ZeroTier address first. Filtrations
@ -599,7 +593,8 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr<Network> &network,const
if ((bridges[0]) && (bridges[0] != RR->identity.address()) && (network->config().permitsBridging(bridges[0]))) { if ((bridges[0]) && (bridges[0] != RR->identity.address()) && (network->config().permitsBridging(bridges[0]))) {
/* We have a known bridge route for this MAC, send it there. */ /* We have a known bridge route for this MAC, send it there. */
++numBridges; ++numBridges;
} else if (!activeBridges.empty()) { }
else if (! activeBridges.empty()) {
/* If there is no known route, spam to up to ZT_MAX_BRIDGE_SPAM active /* If there is no known route, spam to up to ZT_MAX_BRIDGE_SPAM active
* bridges. If someone responds, we'll learn the route. */ * bridges. If someone responds, we'll learn the route. */
std::vector<Address>::const_iterator ab(activeBridges.begin()); std::vector<Address>::const_iterator ab(activeBridges.begin());
@ -609,7 +604,8 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr<Network> &network,const
bridges[numBridges++] = *ab; bridges[numBridges++] = *ab;
++ab; ++ab;
} }
} else { }
else {
// Otherwise pick a random set of them // Otherwise pick a random set of them
while (numBridges < ZT_MAX_BRIDGE_SPAM) { while (numBridges < ZT_MAX_BRIDGE_SPAM) {
if (ab == activeBridges.end()) { if (ab == activeBridges.end()) {
@ -618,7 +614,8 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr<Network> &network,const
if (((unsigned long)RR->node->prng() % (unsigned long)activeBridges.size()) == 0) { if (((unsigned long)RR->node->prng() % (unsigned long)activeBridges.size()) == 0) {
bridges[numBridges++] = *ab; bridges[numBridges++] = *ab;
++ab; ++ab;
} else { }
else {
++ab; ++ab;
} }
} }
@ -638,7 +635,8 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr<Network> &network,const
// if (!network->config().disableCompression()) // if (!network->config().disableCompression())
// outp.compress(); // outp.compress();
aqm_enqueue(tPtr, network, outp, true, qosBucket, flowId); aqm_enqueue(tPtr, network, outp, true, qosBucket, flowId);
} else { }
else {
RR->t->outgoingNetworkFrameDropped(tPtr, network, from, to, etherType, vlanId, len, "filter blocked (bridge replication)"); RR->t->outgoingNetworkFrameDropped(tPtr, network, from, to, etherType, vlanId, len, "filter blocked (bridge replication)");
} }
} }
@ -764,12 +762,14 @@ Switch::dqr Switch::dodequeue(ManagedQueue *q, uint64_t now)
if (sojourn_time < ZT_AQM_TARGET || q->byteLength <= ZT_DEFAULT_MTU) { if (sojourn_time < ZT_AQM_TARGET || q->byteLength <= ZT_DEFAULT_MTU) {
// went below - stay below for at least interval // went below - stay below for at least interval
q->first_above_time = 0; q->first_above_time = 0;
} else { }
else {
if (q->first_above_time == 0) { if (q->first_above_time == 0) {
// just went above from below. if still above at // just went above from below. if still above at
// first_above_time, will say it's ok to drop. // first_above_time, will say it's ok to drop.
q->first_above_time = now + ZT_AQM_INTERVAL; q->first_above_time = now + ZT_AQM_INTERVAL;
} else if (now >= q->first_above_time) { }
else if (now >= q->first_above_time) {
r.ok_to_drop = true; r.ok_to_drop = true;
} }
} }
@ -790,18 +790,19 @@ Switch::TXQueueEntry * Switch::CoDelDequeue(ManagedQueue *q, bool isNew, uint64_
if (! r.ok_to_drop) { if (! r.ok_to_drop) {
// leave dropping state // leave dropping state
q->dropping = false; q->dropping = false;
} else { }
else {
++(q->count); ++(q->count);
// schedule the next drop. // schedule the next drop.
q->drop_next = control_law(q->drop_next, q->count); q->drop_next = control_law(q->drop_next, q->count);
} }
} }
} else if (r.ok_to_drop) { }
else if (r.ok_to_drop) {
q->q.pop_front(); // drop q->q.pop_front(); // drop
r = dodequeue(q, now); r = dodequeue(q, now);
q->dropping = true; q->dropping = true;
q->count = (q->count > 2 && now - q->drop_next < 8*ZT_AQM_INTERVAL)? q->count = (q->count > 2 && now - q->drop_next < 8 * ZT_AQM_INTERVAL) ? q->count - 2 : 1;
q->count - 2 : 1;
q->drop_next = control_law(now, q->count); q->drop_next = control_law(now, q->count);
} }
return r.p; return r.p;
@ -833,14 +834,16 @@ void Switch::aqm_dequeue(void *tPtr)
// DEBUG_INFO("moving q=%p from NEW to OLD list", queueAtFrontOfList); // DEBUG_INFO("moving q=%p from NEW to OLD list", queueAtFrontOfList);
oldQueues->push_back(queueAtFrontOfList); oldQueues->push_back(queueAtFrontOfList);
currQueues->erase(currQueues->begin()); currQueues->erase(currQueues->begin());
} else { }
else {
entryToEmit = CoDelDequeue(queueAtFrontOfList, examiningNewQueues, now); entryToEmit = CoDelDequeue(queueAtFrontOfList, examiningNewQueues, now);
if (! entryToEmit) { if (! entryToEmit) {
// Move to end of list of OLD queues // Move to end of list of OLD queues
// DEBUG_INFO("moving q=%p from NEW to OLD list", queueAtFrontOfList); // DEBUG_INFO("moving q=%p from NEW to OLD list", queueAtFrontOfList);
oldQueues->push_back(queueAtFrontOfList); oldQueues->push_back(queueAtFrontOfList);
currQueues->erase(currQueues->begin()); currQueues->erase(currQueues->begin());
} else { }
else {
int len = entryToEmit->packet.payloadLength(); int len = entryToEmit->packet.payloadLength();
queueAtFrontOfList->byteLength -= len; queueAtFrontOfList->byteLength -= len;
queueAtFrontOfList->byteCredit -= len; queueAtFrontOfList->byteCredit -= len;
@ -865,14 +868,16 @@ void Switch::aqm_dequeue(void *tPtr)
queueAtFrontOfList->byteCredit += ZT_AQM_QUANTUM; queueAtFrontOfList->byteCredit += ZT_AQM_QUANTUM;
oldQueues->push_back(queueAtFrontOfList); oldQueues->push_back(queueAtFrontOfList);
currQueues->erase(currQueues->begin()); currQueues->erase(currQueues->begin());
} else { }
else {
entryToEmit = CoDelDequeue(queueAtFrontOfList, examiningNewQueues, now); entryToEmit = CoDelDequeue(queueAtFrontOfList, examiningNewQueues, now);
if (! entryToEmit) { if (! entryToEmit) {
// DEBUG_INFO("moving q=%p from OLD to INACTIVE list", queueAtFrontOfList); // DEBUG_INFO("moving q=%p from OLD to INACTIVE list", queueAtFrontOfList);
// Move to inactive list of queues // Move to inactive list of queues
inactiveQueues->push_back(queueAtFrontOfList); inactiveQueues->push_back(queueAtFrontOfList);
currQueues->erase(currQueues->begin()); currQueues->erase(currQueues->begin());
} else { }
else {
int len = entryToEmit->packet.payloadLength(); int len = entryToEmit->packet.payloadLength();
queueAtFrontOfList->byteLength -= len; queueAtFrontOfList->byteLength -= len;
queueAtFrontOfList->byteCredit -= len; queueAtFrontOfList->byteCredit -= len;
@ -933,7 +938,8 @@ void Switch::requestWhois(void *tPtr,const int64_t now,const Address &addr)
int64_t& last = _lastSentWhoisRequest[addr]; int64_t& last = _lastSentWhoisRequest[addr];
if ((now - last) < ZT_WHOIS_RETRY_DELAY) { if ((now - last) < ZT_WHOIS_RETRY_DELAY) {
return; return;
} else { }
else {
last = now; last = now;
} }
} }
@ -971,10 +977,12 @@ void Switch::doAnythingWaitingForPeer(void *tPtr,const SharedPtr<Peer> &peer)
if (txi->dest == peer->address()) { if (txi->dest == peer->address()) {
if (_trySend(tPtr, txi->packet, txi->encrypt, txi->flowId)) { if (_trySend(tPtr, txi->packet, txi->encrypt, txi->flowId)) {
_txQueue.erase(txi++); _txQueue.erase(txi++);
} else { }
else {
++txi; ++txi;
} }
} else { }
else {
++txi; ++txi;
} }
} }
@ -996,9 +1004,11 @@ unsigned long Switch::doTimerTasks(void *tPtr,int64_t now)
for (std::list<TXQueueEntry>::iterator txi(_txQueue.begin()); txi != _txQueue.end();) { for (std::list<TXQueueEntry>::iterator txi(_txQueue.begin()); txi != _txQueue.end();) {
if (_trySend(tPtr, txi->packet, txi->encrypt, txi->flowId)) { if (_trySend(tPtr, txi->packet, txi->encrypt, txi->flowId)) {
_txQueue.erase(txi++); _txQueue.erase(txi++);
} else if ((now - txi->creationTime) > ZT_TRANSMIT_QUEUE_TIMEOUT) { }
else if ((now - txi->creationTime) > ZT_TRANSMIT_QUEUE_TIMEOUT) {
_txQueue.erase(txi++); _txQueue.erase(txi++);
} else { }
else {
if (! RR->topology->getPeer(tPtr, txi->dest)) { if (! RR->topology->getPeer(tPtr, txi->dest)) {
needWhois.push_back(txi->dest); needWhois.push_back(txi->dest);
} }
@ -1016,7 +1026,8 @@ unsigned long Switch::doTimerTasks(void *tPtr,int64_t now)
if ((rq->timestamp) && (rq->complete)) { if ((rq->timestamp) && (rq->complete)) {
if ((rq->frag0.tryDecode(RR, tPtr, rq->flowId)) || ((now - rq->timestamp) > ZT_RECEIVE_QUEUE_TIMEOUT)) { if ((rq->frag0.tryDecode(RR, tPtr, rq->flowId)) || ((now - rq->timestamp) > ZT_RECEIVE_QUEUE_TIMEOUT)) {
rq->timestamp = 0; rq->timestamp = 0;
} else { }
else {
const Address src(rq->frag0.source()); const Address src(rq->frag0.source());
if (! RR->topology->getPeer(tPtr, src)) { if (! RR->topology->getPeer(tPtr, src)) {
requestWhois(tPtr, now, src); requestWhois(tPtr, now, src);
@ -1071,8 +1082,7 @@ bool Switch::_trySend(void *tPtr,Packet &packet,bool encrypt,int32_t flowId)
const SharedPtr<Peer> peer(RR->topology->getPeer(tPtr, destination)); const SharedPtr<Peer> peer(RR->topology->getPeer(tPtr, destination));
if (peer) { if (peer) {
if ((peer->bondingPolicy() == ZT_BOND_POLICY_BROADCAST) if ((peer->bondingPolicy() == ZT_BOND_POLICY_BROADCAST) && (packet.verb() == Packet::VERB_FRAME || packet.verb() == Packet::VERB_EXT_FRAME)) {
&& (packet.verb() == Packet::VERB_FRAME || packet.verb() == Packet::VERB_EXT_FRAME)) {
const SharedPtr<Peer> relay(RR->topology->getUpstreamPeer()); const SharedPtr<Peer> relay(RR->topology->getUpstreamPeer());
Mutex::Lock _l(peer->_paths_m); Mutex::Lock _l(peer->_paths_m);
for (int i = 0; i < ZT_MAX_PEER_NETWORK_PATHS; ++i) { for (int i = 0; i < ZT_MAX_PEER_NETWORK_PATHS; ++i) {
@ -1082,7 +1092,8 @@ bool Switch::_trySend(void *tPtr,Packet &packet,bool encrypt,int32_t flowId)
} }
} }
return true; return true;
} else { }
else {
viaPath = peer->getAppropriatePath(now, false, flowId); viaPath = peer->getAppropriatePath(now, false, flowId);
if (! viaPath) { if (! viaPath) {
peer->tryMemorizedPath(tPtr, now); // periodically attempt memorized or statically defined paths, if any are known peer->tryMemorizedPath(tPtr, now); // periodically attempt memorized or statically defined paths, if any are known
@ -1117,7 +1128,8 @@ void Switch::_sendViaSpecificPath(void *tPtr,SharedPtr<Peer> peer,SharedPtr<Path
if (trustedPathId) { if (trustedPathId) {
packet.setTrusted(trustedPathId); packet.setTrusted(trustedPathId);
} else { }
else {
if (! packet.isEncrypted()) { if (! packet.isEncrypted()) {
packet.armor(peer->key(), encrypt, false, peer->aesKeysIfSupported(), peer->identity()); packet.armor(peer->key(), encrypt, false, peer->aesKeysIfSupported(), peer->identity());
} }
@ -1148,7 +1160,8 @@ void Switch::_sendViaSpecificPath(void *tPtr,SharedPtr<Peer> peer,SharedPtr<Path
} }
} }
void Switch::_recordOutgoingPacketMetrics(const Packet &p) { void Switch::_recordOutgoingPacketMetrics(const Packet& p)
{
switch (p.verb()) { switch (p.verb()) {
case Packet::VERB_NOP: case Packet::VERB_NOP:
Metrics::pkt_nop_out++; Metrics::pkt_nop_out++;

View file

@ -14,22 +14,22 @@
#ifndef ZT_N_SWITCH_HPP #ifndef ZT_N_SWITCH_HPP
#define ZT_N_SWITCH_HPP #define ZT_N_SWITCH_HPP
#include "Constants.hpp"
#include "Hashtable.hpp"
#include "IncomingPacket.hpp"
#include "InetAddress.hpp"
#include "MAC.hpp"
#include "Mutex.hpp"
#include "Network.hpp"
#include "Packet.hpp"
#include "SharedPtr.hpp"
#include "Topology.hpp"
#include "Utils.hpp"
#include <list>
#include <map> #include <map>
#include <set> #include <set>
#include <vector> #include <vector>
#include <list>
#include "Constants.hpp"
#include "Mutex.hpp"
#include "MAC.hpp"
#include "Packet.hpp"
#include "Utils.hpp"
#include "InetAddress.hpp"
#include "Topology.hpp"
#include "Network.hpp"
#include "SharedPtr.hpp"
#include "IncomingPacket.hpp"
#include "Hashtable.hpp"
/* Ethernet frame types that might be relevant to us */ /* Ethernet frame types that might be relevant to us */
#define ZT_ETHERTYPE_IPV4 0x0800 #define ZT_ETHERTYPE_IPV4 0x0800
@ -54,8 +54,7 @@ class Peer;
* packets from tap devices, and this sends them where they need to go and * packets from tap devices, and this sends them where they need to go and
* wraps/unwraps accordingly. It also handles queues and timeouts and such. * wraps/unwraps accordingly. It also handles queues and timeouts and such.
*/ */
class Switch class Switch {
{
struct ManagedQueue; struct ManagedQueue;
struct TXQueueEntry; struct TXQueueEntry;
@ -219,9 +218,10 @@ private:
Mutex _lastSentWhoisRequest_m; Mutex _lastSentWhoisRequest_m;
// Packets waiting for WHOIS replies or other decode info or missing fragments // Packets waiting for WHOIS replies or other decode info or missing fragments
struct RXQueueEntry struct RXQueueEntry {
RXQueueEntry() : timestamp(0)
{ {
RXQueueEntry() : timestamp(0) {} }
volatile int64_t timestamp; // 0 if entry is not in use volatile int64_t timestamp; // 0 if entry is not in use
volatile uint64_t packetId; volatile uint64_t packetId;
IncomingPacket frag0; // head of packet IncomingPacket frag0; // head of packet
@ -256,15 +256,13 @@ private:
} }
// ZeroTier-layer TX queue entry // ZeroTier-layer TX queue entry
struct TXQueueEntry struct TXQueueEntry {
TXQueueEntry()
{ {
TXQueueEntry() {} }
TXQueueEntry(Address d,uint64_t ct,const Packet &p,bool enc,int32_t fid) : TXQueueEntry(Address d, uint64_t ct, const Packet& p, bool enc, int32_t fid) : dest(d), creationTime(ct), packet(p), encrypt(enc), flowId(fid)
dest(d), {
creationTime(ct), }
packet(p),
encrypt(enc),
flowId(fid) {}
Address dest; Address dest;
uint64_t creationTime; uint64_t creationTime;
@ -277,35 +275,39 @@ private:
Mutex _aqm_m; Mutex _aqm_m;
// Tracks sending of VERB_RENDEZVOUS to relaying peers // Tracks sending of VERB_RENDEZVOUS to relaying peers
struct _LastUniteKey struct _LastUniteKey {
_LastUniteKey() : x(0), y(0)
{ {
_LastUniteKey() : x(0),y(0) {} }
_LastUniteKey(const Address& a1, const Address& a2) _LastUniteKey(const Address& a1, const Address& a2)
{ {
if (a1 > a2) { if (a1 > a2) {
x = a2.toInt(); x = a2.toInt();
y = a1.toInt(); y = a1.toInt();
} else { }
else {
x = a1.toInt(); x = a1.toInt();
y = a2.toInt(); y = a2.toInt();
} }
} }
inline unsigned long hashCode() const { return ((unsigned long)x ^ (unsigned long)y); } inline unsigned long hashCode() const
inline bool operator==(const _LastUniteKey &k) const { return ((x == k.x)&&(y == k.y)); } {
return ((unsigned long)x ^ (unsigned long)y);
}
inline bool operator==(const _LastUniteKey& k) const
{
return ((x == k.x) && (y == k.y));
}
uint64_t x, y; uint64_t x, y;
}; };
Hashtable<_LastUniteKey, uint64_t> _lastUniteAttempt; // key is always sorted in ascending order, for set-like behavior Hashtable<_LastUniteKey, uint64_t> _lastUniteAttempt; // key is always sorted in ascending order, for set-like behavior
Mutex _lastUniteAttempt_m; Mutex _lastUniteAttempt_m;
// Queue with additional flow state variables // Queue with additional flow state variables
struct ManagedQueue struct ManagedQueue {
ManagedQueue(int id) : id(id), byteCredit(ZT_AQM_QUANTUM), byteLength(0), dropping(false)
{ {
ManagedQueue(int id) : }
id(id),
byteCredit(ZT_AQM_QUANTUM),
byteLength(0),
dropping(false)
{}
int id; int id;
int byteCredit; int byteCredit;
int byteLength; int byteLength;
@ -317,8 +319,7 @@ private:
std::list<TXQueueEntry*> q; std::list<TXQueueEntry*> q;
}; };
// To implement fq_codel we need to maintain a queue of queues // To implement fq_codel we need to maintain a queue of queues
struct NetworkQoSControlBlock struct NetworkQoSControlBlock {
{
int _currEnqueuedPackets; int _currEnqueuedPackets;
std::vector<ManagedQueue*> newQueues; std::vector<ManagedQueue*> newQueues;
std::vector<ManagedQueue*> oldQueues; std::vector<ManagedQueue*> oldQueues;

View file

@ -12,12 +12,13 @@
/****/ /****/
#include "Tag.hpp" #include "Tag.hpp"
#include "RuntimeEnvironment.hpp"
#include "Identity.hpp" #include "Identity.hpp"
#include "Topology.hpp"
#include "Switch.hpp"
#include "Network.hpp" #include "Network.hpp"
#include "Node.hpp" #include "Node.hpp"
#include "RuntimeEnvironment.hpp"
#include "Switch.hpp"
#include "Topology.hpp"
namespace ZeroTier { namespace ZeroTier {
@ -35,7 +36,8 @@ int Tag::verify(const RuntimeEnvironment *RR,void *tPtr) const
Buffer<(sizeof(Tag) * 2)> tmp; Buffer<(sizeof(Tag) * 2)> tmp;
this->serialize(tmp, true); this->serialize(tmp, true);
return (id.verify(tmp.data(), tmp.size(), _signature) ? 0 : -1); return (id.verify(tmp.data(), tmp.size(), _signature) ? 0 : -1);
} catch ( ... ) { }
catch (...) {
return -1; return -1;
} }
} }

View file

@ -14,18 +14,18 @@
#ifndef ZT_TAG_HPP #ifndef ZT_TAG_HPP
#define ZT_TAG_HPP #define ZT_TAG_HPP
#include "Address.hpp"
#include "Buffer.hpp"
#include "Constants.hpp"
#include "Credential.hpp"
#include "ECC.hpp"
#include "Identity.hpp"
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "Constants.hpp"
#include "Credential.hpp"
#include "ECC.hpp"
#include "Address.hpp"
#include "Identity.hpp"
#include "Buffer.hpp"
namespace ZeroTier { namespace ZeroTier {
class RuntimeEnvironment; class RuntimeEnvironment;
@ -47,16 +47,14 @@ class RuntimeEnvironment;
* Unlike capabilities tags are signed only by the issuer and are never * Unlike capabilities tags are signed only by the issuer and are never
* transferable. * transferable.
*/ */
class Tag : public Credential class Tag : public Credential {
{
public: public:
static inline Credential::Type credentialType() { return Credential::CREDENTIAL_TYPE_TAG; } static inline Credential::Type credentialType()
{
return Credential::CREDENTIAL_TYPE_TAG;
}
Tag() : Tag() : _id(0), _value(0), _networkId(0), _ts(0)
_id(0),
_value(0),
_networkId(0),
_ts(0)
{ {
memset(_signature.data, 0, sizeof(_signature.data)); memset(_signature.data, 0, sizeof(_signature.data));
} }
@ -68,23 +66,35 @@ public:
* @param id Tag ID * @param id Tag ID
* @param value Tag value * @param value Tag value
*/ */
Tag(const uint64_t nwid,const int64_t ts,const Address &issuedTo,const uint32_t id,const uint32_t value) : Tag(const uint64_t nwid, const int64_t ts, const Address& issuedTo, const uint32_t id, const uint32_t value) : _id(id), _value(value), _networkId(nwid), _ts(ts), _issuedTo(issuedTo), _signedBy()
_id(id),
_value(value),
_networkId(nwid),
_ts(ts),
_issuedTo(issuedTo),
_signedBy()
{ {
memset(_signature.data, 0, sizeof(_signature.data)); memset(_signature.data, 0, sizeof(_signature.data));
} }
inline uint32_t id() const { return _id; } inline uint32_t id() const
inline const uint32_t &value() const { return _value; } {
inline uint64_t networkId() const { return _networkId; } return _id;
inline int64_t timestamp() const { return _ts; } }
inline const Address &issuedTo() const { return _issuedTo; } inline const uint32_t& value() const
inline const Address &signedBy() const { return _signedBy; } {
return _value;
}
inline uint64_t networkId() const
{
return _networkId;
}
inline int64_t timestamp() const
{
return _ts;
}
inline const Address& issuedTo() const
{
return _issuedTo;
}
inline const Address& signedBy() const
{
return _signedBy;
}
/** /**
* Sign this tag * Sign this tag
@ -113,8 +123,7 @@ public:
*/ */
int verify(const RuntimeEnvironment* RR, void* tPtr) const; int verify(const RuntimeEnvironment* RR, void* tPtr) const;
template<unsigned int C> template <unsigned int C> inline void serialize(Buffer<C>& b, const bool forSign = false) const
inline void serialize(Buffer<C> &b,const bool forSign = false) const
{ {
if (forSign) { if (forSign) {
b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL); b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
@ -140,8 +149,7 @@ public:
} }
} }
template<unsigned int C> template <unsigned int C> inline unsigned int deserialize(const Buffer<C>& b, unsigned int startAt = 0)
inline unsigned int deserialize(const Buffer<C> &b,unsigned int startAt = 0)
{ {
unsigned int p = startAt; unsigned int p = startAt;
@ -168,7 +176,8 @@ public:
p += 2; p += 2;
memcpy(_signature.data, b.field(p, ZT_ECC_SIGNATURE_LEN), ZT_ECC_SIGNATURE_LEN); memcpy(_signature.data, b.field(p, ZT_ECC_SIGNATURE_LEN), ZT_ECC_SIGNATURE_LEN);
p += ZT_ECC_SIGNATURE_LEN; p += ZT_ECC_SIGNATURE_LEN;
} else { }
else {
p += 2 + b.template at<uint16_t>(p); p += 2 + b.template at<uint16_t>(p);
} }
@ -181,23 +190,58 @@ public:
} }
// Provides natural sort order by ID // Provides natural sort order by ID
inline bool operator<(const Tag &t) const { return (_id < t._id); } inline bool operator<(const Tag& t) const
{
return (_id < t._id);
}
inline bool operator==(const Tag &t) const { return (memcmp(this,&t,sizeof(Tag)) == 0); } inline bool operator==(const Tag& t) const
inline bool operator!=(const Tag &t) const { return (memcmp(this,&t,sizeof(Tag)) != 0); } {
return (memcmp(this, &t, sizeof(Tag)) == 0);
}
inline bool operator!=(const Tag& t) const
{
return (memcmp(this, &t, sizeof(Tag)) != 0);
}
// For searching sorted arrays or lists of Tags by ID // For searching sorted arrays or lists of Tags by ID
struct IdComparePredicate struct IdComparePredicate {
inline bool operator()(const Tag& a, const Tag& b) const
{ {
inline bool operator()(const Tag &a,const Tag &b) const { return (a.id() < b.id()); } return (a.id() < b.id());
inline bool operator()(const uint32_t a,const Tag &b) const { return (a < b.id()); } }
inline bool operator()(const Tag &a,const uint32_t b) const { return (a.id() < b); } inline bool operator()(const uint32_t a, const Tag& b) const
inline bool operator()(const Tag *a,const Tag *b) const { return (a->id() < b->id()); } {
inline bool operator()(const Tag *a,const Tag &b) const { return (a->id() < b.id()); } return (a < b.id());
inline bool operator()(const Tag &a,const Tag *b) const { return (a.id() < b->id()); } }
inline bool operator()(const uint32_t a,const Tag *b) const { return (a < b->id()); } inline bool operator()(const Tag& a, const uint32_t b) const
inline bool operator()(const Tag *a,const uint32_t b) const { return (a->id() < b); } {
inline bool operator()(const uint32_t a,const uint32_t b) const { return (a < b); } return (a.id() < b);
}
inline bool operator()(const Tag* a, const Tag* b) const
{
return (a->id() < b->id());
}
inline bool operator()(const Tag* a, const Tag& b) const
{
return (a->id() < b.id());
}
inline bool operator()(const Tag& a, const Tag* b) const
{
return (a.id() < b->id());
}
inline bool operator()(const uint32_t a, const Tag* b) const
{
return (a < b->id());
}
inline bool operator()(const Tag* a, const uint32_t b) const
{
return (a->id() < b);
}
inline bool operator()(const uint32_t a, const uint32_t b) const
{
return (a < b);
}
}; };
private: private:

View file

@ -11,24 +11,38 @@
*/ */
/****/ /****/
#include "Constants.hpp"
#include "Topology.hpp" #include "Topology.hpp"
#include "RuntimeEnvironment.hpp"
#include "Node.hpp" #include "Buffer.hpp"
#include "Constants.hpp"
#include "Network.hpp" #include "Network.hpp"
#include "NetworkConfig.hpp" #include "NetworkConfig.hpp"
#include "Buffer.hpp" #include "Node.hpp"
#include "RuntimeEnvironment.hpp"
#include "Switch.hpp" #include "Switch.hpp"
namespace ZeroTier { namespace ZeroTier {
#define ZT_DEFAULT_WORLD_LENGTH 570 #define ZT_DEFAULT_WORLD_LENGTH 570
static const unsigned char ZT_DEFAULT_WORLD[ZT_DEFAULT_WORLD_LENGTH] = {0x01,0x00,0x00,0x00,0x00,0x08,0xea,0xc9,0x0a,0x00,0x00,0x01,0x7e,0xe9,0x57,0x60,0xcd,0xb8,0xb3,0x88,0xa4,0x69,0x22,0x14,0x91,0xaa,0x9a,0xcd,0x66,0xcc,0x76,0x4c,0xde,0xfd,0x56,0x03,0x9f,0x10,0x67,0xae,0x15,0xe6,0x9c,0x6f,0xb4,0x2d,0x7b,0x55,0x33,0x0e,0x3f,0xda,0xac,0x52,0x9c,0x07,0x92,0xfd,0x73,0x40,0xa6,0xaa,0x21,0xab,0xa8,0xa4,0x89,0xfd,0xae,0xa4,0x4a,0x39,0xbf,0x2d,0x00,0x65,0x9a,0xc9,0xc8,0x18,0xeb,0x36,0x00,0x92,0x76,0x37,0xef,0x4d,0x14,0x04,0xa4,0x4d,0x54,0x46,0x84,0x85,0x13,0x79,0x75,0x1f,0xaa,0x79,0xb4,0xc4,0xea,0x85,0x04,0x01,0x75,0xea,0x06,0x58,0x60,0x48,0x24,0x02,0xe1,0xeb,0x34,0x20,0x52,0x00,0x0e,0x62,0x90,0x06,0x1a,0x9b,0xe0,0xcd,0x29,0x3c,0x8b,0x55,0xf1,0xc3,0xd2,0x52,0x48,0x08,0xaf,0xc5,0x49,0x22,0x08,0x0e,0x35,0x39,0xa7,0x5a,0xdd,0xc3,0xce,0xf0,0xf6,0xad,0x26,0x0d,0x58,0x82,0x93,0xbb,0x77,0x86,0xe7,0x1e,0xfa,0x4b,0x90,0x57,0xda,0xd9,0x86,0x7a,0xfe,0x12,0xdd,0x04,0xca,0xfe,0x9e,0xfe,0xb9,0x00,0xcc,0xde,0xf7,0x6b,0xc7,0xb9,0x7d,0xed,0x90,0x4e,0xab,0xc5,0xdf,0x09,0x88,0x6d,0x9c,0x15,0x14,0xa6,0x10,0x03,0x6c,0xb9,0x13,0x9c,0xc2,0x14,0x00,0x1a,0x29,0x58,0x97,0x8e,0xfc,0xec,0x15,0x71,0x2d,0xd3,0x94,0x8c,0x6e,0x6b,0x3a,0x8e,0x89,0x3d,0xf0,0x1f,0xf4,0x93,0xd1,0xf8,0xd9,0x80,0x6a,0x86,0x0c,0x54,0x20,0x57,0x1b,0xf0,0x00,0x02,0x04,0x68,0xc2,0x08,0x86,0x27,0x09,0x06,0x26,0x05,0x98,0x80,0x02,0x00,0x12,0x00,0x00,0x30,0x05,0x71,0x0e,0x34,0x00,0x51,0x27,0x09,0x77,0x8c,0xde,0x71,0x90,0x00,0x3f,0x66,0x81,0xa9,0x9e,0x5a,0xd1,0x89,0x5e,0x9f,0xba,0x33,0xe6,0x21,0x2d,0x44,0x54,0xe1,0x68,0xbc,0xec,0x71,0x12,0x10,0x1b,0xf0,0x00,0x95,0x6e,0xd8,0xe9,0x2e,0x42,0x89,0x2c,0xb6,0xf2,0xec,0x41,0x08,0x81,0xa8,0x4a,0xb1,0x9d,0xa5,0x0e,0x12,0x87,0xba,0x3d,0x92,0x6c,0x3a,0x1f,0x75,0x5c,0xcc,0xf2,0x99,0xa1,0x20,0x70,0x55,0x00,0x02,0x04,0x67,0xc3,0x67,0x42,0x27,0x09,0x06,0x26,0x05,0x98,0x80,0x04,0x00,0x00,0xc3,0x02,0x54,0xf2,0xbc,0xa1,0xf7,0x00,0x19,0x27,0x09,0x62,0xf8,0x65,0xae,0x71,0x00,0xe2,0x07,0x6c,0x57,0xde,0x87,0x0e,0x62,0x88,0xd7,0xd5,0xe7,0x40,0x44,0x08,0xb1,0x54,0x5e,0xfc,0xa3,0x7d,0x67,0xf7,0x7b,0x87,0xe9,0xe5,0x41,0x68,0xc2,0x5d,0x3e,0xf1,0xa9,0xab,0xf2,0x90,0x5e,0xa5,0xe7,0x85,0xc0,0x1d,0xff,0x23,0x88,0x7a,0xd4,0x23,0x2d,0x95,0xc7,0xa8,0xfd,0x2c,0x27,0x11,0x1a,0x72,0xbd,0x15,0x93,0x22,0xdc,0x00,0x02,0x04,0x32,0x07,0xfc,0x8a,0x27,0x09,0x06,0x20,0x01,0x49,0xf0,0xd0,0xdb,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x27,0x09,0xca,0xfe,0x04,0xeb,0xa9,0x00,0x6c,0x6a,0x9d,0x1d,0xea,0x55,0xc1,0x61,0x6b,0xfe,0x2a,0x2b,0x8f,0x0f,0xf9,0xa8,0xca,0xca,0xf7,0x03,0x74,0xfb,0x1f,0x39,0xe3,0xbe,0xf8,0x1c,0xbf,0xeb,0xef,0x17,0xb7,0x22,0x82,0x68,0xa0,0xa2,0xa2,0x9d,0x34,0x88,0xc7,0x52,0x56,0x5c,0x6c,0x96,0x5c,0xbd,0x65,0x06,0xec,0x24,0x39,0x7c,0xc8,0xa5,0xd9,0xd1,0x52,0x85,0xa8,0x7f,0x00,0x02,0x04,0x54,0x11,0x35,0x9b,0x27,0x09,0x06,0x2a,0x02,0x6e,0xa0,0xd4,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x99,0x93,0x27,0x09}; static const unsigned char ZT_DEFAULT_WORLD[ZT_DEFAULT_WORLD_LENGTH] = {
0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xea, 0xc9, 0x0a, 0x00, 0x00, 0x01, 0x7e, 0xe9, 0x57, 0x60, 0xcd, 0xb8, 0xb3, 0x88, 0xa4, 0x69, 0x22, 0x14, 0x91, 0xaa, 0x9a, 0xcd, 0x66, 0xcc, 0x76, 0x4c, 0xde, 0xfd, 0x56, 0x03, 0x9f, 0x10,
0x67, 0xae, 0x15, 0xe6, 0x9c, 0x6f, 0xb4, 0x2d, 0x7b, 0x55, 0x33, 0x0e, 0x3f, 0xda, 0xac, 0x52, 0x9c, 0x07, 0x92, 0xfd, 0x73, 0x40, 0xa6, 0xaa, 0x21, 0xab, 0xa8, 0xa4, 0x89, 0xfd, 0xae, 0xa4, 0x4a, 0x39, 0xbf, 0x2d, 0x00, 0x65,
0x9a, 0xc9, 0xc8, 0x18, 0xeb, 0x36, 0x00, 0x92, 0x76, 0x37, 0xef, 0x4d, 0x14, 0x04, 0xa4, 0x4d, 0x54, 0x46, 0x84, 0x85, 0x13, 0x79, 0x75, 0x1f, 0xaa, 0x79, 0xb4, 0xc4, 0xea, 0x85, 0x04, 0x01, 0x75, 0xea, 0x06, 0x58, 0x60, 0x48,
0x24, 0x02, 0xe1, 0xeb, 0x34, 0x20, 0x52, 0x00, 0x0e, 0x62, 0x90, 0x06, 0x1a, 0x9b, 0xe0, 0xcd, 0x29, 0x3c, 0x8b, 0x55, 0xf1, 0xc3, 0xd2, 0x52, 0x48, 0x08, 0xaf, 0xc5, 0x49, 0x22, 0x08, 0x0e, 0x35, 0x39, 0xa7, 0x5a, 0xdd, 0xc3,
0xce, 0xf0, 0xf6, 0xad, 0x26, 0x0d, 0x58, 0x82, 0x93, 0xbb, 0x77, 0x86, 0xe7, 0x1e, 0xfa, 0x4b, 0x90, 0x57, 0xda, 0xd9, 0x86, 0x7a, 0xfe, 0x12, 0xdd, 0x04, 0xca, 0xfe, 0x9e, 0xfe, 0xb9, 0x00, 0xcc, 0xde, 0xf7, 0x6b, 0xc7, 0xb9,
0x7d, 0xed, 0x90, 0x4e, 0xab, 0xc5, 0xdf, 0x09, 0x88, 0x6d, 0x9c, 0x15, 0x14, 0xa6, 0x10, 0x03, 0x6c, 0xb9, 0x13, 0x9c, 0xc2, 0x14, 0x00, 0x1a, 0x29, 0x58, 0x97, 0x8e, 0xfc, 0xec, 0x15, 0x71, 0x2d, 0xd3, 0x94, 0x8c, 0x6e, 0x6b,
0x3a, 0x8e, 0x89, 0x3d, 0xf0, 0x1f, 0xf4, 0x93, 0xd1, 0xf8, 0xd9, 0x80, 0x6a, 0x86, 0x0c, 0x54, 0x20, 0x57, 0x1b, 0xf0, 0x00, 0x02, 0x04, 0x68, 0xc2, 0x08, 0x86, 0x27, 0x09, 0x06, 0x26, 0x05, 0x98, 0x80, 0x02, 0x00, 0x12, 0x00,
0x00, 0x30, 0x05, 0x71, 0x0e, 0x34, 0x00, 0x51, 0x27, 0x09, 0x77, 0x8c, 0xde, 0x71, 0x90, 0x00, 0x3f, 0x66, 0x81, 0xa9, 0x9e, 0x5a, 0xd1, 0x89, 0x5e, 0x9f, 0xba, 0x33, 0xe6, 0x21, 0x2d, 0x44, 0x54, 0xe1, 0x68, 0xbc, 0xec, 0x71,
0x12, 0x10, 0x1b, 0xf0, 0x00, 0x95, 0x6e, 0xd8, 0xe9, 0x2e, 0x42, 0x89, 0x2c, 0xb6, 0xf2, 0xec, 0x41, 0x08, 0x81, 0xa8, 0x4a, 0xb1, 0x9d, 0xa5, 0x0e, 0x12, 0x87, 0xba, 0x3d, 0x92, 0x6c, 0x3a, 0x1f, 0x75, 0x5c, 0xcc, 0xf2, 0x99,
0xa1, 0x20, 0x70, 0x55, 0x00, 0x02, 0x04, 0x67, 0xc3, 0x67, 0x42, 0x27, 0x09, 0x06, 0x26, 0x05, 0x98, 0x80, 0x04, 0x00, 0x00, 0xc3, 0x02, 0x54, 0xf2, 0xbc, 0xa1, 0xf7, 0x00, 0x19, 0x27, 0x09, 0x62, 0xf8, 0x65, 0xae, 0x71, 0x00,
0xe2, 0x07, 0x6c, 0x57, 0xde, 0x87, 0x0e, 0x62, 0x88, 0xd7, 0xd5, 0xe7, 0x40, 0x44, 0x08, 0xb1, 0x54, 0x5e, 0xfc, 0xa3, 0x7d, 0x67, 0xf7, 0x7b, 0x87, 0xe9, 0xe5, 0x41, 0x68, 0xc2, 0x5d, 0x3e, 0xf1, 0xa9, 0xab, 0xf2, 0x90, 0x5e,
0xa5, 0xe7, 0x85, 0xc0, 0x1d, 0xff, 0x23, 0x88, 0x7a, 0xd4, 0x23, 0x2d, 0x95, 0xc7, 0xa8, 0xfd, 0x2c, 0x27, 0x11, 0x1a, 0x72, 0xbd, 0x15, 0x93, 0x22, 0xdc, 0x00, 0x02, 0x04, 0x32, 0x07, 0xfc, 0x8a, 0x27, 0x09, 0x06, 0x20, 0x01,
0x49, 0xf0, 0xd0, 0xdb, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x27, 0x09, 0xca, 0xfe, 0x04, 0xeb, 0xa9, 0x00, 0x6c, 0x6a, 0x9d, 0x1d, 0xea, 0x55, 0xc1, 0x61, 0x6b, 0xfe, 0x2a, 0x2b, 0x8f, 0x0f, 0xf9, 0xa8,
0xca, 0xca, 0xf7, 0x03, 0x74, 0xfb, 0x1f, 0x39, 0xe3, 0xbe, 0xf8, 0x1c, 0xbf, 0xeb, 0xef, 0x17, 0xb7, 0x22, 0x82, 0x68, 0xa0, 0xa2, 0xa2, 0x9d, 0x34, 0x88, 0xc7, 0x52, 0x56, 0x5c, 0x6c, 0x96, 0x5c, 0xbd, 0x65, 0x06, 0xec, 0x24,
0x39, 0x7c, 0xc8, 0xa5, 0xd9, 0xd1, 0x52, 0x85, 0xa8, 0x7f, 0x00, 0x02, 0x04, 0x54, 0x11, 0x35, 0x9b, 0x27, 0x09, 0x06, 0x2a, 0x02, 0x6e, 0xa0, 0xd4, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99, 0x93, 0x27, 0x09
};
Topology::Topology(const RuntimeEnvironment *renv,void *tPtr) : Topology::Topology(const RuntimeEnvironment* renv, void* tPtr) : RR(renv), _numConfiguredPhysicalPaths(0), _amUpstream(false)
RR(renv),
_numConfiguredPhysicalPaths(0),
_amUpstream(false)
{ {
uint8_t tmp[ZT_WORLD_MAX_SERIALIZED_LENGTH]; uint8_t tmp[ZT_WORLD_MAX_SERIALIZED_LENGTH];
uint64_t idtmp[2]; uint64_t idtmp[2];
@ -40,7 +54,9 @@ Topology::Topology(const RuntimeEnvironment *renv,void *tPtr) :
World cachedPlanet; World cachedPlanet;
cachedPlanet.deserialize(Buffer<ZT_WORLD_MAX_SERIALIZED_LENGTH>(tmp, (unsigned int)n), 0); cachedPlanet.deserialize(Buffer<ZT_WORLD_MAX_SERIALIZED_LENGTH>(tmp, (unsigned int)n), 0);
addWorld(tPtr, cachedPlanet, false); addWorld(tPtr, cachedPlanet, false);
} catch ( ... ) {} // ignore invalid cached planets }
catch (...) {
} // ignore invalid cached planets
} }
World defaultPlanet; World defaultPlanet;
@ -108,7 +124,9 @@ SharedPtr<Peer> Topology::getPeer(void *tPtr,const Address &zta)
} }
return SharedPtr<Peer>(); return SharedPtr<Peer>();
} }
} catch ( ... ) {} // ignore invalid identities or other strange failures }
catch (...) {
} // ignore invalid identities or other strange failures
return SharedPtr<Peer>(); return SharedPtr<Peer>();
} }
@ -117,7 +135,8 @@ Identity Topology::getIdentity(void *tPtr,const Address &zta)
{ {
if (zta == RR->identity.address()) { if (zta == RR->identity.address()) {
return RR->identity; return RR->identity;
} else { }
else {
Mutex::Lock _l(_peers_m); Mutex::Lock _l(_peers_m);
const SharedPtr<Peer>* const ap = _peers.get(zta); const SharedPtr<Peer>* const ap = _peers.get(zta);
if (ap) { if (ap) {
@ -255,14 +274,17 @@ bool Topology::addWorld(void *tPtr,const World &newWorld,bool alwaysAcceptNew)
if (existing) { if (existing) {
if (existing->shouldBeReplacedBy(newWorld)) { if (existing->shouldBeReplacedBy(newWorld)) {
*existing = newWorld; *existing = newWorld;
} else { }
else {
return false; return false;
} }
} else if (newWorld.type() == World::TYPE_MOON) { }
else if (newWorld.type() == World::TYPE_MOON) {
if (alwaysAcceptNew) { if (alwaysAcceptNew) {
_moons.push_back(newWorld); _moons.push_back(newWorld);
existing = &(_moons.back()); existing = &(_moons.back());
} else { }
else {
for (std::vector<std::pair<uint64_t, Address> >::iterator m(_moonSeeds.begin()); m != _moonSeeds.end(); ++m) { for (std::vector<std::pair<uint64_t, Address> >::iterator m(_moonSeeds.begin()); m != _moonSeeds.end(); ++m) {
if (m->first == newWorld.id()) { if (m->first == newWorld.id()) {
for (std::vector<World::Root>::const_iterator r(newWorld.roots().begin()); r != newWorld.roots().end(); ++r) { for (std::vector<World::Root>::const_iterator r(newWorld.roots().begin()); r != newWorld.roots().end(); ++r) {
@ -282,7 +304,8 @@ bool Topology::addWorld(void *tPtr,const World &newWorld,bool alwaysAcceptNew)
if (! existing) { if (! existing) {
return false; return false;
} }
} else { }
else {
return false; return false;
} }
@ -293,7 +316,9 @@ bool Topology::addWorld(void *tPtr,const World &newWorld,bool alwaysAcceptNew)
idtmp[0] = existing->id(); idtmp[0] = existing->id();
idtmp[1] = 0; idtmp[1] = 0;
RR->node->stateObjectPut(tPtr, (existing->type() == World::TYPE_PLANET) ? ZT_STATE_OBJECT_PLANET : ZT_STATE_OBJECT_MOON, idtmp, sbuf.data(), sbuf.size()); RR->node->stateObjectPut(tPtr, (existing->type() == World::TYPE_PLANET) ? ZT_STATE_OBJECT_PLANET : ZT_STATE_OBJECT_MOON, idtmp, sbuf.data(), sbuf.size());
} catch ( ... ) {} }
catch (...) {
}
_memoizeUpstreams(tPtr); _memoizeUpstreams(tPtr);
@ -315,7 +340,9 @@ void Topology::addMoon(void *tPtr,const uint64_t id,const Address &seed)
addWorld(tPtr, w, true); addWorld(tPtr, w, true);
return; return;
} }
} catch ( ... ) {} }
catch (...) {
}
} }
if (seed) { if (seed) {
@ -335,7 +362,8 @@ void Topology::removeMoon(void *tPtr,const uint64_t id)
for (std::vector<World>::const_iterator m(_moons.begin()); m != _moons.end(); ++m) { for (std::vector<World>::const_iterator m(_moons.begin()); m != _moons.end(); ++m) {
if (m->id() != id) { if (m->id() != id) {
nm.push_back(*m); nm.push_back(*m);
} else { }
else {
uint64_t idtmp[2]; uint64_t idtmp[2];
idtmp[0] = id; idtmp[0] = id;
idtmp[1] = 0; idtmp[1] = 0;
@ -394,7 +422,8 @@ void Topology::_memoizeUpstreams(void *tPtr)
const Identity& id = i->identity; const Identity& id = i->identity;
if (id == RR->identity) { if (id == RR->identity) {
_amUpstream = true; _amUpstream = true;
} else if (std::find(_upstreamAddresses.begin(),_upstreamAddresses.end(),id.address()) == _upstreamAddresses.end()) { }
else if (std::find(_upstreamAddresses.begin(), _upstreamAddresses.end(), id.address()) == _upstreamAddresses.end()) {
_upstreamAddresses.push_back(id.address()); _upstreamAddresses.push_back(id.address());
SharedPtr<Peer>& hp = _peers[id.address()]; SharedPtr<Peer>& hp = _peers[id.address()];
if (! hp) { if (! hp) {
@ -407,7 +436,8 @@ void Topology::_memoizeUpstreams(void *tPtr)
for (std::vector<World::Root>::const_iterator i(m->roots().begin()); i != m->roots().end(); ++i) { for (std::vector<World::Root>::const_iterator i(m->roots().begin()); i != m->roots().end(); ++i) {
if (i->identity == RR->identity) { if (i->identity == RR->identity) {
_amUpstream = true; _amUpstream = true;
} else if (std::find(_upstreamAddresses.begin(),_upstreamAddresses.end(),i->identity.address()) == _upstreamAddresses.end()) { }
else if (std::find(_upstreamAddresses.begin(), _upstreamAddresses.end(), i->identity.address()) == _upstreamAddresses.end()) {
_upstreamAddresses.push_back(i->identity.address()); _upstreamAddresses.push_back(i->identity.address());
SharedPtr<Peer>& hp = _peers[i->identity.address()]; SharedPtr<Peer>& hp = _peers[i->identity.address()];
if (! hp) { if (! hp) {
@ -429,7 +459,9 @@ void Topology::_savePeer(void *tPtr,const SharedPtr<Peer> &peer)
tmpid[0] = peer->address().toInt(); tmpid[0] = peer->address().toInt();
tmpid[1] = 0; tmpid[1] = 0;
RR->node->stateObjectPut(tPtr, ZT_STATE_OBJECT_PEER, tmpid, buf.data(), buf.size()); RR->node->stateObjectPut(tPtr, ZT_STATE_OBJECT_PEER, tmpid, buf.data(), buf.size());
} catch ( ... ) {} // sanity check, discard invalid entries }
catch (...) {
} // sanity check, discard invalid entries
} }
} // namespace ZeroTier } // namespace ZeroTier

View file

@ -14,25 +14,23 @@
#ifndef ZT_TOPOLOGY_HPP #ifndef ZT_TOPOLOGY_HPP
#define ZT_TOPOLOGY_HPP #define ZT_TOPOLOGY_HPP
#include "../include/ZeroTierOne.h"
#include "Address.hpp"
#include "Constants.hpp"
#include "Hashtable.hpp"
#include "Identity.hpp"
#include "InetAddress.hpp"
#include "Mutex.hpp"
#include "Path.hpp"
#include "Peer.hpp"
#include "World.hpp"
#include <algorithm>
#include <stdexcept>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <vector>
#include <stdexcept>
#include <algorithm>
#include <utility> #include <utility>
#include <vector>
#include "Constants.hpp"
#include "../include/ZeroTierOne.h"
#include "Address.hpp"
#include "Identity.hpp"
#include "Peer.hpp"
#include "Path.hpp"
#include "Mutex.hpp"
#include "InetAddress.hpp"
#include "Hashtable.hpp"
#include "World.hpp"
namespace ZeroTier { namespace ZeroTier {
@ -41,8 +39,7 @@ class RuntimeEnvironment;
/** /**
* Database of network topology * Database of network topology
*/ */
class Topology class Topology {
{
public: public:
Topology(const RuntimeEnvironment* renv, void* tPtr); Topology(const RuntimeEnvironment* renv, void* tPtr);
~Topology(); ~Topology();
@ -306,8 +303,7 @@ public:
* @param f Function to apply * @param f Function to apply
* @tparam F Function or function object type * @tparam F Function or function object type
*/ */
template<typename F> template <typename F> inline void eachPeer(F f)
inline void eachPeer(F f)
{ {
Mutex::Lock _l(_peers_m); Mutex::Lock _l(_peers_m);
Hashtable<Address, SharedPtr<Peer> >::Iterator i(_peers); Hashtable<Address, SharedPtr<Peer> >::Iterator i(_peers);
@ -330,7 +326,10 @@ public:
/** /**
* @return True if I am a root server in a planet or moon * @return True if I am a root server in a planet or moon
*/ */
inline bool amUpstream() const { return _amUpstream; } inline bool amUpstream() const
{
return _amUpstream;
}
/** /**
* Get info about a path * Get info about a path
@ -407,7 +406,8 @@ public:
{ {
if (! pathNetwork) { if (! pathNetwork) {
_numConfiguredPhysicalPaths = 0; _numConfiguredPhysicalPaths = 0;
} else { }
else {
std::map<InetAddress, ZT_PhysicalPathConfiguration> cpaths; std::map<InetAddress, ZT_PhysicalPathConfiguration> cpaths;
for (unsigned int i = 0, j = _numConfiguredPhysicalPaths; i < j; ++i) { for (unsigned int i = 0, j = _numConfiguredPhysicalPaths; i < j; ++i) {
cpaths[_physicalPathConfig[i].first] = _physicalPathConfig[i].second; cpaths[_physicalPathConfig[i].first] = _physicalPathConfig[i].second;
@ -418,14 +418,17 @@ public:
if (pc.mtu <= 0) { if (pc.mtu <= 0) {
pc.mtu = ZT_DEFAULT_PHYSMTU; pc.mtu = ZT_DEFAULT_PHYSMTU;
} else if (pc.mtu < ZT_MIN_PHYSMTU) { }
else if (pc.mtu < ZT_MIN_PHYSMTU) {
pc.mtu = ZT_MIN_PHYSMTU; pc.mtu = ZT_MIN_PHYSMTU;
} else if (pc.mtu > ZT_MAX_PHYSMTU) { }
else if (pc.mtu > ZT_MAX_PHYSMTU) {
pc.mtu = ZT_MAX_PHYSMTU; pc.mtu = ZT_MAX_PHYSMTU;
} }
cpaths[*(reinterpret_cast<const InetAddress*>(pathNetwork))] = pc; cpaths[*(reinterpret_cast<const InetAddress*>(pathNetwork))] = pc;
} else { }
else {
cpaths.erase(*(reinterpret_cast<const InetAddress*>(pathNetwork))); cpaths.erase(*(reinterpret_cast<const InetAddress*>(pathNetwork)));
} }

View file

@ -13,21 +13,22 @@
// #define ZT_TRACE // #define ZT_TRACE
#include <stdio.h>
#include <stdarg.h>
#include "Trace.hpp" #include "Trace.hpp"
#include "RuntimeEnvironment.hpp"
#include "Switch.hpp" #include "../include/ZeroTierDebug.h"
#include "Node.hpp" #include "Capability.hpp"
#include "Utils.hpp"
#include "Dictionary.hpp"
#include "CertificateOfMembership.hpp" #include "CertificateOfMembership.hpp"
#include "CertificateOfOwnership.hpp" #include "CertificateOfOwnership.hpp"
#include "Tag.hpp" #include "Dictionary.hpp"
#include "Capability.hpp" #include "Node.hpp"
#include "Revocation.hpp" #include "Revocation.hpp"
#include "../include/ZeroTierDebug.h" #include "RuntimeEnvironment.hpp"
#include "Switch.hpp"
#include "Tag.hpp"
#include "Utils.hpp"
#include <stdarg.h>
#include <stdio.h>
namespace ZeroTier { namespace ZeroTier {
@ -189,7 +190,10 @@ void Trace::outgoingNetworkFrameDropped(void *const tPtr,const SharedPtr<Network
ZT_LOCAL_TRACE(tPtr, RR, "%.16llx DROP frame %s -> %s etherType %.4x size %u (%s)", network->id(), sourceMac.toString(tmp), destMac.toString(tmp2), etherType, frameLen, (reason) ? reason : "unknown reason"); ZT_LOCAL_TRACE(tPtr, RR, "%.16llx DROP frame %s -> %s etherType %.4x size %u (%s)", network->id(), sourceMac.toString(tmp), destMac.toString(tmp2), etherType, frameLen, (reason) ? reason : "unknown reason");
std::pair<Address, Trace::Level> byn; std::pair<Address, Trace::Level> byn;
{ Mutex::Lock l(_byNet_m); _byNet.get(network->id(),byn); } {
Mutex::Lock l(_byNet_m);
_byNet.get(network->id(), byn);
}
if (((_globalTarget) && ((int)_globalLevel >= (int)Trace::LEVEL_VERBOSE)) || ((byn.first) && ((int)byn.second >= (int)Trace::LEVEL_VERBOSE))) { if (((_globalTarget) && ((int)_globalLevel >= (int)Trace::LEVEL_VERBOSE)) || ((byn.first) && ((int)byn.second >= (int)Trace::LEVEL_VERBOSE))) {
Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> d; Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> d;
@ -213,17 +217,37 @@ void Trace::outgoingNetworkFrameDropped(void *const tPtr,const SharedPtr<Network
} }
} }
void Trace::incomingNetworkAccessDenied(void *const tPtr,const SharedPtr<Network> &network,const SharedPtr<Path> &path,const uint64_t packetId,const unsigned int packetLength,const Address &source,const Packet::Verb verb,bool credentialsRequested) void Trace::incomingNetworkAccessDenied(
void* const tPtr,
const SharedPtr<Network>& network,
const SharedPtr<Path>& path,
const uint64_t packetId,
const unsigned int packetLength,
const Address& source,
const Packet::Verb verb,
bool credentialsRequested)
{ {
char tmp[128]; char tmp[128];
if (! network) { if (! network) {
return; // sanity check return; // sanity check
} }
ZT_LOCAL_TRACE(tPtr,RR,"%.16llx DENIED packet from %.10llx(%s) verb %d size %u%s",network->id(),source.toInt(),(path) ? (path->address().toString(tmp)) : "???",(int)verb,packetLength,credentialsRequested ? " (credentials requested)" : " (credentials not requested)"); ZT_LOCAL_TRACE(
tPtr,
RR,
"%.16llx DENIED packet from %.10llx(%s) verb %d size %u%s",
network->id(),
source.toInt(),
(path) ? (path->address().toString(tmp)) : "???",
(int)verb,
packetLength,
credentialsRequested ? " (credentials requested)" : " (credentials not requested)");
std::pair<Address, Trace::Level> byn; std::pair<Address, Trace::Level> byn;
{ Mutex::Lock l(_byNet_m); _byNet.get(network->id(),byn); } {
Mutex::Lock l(_byNet_m);
_byNet.get(network->id(), byn);
}
if (((_globalTarget) && ((int)_globalLevel >= (int)Trace::LEVEL_VERBOSE)) || ((byn.first) && ((int)byn.second >= (int)Trace::LEVEL_VERBOSE))) { if (((_globalTarget) && ((int)_globalLevel >= (int)Trace::LEVEL_VERBOSE)) || ((byn.first) && ((int)byn.second >= (int)Trace::LEVEL_VERBOSE))) {
Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> d; Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> d;
@ -246,7 +270,17 @@ void Trace::incomingNetworkAccessDenied(void *const tPtr,const SharedPtr<Network
} }
} }
void Trace::incomingNetworkFrameDropped(void *const tPtr,const SharedPtr<Network> &network,const SharedPtr<Path> &path,const uint64_t packetId,const unsigned int packetLength,const Address &source,const Packet::Verb verb,const MAC &sourceMac,const MAC &destMac,const char *reason) void Trace::incomingNetworkFrameDropped(
void* const tPtr,
const SharedPtr<Network>& network,
const SharedPtr<Path>& path,
const uint64_t packetId,
const unsigned int packetLength,
const Address& source,
const Packet::Verb verb,
const MAC& sourceMac,
const MAC& destMac,
const char* reason)
{ {
char tmp[128]; char tmp[128];
if (! network) { if (! network) {
@ -256,7 +290,10 @@ void Trace::incomingNetworkFrameDropped(void *const tPtr,const SharedPtr<Network
ZT_LOCAL_TRACE(tPtr, RR, "%.16llx DROPPED frame from %.10llx(%s) verb %d size %u", network->id(), source.toInt(), (path) ? (path->address().toString(tmp)) : "???", (int)verb, packetLength); ZT_LOCAL_TRACE(tPtr, RR, "%.16llx DROPPED frame from %.10llx(%s) verb %d size %u", network->id(), source.toInt(), (path) ? (path->address().toString(tmp)) : "???", (int)verb, packetLength);
std::pair<Address, Trace::Level> byn; std::pair<Address, Trace::Level> byn;
{ Mutex::Lock l(_byNet_m); _byNet.get(network->id(),byn); } {
Mutex::Lock l(_byNet_m);
_byNet.get(network->id(), byn);
}
if (((_globalTarget) && ((int)_globalLevel >= (int)Trace::LEVEL_VERBOSE)) || ((byn.first) && ((int)byn.second >= (int)Trace::LEVEL_VERBOSE))) { if (((_globalTarget) && ((int)_globalLevel >= (int)Trace::LEVEL_VERBOSE)) || ((byn.first) && ((int)byn.second >= (int)Trace::LEVEL_VERBOSE))) {
Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> d; Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> d;
@ -387,7 +424,10 @@ void Trace::networkFilter(
const int accept) const int accept)
{ {
std::pair<Address, Trace::Level> byn; std::pair<Address, Trace::Level> byn;
{ Mutex::Lock l(_byNet_m); _byNet.get(network.id(),byn); } {
Mutex::Lock l(_byNet_m);
_byNet.get(network.id(), byn);
}
if (((_globalTarget) && ((int)_globalLevel >= (int)Trace::LEVEL_RULES)) || ((byn.first) && ((int)byn.second >= (int)Trace::LEVEL_RULES))) { if (((_globalTarget) && ((int)_globalLevel >= (int)Trace::LEVEL_RULES)) || ((byn.first) && ((int)byn.second >= (int)Trace::LEVEL_RULES))) {
Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> d; Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> d;

View file

@ -14,21 +14,20 @@
#ifndef ZT_TRACE_HPP #ifndef ZT_TRACE_HPP
#define ZT_TRACE_HPP #define ZT_TRACE_HPP
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include "../include/ZeroTierOne.h" #include "../include/ZeroTierOne.h"
#include "Constants.hpp" #include "Constants.hpp"
#include "SharedPtr.hpp"
#include "Packet.hpp"
#include "Credential.hpp" #include "Credential.hpp"
#include "InetAddress.hpp"
#include "Dictionary.hpp" #include "Dictionary.hpp"
#include "Mutex.hpp"
#include "Hashtable.hpp" #include "Hashtable.hpp"
#include "InetAddress.hpp"
#include "Mutex.hpp"
#include "Packet.hpp"
#include "SharedPtr.hpp"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
namespace ZeroTier { namespace ZeroTier {
@ -49,20 +48,12 @@ class Capability;
/** /**
* Remote tracing and trace logging handler * Remote tracing and trace logging handler
*/ */
class Trace class Trace {
{
public: public:
/** /**
* Trace verbosity level * Trace verbosity level
*/ */
enum Level enum Level { LEVEL_NORMAL = 0, LEVEL_VERBOSE = 10, LEVEL_RULES = 15, LEVEL_DEBUG = 20, LEVEL_INSANE = 30 };
{
LEVEL_NORMAL = 0,
LEVEL_VERBOSE = 10,
LEVEL_RULES = 15,
LEVEL_DEBUG = 20,
LEVEL_INSANE = 30
};
/** /**
* Filter rule evaluation result log * Filter rule evaluation result log
@ -73,10 +64,11 @@ public:
* As with four-bit rules an 00 value here means this was not * As with four-bit rules an 00 value here means this was not
* evaluated or was not relevant. * evaluated or was not relevant.
*/ */
class RuleResultLog class RuleResultLog {
{
public: public:
RuleResultLog() {} RuleResultLog()
{
}
inline void log(const unsigned int rn, const uint8_t thisRuleMatches, const uint8_t thisSetMatches) inline void log(const unsigned int rn, const uint8_t thisRuleMatches, const uint8_t thisSetMatches)
{ {
@ -92,16 +84,20 @@ public:
memset(_l, 0, sizeof(_l)); memset(_l, 0, sizeof(_l));
} }
inline const uint8_t *data() const { return _l; } inline const uint8_t* data() const
inline unsigned int sizeBytes() const { return (ZT_MAX_NETWORK_RULES / 2); } {
return _l;
}
inline unsigned int sizeBytes() const
{
return (ZT_MAX_NETWORK_RULES / 2);
}
private: private:
uint8_t _l[ZT_MAX_NETWORK_RULES / 2]; uint8_t _l[ZT_MAX_NETWORK_RULES / 2];
}; };
Trace(const RuntimeEnvironment *renv) : Trace(const RuntimeEnvironment* renv) : RR(renv), _byNet(8)
RR(renv),
_byNet(8)
{ {
} }
@ -119,8 +115,26 @@ public:
void incomingPacketDroppedHELLO(void* const tPtr, const SharedPtr<Path>& path, const uint64_t packetId, const Address& source, const char* reason); void incomingPacketDroppedHELLO(void* const tPtr, const SharedPtr<Path>& path, const uint64_t packetId, const Address& source, const char* reason);
void outgoingNetworkFrameDropped(void* const tPtr, const SharedPtr<Network>& network, const MAC& sourceMac, const MAC& destMac, const unsigned int etherType, const unsigned int vlanId, const unsigned int frameLen, const char* reason); void outgoingNetworkFrameDropped(void* const tPtr, const SharedPtr<Network>& network, const MAC& sourceMac, const MAC& destMac, const unsigned int etherType, const unsigned int vlanId, const unsigned int frameLen, const char* reason);
void incomingNetworkAccessDenied(void *const tPtr,const SharedPtr<Network> &network,const SharedPtr<Path> &path,const uint64_t packetId,const unsigned int packetLength,const Address &source,const Packet::Verb verb,bool credentialsRequested); void incomingNetworkAccessDenied(
void incomingNetworkFrameDropped(void *const tPtr,const SharedPtr<Network> &network,const SharedPtr<Path> &path,const uint64_t packetId,const unsigned int packetLength,const Address &source,const Packet::Verb verb,const MAC &sourceMac,const MAC &destMac,const char *reason); void* const tPtr,
const SharedPtr<Network>& network,
const SharedPtr<Path>& path,
const uint64_t packetId,
const unsigned int packetLength,
const Address& source,
const Packet::Verb verb,
bool credentialsRequested);
void incomingNetworkFrameDropped(
void* const tPtr,
const SharedPtr<Network>& network,
const SharedPtr<Path>& path,
const uint64_t packetId,
const unsigned int packetLength,
const Address& source,
const Packet::Verb verb,
const MAC& sourceMac,
const MAC& destMac,
const char* reason);
void networkConfigRequestSent(void* const tPtr, const Network& network, const Address& controller); void networkConfigRequestSent(void* const tPtr, const Network& network, const Address& controller);
void networkFilter( void networkFilter(

View file

@ -11,23 +11,23 @@
*/ */
/****/ /****/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <time.h>
#include <sys/stat.h>
#include "Constants.hpp" #include "Constants.hpp"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
#ifdef __UNIX_LIKE__ #ifdef __UNIX_LIKE__
#include <unistd.h> #include <dirent.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h>
#include <sys/uio.h> #include <sys/uio.h>
#include <dirent.h> #include <unistd.h>
#ifdef ZT_ARCH_ARM_HAS_NEON #ifdef ZT_ARCH_ARM_HAS_NEON
#ifdef __LINUX__ #ifdef __LINUX__
#include <sys/auxv.h> #include <sys/auxv.h>
@ -36,13 +36,13 @@
#endif #endif
#ifdef __WINDOWS__ #ifdef __WINDOWS__
#include <wincrypt.h>
#include <intrin.h> #include <intrin.h>
#include <wincrypt.h>
#endif #endif
#include "Utils.hpp"
#include "Mutex.hpp" #include "Mutex.hpp"
#include "Salsa20.hpp" #include "Salsa20.hpp"
#include "Utils.hpp"
#ifdef __APPLE__ #ifdef __APPLE__
#include <TargetConditionals.h> #include <TargetConditionals.h>
@ -55,8 +55,8 @@
#ifdef ZT_ARCH_ARM_HAS_NEON #ifdef ZT_ARCH_ARM_HAS_NEON
#ifdef __LINUX__ #ifdef __LINUX__
#include <sys/auxv.h>
#include <asm/hwcap.h> #include <asm/hwcap.h>
#include <sys/auxv.h>
#endif #endif
#if defined(__FreeBSD__) #if defined(__FreeBSD__)
@ -116,7 +116,8 @@ Utils::ARMCapabilities::ARMCapabilities() noexcept
this->pmull = (hwcaps2 & HWCAP2_PMULL) != 0; this->pmull = (hwcaps2 & HWCAP2_PMULL) != 0;
this->sha1 = (hwcaps2 & HWCAP2_SHA1) != 0; this->sha1 = (hwcaps2 & HWCAP2_SHA1) != 0;
this->sha2 = (hwcaps2 & HWCAP2_SHA2) != 0; this->sha2 = (hwcaps2 & HWCAP2_SHA2) != 0;
} else { }
else {
#endif #endif
const long hwcaps = getauxval(AT_HWCAP); const long hwcaps = getauxval(AT_HWCAP);
this->aes = (hwcaps & HWCAP_AES) != 0; this->aes = (hwcaps & HWCAP_AES) != 0;
@ -148,11 +149,7 @@ Utils::CPUIDRegisters::CPUIDRegisters() noexcept
ecx = (uint32_t)regs[2]; ecx = (uint32_t)regs[2];
edx = (uint32_t)regs[3]; edx = (uint32_t)regs[3];
#else #else
__asm__ __volatile__ ( __asm__ __volatile__("cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "a"(1), "c"(0));
"cpuid"
: "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
: "a"(1), "c"(0)
);
#endif #endif
rdrand = ((ecx & (1U << 30U)) != 0); rdrand = ((ecx & (1U << 30U)) != 0);
@ -166,11 +163,7 @@ Utils::CPUIDRegisters::CPUIDRegisters() noexcept
ecx = (uint32_t)regs[2]; ecx = (uint32_t)regs[2];
edx = (uint32_t)regs[3]; edx = (uint32_t)regs[3];
#else #else
__asm__ __volatile__ ( __asm__ __volatile__("cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "a"(7), "c"(0));
"cpuid"
: "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
: "a"(7), "c"(0)
);
#endif #endif
vaes = aes && avx && ((ecx & (1U << 9U)) != 0); vaes = aes && avx && ((ecx & (1U << 9U)) != 0);
@ -193,7 +186,10 @@ static void _Utils_doBurn(volatile uint8_t *ptr,unsigned int len)
} }
} }
static void (*volatile _Utils_doBurn_ptr)(volatile uint8_t*, unsigned int) = _Utils_doBurn; static void (*volatile _Utils_doBurn_ptr)(volatile uint8_t*, unsigned int) = _Utils_doBurn;
void Utils::burn(void *ptr,unsigned int len) { (_Utils_doBurn_ptr)((volatile uint8_t *)ptr,len); } void Utils::burn(void* ptr, unsigned int len)
{
(_Utils_doBurn_ptr)((volatile uint8_t*)ptr, len);
}
static unsigned long _Utils_itoa(unsigned long n, char* s) static unsigned long _Utils_itoa(unsigned long n, char* s)
{ {
@ -292,7 +288,8 @@ void Utils::getSecureRandom(void *buf,unsigned int bytes)
exit(1); exit(1);
return; return;
} }
} else { }
else {
break; break;
} }
} }

View file

@ -14,17 +14,16 @@
#ifndef ZT_UTILS_HPP #ifndef ZT_UTILS_HPP
#define ZT_UTILS_HPP #define ZT_UTILS_HPP
#include <algorithm>
#include <map>
#include <stdexcept>
#include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h>
#include <string.h> #include <string.h>
#include <time.h>
#include <string> #include <string>
#include <stdexcept> #include <time.h>
#include <vector> #include <vector>
#include <map>
#include <algorithm>
#if defined(__FreeBSD__) #if defined(__FreeBSD__)
#include <sys/endian.h> #include <sys/endian.h>
@ -34,15 +33,9 @@
#if __BYTE_ORDER == __LITTLE_ENDIAN #if __BYTE_ORDER == __LITTLE_ENDIAN
#define ZT_CONST_TO_BE_UINT16(x) ((uint16_t)((uint16_t)((uint16_t)(x) << 8U) | (uint16_t)((uint16_t)(x) >> 8U))) #define ZT_CONST_TO_BE_UINT16(x) ((uint16_t)((uint16_t)((uint16_t)(x) << 8U) | (uint16_t)((uint16_t)(x) >> 8U)))
#define ZT_CONST_TO_BE_UINT64(x) ( \ #define ZT_CONST_TO_BE_UINT64(x) \
(((uint64_t)(x) & 0x00000000000000ffULL) << 56U) | \ ((((uint64_t)(x) & 0x00000000000000ffULL) << 56U) | (((uint64_t)(x) & 0x000000000000ff00ULL) << 40U) | (((uint64_t)(x) & 0x0000000000ff0000ULL) << 24U) | (((uint64_t)(x) & 0x00000000ff000000ULL) << 8U) \
(((uint64_t)(x) & 0x000000000000ff00ULL) << 40U) | \ | (((uint64_t)(x) & 0x000000ff00000000ULL) >> 8U) | (((uint64_t)(x) & 0x0000ff0000000000ULL) >> 24U) | (((uint64_t)(x) & 0x00ff000000000000ULL) >> 40U) | (((uint64_t)(x) & 0xff00000000000000ULL) >> 56U))
(((uint64_t)(x) & 0x0000000000ff0000ULL) << 24U) | \
(((uint64_t)(x) & 0x00000000ff000000ULL) << 8U) | \
(((uint64_t)(x) & 0x000000ff00000000ULL) >> 8U) | \
(((uint64_t)(x) & 0x0000ff0000000000ULL) >> 24U) | \
(((uint64_t)(x) & 0x00ff000000000000ULL) >> 40U) | \
(((uint64_t)(x) & 0xff00000000000000ULL) >> 56U))
#else #else
#define ZT_CONST_TO_BE_UINT16(x) ((uint16_t)(x)) #define ZT_CONST_TO_BE_UINT16(x) ((uint16_t)(x))
#define ZT_CONST_TO_BE_UINT64(x) ((uint64_t)(x)) #define ZT_CONST_TO_BE_UINT64(x) ((uint64_t)(x))
@ -58,14 +51,12 @@ namespace ZeroTier {
/** /**
* Miscellaneous utility functions and global constants * Miscellaneous utility functions and global constants
*/ */
class Utils class Utils {
{
public: public:
static const uint64_t ZERO256[4]; static const uint64_t ZERO256[4];
#ifdef ZT_ARCH_ARM_HAS_NEON #ifdef ZT_ARCH_ARM_HAS_NEON
struct ARMCapabilities struct ARMCapabilities {
{
ARMCapabilities() noexcept; ARMCapabilities() noexcept;
bool aes; bool aes;
@ -78,8 +69,7 @@ public:
#endif #endif
#ifdef ZT_ARCH_X64 #ifdef ZT_ARCH_X64
struct CPUIDRegisters struct CPUIDRegisters {
{
CPUIDRegisters() noexcept; CPUIDRegisters() noexcept;
bool rdrand; bool rdrand;
@ -241,9 +231,11 @@ public:
uint8_t c = 0; uint8_t c = 0;
if ((hc >= 48) && (hc <= 57)) { // 0..9 if ((hc >= 48) && (hc <= 57)) { // 0..9
c = hc - 48; c = hc - 48;
} else if ((hc >= 97)&&(hc <= 102)) { // a..f }
else if ((hc >= 97) && (hc <= 102)) { // a..f
c = hc - 87; c = hc - 87;
} else if ((hc >= 65)&&(hc <= 70)) { // A..F }
else if ((hc >= 65) && (hc <= 70)) { // A..F
c = hc - 55; c = hc - 55;
} }
@ -255,9 +247,11 @@ public:
c <<= 4; c <<= 4;
if ((hc >= 48) && (hc <= 57)) { if ((hc >= 48) && (hc <= 57)) {
c |= hc - 48; c |= hc - 48;
} else if ((hc >= 97)&&(hc <= 102)) { }
else if ((hc >= 97) && (hc <= 102)) {
c |= hc - 87; c |= hc - 87;
} else if ((hc >= 65)&&(hc <= 70)) { }
else if ((hc >= 65) && (hc <= 70)) {
c |= hc - 55; c |= hc - 55;
} }
@ -282,9 +276,11 @@ public:
uint8_t c = 0; uint8_t c = 0;
if ((hc >= 48) && (hc <= 57)) { if ((hc >= 48) && (hc <= 57)) {
c = hc - 48; c = hc - 48;
} else if ((hc >= 97)&&(hc <= 102)) { }
else if ((hc >= 97) && (hc <= 102)) {
c = hc - 87; c = hc - 87;
} else if ((hc >= 65)&&(hc <= 70)) { }
else if ((hc >= 65) && (hc <= 70)) {
c = hc - 55; c = hc - 55;
} }
@ -299,9 +295,11 @@ public:
c <<= 4; c <<= 4;
if ((hc >= 48) && (hc <= 57)) { if ((hc >= 48) && (hc <= 57)) {
c |= hc - 48; c |= hc - 48;
} else if ((hc >= 97)&&(hc <= 102)) { }
else if ((hc >= 97) && (hc <= 102)) {
c |= hc - 87; c |= hc - 87;
} else if ((hc >= 65)&&(hc <= 70)) { }
else if ((hc >= 65) && (hc <= 70)) {
c |= hc - 55; c |= hc - 55;
} }
@ -345,11 +343,26 @@ public:
#endif #endif
} }
static inline unsigned int strToUInt(const char *s) { return (unsigned int)strtoul(s,(char **)0,10); } static inline unsigned int strToUInt(const char* s)
static inline int strToInt(const char *s) { return (int)strtol(s,(char **)0,10); } {
static inline unsigned long strToULong(const char *s) { return strtoul(s,(char **)0,10); } return (unsigned int)strtoul(s, (char**)0, 10);
static inline long strToLong(const char *s) { return strtol(s,(char **)0,10); } }
static inline double strToDouble(const char *s) { return strtod(s,NULL); } static inline int strToInt(const char* s)
{
return (int)strtol(s, (char**)0, 10);
}
static inline unsigned long strToULong(const char* s)
{
return strtoul(s, (char**)0, 10);
}
static inline long strToLong(const char* s)
{
return strtol(s, (char**)0, 10);
}
static inline double strToDouble(const char* s)
{
return strtod(s, NULL);
}
static inline unsigned long long strToU64(const char* s) static inline unsigned long long strToU64(const char* s)
{ {
#ifdef __WINDOWS__ #ifdef __WINDOWS__
@ -366,10 +379,22 @@ public:
return strtoll(s, (char**)0, 10); return strtoll(s, (char**)0, 10);
#endif #endif
} }
static inline unsigned int hexStrToUInt(const char *s) { return (unsigned int)strtoul(s,(char **)0,16); } static inline unsigned int hexStrToUInt(const char* s)
static inline int hexStrToInt(const char *s) { return (int)strtol(s,(char **)0,16); } {
static inline unsigned long hexStrToULong(const char *s) { return strtoul(s,(char **)0,16); } return (unsigned int)strtoul(s, (char**)0, 16);
static inline long hexStrToLong(const char *s) { return strtol(s,(char **)0,16); } }
static inline int hexStrToInt(const char* s)
{
return (int)strtol(s, (char**)0, 16);
}
static inline unsigned long hexStrToULong(const char* s)
{
return strtoul(s, (char**)0, 16);
}
static inline long hexStrToLong(const char* s)
{
return strtol(s, (char**)0, 16);
}
static inline unsigned long long hexStrToU64(const char* s) static inline unsigned long long hexStrToU64(const char* s)
{ {
#ifdef __WINDOWS__ #ifdef __WINDOWS__
@ -476,15 +501,8 @@ public:
return (uint64_t)_byteswap_uint64((unsigned __int64)n); return (uint64_t)_byteswap_uint64((unsigned __int64)n);
#else #else
return ( return (
((n & 0x00000000000000ffULL) << 56) | ((n & 0x00000000000000ffULL) << 56) | ((n & 0x000000000000ff00ULL) << 40) | ((n & 0x0000000000ff0000ULL) << 24) | ((n & 0x00000000ff000000ULL) << 8) | ((n & 0x000000ff00000000ULL) >> 8) | ((n & 0x0000ff0000000000ULL) >> 24)
((n & 0x000000000000ff00ULL) << 40) | | ((n & 0x00ff000000000000ULL) >> 40) | ((n & 0xff00000000000000ULL) >> 56));
((n & 0x0000000000ff0000ULL) << 24) |
((n & 0x00000000ff000000ULL) << 8) |
((n & 0x000000ff00000000ULL) >> 8) |
((n & 0x0000ff0000000000ULL) >> 24) |
((n & 0x00ff000000000000ULL) >> 40) |
((n & 0xff00000000000000ULL) >> 56)
);
#endif #endif
#endif #endif
} }
@ -529,109 +547,106 @@ public:
// These are helper adapters to load and swap integer types special cased by size // These are helper adapters to load and swap integer types special cased by size
// to work with all typedef'd variants, signed/unsigned, etc. // to work with all typedef'd variants, signed/unsigned, etc.
template< typename I, unsigned int S > template <typename I, unsigned int S> class _swap_bytes_bysize;
class _swap_bytes_bysize;
template< typename I > template <typename I> class _swap_bytes_bysize<I, 1> {
class _swap_bytes_bysize< I, 1 >
{
public: public:
static ZT_INLINE I s(const I n) noexcept static ZT_INLINE I s(const I n) noexcept
{ return n; } {
return n;
}
}; };
template< typename I > template <typename I> class _swap_bytes_bysize<I, 2> {
class _swap_bytes_bysize< I, 2 >
{
public: public:
static ZT_INLINE I s(const I n) noexcept static ZT_INLINE I s(const I n) noexcept
{ return (I)swapBytes((uint16_t)n); } {
return (I)swapBytes((uint16_t)n);
}
}; };
template< typename I > template <typename I> class _swap_bytes_bysize<I, 4> {
class _swap_bytes_bysize< I, 4 >
{
public: public:
static ZT_INLINE I s(const I n) noexcept static ZT_INLINE I s(const I n) noexcept
{ return (I)swapBytes((uint32_t)n); } {
return (I)swapBytes((uint32_t)n);
}
}; };
template< typename I > template <typename I> class _swap_bytes_bysize<I, 8> {
class _swap_bytes_bysize< I, 8 >
{
public: public:
static ZT_INLINE I s(const I n) noexcept static ZT_INLINE I s(const I n) noexcept
{ return (I)swapBytes((uint64_t)n); } {
return (I)swapBytes((uint64_t)n);
}
}; };
template< typename I, unsigned int S > template <typename I, unsigned int S> class _load_be_bysize;
class _load_be_bysize;
template< typename I > template <typename I> class _load_be_bysize<I, 1> {
class _load_be_bysize< I, 1 >
{
public: public:
static ZT_INLINE I l(const uint8_t* const p) noexcept static ZT_INLINE I l(const uint8_t* const p) noexcept
{ return p[0]; } {
return p[0];
}
}; };
template< typename I > template <typename I> class _load_be_bysize<I, 2> {
class _load_be_bysize< I, 2 >
{
public: public:
static ZT_INLINE I l(const uint8_t* const p) noexcept static ZT_INLINE I l(const uint8_t* const p) noexcept
{ return (I)(((unsigned int)p[0] << 8U) | (unsigned int)p[1]); } {
return (I)(((unsigned int)p[0] << 8U) | (unsigned int)p[1]);
}
}; };
template< typename I > template <typename I> class _load_be_bysize<I, 4> {
class _load_be_bysize< I, 4 >
{
public: public:
static ZT_INLINE I l(const uint8_t* const p) noexcept static ZT_INLINE I l(const uint8_t* const p) noexcept
{ return (I)(((uint32_t)p[0] << 24U) | ((uint32_t)p[1] << 16U) | ((uint32_t)p[2] << 8U) | (uint32_t)p[3]); } {
return (I)(((uint32_t)p[0] << 24U) | ((uint32_t)p[1] << 16U) | ((uint32_t)p[2] << 8U) | (uint32_t)p[3]);
}
}; };
template< typename I > template <typename I> class _load_be_bysize<I, 8> {
class _load_be_bysize< I, 8 >
{
public: public:
static ZT_INLINE I l(const uint8_t* const p) noexcept static ZT_INLINE I l(const uint8_t* const p) noexcept
{ return (I)(((uint64_t)p[0] << 56U) | ((uint64_t)p[1] << 48U) | ((uint64_t)p[2] << 40U) | ((uint64_t)p[3] << 32U) | ((uint64_t)p[4] << 24U) | ((uint64_t)p[5] << 16U) | ((uint64_t)p[6] << 8U) | (uint64_t)p[7]); } {
return (I)(((uint64_t)p[0] << 56U) | ((uint64_t)p[1] << 48U) | ((uint64_t)p[2] << 40U) | ((uint64_t)p[3] << 32U) | ((uint64_t)p[4] << 24U) | ((uint64_t)p[5] << 16U) | ((uint64_t)p[6] << 8U) | (uint64_t)p[7]);
}
}; };
template< typename I, unsigned int S > template <typename I, unsigned int S> class _load_le_bysize;
class _load_le_bysize;
template< typename I > template <typename I> class _load_le_bysize<I, 1> {
class _load_le_bysize< I, 1 >
{
public: public:
static ZT_INLINE I l(const uint8_t* const p) noexcept static ZT_INLINE I l(const uint8_t* const p) noexcept
{ return p[0]; } {
return p[0];
}
}; };
template< typename I > template <typename I> class _load_le_bysize<I, 2> {
class _load_le_bysize< I, 2 >
{
public: public:
static ZT_INLINE I l(const uint8_t* const p) noexcept static ZT_INLINE I l(const uint8_t* const p) noexcept
{ return (I)((unsigned int)p[0] | ((unsigned int)p[1] << 8U)); } {
return (I)((unsigned int)p[0] | ((unsigned int)p[1] << 8U));
}
}; };
template< typename I > template <typename I> class _load_le_bysize<I, 4> {
class _load_le_bysize< I, 4 >
{
public: public:
static ZT_INLINE I l(const uint8_t* const p) noexcept static ZT_INLINE I l(const uint8_t* const p) noexcept
{ return (I)((uint32_t)p[0] | ((uint32_t)p[1] << 8U) | ((uint32_t)p[2] << 16U) | ((uint32_t)p[3] << 24U)); } {
return (I)((uint32_t)p[0] | ((uint32_t)p[1] << 8U) | ((uint32_t)p[2] << 16U) | ((uint32_t)p[3] << 24U));
}
}; };
template< typename I > template <typename I> class _load_le_bysize<I, 8> {
class _load_le_bysize< I, 8 >
{
public: public:
static ZT_INLINE I l(const uint8_t* const p) noexcept static ZT_INLINE I l(const uint8_t* const p) noexcept
{ return (I)((uint64_t)p[0] | ((uint64_t)p[1] << 8U) | ((uint64_t)p[2] << 16U) | ((uint64_t)p[3] << 24U) | ((uint64_t)p[4] << 32U) | ((uint64_t)p[5] << 40U) | ((uint64_t)p[6] << 48U) | ((uint64_t)p[7]) << 56U); } {
return (I)((uint64_t)p[0] | ((uint64_t)p[1] << 8U) | ((uint64_t)p[2] << 16U) | ((uint64_t)p[3] << 24U) | ((uint64_t)p[4] << 32U) | ((uint64_t)p[5] << 40U) | ((uint64_t)p[6] << 48U) | ((uint64_t)p[7]) << 56U);
}
}; };
/** /**
@ -641,8 +656,7 @@ public:
* @param n Value to convert * @param n Value to convert
* @return Value in big-endian order * @return Value in big-endian order
*/ */
template< typename I > template <typename I> static ZT_INLINE I hton(const I n) noexcept
static ZT_INLINE I hton(const I n) noexcept
{ {
#if __BYTE_ORDER == __LITTLE_ENDIAN #if __BYTE_ORDER == __LITTLE_ENDIAN
return _swap_bytes_bysize<I, sizeof(I)>::s(n); return _swap_bytes_bysize<I, sizeof(I)>::s(n);
@ -658,8 +672,7 @@ public:
* @param n Value to convert * @param n Value to convert
* @return Value in host byte order * @return Value in host byte order
*/ */
template< typename I > template <typename I> static ZT_INLINE I ntoh(const I n) noexcept
static ZT_INLINE I ntoh(const I n) noexcept
{ {
#if __BYTE_ORDER == __LITTLE_ENDIAN #if __BYTE_ORDER == __LITTLE_ENDIAN
return _swap_bytes_bysize<I, sizeof(I)>::s(n); return _swap_bytes_bysize<I, sizeof(I)>::s(n);
@ -675,8 +688,7 @@ public:
* @param p Byte stream, must be at least sizeof(I) in size * @param p Byte stream, must be at least sizeof(I) in size
* @return Loaded raw integer * @return Loaded raw integer
*/ */
template< typename I > template <typename I> static ZT_INLINE I loadMachineEndian(const void* const p) noexcept
static ZT_INLINE I loadMachineEndian(const void *const p) noexcept
{ {
#ifdef ZT_NO_UNALIGNED_ACCESS #ifdef ZT_NO_UNALIGNED_ACCESS
I tmp; I tmp;
@ -696,8 +708,7 @@ public:
* @param p Byte array (must be at least sizeof(I)) * @param p Byte array (must be at least sizeof(I))
* @param i Integer to store * @param i Integer to store
*/ */
template< typename I > template <typename I> static ZT_INLINE void storeMachineEndian(void* const p, const I i) noexcept
static ZT_INLINE void storeMachineEndian(void *const p, const I i) noexcept
{ {
#ifdef ZT_NO_UNALIGNED_ACCESS #ifdef ZT_NO_UNALIGNED_ACCESS
for (unsigned int k = 0; k < sizeof(I); ++k) { for (unsigned int k = 0; k < sizeof(I); ++k) {
@ -715,8 +726,7 @@ public:
* @param p Byte stream, must be at least sizeof(I) in size * @param p Byte stream, must be at least sizeof(I) in size
* @return Decoded integer * @return Decoded integer
*/ */
template< typename I > template <typename I> static ZT_INLINE I loadBigEndian(const void* const p) noexcept
static ZT_INLINE I loadBigEndian(const void *const p) noexcept
{ {
#ifdef ZT_NO_UNALIGNED_ACCESS #ifdef ZT_NO_UNALIGNED_ACCESS
return _load_be_bysize<I, sizeof(I)>::l(reinterpret_cast<const uint8_t*>(p)); return _load_be_bysize<I, sizeof(I)>::l(reinterpret_cast<const uint8_t*>(p));
@ -732,8 +742,7 @@ public:
* @param p Byte stream to write (must be at least sizeof(I)) * @param p Byte stream to write (must be at least sizeof(I))
* #param i Integer to write * #param i Integer to write
*/ */
template< typename I > template <typename I> static ZT_INLINE void storeBigEndian(void* const p, I i) noexcept
static ZT_INLINE void storeBigEndian(void *const p, I i) noexcept
{ {
#ifdef ZT_NO_UNALIGNED_ACCESS #ifdef ZT_NO_UNALIGNED_ACCESS
storeMachineEndian(p, hton(i)); storeMachineEndian(p, hton(i));
@ -749,8 +758,7 @@ public:
* @param p Byte stream, must be at least sizeof(I) in size * @param p Byte stream, must be at least sizeof(I) in size
* @return Decoded integer * @return Decoded integer
*/ */
template< typename I > template <typename I> static ZT_INLINE I loadLittleEndian(const void* const p) noexcept
static ZT_INLINE I loadLittleEndian(const void *const p) noexcept
{ {
#if __BYTE_ORDER == __BIG_ENDIAN || defined(ZT_NO_UNALIGNED_ACCESS) #if __BYTE_ORDER == __BIG_ENDIAN || defined(ZT_NO_UNALIGNED_ACCESS)
return _load_le_bysize<I, sizeof(I)>::l(reinterpret_cast<const uint8_t*>(p)); return _load_le_bysize<I, sizeof(I)>::l(reinterpret_cast<const uint8_t*>(p));
@ -766,8 +774,7 @@ public:
* @param p Byte stream to write (must be at least sizeof(I)) * @param p Byte stream to write (must be at least sizeof(I))
* #param i Integer to write * #param i Integer to write
*/ */
template< typename I > template <typename I> static ZT_INLINE void storeLittleEndian(void* const p, const I i) noexcept
static ZT_INLINE void storeLittleEndian(void *const p, const I i) noexcept
{ {
#if __BYTE_ORDER == __BIG_ENDIAN #if __BYTE_ORDER == __BIG_ENDIAN
storeMachineEndian(p, _swap_bytes_bysize<I, sizeof(I)>::s(i)); storeMachineEndian(p, _swap_bytes_bysize<I, sizeof(I)>::s(i));
@ -787,8 +794,7 @@ public:
* @param dest Destination memory * @param dest Destination memory
* @param src Source memory * @param src Source memory
*/ */
template< unsigned long L > template <unsigned long L> static ZT_INLINE void copy(void* dest, const void* src) noexcept
static ZT_INLINE void copy(void *dest, const void *src) noexcept
{ {
#if defined(ZT_ARCH_X64) && defined(__GNUC__) #if defined(ZT_ARCH_X64) && defined(__GNUC__)
uintptr_t l = L; uintptr_t l = L;
@ -820,8 +826,7 @@ public:
* @tparam L Size in bytes * @tparam L Size in bytes
* @param dest Memory to zero * @param dest Memory to zero
*/ */
template< unsigned long L > template <unsigned long L> static ZT_INLINE void zero(void* dest) noexcept
static ZT_INLINE void zero(void *dest) noexcept
{ {
#if defined(ZT_ARCH_X64) && defined(__GNUC__) #if defined(ZT_ARCH_X64) && defined(__GNUC__)
uintptr_t l = L; uintptr_t l = L;

View file

@ -14,14 +14,14 @@
#ifndef ZT_WORLD_HPP #ifndef ZT_WORLD_HPP
#define ZT_WORLD_HPP #define ZT_WORLD_HPP
#include <vector>
#include <string>
#include "Constants.hpp"
#include "InetAddress.hpp"
#include "Identity.hpp"
#include "Buffer.hpp" #include "Buffer.hpp"
#include "Constants.hpp"
#include "ECC.hpp" #include "ECC.hpp"
#include "Identity.hpp"
#include "InetAddress.hpp"
#include <string>
#include <vector>
/** /**
* Maximum number of roots (sanity limit, okay to increase) * Maximum number of roots (sanity limit, okay to increase)
@ -76,14 +76,12 @@ namespace ZeroTier {
* world ID for Mars and nearby space is defined but not yet used, and a test * world ID for Mars and nearby space is defined but not yet used, and a test
* world ID is provided for testing purposes. * world ID is provided for testing purposes.
*/ */
class World class World {
{
public: public:
/** /**
* World type -- do not change IDs * World type -- do not change IDs
*/ */
enum Type enum Type {
{
TYPE_NULL = 0, TYPE_NULL = 0,
TYPE_PLANET = 1, // Planets, of which there is currently one (Earth) TYPE_PLANET = 1, // Planets, of which there is currently one (Earth)
TYPE_MOON = 127 // Moons, which are user-created and many TYPE_MOON = 127 // Moons, which are user-created and many
@ -92,53 +90,78 @@ public:
/** /**
* Upstream server definition in world/moon * Upstream server definition in world/moon
*/ */
struct Root struct Root {
{
Identity identity; Identity identity;
std::vector<InetAddress> stableEndpoints; std::vector<InetAddress> stableEndpoints;
inline bool operator==(const Root &r) const { return ((identity == r.identity)&&(stableEndpoints == r.stableEndpoints)); } inline bool operator==(const Root& r) const
inline bool operator!=(const Root &r) const { return (!(*this == r)); } {
inline bool operator<(const Root &r) const { return (identity < r.identity); } // for sorting return ((identity == r.identity) && (stableEndpoints == r.stableEndpoints));
}
inline bool operator!=(const Root& r) const
{
return (! (*this == r));
}
inline bool operator<(const Root& r) const
{
return (identity < r.identity);
} // for sorting
}; };
/** /**
* Construct an empty / null World * Construct an empty / null World
*/ */
World() : World() : _id(0), _ts(0), _type(TYPE_NULL)
_id(0), {
_ts(0), }
_type(TYPE_NULL) {}
/** /**
* @return Root servers for this world and their stable endpoints * @return Root servers for this world and their stable endpoints
*/ */
inline const std::vector<World::Root> &roots() const { return _roots; } inline const std::vector<World::Root>& roots() const
{
return _roots;
}
/** /**
* @return World type: planet or moon * @return World type: planet or moon
*/ */
inline Type type() const { return _type; } inline Type type() const
{
return _type;
}
/** /**
* @return World unique identifier * @return World unique identifier
*/ */
inline uint64_t id() const { return _id; } inline uint64_t id() const
{
return _id;
}
/** /**
* @return World definition timestamp * @return World definition timestamp
*/ */
inline uint64_t timestamp() const { return _ts; } inline uint64_t timestamp() const
{
return _ts;
}
/** /**
* @return C25519 signature * @return C25519 signature
*/ */
inline const ECC::Signature &signature() const { return _signature; } inline const ECC::Signature& signature() const
{
return _signature;
}
/** /**
* @return Public key that must sign next update * @return Public key that must sign next update
*/ */
inline const ECC::Public &updatesMustBeSignedBy() const { return _updatesMustBeSignedBy; } inline const ECC::Public& updatesMustBeSignedBy() const
{
return _updatesMustBeSignedBy;
}
/** /**
* Check whether a world update should replace this one * Check whether a world update should replace this one
@ -162,10 +185,12 @@ public:
/** /**
* @return True if this World is non-empty * @return True if this World is non-empty
*/ */
inline operator bool() const { return (_type != TYPE_NULL); } inline operator bool() const
{
return (_type != TYPE_NULL);
}
template<unsigned int C> template <unsigned int C> inline void serialize(Buffer<C>& b, bool forSign = false) const
inline void serialize(Buffer<C> &b,bool forSign = false) const
{ {
if (forSign) { if (forSign) {
b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL); b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
@ -195,8 +220,7 @@ public:
} }
} }
template<unsigned int C> template <unsigned int C> inline unsigned int deserialize(const Buffer<C>& b, unsigned int startAt = 0)
inline unsigned int deserialize(const Buffer<C> &b,unsigned int startAt = 0)
{ {
unsigned int p = startAt; unsigned int p = startAt;
@ -248,8 +272,16 @@ public:
return (p - startAt); return (p - startAt);
} }
inline bool operator==(const World &w) const { return ((_id == w._id)&&(_ts == w._ts)&&(memcmp(_updatesMustBeSignedBy.data,w._updatesMustBeSignedBy.data,ZT_ECC_PUBLIC_KEY_SET_LEN) == 0)&&(memcmp(_signature.data,w._signature.data,ZT_ECC_SIGNATURE_LEN) == 0)&&(_roots == w._roots)&&(_type == w._type)); } inline bool operator==(const World& w) const
inline bool operator!=(const World &w) const { return (!(*this == w)); } {
return (
(_id == w._id) && (_ts == w._ts) && (memcmp(_updatesMustBeSignedBy.data, w._updatesMustBeSignedBy.data, ZT_ECC_PUBLIC_KEY_SET_LEN) == 0) && (memcmp(_signature.data, w._signature.data, ZT_ECC_SIGNATURE_LEN) == 0)
&& (_roots == w._roots) && (_type == w._type));
}
inline bool operator!=(const World& w) const
{
return (! (*this == w));
}
/** /**
* Create a World object signed with a key pair * Create a World object signed with a key pair

View file

@ -11,21 +11,20 @@
*/ */
/****/ /****/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "Arp.hpp" #include "Arp.hpp"
#include "OSUtils.hpp" #include "OSUtils.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
namespace ZeroTier { namespace ZeroTier {
static const uint8_t ARP_REQUEST_HEADER[8] = { 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01 }; static const uint8_t ARP_REQUEST_HEADER[8] = { 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01 };
static const uint8_t ARP_RESPONSE_HEADER[8] = { 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x02 }; static const uint8_t ARP_RESPONSE_HEADER[8] = { 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x02 };
Arp::Arp() : Arp::Arp() : _cache(256), _lastCleaned(OSUtils::now())
_cache(256),
_lastCleaned(OSUtils::now())
{ {
} }
@ -63,7 +62,8 @@ uint32_t Arp::processIncomingArp(const void *arp,unsigned int len,void *response
responseLen = 28; responseLen = 28;
responseDest.setTo(reinterpret_cast<const uint8_t*>(arp) + 8, 6); responseDest.setTo(reinterpret_cast<const uint8_t*>(arp) + 8, 6);
} }
} else if (!memcmp(arp,ARP_RESPONSE_HEADER,8)) { }
else if (! memcmp(arp, ARP_RESPONSE_HEADER, 8)) {
// Learn cache entries for remote IPs from relevant ARP replies // Learn cache entries for remote IPs from relevant ARP replies
uint32_t responseIp = 0; uint32_t responseIp = 0;
memcpy(&responseIp, reinterpret_cast<const uint8_t*>(arp) + 14, 4); memcpy(&responseIp, reinterpret_cast<const uint8_t*>(arp) + 14, 4);
@ -96,21 +96,26 @@ MAC Arp::query(const MAC &localMac,uint32_t localIp,uint32_t targetIp,void *quer
_ArpEntry& e = _cache[targetIp]; _ArpEntry& e = _cache[targetIp];
if ( ((e.mac)&&((now - e.lastResponseReceived) >= (ZT_ARP_EXPIRE / 3))) || if (((e.mac) && ((now - e.lastResponseReceived) >= (ZT_ARP_EXPIRE / 3))) || ((! e.mac) && ((now - e.lastQuerySent) >= ZT_ARP_QUERY_INTERVAL))) {
((!e.mac)&&((now - e.lastQuerySent) >= ZT_ARP_QUERY_INTERVAL)) ) {
e.lastQuerySent = now; e.lastQuerySent = now;
uint8_t* q = reinterpret_cast<uint8_t*>(query); uint8_t* q = reinterpret_cast<uint8_t*>(query);
memcpy(q,ARP_REQUEST_HEADER,8); q += 8; // ARP request header information, always the same memcpy(q, ARP_REQUEST_HEADER, 8);
localMac.copyTo(q,6); q += 6; // sending host MAC address q += 8; // ARP request header information, always the same
memcpy(q,&localIp,4); q += 4; // sending host IP (IP already in big-endian byte order) localMac.copyTo(q, 6);
memset(q,0,6); q += 6; // sending zeros for target MAC address as thats what we want to find q += 6; // sending host MAC address
memcpy(q, &localIp, 4);
q += 4; // sending host IP (IP already in big-endian byte order)
memset(q, 0, 6);
q += 6; // sending zeros for target MAC address as thats what we want to find
memcpy(q, &targetIp, 4); // target IP address for resolution (IP already in big-endian byte order) memcpy(q, &targetIp, 4); // target IP address for resolution (IP already in big-endian byte order)
queryLen = 28; queryLen = 28;
if (e.mac) if (e.mac)
queryDest = e.mac; // confirmation query, send directly to address holder queryDest = e.mac; // confirmation query, send directly to address holder
else queryDest = (uint64_t)0xffffffffffffULL; // broadcast query else
} else { queryDest = (uint64_t)0xffffffffffffULL; // broadcast query
}
else {
queryLen = 0; queryLen = 0;
queryDest.zero(); queryDest.zero();
} }

View file

@ -14,14 +14,13 @@
#ifndef ZT_ARP_HPP #ifndef ZT_ARP_HPP
#define ZT_ARP_HPP #define ZT_ARP_HPP
#include <stdint.h>
#include <utility>
#include "../node/Constants.hpp" #include "../node/Constants.hpp"
#include "../node/Hashtable.hpp" #include "../node/Hashtable.hpp"
#include "../node/MAC.hpp" #include "../node/MAC.hpp"
#include <stdint.h>
#include <utility>
/** /**
* Maximum possible ARP length * Maximum possible ARP length
* *
@ -67,8 +66,7 @@ namespace ZeroTier {
* This class is not thread-safe and must be guarded if used in multi-threaded * This class is not thread-safe and must be guarded if used in multi-threaded
* code. * code.
*/ */
class Arp class Arp {
{
public: public:
Arp(); Arp();
@ -125,9 +123,10 @@ public:
MAC query(const MAC& localMac, uint32_t localIp, uint32_t targetIp, void* query, unsigned int& queryLen, MAC& queryDest); MAC query(const MAC& localMac, uint32_t localIp, uint32_t targetIp, void* query, unsigned int& queryLen, MAC& queryDest);
private: private:
struct _ArpEntry struct _ArpEntry {
_ArpEntry() : lastQuerySent(0), lastResponseReceived(0), mac(), local(false)
{ {
_ArpEntry() : lastQuerySent(0),lastResponseReceived(0),mac(),local(false) {} }
uint64_t lastQuerySent; // Time last query was sent or 0 for local IP uint64_t lastQuerySent; // Time last query was sent or 0 for local IP
uint64_t lastResponseReceived; // Time of last ARP response or 0 for local IP uint64_t lastResponseReceived; // Time of last ARP response or 0 for local IP
MAC mac; // MAC address of device responsible for IP or null if not known yet MAC mac; // MAC address of device responsible for IP or null if not known yet

View file

@ -11,49 +11,46 @@
*/ */
/****/ /****/
#include <stdint.h> #include "BSDEthernetTap.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h> #include "../node/Constants.hpp"
#include <signal.h> #include "../node/Mutex.hpp"
#include "../node/Utils.hpp"
#include "OSUtils.hpp"
#include <fcntl.h> #include <algorithm>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <sys/select.h>
#include <sys/cdefs.h>
#include <sys/uio.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <net/if.h> #include <errno.h>
#include <fcntl.h>
#include <ifaddrs.h> #include <ifaddrs.h>
#include <map>
#include <net/if.h>
#include <net/if_arp.h> #include <net/if_arp.h>
#include <net/if_dl.h> #include <net/if_dl.h>
#include <net/if_media.h> #include <net/if_media.h>
#include <net/route.h> #include <net/route.h>
#include <netinet/in.h>
#include <pthread_np.h> #include <pthread_np.h>
#include <sched.h> #include <sched.h>
#include <string>
#include <map>
#include <set> #include <set>
#include <algorithm> #include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <sys/cdefs.h>
#include <sys/ioctl.h>
#include <sys/param.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <sys/wait.h>
#include <unistd.h>
#include <utility> #include <utility>
#include "../node/Constants.hpp"
#include "../node/Utils.hpp"
#include "../node/Mutex.hpp"
#include "OSUtils.hpp"
#include "BSDEthernetTap.hpp"
#define ZT_BASE32_CHARS "0123456789abcdefghijklmnopqrstuv" #define ZT_BASE32_CHARS "0123456789abcdefghijklmnopqrstuv"
#define ZT_TAP_BUF_SIZE (1024 * 16) #define ZT_TAP_BUF_SIZE (1024 * 16)
@ -72,17 +69,17 @@ BSDEthernetTap::BSDEthernetTap(
uint64_t nwid, uint64_t nwid,
const char* friendlyName, const char* friendlyName,
void (*handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void*, unsigned int), void (*handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void*, unsigned int),
void *arg) : void* arg)
_handler(handler), : _handler(handler)
_concurrency(concurrency), , _concurrency(concurrency)
_pinning(pinning), , _pinning(pinning)
_arg(arg), , _arg(arg)
_nwid(nwid), , _nwid(nwid)
_mtu(mtu), , _mtu(mtu)
_metric(metric), , _metric(metric)
_fd(0), , _fd(0)
_enabled(true), , _enabled(true)
_lastIfAddrsUpdate(0) , _lastIfAddrsUpdate(0)
{ {
static Mutex globalTapCreateLock; static Mutex globalTapCreateLock;
char devpath[64], ethaddr[64], mtustr[32], metstr[32], tmpdevname[32]; char devpath[64], ethaddr[64], mtustr[32], metstr[32], tmpdevname[32];
@ -119,10 +116,13 @@ BSDEthernetTap::BSDEthernetTap(
#endif #endif
::execl("/sbin/ifconfig", "/sbin/ifconfig", tmpdevname, "create", (const char*)0); ::execl("/sbin/ifconfig", "/sbin/ifconfig", tmpdevname, "create", (const char*)0);
::_exit(-1); ::_exit(-1);
} else if (cpid > 0) { }
else if (cpid > 0) {
int exitcode = -1; int exitcode = -1;
::waitpid(cpid, &exitcode, 0); ::waitpid(cpid, &exitcode, 0);
} else throw std::runtime_error("fork() failed"); }
else
throw std::runtime_error("fork() failed");
struct stat stattmp; struct stat stattmp;
if (! stat(devpath, &stattmp)) { if (! stat(devpath, &stattmp)) {
@ -133,18 +133,23 @@ BSDEthernetTap::BSDEthernetTap(
#endif #endif
::execl("/sbin/ifconfig", "/sbin/ifconfig", tmpdevname, "name", _dev.c_str(), (const char*)0); ::execl("/sbin/ifconfig", "/sbin/ifconfig", tmpdevname, "name", _dev.c_str(), (const char*)0);
::_exit(-1); ::_exit(-1);
} else if (cpid > 0) { }
else if (cpid > 0) {
int exitcode = -1; int exitcode = -1;
::waitpid(cpid, &exitcode, 0); ::waitpid(cpid, &exitcode, 0);
if (exitcode) if (exitcode)
throw std::runtime_error("ifconfig rename operation failed"); throw std::runtime_error("ifconfig rename operation failed");
} else throw std::runtime_error("fork() failed"); }
else
throw std::runtime_error("fork() failed");
_fd = ::open(devpath, O_RDWR); _fd = ::open(devpath, O_RDWR);
if (_fd > 0) if (_fd > 0)
break; break;
else throw std::runtime_error("unable to open created tap device"); else
} else { throw std::runtime_error("unable to open created tap device");
}
else {
throw std::runtime_error("cannot find /dev node for newly created tap device"); throw std::runtime_error("cannot find /dev node for newly created tap device");
} }
} }
@ -182,7 +187,8 @@ BSDEthernetTap::BSDEthernetTap(
#endif #endif
::execl("/sbin/ifconfig", "/sbin/ifconfig", _dev.c_str(), "lladdr", ethaddr, "mtu", mtustr, "metric", metstr, "up", (const char*)0); ::execl("/sbin/ifconfig", "/sbin/ifconfig", _dev.c_str(), "lladdr", ethaddr, "mtu", mtustr, "metric", metstr, "up", (const char*)0);
::_exit(-1); ::_exit(-1);
} else if (cpid > 0) { }
else if (cpid > 0) {
int exitcode = -1; int exitcode = -1;
::waitpid(cpid, &exitcode, 0); ::waitpid(cpid, &exitcode, 0);
if (exitcode) { if (exitcode) {
@ -212,7 +218,8 @@ BSDEthernetTap::~BSDEthernetTap()
#endif #endif
::execl("/sbin/ifconfig", "/sbin/ifconfig", _dev.c_str(), "destroy", (const char*)0); ::execl("/sbin/ifconfig", "/sbin/ifconfig", _dev.c_str(), "destroy", (const char*)0);
::_exit(-1); ::_exit(-1);
} else if (cpid > 0) { }
else if (cpid > 0) {
int exitcode = -1; int exitcode = -1;
::waitpid(cpid, &exitcode, 0); ::waitpid(cpid, &exitcode, 0);
} }
@ -242,7 +249,8 @@ static bool ___removeIp(const std::string &_dev,const InetAddress &ip)
#endif #endif
execl("/sbin/ifconfig", "/sbin/ifconfig", _dev.c_str(), "inet", ip.toIpString(ipbuf), "-alias", (const char*)0); execl("/sbin/ifconfig", "/sbin/ifconfig", _dev.c_str(), "inet", ip.toIpString(ipbuf), "-alias", (const char*)0);
_exit(-1); _exit(-1);
} else if (cpid > 0) { }
else if (cpid > 0) {
int exitcode = -1; int exitcode = -1;
waitpid(cpid, &exitcode, 0); waitpid(cpid, &exitcode, 0);
return (exitcode == 0); return (exitcode == 0);
@ -275,7 +283,8 @@ bool BSDEthernetTap::addIp(const InetAddress &ip)
#endif #endif
::execl("/sbin/ifconfig", "/sbin/ifconfig", _dev.c_str(), ip.isV4() ? "inet" : "inet6", ip.toString(tmp), "alias", (const char*)0); ::execl("/sbin/ifconfig", "/sbin/ifconfig", _dev.c_str(), ip.isV4() ? "inet" : "inet6", ip.toString(tmp), "alias", (const char*)0);
::_exit(-1); ::_exit(-1);
} else if (cpid > 0) { }
else if (cpid > 0) {
int exitcode = -1; int exitcode = -1;
::waitpid(cpid, &exitcode, 0); ::waitpid(cpid, &exitcode, 0);
return (exitcode == 0); return (exitcode == 0);
@ -417,15 +426,15 @@ void BSDEthernetTap::setMtu(unsigned int mtu)
#endif #endif
execl("/sbin/ifconfig", "/sbin/ifconfig", _dev.c_str(), "mtu", tmp, (const char*)0); execl("/sbin/ifconfig", "/sbin/ifconfig", _dev.c_str(), "mtu", tmp, (const char*)0);
_exit(-1); _exit(-1);
} else if (cpid > 0) { }
else if (cpid > 0) {
int exitcode = -1; int exitcode = -1;
waitpid(cpid, &exitcode, 0); waitpid(cpid, &exitcode, 0);
} }
} }
} }
void BSDEthernetTap::threadMain() void BSDEthernetTap::threadMain() throw()
throw()
{ {
// Wait for a moment after startup -- wait for Network to finish // Wait for a moment after startup -- wait for Network to finish
// constructing itself. // constructing itself.
@ -433,7 +442,6 @@ void BSDEthernetTap::threadMain()
for (unsigned int i = 0; i < _concurrency; ++i) { for (unsigned int i = 0; i < _concurrency; ++i) {
_rxThreads.push_back(std::thread([this, i, _pinning] { _rxThreads.push_back(std::thread([this, i, _pinning] {
if (_pinning) { if (_pinning) {
int pinCore = i % _concurrency; int pinCore = i % _concurrency;
fprintf(stderr, "Pinning thread %d to core %d\n", i, pinCore); fprintf(stderr, "Pinning thread %d to core %d\n", i, pinCore);
@ -443,8 +451,7 @@ void BSDEthernetTap::threadMain()
CPU_SET(pinCore, &cpuset); CPU_SET(pinCore, &cpuset);
// int rc = sched_setaffinity(self, sizeof(cpu_set_t), &cpuset); // int rc = sched_setaffinity(self, sizeof(cpu_set_t), &cpuset);
int rc = pthread_setaffinity_np(self, sizeof(cpu_set_t), &cpuset); int rc = pthread_setaffinity_np(self, sizeof(cpu_set_t), &cpuset);
if (rc != 0) if (rc != 0) {
{
fprintf(stderr, "Failed to pin thread %d to core %d: %s\n", i, pinCore, strerror(errno)); fprintf(stderr, "Failed to pin thread %d to core %d: %s\n", i, pinCore, strerror(errno));
exit(1); exit(1);
} }
@ -474,7 +481,8 @@ void BSDEthernetTap::threadMain()
if (n < 0) { if (n < 0) {
if ((errno != EINTR) && (errno != ETIMEDOUT)) if ((errno != EINTR) && (errno != ETIMEDOUT))
break; break;
} else { }
else {
// Some tap drivers like to send the ethernet frame and the // Some tap drivers like to send the ethernet frame and the
// payload in two chunks, so handle that by accumulating // payload in two chunks, so handle that by accumulating
// data until we have at least a frame. // data until we have at least a frame.

View file

@ -14,24 +14,22 @@
#ifndef ZT_BSDETHERNETTAP_HPP #ifndef ZT_BSDETHERNETTAP_HPP
#define ZT_BSDETHERNETTAP_HPP #define ZT_BSDETHERNETTAP_HPP
#include "../node/Constants.hpp"
#include "../node/MAC.hpp"
#include "../node/MulticastGroup.hpp"
#include "EthernetTap.hpp"
#include "Thread.hpp"
#include <stdexcept>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string> #include <string>
#include <vector>
#include <stdexcept>
#include <thread> #include <thread>
#include <vector>
#include "../node/Constants.hpp"
#include "../node/MulticastGroup.hpp"
#include "../node/MAC.hpp"
#include "Thread.hpp"
#include "EthernetTap.hpp"
namespace ZeroTier { namespace ZeroTier {
class BSDEthernetTap : public EthernetTap class BSDEthernetTap : public EthernetTap {
{
public: public:
BSDEthernetTap( BSDEthernetTap(
const char* homePath, const char* homePath,
@ -57,10 +55,11 @@ public:
virtual void setFriendlyName(const char* friendlyName); virtual void setFriendlyName(const char* friendlyName);
virtual void scanMulticastGroups(std::vector<MulticastGroup>& added, std::vector<MulticastGroup>& removed); virtual void scanMulticastGroups(std::vector<MulticastGroup>& added, std::vector<MulticastGroup>& removed);
virtual void setMtu(unsigned int mtu); virtual void setMtu(unsigned int mtu);
virtual void setDns(const char *domain, const std::vector<InetAddress> &servers) {} virtual void setDns(const char* domain, const std::vector<InetAddress>& servers)
{
}
void threadMain() void threadMain() throw();
throw();
private: private:
void (*_handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void*, unsigned int); void (*_handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void*, unsigned int);

View file

@ -22,11 +22,11 @@
#include <string.h> #include <string.h>
#ifdef __WINDOWS__ #ifdef __WINDOWS__
#include <shlobj.h>
#include <winsock2.h>
#include <windows.h>
#include <iphlpapi.h> #include <iphlpapi.h>
#include <netioapi.h> #include <netioapi.h>
#include <shlobj.h>
#include <windows.h>
#include <winsock2.h>
#else #else
#include <ifaddrs.h> #include <ifaddrs.h>
#include <sys/socket.h> #include <sys/socket.h>
@ -34,9 +34,9 @@
#include <sys/wait.h> #include <sys/wait.h>
#include <unistd.h> #include <unistd.h>
#ifdef __LINUX__ #ifdef __LINUX__
#include <linux/if_addr.h>
#include <net/if.h> #include <net/if.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <linux/if_addr.h>
#endif #endif
#endif #endif

View file

@ -14,11 +14,11 @@
#ifndef ZT_BLOCKINGQUEUE_HPP #ifndef ZT_BLOCKINGQUEUE_HPP
#define ZT_BLOCKINGQUEUE_HPP #define ZT_BLOCKINGQUEUE_HPP
#include <queue>
#include <mutex>
#include <condition_variable>
#include <chrono>
#include <atomic> #include <atomic>
#include <chrono>
#include <condition_variable>
#include <mutex>
#include <queue>
#include <vector> #include <vector>
namespace ZeroTier { namespace ZeroTier {
@ -28,11 +28,11 @@ namespace ZeroTier {
* *
* Do not use in node/ since we have not gone C++11 there yet. * Do not use in node/ since we have not gone C++11 there yet.
*/ */
template <class T> template <class T> class BlockingQueue {
class BlockingQueue
{
public: public:
BlockingQueue(void) : r(true) {} BlockingQueue(void) : r(true)
{
}
inline void post(T t) inline void post(T t)
{ {
@ -92,12 +92,7 @@ public:
return v; return v;
} }
enum TimedWaitResult enum TimedWaitResult { OK, TIMED_OUT, STOP };
{
OK,
TIMED_OUT,
STOP
};
inline TimedWaitResult get(T& value, const unsigned long ms) inline TimedWaitResult get(T& value, const unsigned long ms)
{ {
@ -116,7 +111,8 @@ public:
return OK; return OK;
} }
inline size_t size() const { inline size_t size() const
{
return q.size(); return q.size();
} }

View file

@ -12,6 +12,7 @@
/****/ /****/
#include "EthernetTap.hpp" #include "EthernetTap.hpp"
#include "OSUtils.hpp" #include "OSUtils.hpp"
#include <stdlib.h> #include <stdlib.h>
@ -20,15 +21,16 @@
#ifdef ZT_SDK #ifdef ZT_SDK
#include "../controller/EmbeddedNetworkController.hpp" #include "../controller/EmbeddedNetworkController.hpp"
#include "../node/Node.hpp"
#include "../include/VirtualTap.hpp" #include "../include/VirtualTap.hpp"
#include "../node/Node.hpp"
#else #else
#ifdef __APPLE__ #ifdef __APPLE__
#include <sys/sysctl.h>
#include "MacEthernetTap.hpp" #include "MacEthernetTap.hpp"
#include "MacKextEthernetTap.hpp" #include "MacKextEthernetTap.hpp"
#include <sys/sysctl.h>
#endif // __APPLE__ #endif // __APPLE__
#ifdef __LINUX__ #ifdef __LINUX__
@ -68,7 +70,6 @@ std::shared_ptr<EthernetTap> EthernetTap::newInstance(
void (*handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void*, unsigned int), void (*handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void*, unsigned int),
void* arg) void* arg)
{ {
#ifdef ZT_SDK #ifdef ZT_SDK
return std::shared_ptr<EthernetTap>(new VirtualTap(homePath, mac, mtu, metric, nwid, friendlyName, handler, arg)); return std::shared_ptr<EthernetTap>(new VirtualTap(homePath, mac, mtu, metric, nwid, friendlyName, handler, arg));
@ -86,7 +87,8 @@ std::shared_ptr<EthernetTap> EthernetTap::newInstance(
// (Sierra and earlier) must use the a kernel extension. // (Sierra and earlier) must use the a kernel extension.
if (strtol(osrelease, (char**)0, 10) < 17) { if (strtol(osrelease, (char**)0, 10) < 17) {
return std::shared_ptr<EthernetTap>(new MacKextEthernetTap(homePath, mac, mtu, metric, nwid, friendlyName, handler, arg)); return std::shared_ptr<EthernetTap>(new MacKextEthernetTap(homePath, mac, mtu, metric, nwid, friendlyName, handler, arg));
} else { }
else {
return std::shared_ptr<EthernetTap>(new MacEthernetTap(homePath, mac, mtu, metric, nwid, friendlyName, handler, arg)); return std::shared_ptr<EthernetTap>(new MacEthernetTap(homePath, mac, mtu, metric, nwid, friendlyName, handler, arg));
} }
} }
@ -109,17 +111,7 @@ std::shared_ptr<EthernetTap> EthernetTap::newInstance(
{ {
Mutex::Lock l(_comInit_m); Mutex::Lock l(_comInit_m);
if (! _comInit) { if (! _comInit) {
hres = CoInitializeSecurity( hres = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
NULL,
-1,
NULL,
NULL,
RPC_C_AUTHN_LEVEL_PKT,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
EOAC_NONE,
NULL
);
if (FAILED(hres)) { if (FAILED(hres)) {
CoUninitialize(); CoUninitialize();
fprintf(stderr, "WinEthernetTap: Failed to initialize security"); fprintf(stderr, "WinEthernetTap: Failed to initialize security");
@ -148,8 +140,12 @@ std::shared_ptr<EthernetTap> EthernetTap::newInstance(
return std::shared_ptr<EthernetTap>(); return std::shared_ptr<EthernetTap>();
} }
EthernetTap::EthernetTap() {} EthernetTap::EthernetTap()
EthernetTap::~EthernetTap() {} {
}
EthernetTap::~EthernetTap()
{
}
bool EthernetTap::addIps(std::vector<InetAddress> ips) bool EthernetTap::addIps(std::vector<InetAddress> ips)
{ {

View file

@ -15,20 +15,19 @@
#define ZT_ETHERNETTAP_HPP #define ZT_ETHERNETTAP_HPP
#include "../node/Constants.hpp" #include "../node/Constants.hpp"
#include "../node/MAC.hpp"
#include "../node/InetAddress.hpp" #include "../node/InetAddress.hpp"
#include "../node/MAC.hpp"
#include "../node/MulticastGroup.hpp" #include "../node/MulticastGroup.hpp"
#include <string>
#include <memory> #include <memory>
#include <string>
#include <vector> #include <vector>
#define GETIFADDRS_CACHE_TIME 1000 #define GETIFADDRS_CACHE_TIME 1000
namespace ZeroTier { namespace ZeroTier {
class EthernetTap class EthernetTap {
{
public: public:
static std::shared_ptr<EthernetTap> newInstance( static std::shared_ptr<EthernetTap> newInstance(
const char* tapDeviceType, // OS-specific, NULL for default const char* tapDeviceType, // OS-specific, NULL for default

View file

@ -11,15 +11,16 @@
*/ */
/****/ /****/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "Http.hpp" #include "Http.hpp"
#include "Phy.hpp"
#include "OSUtils.hpp"
#include "../node/Constants.hpp" #include "../node/Constants.hpp"
#include "../node/Utils.hpp" #include "../node/Utils.hpp"
#include "OSUtils.hpp"
#include "Phy.hpp"
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#ifdef ZT_USE_SYSTEM_HTTP_PARSER #ifdef ZT_USE_SYSTEM_HTTP_PARSER
#include <http_parser.h> #include <http_parser.h>
@ -45,39 +46,26 @@ static int ShttpOnBody(http_parser *parser,const char *ptr,size_t length);
static int ShttpOnMessageComplete(http_parser* parser); static int ShttpOnMessageComplete(http_parser* parser);
#if (HTTP_PARSER_VERSION_MAJOR >= 2) && (HTTP_PARSER_VERSION_MINOR >= 1) #if (HTTP_PARSER_VERSION_MAJOR >= 2) && (HTTP_PARSER_VERSION_MINOR >= 1)
static const struct http_parser_settings HTTP_PARSER_SETTINGS = { static const struct http_parser_settings HTTP_PARSER_SETTINGS = { ShttpOnMessageBegin, ShttpOnUrl, ShttpOnStatus, ShttpOnHeaderField, ShttpOnValue, ShttpOnHeadersComplete, ShttpOnBody, ShttpOnMessageComplete };
ShttpOnMessageBegin,
ShttpOnUrl,
ShttpOnStatus,
ShttpOnHeaderField,
ShttpOnValue,
ShttpOnHeadersComplete,
ShttpOnBody,
ShttpOnMessageComplete
};
#else #else
static const struct http_parser_settings HTTP_PARSER_SETTINGS = { static const struct http_parser_settings HTTP_PARSER_SETTINGS = { ShttpOnMessageBegin, ShttpOnUrl, ShttpOnHeaderField, ShttpOnValue, ShttpOnHeadersComplete, ShttpOnBody, ShttpOnMessageComplete };
ShttpOnMessageBegin,
ShttpOnUrl,
ShttpOnHeaderField,
ShttpOnValue,
ShttpOnHeadersComplete,
ShttpOnBody,
ShttpOnMessageComplete
};
#endif #endif
struct HttpPhyHandler struct HttpPhyHandler {
{
// not used // not used
inline void phyOnDatagram(PhySocket *sock,void **uptr,const struct sockaddr *localAddr,const struct sockaddr *from,void *data,unsigned long len) {} inline void phyOnDatagram(PhySocket* sock, void** uptr, const struct sockaddr* localAddr, const struct sockaddr* from, void* data, unsigned long len)
inline void phyOnTcpAccept(PhySocket *sockL,PhySocket *sockN,void **uptrL,void **uptrN,const struct sockaddr *from) {} {
}
inline void phyOnTcpAccept(PhySocket* sockL, PhySocket* sockN, void** uptrL, void** uptrN, const struct sockaddr* from)
{
}
inline void phyOnTcpConnect(PhySocket* sock, void** uptr, bool success) inline void phyOnTcpConnect(PhySocket* sock, void** uptr, bool success)
{ {
if (success) { if (success) {
phy->setNotifyWritable(sock, true); phy->setNotifyWritable(sock, true);
} else { }
else {
*responseBody = "connection failed"; *responseBody = "connection failed";
error = true; error = true;
done = true; done = true;
@ -108,12 +96,22 @@ struct HttpPhyHandler
phy->setNotifyWritable(sock, false); phy->setNotifyWritable(sock, false);
} }
inline void phyOnFileDescriptorActivity(PhySocket *sock,void **uptr,bool readable,bool writable) {} inline void phyOnFileDescriptorActivity(PhySocket* sock, void** uptr, bool readable, bool writable)
{
}
#ifdef __UNIX_LIKE__ #ifdef __UNIX_LIKE__
inline void phyOnUnixAccept(PhySocket *sockL,PhySocket *sockN,void **uptrL,void **uptrN) {} inline void phyOnUnixAccept(PhySocket* sockL, PhySocket* sockN, void** uptrL, void** uptrN)
inline void phyOnUnixClose(PhySocket *sock,void **uptr) {} {
inline void phyOnUnixData(PhySocket *sock,void **uptr,void *data,unsigned long len) {} }
inline void phyOnUnixWritable(PhySocket *sock,void **uptr) {} inline void phyOnUnixClose(PhySocket* sock, void** uptr)
{
}
inline void phyOnUnixData(PhySocket* sock, void** uptr, void* data, unsigned long len)
{
}
inline void phyOnUnixWritable(PhySocket* sock, void** uptr)
{
}
#endif // __UNIX_LIKE__ #endif // __UNIX_LIKE__
http_parser parser; http_parser parser;
@ -240,14 +238,16 @@ unsigned int Http::_do(
handler.writeBuf.append("\r\n"); handler.writeBuf.append("\r\n");
if ((requestBody) && (requestBodyLength)) if ((requestBody) && (requestBodyLength))
handler.writeBuf.append((const char*)requestBody, requestBodyLength); handler.writeBuf.append((const char*)requestBody, requestBodyLength);
} catch ( ... ) { }
catch (...) {
responseBody = "request too large"; responseBody = "request too large";
return 0; return 0;
} }
if (maxResponseSize) { if (maxResponseSize) {
handler.maxResponseSize = maxResponseSize; handler.maxResponseSize = maxResponseSize;
} else { }
else {
handler.maxResponseSize = 2147483647; handler.maxResponseSize = 2147483647;
} }
handler.responseHeaders = &responseHeaders; handler.responseHeaders = &responseHeaders;
@ -275,10 +275,12 @@ unsigned int Http::_do(
} }
return ((handler.error) ? 0 : ((handler.parser.http_errno != HPE_OK) ? 0 : handler.parser.status_code)); return ((handler.error) ? 0 : ((handler.parser.http_errno != HPE_OK) ? 0 : handler.parser.status_code));
} catch (std::exception &exc) { }
catch (std::exception& exc) {
responseBody = exc.what(); responseBody = exc.what();
return 0; return 0;
} catch ( ... ) { }
catch (...) {
responseBody = "unknown exception"; responseBody = "unknown exception";
return 0; return 0;
} }

View file

@ -14,21 +14,21 @@
#ifndef ZT_HTTP_HPP #ifndef ZT_HTTP_HPP
#define ZT_HTTP_HPP #define ZT_HTTP_HPP
#include <string>
#include <map> #include <map>
#include <stdexcept> #include <stdexcept>
#include <string>
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
#include <windows.h>
#include <winsock2.h> #include <winsock2.h>
#include <ws2tcpip.h> #include <ws2tcpip.h>
#include <windows.h>
#else #else
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#endif #endif
namespace ZeroTier { namespace ZeroTier {
@ -36,8 +36,7 @@ namespace ZeroTier {
/** /**
* Simple synchronous HTTP client used for updater and cli * Simple synchronous HTTP client used for updater and cli
*/ */
class Http class Http {
{
public: public:
/** /**
* Make HTTP GET request * Make HTTP GET request
@ -46,8 +45,8 @@ public:
* *
* @return HTTP status code or 0 on error (responseBody will contain error message) * @return HTTP status code or 0 on error (responseBody will contain error message)
*/ */
static inline unsigned int GET( static inline unsigned int
unsigned long maxResponseSize, GET(unsigned long maxResponseSize,
unsigned long timeout, unsigned long timeout,
const struct sockaddr* remoteAddress, const struct sockaddr* remoteAddress,
const char* path, const char* path,
@ -55,17 +54,7 @@ public:
std::map<std::string, std::string>& responseHeaders, std::map<std::string, std::string>& responseHeaders,
std::string& responseBody) std::string& responseBody)
{ {
return _do( return _do("GET", maxResponseSize, timeout, remoteAddress, path, requestHeaders, (const void*)0, 0, responseHeaders, responseBody);
"GET",
maxResponseSize,
timeout,
remoteAddress,
path,
requestHeaders,
(const void *)0,
0,
responseHeaders,
responseBody);
} }
/** /**
@ -75,8 +64,8 @@ public:
* *
* @return HTTP status code or 0 on error (responseBody will contain error message) * @return HTTP status code or 0 on error (responseBody will contain error message)
*/ */
static inline unsigned int DEL( static inline unsigned int
unsigned long maxResponseSize, DEL(unsigned long maxResponseSize,
unsigned long timeout, unsigned long timeout,
const struct sockaddr* remoteAddress, const struct sockaddr* remoteAddress,
const char* path, const char* path,
@ -84,17 +73,7 @@ public:
std::map<std::string, std::string>& responseHeaders, std::map<std::string, std::string>& responseHeaders,
std::string& responseBody) std::string& responseBody)
{ {
return _do( return _do("DELETE", maxResponseSize, timeout, remoteAddress, path, requestHeaders, (const void*)0, 0, responseHeaders, responseBody);
"DELETE",
maxResponseSize,
timeout,
remoteAddress,
path,
requestHeaders,
(const void *)0,
0,
responseHeaders,
responseBody);
} }
/** /**
@ -117,17 +96,7 @@ public:
std::map<std::string, std::string>& responseHeaders, std::map<std::string, std::string>& responseHeaders,
std::string& responseBody) std::string& responseBody)
{ {
return _do( return _do("POST", maxResponseSize, timeout, remoteAddress, path, requestHeaders, postData, postDataLength, responseHeaders, responseBody);
"POST",
maxResponseSize,
timeout,
remoteAddress,
path,
requestHeaders,
postData,
postDataLength,
responseHeaders,
responseBody);
} }
/** /**
@ -139,8 +108,8 @@ public:
* *
* @return HTTP status code or 0 on error (responseBody will contain error message) * @return HTTP status code or 0 on error (responseBody will contain error message)
*/ */
static inline unsigned int PUT( static inline unsigned int
unsigned long maxResponseSize, PUT(unsigned long maxResponseSize,
unsigned long timeout, unsigned long timeout,
const struct sockaddr* remoteAddress, const struct sockaddr* remoteAddress,
const char* path, const char* path,
@ -150,22 +119,12 @@ public:
std::map<std::string, std::string>& responseHeaders, std::map<std::string, std::string>& responseHeaders,
std::string& responseBody) std::string& responseBody)
{ {
return _do( return _do("PUT", maxResponseSize, timeout, remoteAddress, path, requestHeaders, postData, postDataLength, responseHeaders, responseBody);
"PUT",
maxResponseSize,
timeout,
remoteAddress,
path,
requestHeaders,
postData,
postDataLength,
responseHeaders,
responseBody);
} }
private: private:
static unsigned int _do( static unsigned int
const char *method, _do(const char* method,
unsigned long maxResponseSize, unsigned long maxResponseSize,
unsigned long timeout, unsigned long timeout,
const struct sockaddr* remoteAddress, const struct sockaddr* remoteAddress,

View file

@ -19,42 +19,39 @@
#ifdef __LINUX__ #ifdef __LINUX__
#include "../node/Utils.hpp"
#include "../node/Mutex.hpp"
#include "../node/Dictionary.hpp" #include "../node/Dictionary.hpp"
#include "OSUtils.hpp" #include "../node/Mutex.hpp"
#include "../node/Utils.hpp"
#include "LinuxEthernetTap.hpp" #include "LinuxEthernetTap.hpp"
#include "LinuxNetLink.hpp" #include "LinuxNetLink.hpp"
#include "OSUtils.hpp"
#include <algorithm>
#include <arpa/inet.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <ifaddrs.h>
#include <linux/if.h>
#include <linux/if_addr.h>
#include <linux/if_ether.h>
#include <linux/if_tun.h>
#include <net/if_arp.h>
#include <netinet/in.h>
#include <signal.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <sys/select.h>
#include <netinet/in.h>
#include <net/if_arp.h>
#include <arpa/inet.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#include <linux/if_addr.h>
#include <linux/if_ether.h>
#include <ifaddrs.h>
#include <algorithm>
#include <utility>
#include <string> #include <string>
#include <sys/ioctl.h>
#include <ctype.h> #include <sys/select.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/utsname.h> #include <sys/utsname.h>
#include <sys/wait.h>
#include <unistd.h>
#include <utility>
#ifndef IFNAMSIZ #ifndef IFNAMSIZ
#define IFNAMSIZ 16 #define IFNAMSIZ 16
@ -72,7 +69,8 @@ namespace ZeroTier {
// the tap devices. // the tap devices.
// //
// Returns true if the kernel major version is < 3 // Returns true if the kernel major version is < 3
bool isOldLinuxKernel() { bool isOldLinuxKernel()
{
struct utsname buffer; struct utsname buffer;
char* p; char* p;
long ver[16]; long ver[16];
@ -88,7 +86,8 @@ bool isOldLinuxKernel() {
if (isdigit(*p)) { if (isdigit(*p)) {
ver[i] = strtol(p, &p, 10); ver[i] = strtol(p, &p, 10);
i++; i++;
} else { }
else {
p++; p++;
} }
} }
@ -119,23 +118,22 @@ LinuxEthernetTap::LinuxEthernetTap(
uint64_t nwid, uint64_t nwid,
const char* friendlyName, const char* friendlyName,
void (*handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void*, unsigned int), void (*handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void*, unsigned int),
void *arg) : void* arg)
_handler(handler), : _handler(handler)
_arg(arg), , _arg(arg)
_nwid(nwid), , _nwid(nwid)
_mac(mac), , _mac(mac)
_homePath(homePath), , _homePath(homePath)
_mtu(mtu), , _mtu(mtu)
_fd(0), , _fd(0)
_enabled(true), , _enabled(true)
_run(true), , _run(true)
_lastIfAddrsUpdate(0) , _lastIfAddrsUpdate(0)
{ {
static std::mutex s_tapCreateLock; static std::mutex s_tapCreateLock;
char procpath[128], nwids[32]; char procpath[128], nwids[32];
struct stat sbuf; struct stat sbuf;
// Create only one tap at a time globally. // Create only one tap at a time globally.
std::lock_guard<std::mutex> tapCreateLock(s_tapCreateLock); std::lock_guard<std::mutex> tapCreateLock(s_tapCreateLock);
@ -165,9 +163,12 @@ LinuxEthernetTap::LinuxEthernetTap(
char* y = (char*)0; char* y = (char*)0;
char* saveptr = (char*)0; char* saveptr = (char*)0;
for (char* f = Utils::stok(buf, "\r\n=", &saveptr); (f); f = Utils::stok((char*)0, "\r\n=", &saveptr)) { for (char* f = Utils::stok(buf, "\r\n=", &saveptr); (f); f = Utils::stok((char*)0, "\r\n=", &saveptr)) {
if (!x) x = f; if (! x)
else if (!y) y = f; x = f;
else break; else if (! y)
y = f;
else
break;
} }
if ((x) && (y) && (x[0]) && (y[0])) if ((x) && (y) && (x[0]) && (y[0]))
globalDeviceMap[x] = y; globalDeviceMap[x] = y;
@ -224,7 +225,6 @@ LinuxEthernetTap::LinuxEthernetTap(
for (unsigned int i = 0; i < concurrency; ++i) { for (unsigned int i = 0; i < concurrency; ++i) {
_rxThreads.push_back(std::thread([this, i, concurrency, pinning] { _rxThreads.push_back(std::thread([this, i, concurrency, pinning] {
if (pinning) { if (pinning) {
int pinCore = i % concurrency; int pinCore = i % concurrency;
fprintf(stderr, "Pinning tap thread %d to core %d\n", i, pinCore); fprintf(stderr, "Pinning tap thread %d to core %d\n", i, pinCore);
@ -233,8 +233,7 @@ LinuxEthernetTap::LinuxEthernetTap(
CPU_ZERO(&cpuset); CPU_ZERO(&cpuset);
CPU_SET(pinCore, &cpuset); CPU_SET(pinCore, &cpuset);
int rc = pthread_setaffinity_np(self, sizeof(cpu_set_t), &cpuset); int rc = pthread_setaffinity_np(self, sizeof(cpu_set_t), &cpuset);
if (rc != 0) if (rc != 0) {
{
fprintf(stderr, "Failed to pin tap thread %d to core %d: %s\n", i, pinCore, strerror(errno)); fprintf(stderr, "Failed to pin tap thread %d to core %d: %s\n", i, pinCore, strerror(errno));
exit(1); exit(1);
} }
@ -407,14 +406,13 @@ bool LinuxEthernetTap::addIps(std::vector<InetAddress> ips)
if (ips[i].isV4()) { if (ips[i].isV4()) {
char iptmp[64], iptmp2[64]; char iptmp[64], iptmp2[64];
std::string numstr4 = ip4_tot > 1 ? std::to_string(ip4) : ""; std::string numstr4 = ip4_tot > 1 ? std::to_string(ip4) : "";
cfg_contents += "\nIPADDR"+numstr4+"="+ips[i].toIpString(iptmp) cfg_contents += "\nIPADDR" + numstr4 + "=" + ips[i].toIpString(iptmp) + "\nNETMASK" + numstr4 + "=" + ips[i].netmask().toIpString(iptmp2) + "\n";
+ "\nNETMASK"+numstr4+"="+ips[i].netmask().toIpString(iptmp2)+"\n";
ip4++; ip4++;
} else { }
else {
char iptmp[64], iptmp2[64]; char iptmp[64], iptmp2[64];
std::string numstr6 = ip6_tot > 1 ? std::to_string(ip6) : ""; std::string numstr6 = ip6_tot > 1 ? std::to_string(ip6) : "";
cfg_contents += "\nIPV6ADDR"+numstr6+"="+ips[i].toIpString(iptmp) cfg_contents += "\nIPV6ADDR" + numstr6 + "=" + ips[i].toIpString(iptmp) + "\nNETMASK" + numstr6 + "=" + ips[i].netmask().toIpString(iptmp2) + "\n";
+ "\nNETMASK"+numstr6+"="+ips[i].netmask().toIpString(iptmp2)+"\n";
ip6++; ip6++;
} }
} }
@ -462,7 +460,6 @@ bool LinuxEthernetTap::removeIp(const InetAddress &ip)
std::vector<InetAddress> LinuxEthernetTap::ips() const std::vector<InetAddress> LinuxEthernetTap::ips() const
{ {
uint64_t now = OSUtils::now(); uint64_t now = OSUtils::now();
if ((now - _lastIfAddrsUpdate) <= GETIFADDRS_CACHE_TIME) { if ((now - _lastIfAddrsUpdate) <= GETIFADDRS_CACHE_TIME) {

View file

@ -14,24 +14,23 @@
#ifndef ZT_LINUXETHERNETTAP_HPP #ifndef ZT_LINUXETHERNETTAP_HPP
#define ZT_LINUXETHERNETTAP_HPP #define ZT_LINUXETHERNETTAP_HPP
#include "../node/MulticastGroup.hpp"
#include "BlockingQueue.hpp"
#include "EthernetTap.hpp"
#include <array>
#include <atomic>
#include <mutex>
#include <stdexcept>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string> #include <string>
#include <vector>
#include <stdexcept>
#include <atomic>
#include <array>
#include <thread> #include <thread>
#include <mutex> #include <vector>
#include "../node/MulticastGroup.hpp"
#include "EthernetTap.hpp"
#include "BlockingQueue.hpp"
namespace ZeroTier { namespace ZeroTier {
class LinuxEthernetTap : public EthernetTap class LinuxEthernetTap : public EthernetTap {
{
public: public:
LinuxEthernetTap( LinuxEthernetTap(
const char* homePath, const char* homePath,
@ -58,7 +57,9 @@ public:
virtual void setFriendlyName(const char* friendlyName); virtual void setFriendlyName(const char* friendlyName);
virtual void scanMulticastGroups(std::vector<MulticastGroup>& added, std::vector<MulticastGroup>& removed); virtual void scanMulticastGroups(std::vector<MulticastGroup>& added, std::vector<MulticastGroup>& removed);
virtual void setMtu(unsigned int mtu); virtual void setMtu(unsigned int mtu);
virtual void setDns(const char *domain, const std::vector<InetAddress> &servers) {} virtual void setDns(const char* domain, const std::vector<InetAddress>& servers)
{
}
private: private:
void (*_handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void*, unsigned int); void (*_handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void*, unsigned int);

View file

@ -21,8 +21,8 @@
#include "LinuxNetLink.hpp" #include "LinuxNetLink.hpp"
#include <unistd.h>
#include <linux/if_tun.h> #include <linux/if_tun.h>
#include <unistd.h>
#ifndef IFNAMSIZ #ifndef IFNAMSIZ
#define IFNAMSIZ 16 #define IFNAMSIZ 16
@ -49,14 +49,7 @@ struct nl_adr_req {
char buf[8192]; char buf[8192];
}; };
LinuxNetLink::LinuxNetLink() LinuxNetLink::LinuxNetLink() : _t(), _running(false), _seq(0), _interfaces(), _if_m(), _fd(socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)), _la({ 0 })
: _t()
, _running(false)
, _seq(0)
, _interfaces()
, _if_m()
, _fd(socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE))
, _la({0})
{ {
// set socket timeout to 1 sec so we're not permablocking recv() calls // set socket timeout to 1 sec so we're not permablocking recv() calls
_setSocketTimeout(_fd, 1); _setSocketTimeout(_fd, 1);
@ -137,8 +130,7 @@ int LinuxNetLink::_doRecv(int fd)
break; break;
} }
if( (nlp->nlmsg_flags & NLM_F_MULTI) == NLM_F_MULTI || (nlp->nlmsg_type == NLMSG_DONE)) if ((nlp->nlmsg_flags & NLM_F_MULTI) == NLM_F_MULTI || (nlp->nlmsg_type == NLMSG_DONE)) {
{
if (nlp->nlmsg_type == NLMSG_DONE) { if (nlp->nlmsg_type == NLMSG_DONE) {
_processMessage(nlp, nll); _processMessage(nlp, nll);
p = buf; p = buf;
@ -165,7 +157,8 @@ int LinuxNetLink::_doRecv(int fd)
p = buf; p = buf;
nll = 0; nll = 0;
break; break;
} else { }
else {
break; break;
} }
} }
@ -189,10 +182,8 @@ void LinuxNetLink::threadMain() throw()
void LinuxNetLink::_processMessage(struct nlmsghdr* nlp, int nll) void LinuxNetLink::_processMessage(struct nlmsghdr* nlp, int nll)
{ {
for(; NLMSG_OK(nlp, nll); nlp=NLMSG_NEXT(nlp, nll)) for (; NLMSG_OK(nlp, nll); nlp = NLMSG_NEXT(nlp, nll)) {
{ switch (nlp->nlmsg_type) {
switch(nlp->nlmsg_type)
{
case RTM_NEWLINK: case RTM_NEWLINK:
_linkAdded(nlp); _linkAdded(nlp);
break; break;
@ -229,8 +220,7 @@ void LinuxNetLink::_ipAddressAdded(struct nlmsghdr *nlp)
char label[40] = { 0 }; char label[40] = { 0 };
char bcast[40] = { 0 }; char bcast[40] = { 0 };
for(;RTA_OK(rtap, ifal); rtap=RTA_NEXT(rtap,ifal)) for (; RTA_OK(rtap, ifal); rtap = RTA_NEXT(rtap, ifal)) {
{
switch (rtap->rta_type) { switch (rtap->rta_type) {
case IFA_ADDRESS: case IFA_ADDRESS:
inet_ntop(ifap->ifa_family, RTA_DATA(rtap), addr, 40); inet_ntop(ifap->ifa_family, RTA_DATA(rtap), addr, 40);
@ -263,8 +253,7 @@ void LinuxNetLink::_ipAddressDeleted(struct nlmsghdr *nlp)
char label[40] = { 0 }; char label[40] = { 0 };
char bcast[40] = { 0 }; char bcast[40] = { 0 };
for(;RTA_OK(rtap, ifal); rtap=RTA_NEXT(rtap,ifal)) for (; RTA_OK(rtap, ifal); rtap = RTA_NEXT(rtap, ifal)) {
{
switch (rtap->rta_type) { switch (rtap->rta_type) {
case IFA_ADDRESS: case IFA_ADDRESS:
inet_ntop(ifap->ifa_family, RTA_DATA(rtap), addr, 40); inet_ntop(ifap->ifa_family, RTA_DATA(rtap), addr, 40);
@ -300,10 +289,8 @@ void LinuxNetLink::_routeAdded(struct nlmsghdr *nlp)
Route r; Route r;
bool wecare = false; bool wecare = false;
for(;RTA_OK(rtap, rtl); rtap=RTA_NEXT(rtap, rtl)) for (; RTA_OK(rtap, rtl); rtap = RTA_NEXT(rtap, rtl)) {
{ switch (rtap->rta_type) {
switch(rtap->rta_type)
{
case RTA_DST: case RTA_DST:
switch (rtp->rtm_family) { switch (rtp->rtm_family) {
case AF_INET: case AF_INET:
@ -388,10 +375,8 @@ void LinuxNetLink::_routeDeleted(struct nlmsghdr *nlp)
Route r; Route r;
bool wecare = false; bool wecare = false;
for(;RTA_OK(rtap, rtl); rtap=RTA_NEXT(rtap, rtl)) for (; RTA_OK(rtap, rtl); rtap = RTA_NEXT(rtap, rtl)) {
{ switch (rtap->rta_type) {
switch(rtap->rta_type)
{
case RTA_DST: case RTA_DST:
switch (rtp->rtm_family) { switch (rtp->rtm_family) {
case AF_INET: case AF_INET:
@ -472,8 +457,7 @@ void LinuxNetLink::_linkAdded(struct nlmsghdr *nlp)
int ifil = RTM_PAYLOAD(nlp); int ifil = RTM_PAYLOAD(nlp);
const char* ptr = (const char*)0; const char* ptr = (const char*)0;
for(;RTA_OK(rtap, ifil);rtap=RTA_NEXT(rtap, ifil)) for (; RTA_OK(rtap, ifil); rtap = RTA_NEXT(rtap, ifil)) {
{
switch (rtap->rta_type) { switch (rtap->rta_type) {
case IFLA_ADDRESS: case IFLA_ADDRESS:
ptr = (const char*)RTA_DATA(rtap); ptr = (const char*)RTA_DATA(rtap);
@ -494,7 +478,16 @@ void LinuxNetLink::_linkAdded(struct nlmsghdr *nlp)
struct iface_entry& entry = _interfaces[ifip->ifi_index]; struct iface_entry& entry = _interfaces[ifip->ifi_index];
entry.index = ifip->ifi_index; entry.index = ifip->ifi_index;
memcpy(entry.ifacename, ifname, sizeof(ifname)); memcpy(entry.ifacename, ifname, sizeof(ifname));
snprintf(entry.mac,sizeof(entry.mac),"%.02x:%.02x:%.02x:%.02x:%.02x:%.02x",(unsigned int)mac_bin[0],(unsigned int)mac_bin[1],(unsigned int)mac_bin[2],(unsigned int)mac_bin[3],(unsigned int)mac_bin[4],(unsigned int)mac_bin[5]); snprintf(
entry.mac,
sizeof(entry.mac),
"%.02x:%.02x:%.02x:%.02x:%.02x:%.02x",
(unsigned int)mac_bin[0],
(unsigned int)mac_bin[1],
(unsigned int)mac_bin[2],
(unsigned int)mac_bin[3],
(unsigned int)mac_bin[4],
(unsigned int)mac_bin[5]);
memcpy(entry.mac_bin, mac_bin, 6); memcpy(entry.mac_bin, mac_bin, 6);
entry.mtu = mtu; entry.mtu = mtu;
} }
@ -510,8 +503,7 @@ void LinuxNetLink::_linkDeleted(struct nlmsghdr *nlp)
int ifil = RTM_PAYLOAD(nlp); int ifil = RTM_PAYLOAD(nlp);
const char* ptr = (const char*)0; const char* ptr = (const char*)0;
for(;RTA_OK(rtap, ifil);rtap=RTA_NEXT(rtap, ifil)) for (; RTA_OK(rtap, ifil); rtap = RTA_NEXT(rtap, ifil)) {
{
switch (rtap->rta_type) { switch (rtap->rta_type) {
case IFLA_IFNAME: case IFLA_IFNAME:
ptr = (const char*)RTA_DATA(rtap); ptr = (const char*)RTA_DATA(rtap);
@ -690,7 +682,8 @@ void LinuxNetLink::_requestInterfaceList()
void LinuxNetLink::addRoute(const InetAddress& target, const InetAddress& via, const InetAddress& src, const char* ifaceName) void LinuxNetLink::addRoute(const InetAddress& target, const InetAddress& via, const InetAddress& src, const char* ifaceName)
{ {
if (!target) return; if (! target)
return;
int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if (fd == -1) { if (fd == -1) {
@ -727,7 +720,8 @@ void LinuxNetLink::addRoute(const InetAddress &target, const InetAddress &via, c
if (target.isV4()) { if (target.isV4()) {
rtap->rta_len = RTA_LENGTH(sizeof(struct in_addr)); rtap->rta_len = RTA_LENGTH(sizeof(struct in_addr));
memcpy(RTA_DATA(rtap), &((struct sockaddr_in*)&target)->sin_addr, sizeof(struct in_addr)); memcpy(RTA_DATA(rtap), &((struct sockaddr_in*)&target)->sin_addr, sizeof(struct in_addr));
} else { }
else {
rtap->rta_len = RTA_LENGTH(sizeof(struct in6_addr)); rtap->rta_len = RTA_LENGTH(sizeof(struct in6_addr));
memcpy(RTA_DATA(rtap), &((struct sockaddr_in6*)&target)->sin6_addr, sizeof(struct in6_addr)); memcpy(RTA_DATA(rtap), &((struct sockaddr_in6*)&target)->sin6_addr, sizeof(struct in6_addr));
} }
@ -756,19 +750,21 @@ void LinuxNetLink::addRoute(const InetAddress &target, const InetAddress &via, c
if (via.isV4()) { if (via.isV4()) {
rtap->rta_len = RTA_LENGTH(sizeof(struct in_addr)); rtap->rta_len = RTA_LENGTH(sizeof(struct in_addr));
memcpy(RTA_DATA(rtap), &((struct sockaddr_in*)&via)->sin_addr, sizeof(struct in_addr)); memcpy(RTA_DATA(rtap), &((struct sockaddr_in*)&via)->sin_addr, sizeof(struct in_addr));
} else { }
else {
rtap->rta_len = RTA_LENGTH(sizeof(struct in6_addr)); rtap->rta_len = RTA_LENGTH(sizeof(struct in6_addr));
memcpy(RTA_DATA(rtap), &((struct sockaddr_in6*)&via)->sin6_addr, sizeof(struct in6_addr)); memcpy(RTA_DATA(rtap), &((struct sockaddr_in6*)&via)->sin6_addr, sizeof(struct in6_addr));
} }
rtl += rtap->rta_len; rtl += rtap->rta_len;
} else if (src) { }
else if (src) {
rtap = (struct rtattr*)(((char*)rtap) + rtap->rta_len); rtap = (struct rtattr*)(((char*)rtap) + rtap->rta_len);
rtap->rta_type = RTA_SRC; rtap->rta_type = RTA_SRC;
if (src.isV4()) { if (src.isV4()) {
rtap->rta_len = RTA_LENGTH(sizeof(struct in_addr)); rtap->rta_len = RTA_LENGTH(sizeof(struct in_addr));
memcpy(RTA_DATA(rtap), &((struct sockaddr_in*)&src)->sin_addr, sizeof(struct in_addr)); memcpy(RTA_DATA(rtap), &((struct sockaddr_in*)&src)->sin_addr, sizeof(struct in_addr));
}
} else { else {
rtap->rta_len = RTA_LENGTH(sizeof(struct in6_addr)); rtap->rta_len = RTA_LENGTH(sizeof(struct in6_addr));
memcpy(RTA_DATA(rtap), &((struct sockaddr_in6*)&src)->sin6_addr, sizeof(struct in6_addr)); memcpy(RTA_DATA(rtap), &((struct sockaddr_in6*)&src)->sin6_addr, sizeof(struct in6_addr));
} }
@ -823,7 +819,8 @@ void LinuxNetLink::addRoute(const InetAddress &target, const InetAddress &via, c
void LinuxNetLink::delRoute(const InetAddress& target, const InetAddress& via, const InetAddress& src, const char* ifaceName) void LinuxNetLink::delRoute(const InetAddress& target, const InetAddress& via, const InetAddress& src, const char* ifaceName)
{ {
if (!target) return; if (! target)
return;
int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if (fd == -1) { if (fd == -1) {
@ -859,7 +856,8 @@ void LinuxNetLink::delRoute(const InetAddress &target, const InetAddress &via, c
if (target.isV4()) { if (target.isV4()) {
rtap->rta_len = RTA_LENGTH(sizeof(struct in_addr)); rtap->rta_len = RTA_LENGTH(sizeof(struct in_addr));
memcpy(RTA_DATA(rtap), &((struct sockaddr_in*)&target)->sin_addr, sizeof(struct in_addr)); memcpy(RTA_DATA(rtap), &((struct sockaddr_in*)&target)->sin_addr, sizeof(struct in_addr));
} else { }
else {
rtap->rta_len = RTA_LENGTH(sizeof(struct in6_addr)); rtap->rta_len = RTA_LENGTH(sizeof(struct in6_addr));
memcpy(RTA_DATA(rtap), &((struct sockaddr_in6*)&target)->sin6_addr, sizeof(struct in6_addr)); memcpy(RTA_DATA(rtap), &((struct sockaddr_in6*)&target)->sin6_addr, sizeof(struct in6_addr));
} }
@ -871,19 +869,21 @@ void LinuxNetLink::delRoute(const InetAddress &target, const InetAddress &via, c
if (via.isV4()) { if (via.isV4()) {
rtap->rta_len = RTA_LENGTH(sizeof(struct in_addr)); rtap->rta_len = RTA_LENGTH(sizeof(struct in_addr));
memcpy(RTA_DATA(rtap), &((struct sockaddr_in*)&via)->sin_addr, sizeof(struct in_addr)); memcpy(RTA_DATA(rtap), &((struct sockaddr_in*)&via)->sin_addr, sizeof(struct in_addr));
} else { }
else {
rtap->rta_len = RTA_LENGTH(sizeof(struct in6_addr)); rtap->rta_len = RTA_LENGTH(sizeof(struct in6_addr));
memcpy(RTA_DATA(rtap), &((struct sockaddr_in6*)&via)->sin6_addr, sizeof(struct in6_addr)); memcpy(RTA_DATA(rtap), &((struct sockaddr_in6*)&via)->sin6_addr, sizeof(struct in6_addr));
} }
rtl += rtap->rta_len; rtl += rtap->rta_len;
} else if (src) { }
else if (src) {
rtap = (struct rtattr*)(((char*)rtap) + rtap->rta_len); rtap = (struct rtattr*)(((char*)rtap) + rtap->rta_len);
rtap->rta_type = RTA_SRC; rtap->rta_type = RTA_SRC;
if (src.isV4()) { if (src.isV4()) {
rtap->rta_len = RTA_LENGTH(sizeof(struct in_addr)); rtap->rta_len = RTA_LENGTH(sizeof(struct in_addr));
memcpy(RTA_DATA(rtap), &((struct sockaddr_in*)&src)->sin_addr, sizeof(struct in_addr)); memcpy(RTA_DATA(rtap), &((struct sockaddr_in*)&src)->sin_addr, sizeof(struct in_addr));
}
} else { else {
rtap->rta_len = RTA_LENGTH(sizeof(struct in6_addr)); rtap->rta_len = RTA_LENGTH(sizeof(struct in6_addr));
memcpy(RTA_DATA(rtap), &((struct sockaddr_in6*)&src)->sin6_addr, sizeof(struct in6_addr)); memcpy(RTA_DATA(rtap), &((struct sockaddr_in6*)&src)->sin6_addr, sizeof(struct in6_addr));
} }
@ -952,7 +952,8 @@ void LinuxNetLink::addAddress(const InetAddress &addr, const char *iface)
la.nl_pid = 0; // getpid(); la.nl_pid = 0; // getpid();
if (addr.isV4()) { if (addr.isV4()) {
la.nl_groups = RTMGRP_IPV4_IFADDR; la.nl_groups = RTMGRP_IPV4_IFADDR;
} else { }
else {
la.nl_groups = RTMGRP_IPV6_IFADDR; la.nl_groups = RTMGRP_IPV6_IFADDR;
} }
@ -983,7 +984,8 @@ void LinuxNetLink::addAddress(const InetAddress &addr, const char *iface)
struct nl_adr_req req; struct nl_adr_req req;
bzero(&req, sizeof(struct nl_adr_req)); bzero(&req, sizeof(struct nl_adr_req));
struct rtattr *rtap = (struct rtattr *)req.buf;; struct rtattr* rtap = (struct rtattr*)req.buf;
;
if (addr.isV4()) { if (addr.isV4()) {
struct sockaddr_in* addr_v4 = (struct sockaddr_in*)&addr; struct sockaddr_in* addr_v4 = (struct sockaddr_in*)&addr;
rtap->rta_type = IFA_ADDRESS; rtap->rta_type = IFA_ADDRESS;
@ -1006,7 +1008,8 @@ void LinuxNetLink::addAddress(const InetAddress &addr, const char *iface)
memcpy(RTA_DATA(rtap), &bcast->sin_addr, sizeof(struct in_addr)); memcpy(RTA_DATA(rtap), &bcast->sin_addr, sizeof(struct in_addr));
rtl += rtap->rta_len; rtl += rtap->rta_len;
} }
} else { //V6 }
else { // V6
rtap->rta_type = IFA_ADDRESS; rtap->rta_type = IFA_ADDRESS;
struct sockaddr_in6* addr_v6 = (struct sockaddr_in6*)&addr; struct sockaddr_in6* addr_v6 = (struct sockaddr_in6*)&addr;
rtap->rta_len = RTA_LENGTH(sizeof(struct in6_addr)); rtap->rta_len = RTA_LENGTH(sizeof(struct in6_addr));
@ -1069,7 +1072,8 @@ void LinuxNetLink::removeAddress(const InetAddress &addr, const char *iface)
la.nl_pid = 0; // getpid(); la.nl_pid = 0; // getpid();
if (addr.isV4()) { if (addr.isV4()) {
la.nl_groups = RTMGRP_IPV4_IFADDR; la.nl_groups = RTMGRP_IPV4_IFADDR;
} else { }
else {
la.nl_groups = RTMGRP_IPV6_IFADDR; la.nl_groups = RTMGRP_IPV6_IFADDR;
} }
if (bind(fd, (struct sockaddr*)&la, sizeof(struct sockaddr_nl))) { if (bind(fd, (struct sockaddr*)&la, sizeof(struct sockaddr_nl))) {
@ -1118,7 +1122,8 @@ void LinuxNetLink::removeAddress(const InetAddress &addr, const char *iface)
memcpy(RTA_DATA(rtap), &bcast->sin_addr, sizeof(struct in_addr)); memcpy(RTA_DATA(rtap), &bcast->sin_addr, sizeof(struct in_addr));
rtl += rtap->rta_len; rtl += rtap->rta_len;
} }
} else { //V6 }
else { // V6
rtap->rta_type = IFA_ADDRESS; rtap->rta_type = IFA_ADDRESS;
struct sockaddr_in6* addr_v6 = (struct sockaddr_in6*)&addr; struct sockaddr_in6* addr_v6 = (struct sockaddr_in6*)&addr;
rtap->rta_len = RTA_LENGTH(sizeof(struct in6_addr)); rtap->rta_len = RTA_LENGTH(sizeof(struct in6_addr));
@ -1177,7 +1182,8 @@ bool LinuxNetLink::routeIsSet(const InetAddress &target, const InetAddress &via,
const iface_entry* ife = _interfaces.get(ri->ifidx); const iface_entry* ife = _interfaces.get(ri->ifidx);
if ((ife) && (! strncmp(ife->ifacename, ifname, IFNAMSIZ))) if ((ife) && (! strncmp(ife->ifacename, ifname, IFNAMSIZ)))
return true; return true;
} else { }
else {
return true; return true;
} }
} }

View file

@ -18,30 +18,26 @@
#ifdef __LINUX__ #ifdef __LINUX__
#include <vector>
#include <map>
#include <set>
#include <sys/socket.h>
#include <asm/types.h> #include <asm/types.h>
#include <linux/rtnetlink.h> #include <linux/rtnetlink.h>
#include <map>
#include <set>
#include <sys/socket.h> #include <sys/socket.h>
#include <vector>
// #include <linux/if.h> // #include <linux/if.h>
#include "../node/Hashtable.hpp"
#include "../node/InetAddress.hpp" #include "../node/InetAddress.hpp"
#include "../node/MAC.hpp" #include "../node/MAC.hpp"
#include "Thread.hpp"
#include "../node/Hashtable.hpp"
#include "../node/Mutex.hpp" #include "../node/Mutex.hpp"
#include "Thread.hpp"
namespace ZeroTier { namespace ZeroTier {
/** /**
* Interface with Linux's RTNETLINK * Interface with Linux's RTNETLINK
*/ */
class LinuxNetLink class LinuxNetLink {
{
private: private:
LinuxNetLink(); LinuxNetLink();
~LinuxNetLink(); ~LinuxNetLink();
@ -54,20 +50,27 @@ public:
int ifidx; int ifidx;
inline bool operator==(const Route& r) const inline bool operator==(const Route& r) const
{ return ((target == r.target)&&(via == r.via)&&(src == r.src)&&(ifidx == r.ifidx)); } {
return ((target == r.target) && (via == r.via) && (src == r.src) && (ifidx == r.ifidx));
}
inline bool operator!=(const Route& r) const inline bool operator!=(const Route& r) const
{ return (!(*this == r)); } {
return (! (*this == r));
}
inline bool operator<(const Route& r) const inline bool operator<(const Route& r) const
{ {
if (target < r.target) { if (target < r.target) {
return true; return true;
} else if (target == r.target) { }
else if (target == r.target) {
if (via < r.via) { if (via < r.via) {
return true; return true;
} else if (via == r.via) { }
else if (via == r.via) {
if (src < r.src) { if (src < r.src) {
return true; return true;
} else if (src == r.src) { }
else if (src == r.src) {
return (ifidx < r.ifidx); return (ifidx < r.ifidx);
} }
} }
@ -75,11 +78,17 @@ public:
return false; return false;
} }
inline bool operator>(const Route& r) const inline bool operator>(const Route& r) const
{ return (r < *this); } {
return (r < *this);
}
inline bool operator<=(const Route& r) const inline bool operator<=(const Route& r) const
{ return !(r < *this); } {
return ! (r < *this);
}
inline bool operator>=(const Route& r) const inline bool operator>=(const Route& r) const
{ return !(*this < r); } {
return ! (*this < r);
}
}; };
static LinuxNetLink& getInstance() static LinuxNetLink& getInstance()
@ -130,7 +139,9 @@ private:
struct iface_entry { struct iface_entry {
iface_entry() iface_entry()
{ memset(this,0,sizeof(iface_entry)); } {
memset(this, 0, sizeof(iface_entry));
}
int index; int index;
char ifacename[16]; // IFNAMSIZ on Linux == 16 char ifacename[16]; // IFNAMSIZ on Linux == 16
char mac[18]; char mac[18];
@ -145,7 +156,7 @@ private:
struct sockaddr_nl _la; struct sockaddr_nl _la;
}; };
} } // namespace ZeroTier
#endif #endif

View file

@ -1,14 +1,14 @@
#ifndef MAC_DNS_HELPER #ifndef MAC_DNS_HELPER
#define MAC_DNS_HELPER #define MAC_DNS_HELPER
#include <vector>
#include "../node/InetAddress.hpp" #include "../node/InetAddress.hpp"
#include "../node/MAC.hpp" #include "../node/MAC.hpp"
#include <vector>
namespace ZeroTier { namespace ZeroTier {
class MacDNSHelper class MacDNSHelper {
{
public: public:
static void setDNS(uint64_t nwid, const char* domain, const std::vector<InetAddress>& servers); static void setDNS(uint64_t nwid, const char* domain, const std::vector<InetAddress>& servers);
static void removeDNS(uint64_t nwid); static void removeDNS(uint64_t nwid);
@ -18,6 +18,6 @@ public:
static bool removeIps6(uint64_t nwid); static bool removeIps6(uint64_t nwid);
}; };
} } // namespace ZeroTier
#endif #endif

View file

@ -15,47 +15,43 @@
#ifdef __APPLE__ #ifdef __APPLE__
#include "../node/Utils.hpp"
#include "../node/Mutex.hpp"
#include "../node/Dictionary.hpp" #include "../node/Dictionary.hpp"
#include "OSUtils.hpp" #include "../node/Mutex.hpp"
#include "../node/Utils.hpp"
#include "MacDNSHelper.hpp"
#include "MacEthernetTap.hpp" #include "MacEthernetTap.hpp"
#include "MacEthernetTapAgent.h" #include "MacEthernetTapAgent.h"
#include "MacDNSHelper.hpp" #include "OSUtils.hpp"
#include <algorithm>
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <filesystem>
#include <ifaddrs.h>
#include <map>
#include <net/if.h>
#include <net/if_dl.h>
#include <net/route.h>
#include <netinet/in.h>
#include <set>
#include <signal.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <sys/select.h>
#include <sys/cdefs.h>
#include <sys/uio.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/route.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <sys/sysctl.h>
#include <ifaddrs.h>
#include <string> #include <string>
#include <map> #include <sys/cdefs.h>
#include <set> #include <sys/ioctl.h>
#include <algorithm> #include <sys/param.h>
#include <filesystem> #include <sys/select.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/sysctl.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <sys/wait.h>
#include <unistd.h>
static const ZeroTier::MulticastGroup _blindWildcardMulticastGroup(ZeroTier::MAC(0xff), 0); static const ZeroTier::MulticastGroup _blindWildcardMulticastGroup(ZeroTier::MAC(0xff), 0);
@ -75,23 +71,23 @@ MacEthernetTap::MacEthernetTap(
uint64_t nwid, uint64_t nwid,
const char* friendlyName, const char* friendlyName,
void (*handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void* data, unsigned int len), void (*handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void* data, unsigned int len),
void *arg) : void* arg)
_handler(handler), : _handler(handler)
_arg(arg), , _arg(arg)
_nwid(nwid), , _nwid(nwid)
_homePath(homePath), , _homePath(homePath)
_mtu(mtu), , _mtu(mtu)
_metric(metric), , _metric(metric)
_devNo(0), , _devNo(0)
_agentStdin(-1), , _agentStdin(-1)
_agentStdout(-1), , _agentStdout(-1)
_agentStderr(-1), , _agentStderr(-1)
_agentStdin2(-1), , _agentStdin2(-1)
_agentStdout2(-1), , _agentStdout2(-1)
_agentStderr2(-1), , _agentStderr2(-1)
_agentPid(-1), , _agentPid(-1)
_enabled(true), , _enabled(true)
_lastIfAddrsUpdate(0) , _lastIfAddrsUpdate(0)
{ {
char ethaddr[64], mtustr[16], devnostr[16], devstr[16], metricstr[16]; char ethaddr[64], mtustr[16], devnostr[16], devstr[16], metricstr[16];
OSUtils::ztsnprintf(ethaddr, sizeof(ethaddr), "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", (int)mac[0], (int)mac[1], (int)mac[2], (int)mac[3], (int)mac[4], (int)mac[5]); OSUtils::ztsnprintf(ethaddr, sizeof(ethaddr), "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", (int)mac[0], (int)mac[1], (int)mac[2], (int)mac[3], (int)mac[4], (int)mac[5]);
@ -136,7 +132,8 @@ MacEthernetTap::MacEthernetTap(
if (pid == 0) { if (pid == 0) {
execv(args[0], const_cast<char**>(args)); execv(args[0], const_cast<char**>(args));
_exit(-1); _exit(-1);
} else if (pid > 0) { }
else if (pid > 0) {
int rv = 0; int rv = 0;
waitpid(pid, &rv, 0); waitpid(pid, &rv, 0);
} }
@ -168,7 +165,8 @@ MacEthernetTap::MacEthernetTap(
devNo = (devNo + 1) % 5000; devNo = (devNo + 1) % 5000;
if (devNo < 100) if (devNo < 100)
devNo = 100; devNo = 100;
} else { }
else {
_dev = devstr; _dev = devstr;
_devNo = devNo; _devNo = devNo;
break; break;
@ -196,7 +194,8 @@ MacEthernetTap::MacEthernetTap(
long apid = (long)fork(); long apid = (long)fork();
if (apid < 0) { if (apid < 0) {
throw std::runtime_error("fork failed"); throw std::runtime_error("fork failed");
} else if (apid == 0) { }
else if (apid == 0) {
::dup2(agentStdin[0], STDIN_FILENO); ::dup2(agentStdin[0], STDIN_FILENO);
::dup2(agentStdout[1], STDOUT_FILENO); ::dup2(agentStdout[1], STDOUT_FILENO);
::dup2(agentStderr[1], STDERR_FILENO); ::dup2(agentStderr[1], STDERR_FILENO);
@ -208,7 +207,8 @@ MacEthernetTap::MacEthernetTap(
::close(agentStderr[1]); ::close(agentStderr[1]);
::execl(agentPath.c_str(), agentPath.c_str(), devnostr, ethaddr, mtustr, metricstr, (char*)0); ::execl(agentPath.c_str(), agentPath.c_str(), devnostr, ethaddr, mtustr, metricstr, (char*)0);
::_exit(-1); ::_exit(-1);
} else { }
else {
_agentPid = apid; _agentPid = apid;
// Wait up to 10 seconds for the subprocess to actually create the device. This prevents // Wait up to 10 seconds for the subprocess to actually create the device. This prevents
@ -228,7 +228,8 @@ MacEthernetTap::MacEthernetTap(
} }
if (waitLoops == -1) { if (waitLoops == -1) {
break; break;
} else if (waitLoops >= 100) { // 10 seconds }
else if (waitLoops >= 100) { // 10 seconds
throw std::runtime_error("feth device creation timed out"); throw std::runtime_error("feth device creation timed out");
} }
Thread::sleep(100); Thread::sleep(100);
@ -288,8 +289,14 @@ MacEthernetTap::~MacEthernetTap()
Thread::join(_thread); Thread::join(_thread);
} }
void MacEthernetTap::setEnabled(bool en) { _enabled = en; } void MacEthernetTap::setEnabled(bool en)
bool MacEthernetTap::enabled() const { return _enabled; } {
_enabled = en;
}
bool MacEthernetTap::enabled() const
{
return _enabled;
}
bool MacEthernetTap::addIp(const InetAddress& ip) bool MacEthernetTap::addIp(const InetAddress& ip)
{ {
@ -408,8 +415,13 @@ void MacEthernetTap::put(const MAC &from,const MAC &to,unsigned int etherType,co
} }
} }
std::string MacEthernetTap::deviceName() const { return _dev; } std::string MacEthernetTap::deviceName() const
void MacEthernetTap::setFriendlyName(const char *friendlyName) {} {
return _dev;
}
void MacEthernetTap::setFriendlyName(const char* friendlyName)
{
}
void MacEthernetTap::scanMulticastGroups(std::vector<MulticastGroup>& added, std::vector<MulticastGroup>& removed) void MacEthernetTap::scanMulticastGroups(std::vector<MulticastGroup>& added, std::vector<MulticastGroup>& removed)
{ {
@ -471,8 +483,7 @@ void MacEthernetTap::setMtu(unsigned int mtu)
#define ZT_MACETHERNETTAP_AGENT_READ_BUF_SIZE 131072 #define ZT_MACETHERNETTAP_AGENT_READ_BUF_SIZE 131072
void MacEthernetTap::threadMain() void MacEthernetTap::threadMain() throw()
throw()
{ {
char agentReadBuf[ZT_MACETHERNETTAP_AGENT_READ_BUF_SIZE]; char agentReadBuf[ZT_MACETHERNETTAP_AGENT_READ_BUF_SIZE];
char agentStderrBuf[256]; char agentStderrBuf[256];
@ -514,10 +525,12 @@ void MacEthernetTap::threadMain()
if (agentReadPtr > (len + 2)) { if (agentReadPtr > (len + 2)) {
memmove(agentReadBuf, agentReadBuf + len + 2, agentReadPtr -= (len + 2)); memmove(agentReadBuf, agentReadBuf + len + 2, agentReadPtr -= (len + 2));
} else { }
else {
agentReadPtr = 0; agentReadPtr = 0;
} }
} else { }
else {
break; break;
} }
} }

View file

@ -15,24 +15,22 @@
#define ZT_OSXETHERNETTAP_HPP #define ZT_OSXETHERNETTAP_HPP
#include "../node/Constants.hpp" #include "../node/Constants.hpp"
#include "../node/MAC.hpp"
#include "../node/InetAddress.hpp" #include "../node/InetAddress.hpp"
#include "../node/MAC.hpp"
#include "../node/MulticastGroup.hpp" #include "../node/MulticastGroup.hpp"
#include "../node/Mutex.hpp" #include "../node/Mutex.hpp"
#include "Thread.hpp"
#include "EthernetTap.hpp" #include "EthernetTap.hpp"
#include "Thread.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <stdexcept> #include <stdexcept>
#include <stdio.h>
#include <stdlib.h>
#include <string> #include <string>
#include <vector> #include <vector>
namespace ZeroTier { namespace ZeroTier {
class MacEthernetTap : public EthernetTap class MacEthernetTap : public EthernetTap {
{
public: public:
MacEthernetTap( MacEthernetTap(
const char* homePath, const char* homePath,
@ -58,8 +56,7 @@ public:
virtual void setMtu(unsigned int mtu); virtual void setMtu(unsigned int mtu);
virtual void setDns(const char* domain, const std::vector<InetAddress>& servers); virtual void setDns(const char* domain, const std::vector<InetAddress>& servers);
void threadMain() void threadMain() throw();
throw();
private: private:
void (*_handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void*, unsigned int); void (*_handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void*, unsigned int);
@ -79,7 +76,6 @@ private:
volatile bool _enabled; volatile bool _enabled;
mutable std::vector<InetAddress> _ifaddrs; mutable std::vector<InetAddress> _ifaddrs;
mutable uint64_t _lastIfAddrsUpdate; mutable uint64_t _lastIfAddrsUpdate;
}; };
} // namespace ZeroTier } // namespace ZeroTier

View file

@ -11,39 +11,36 @@
*/ */
/****/ /****/
#include <stdint.h> #include "MacDNSHelper.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <sys/select.h>
#include <sys/cdefs.h>
#include <sys/uio.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <net/route.h> #include <errno.h>
#include <fcntl.h>
#include <net/if.h> #include <net/if.h>
#include <net/if_arp.h> #include <net/if_arp.h>
#include <net/if_dl.h> #include <net/if_dl.h>
#include <net/if_media.h> #include <net/if_media.h>
#include <sys/sysctl.h> #include <net/route.h>
#include <netinet6/in6_var.h>
#include <netinet/in_var.h>
#include <netinet/icmp6.h> #include <netinet/icmp6.h>
#include <netinet/in.h>
#include "MacDNSHelper.hpp" #include <netinet/in_var.h>
#include <netinet6/in6_var.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/cdefs.h>
#include <sys/ioctl.h>
#include <sys/param.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/sysctl.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <sys/wait.h>
#include <unistd.h>
// OSX compile fix... in6_var defines this in a struct which namespaces it for C++ ... why?!? // OSX compile fix... in6_var defines this in a struct which namespaces it for C++ ... why?!?
struct prf_ra { struct prf_ra {
@ -52,8 +49,8 @@ struct prf_ra {
u_char reserved : 6; u_char reserved : 6;
} prf_ra; } prf_ra;
#include <netinet6/nd6.h>
#include <ifaddrs.h> #include <ifaddrs.h>
#include <netinet6/nd6.h>
// These are KERNEL_PRIVATE... why? // These are KERNEL_PRIVATE... why?
#ifndef SIOCAUTOCONF_START #ifndef SIOCAUTOCONF_START
@ -70,8 +67,7 @@ struct prf_ra {
// It's here because OSX 10.6 does not have this convenience function. // It's here because OSX 10.6 does not have this convenience function.
#define SALIGN (sizeof(uint32_t) - 1) #define SALIGN (sizeof(uint32_t) - 1)
#define SA_RLEN(sa) ((sa)->sa_len ? (((sa)->sa_len + SALIGN) & ~SALIGN) : \ #define SA_RLEN(sa) ((sa)->sa_len ? (((sa)->sa_len + SALIGN) & ~SALIGN) : (SALIGN + 1))
(SALIGN + 1))
#define MAX_SYSCTL_TRY 5 #define MAX_SYSCTL_TRY 5
#define RTA_MASKS (RTA_GATEWAY | RTA_IFP | RTA_IFA) #define RTA_MASKS (RTA_GATEWAY | RTA_IFP | RTA_IFA)
@ -146,8 +142,7 @@ static inline int _intl_getifmaddrs(struct _intl_ifmaddrs **pif)
icnt++; icnt++;
p = (char*)(ifmam + 1); p = (char*)(ifmam + 1);
for (i = 0; i < RTAX_MAX; i++) { for (i = 0; i < RTAX_MAX; i++) {
if ((RTA_MASKS & ifmam->ifmam_addrs & if ((RTA_MASKS & ifmam->ifmam_addrs & (1 << i)) == 0)
(1 << i)) == 0)
continue; continue;
sa = (struct sockaddr*)(void*)p; sa = (struct sockaddr*)(void*)p;
len = SA_RLEN(sa); len = SA_RLEN(sa);
@ -183,29 +178,25 @@ static inline int _intl_getifmaddrs(struct _intl_ifmaddrs **pif)
p = (char*)(ifmam + 1); p = (char*)(ifmam + 1);
for (i = 0; i < RTAX_MAX; i++) { for (i = 0; i < RTAX_MAX; i++) {
if ((RTA_MASKS & ifmam->ifmam_addrs & if ((RTA_MASKS & ifmam->ifmam_addrs & (1 << i)) == 0)
(1 << i)) == 0)
continue; continue;
sa = (struct sockaddr*)(void*)p; sa = (struct sockaddr*)(void*)p;
len = SA_RLEN(sa); len = SA_RLEN(sa);
switch (i) { switch (i) {
case RTAX_GATEWAY: case RTAX_GATEWAY:
ift->ifma_lladdr = ift->ifma_lladdr = (struct sockaddr*)(void*)data;
(struct sockaddr *)(void *)data;
memcpy(data, p, len); memcpy(data, p, len);
data += len; data += len;
break; break;
case RTAX_IFP: case RTAX_IFP:
ift->ifma_name = ift->ifma_name = (struct sockaddr*)(void*)data;
(struct sockaddr *)(void *)data;
memcpy(data, p, len); memcpy(data, p, len);
data += len; data += len;
break; break;
case RTAX_IFA: case RTAX_IFA:
ift->ifma_addr = ift->ifma_addr = (struct sockaddr*)(void*)data;
(struct sockaddr *)(void *)data;
memcpy(data, p, len); memcpy(data, p, len);
data += len; data += len;
break; break;
@ -228,7 +219,8 @@ static inline int _intl_getifmaddrs(struct _intl_ifmaddrs **pif)
ift--; ift--;
ift->ifma_next = NULL; ift->ifma_next = NULL;
*pif = ifa; *pif = ifa;
} else { }
else {
*pif = NULL; *pif = NULL;
free(ifa); free(ifa);
} }
@ -243,17 +235,17 @@ static inline void _intl_freeifmaddrs(struct _intl_ifmaddrs *ifmp)
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
#include <string> #include "../node/Constants.hpp"
#include "../node/Dictionary.hpp"
#include "../node/Mutex.hpp"
#include "../node/Utils.hpp"
#include "MacKextEthernetTap.hpp"
#include "OSUtils.hpp"
#include <algorithm>
#include <map> #include <map>
#include <set> #include <set>
#include <algorithm> #include <string>
#include "../node/Constants.hpp"
#include "../node/Utils.hpp"
#include "../node/Mutex.hpp"
#include "../node/Dictionary.hpp"
#include "OSUtils.hpp"
#include "MacKextEthernetTap.hpp"
// ff:ff:ff:ff:ff:ff with no ADI // ff:ff:ff:ff:ff:ff with no ADI
static const ZeroTier::MulticastGroup _blindWildcardMulticastGroup(ZeroTier::MAC(0xff), 0); static const ZeroTier::MulticastGroup _blindWildcardMulticastGroup(ZeroTier::MAC(0xff), 0);
@ -279,7 +271,8 @@ static inline bool _setIpv6Stuff(const char *ifname,bool performNUD,bool acceptR
if (performNUD) if (performNUD)
nd.ndi.flags |= ND6_IFF_PERFORMNUD; nd.ndi.flags |= ND6_IFF_PERFORMNUD;
else nd.ndi.flags &= ~ND6_IFF_PERFORMNUD; else
nd.ndi.flags &= ~ND6_IFF_PERFORMNUD;
if (oldFlags != (unsigned long)nd.ndi.flags) { if (oldFlags != (unsigned long)nd.ndi.flags) {
if (ioctl(s, SIOCSIFINFO_FLAGS, &nd)) { if (ioctl(s, SIOCSIFINFO_FLAGS, &nd)) {
@ -312,15 +305,15 @@ MacKextEthernetTap::MacKextEthernetTap(
uint64_t nwid, uint64_t nwid,
const char* friendlyName, const char* friendlyName,
void (*handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void* data, unsigned int len), void (*handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void* data, unsigned int len),
void *arg) : void* arg)
_handler(handler), : _handler(handler)
_arg(arg), , _arg(arg)
_nwid(nwid), , _nwid(nwid)
_homePath(homePath), , _homePath(homePath)
_mtu(mtu), , _mtu(mtu)
_metric(metric), , _metric(metric)
_fd(0), , _fd(0)
_enabled(true) , _enabled(true)
{ {
char devpath[64], ethaddr[64], mtustr[32], metstr[32], nwids[32]; char devpath[64], ethaddr[64], mtustr[32], metstr[32], nwids[32];
struct stat stattmp; struct stat stattmp;
@ -336,7 +329,8 @@ MacKextEthernetTap::MacKextEthernetTap(
OSUtils::redirectUnixOutputs("/dev/null", (const char*)0); OSUtils::redirectUnixOutputs("/dev/null", (const char*)0);
::execl("/sbin/kextload", "/sbin/kextload", "-q", "-repository", homePath, "tap.kext", (const char*)0); ::execl("/sbin/kextload", "/sbin/kextload", "-q", "-repository", homePath, "tap.kext", (const char*)0);
::_exit(-1); ::_exit(-1);
} else if (kextpid > 0) { }
else if (kextpid > 0) {
int exitcode = -1; int exitcode = -1;
::waitpid(kextpid, &exitcode, 0); ::waitpid(kextpid, &exitcode, 0);
} }
@ -355,9 +349,12 @@ MacKextEthernetTap::MacKextEthernetTap(
char* y = (char*)0; char* y = (char*)0;
char* saveptr = (char*)0; char* saveptr = (char*)0;
for (char* f = Utils::stok(buf, "\r\n=", &saveptr); (f); f = Utils::stok((char*)0, "\r\n=", &saveptr)) { for (char* f = Utils::stok(buf, "\r\n=", &saveptr); (f); f = Utils::stok((char*)0, "\r\n=", &saveptr)) {
if (!x) x = f; if (! x)
else if (!y) y = f; x = f;
else break; else if (! y)
y = f;
else
break;
} }
if ((x) && (y) && (x[0]) && (y[0])) if ((x) && (y) && (x[0]) && (y[0]))
globalDeviceMap[x] = y; globalDeviceMap[x] = y;
@ -367,7 +364,8 @@ MacKextEthernetTap::MacKextEthernetTap(
bool recalledDevice = false; bool recalledDevice = false;
std::map<std::string, std::string>::const_iterator gdmEntry = globalDeviceMap.find(nwids); std::map<std::string, std::string>::const_iterator gdmEntry = globalDeviceMap.find(nwids);
if (gdmEntry != globalDeviceMap.end()) { if (gdmEntry != globalDeviceMap.end()) {
std::string devpath("/dev/"); devpath.append(gdmEntry->second); std::string devpath("/dev/");
devpath.append(gdmEntry->second);
if (stat(devpath.c_str(), &stattmp) == 0) { if (stat(devpath.c_str(), &stattmp) == 0) {
_fd = ::open(devpath.c_str(), O_RDWR); _fd = ::open(devpath.c_str(), O_RDWR);
if (_fd > 0) { if (_fd > 0) {
@ -409,7 +407,8 @@ MacKextEthernetTap::MacKextEthernetTap(
if (cpid == 0) { if (cpid == 0) {
::execl("/sbin/ifconfig", "/sbin/ifconfig", _dev.c_str(), "lladdr", ethaddr, "mtu", mtustr, "metric", metstr, "up", (const char*)0); ::execl("/sbin/ifconfig", "/sbin/ifconfig", _dev.c_str(), "lladdr", ethaddr, "mtu", mtustr, "metric", metstr, "up", (const char*)0);
::_exit(-1); ::_exit(-1);
} else if (cpid > 0) { }
else if (cpid > 0) {
int exitcode = -1; int exitcode = -1;
::waitpid(cpid, &exitcode, 0); ::waitpid(cpid, &exitcode, 0);
if (exitcode) { if (exitcode) {
@ -466,7 +465,8 @@ MacKextEthernetTap::~MacKextEthernetTap()
OSUtils::redirectUnixOutputs("/dev/null", (const char*)0); OSUtils::redirectUnixOutputs("/dev/null", (const char*)0);
::execl("/sbin/kextunload", "/sbin/kextunload", tmp, (const char*)0); ::execl("/sbin/kextunload", "/sbin/kextunload", tmp, (const char*)0);
::_exit(-1); ::_exit(-1);
} else if (kextpid > 0) { }
else if (kextpid > 0) {
int exitcode = -1; int exitcode = -1;
::waitpid(kextpid, &exitcode, 0); ::waitpid(kextpid, &exitcode, 0);
} }
@ -495,7 +495,8 @@ bool MacKextEthernetTap::addIp(const InetAddress &ip)
char tmp[128]; char tmp[128];
::execl("/sbin/ifconfig", "/sbin/ifconfig", _dev.c_str(), (ip.ss_family == AF_INET6) ? "inet6" : "inet", ip.toString(tmp), "alias", (const char*)0); ::execl("/sbin/ifconfig", "/sbin/ifconfig", _dev.c_str(), (ip.ss_family == AF_INET6) ? "inet6" : "inet", ip.toString(tmp), "alias", (const char*)0);
::_exit(-1); ::_exit(-1);
} else if (cpid > 0) { }
else if (cpid > 0) {
int exitcode = -1; int exitcode = -1;
::waitpid(cpid, &exitcode, 0); ::waitpid(cpid, &exitcode, 0);
return (exitcode == 0); return (exitcode == 0);
@ -516,7 +517,8 @@ bool MacKextEthernetTap::removeIp(const InetAddress &ip)
char tmp[128]; char tmp[128];
execl("/sbin/ifconfig", "/sbin/ifconfig", _dev.c_str(), (ip.ss_family == AF_INET6) ? "inet6" : "inet", ip.toIpString(tmp), "-alias", (const char*)0); execl("/sbin/ifconfig", "/sbin/ifconfig", _dev.c_str(), (ip.ss_family == AF_INET6) ? "inet6" : "inet", ip.toIpString(tmp), "-alias", (const char*)0);
_exit(-1); _exit(-1);
} else if (cpid > 0) { }
else if (cpid > 0) {
int exitcode = -1; int exitcode = -1;
waitpid(cpid, &exitcode, 0); waitpid(cpid, &exitcode, 0);
return (exitcode == 0); return (exitcode == 0);
@ -634,15 +636,15 @@ void MacKextEthernetTap::setMtu(unsigned int mtu)
OSUtils::ztsnprintf(tmp, sizeof(tmp), "%u", mtu); OSUtils::ztsnprintf(tmp, sizeof(tmp), "%u", mtu);
execl("/sbin/ifconfig", "/sbin/ifconfig", _dev.c_str(), "mtu", tmp, (const char*)0); execl("/sbin/ifconfig", "/sbin/ifconfig", _dev.c_str(), "mtu", tmp, (const char*)0);
_exit(-1); _exit(-1);
} else if (cpid > 0) { }
else if (cpid > 0) {
int exitcode = -1; int exitcode = -1;
waitpid(cpid, &exitcode, 0); waitpid(cpid, &exitcode, 0);
} }
} }
} }
void MacKextEthernetTap::threadMain() void MacKextEthernetTap::threadMain() throw()
throw()
{ {
fd_set readfds, nullfds; fd_set readfds, nullfds;
MAC to, from; MAC to, from;
@ -669,7 +671,8 @@ void MacKextEthernetTap::threadMain()
if (n < 0) { if (n < 0) {
if ((errno != EINTR) && (errno != ETIMEDOUT)) if ((errno != EINTR) && (errno != ETIMEDOUT))
break; break;
} else { }
else {
// Some tap drivers like to send the ethernet frame and the // Some tap drivers like to send the ethernet frame and the
// payload in two chunks, so handle that by accumulating // payload in two chunks, so handle that by accumulating
// data until we have at least a frame. // data until we have at least a frame.

View file

@ -14,26 +14,23 @@
#ifndef ZT_MacKextEthernetTap_HPP #ifndef ZT_MacKextEthernetTap_HPP
#define ZT_MacKextEthernetTap_HPP #define ZT_MacKextEthernetTap_HPP
#include <stdio.h> #include "../node/Constants.hpp"
#include <stdlib.h> #include "../node/InetAddress.hpp"
#include "../node/MAC.hpp"
#include "../node/MulticastGroup.hpp"
#include "EthernetTap.hpp"
#include "Thread.hpp"
#include <stdexcept> #include <stdexcept>
#include <stdio.h>
#include <stdlib.h>
#include <string> #include <string>
#include <vector>
#include <thread> #include <thread>
#include <vector>
#include "../node/Constants.hpp"
#include "../node/MAC.hpp"
#include "../node/InetAddress.hpp"
#include "../node/MulticastGroup.hpp"
#include "Thread.hpp"
#include "EthernetTap.hpp"
namespace ZeroTier { namespace ZeroTier {
class MacKextEthernetTap : public EthernetTap class MacKextEthernetTap : public EthernetTap {
{
public: public:
MacKextEthernetTap( MacKextEthernetTap(
const char* homePath, const char* homePath,
@ -59,9 +56,7 @@ public:
virtual void setMtu(unsigned int mtu); virtual void setMtu(unsigned int mtu);
virtual void setDns(const char* domain, const std::vector<InetAddress>& servers); virtual void setDns(const char* domain, const std::vector<InetAddress>& servers);
void threadMain() throw();
void threadMain()
throw();
private: private:
void (*_handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void*, unsigned int); void (*_handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void*, unsigned int);

View file

@ -20,20 +20,20 @@
#include <string.h> #include <string.h>
#ifdef __WINDOWS__ #ifdef __WINDOWS__
#include <winsock2.h>
#include <windows.h>
#include <netioapi.h>
#include <IPHlpApi.h> #include <IPHlpApi.h>
#include <netioapi.h>
#include <windows.h>
#include <winsock2.h>
#endif #endif
#ifdef __UNIX_LIKE__ #ifdef __UNIX_LIKE__
#include <unistd.h> #include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/param.h> #include <sys/param.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <netinet/in.h> #include <unistd.h>
#include <arpa/inet.h>
#ifndef ZT_SDK #ifndef ZT_SDK
#include <net/route.h> #include <net/route.h>
#endif #endif
@ -45,11 +45,11 @@
#include <ifaddrs.h> #include <ifaddrs.h>
#endif #endif
#include <vector> #include "ManagedRoute.hpp"
#include <algorithm> #include <algorithm>
#include <utility> #include <utility>
#include <vector>
#include "ManagedRoute.hpp"
#ifdef __LINUX__ #ifdef __LINUX__
#include "LinuxNetLink.hpp" #include "LinuxNetLink.hpp"
#endif #endif
@ -72,24 +72,26 @@ static void _forkTarget(const InetAddress &t,InetAddress &left,InetAddress &righ
right = t; right = t;
reinterpret_cast<struct sockaddr_in*>(&right)->sin_addr.s_addr ^= Utils::hton((uint32_t)(1 << (32 - bits))); reinterpret_cast<struct sockaddr_in*>(&right)->sin_addr.s_addr ^= Utils::hton((uint32_t)(1 << (32 - bits)));
right.setPort(bits); right.setPort(bits);
} else { }
else {
right.zero(); right.zero();
} }
} else if (t.ss_family == AF_INET6) { }
else if (t.ss_family == AF_INET6) {
if (bits <= 128) { if (bits <= 128) {
left.setPort(bits); left.setPort(bits);
right = t; right = t;
uint8_t* b = reinterpret_cast<uint8_t*>(reinterpret_cast<struct sockaddr_in6*>(&right)->sin6_addr.s6_addr); uint8_t* b = reinterpret_cast<uint8_t*>(reinterpret_cast<struct sockaddr_in6*>(&right)->sin6_addr.s6_addr);
b[bits / 8] ^= 1 << (8 - (bits % 8)); b[bits / 8] ^= 1 << (8 - (bits % 8));
right.setPort(bits); right.setPort(bits);
} else { }
else {
right.zero(); right.zero();
} }
} }
} }
struct _RTE struct _RTE {
{
InetAddress target; InetAddress target;
InetAddress via; InetAddress via;
char device[128]; char device[128];
@ -167,7 +169,8 @@ static std::vector<_RTE> _getRTEs(const InetAddress &target,bool contains)
#ifdef __APPLE__ #ifdef __APPLE__
isDefault = IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) && ! (rtm->rtm_flags & RTF_IFSCOPE); isDefault = IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) && ! (rtm->rtm_flags & RTF_IFSCOPE);
#endif #endif
} else { }
else {
struct sockaddr_in* sin4 = (struct sockaddr_in*)sa; struct sockaddr_in* sin4 = (struct sockaddr_in*)sa;
isDefault = sin4->sin_addr.s_addr == 0; isDefault = sin4->sin_addr.s_addr == 0;
} }
@ -193,10 +196,12 @@ static std::vector<_RTE> _getRTEs(const InetAddress &target,bool contains)
unsigned char c = (unsigned char)((const struct sockaddr_in6*)sa)->sin6_addr.s6_addr[i]; unsigned char c = (unsigned char)((const struct sockaddr_in6*)sa)->sin6_addr.s6_addr[i];
if (c == 0xff) if (c == 0xff)
bits += 8; bits += 8;
else break; else
break;
} }
sa_t.setPort(bits); sa_t.setPort(bits);
} else if (sa_t.ss_family == AF_INET) { }
else if (sa_t.ss_family == AF_INET) {
salen = sizeof(struct sockaddr_in); salen = sizeof(struct sockaddr_in);
sa_t.setPort((unsigned int)Utils::countBits((uint32_t)((const struct sockaddr_in*)sa)->sin_addr.s_addr)); sa_t.setPort((unsigned int)Utils::countBits((uint32_t)((const struct sockaddr_in*)sa)->sin_addr.s_addr));
} }
@ -220,10 +225,8 @@ static std::vector<_RTE> _getRTEs(const InetAddress &target,bool contains)
saptr += salen; saptr += salen;
} }
deviceIndex = rtm->rtm_index; deviceIndex = rtm->rtm_index;
if (((contains) && (sa_t.containsAddress(target))) || (sa_t == target)) { if (((contains) && (sa_t.containsAddress(target))) || (sa_t == target)) {
rtes.push_back(_RTE()); rtes.push_back(_RTE());
rtes.back().target = sa_t; rtes.back().target = sa_t;
@ -231,7 +234,8 @@ static std::vector<_RTE> _getRTEs(const InetAddress &target,bool contains)
rtes.back().isDefault = isDefault; rtes.back().isDefault = isDefault;
if (deviceIndex >= 0) { if (deviceIndex >= 0) {
if_indextoname(deviceIndex, rtes.back().device); if_indextoname(deviceIndex, rtes.back().device);
} else { }
else {
rtes.back().device[0] = (char)0; rtes.back().device[0] = (char)0;
} }
rtes.back().metric = ((int)rtm->rtm_rmx.rmx_hopcount < 0) ? 0 : (int)rtm->rtm_rmx.rmx_hopcount; rtes.back().metric = ((int)rtm->rtm_rmx.rmx_hopcount < 0) ? 0 : (int)rtm->rtm_rmx.rmx_hopcount;
@ -257,7 +261,8 @@ static void _routeCmd(const char *op,const InetAddress &target,const InetAddress
if (p > 0) { if (p > 0) {
int exitcode = -1; int exitcode = -1;
::waitpid(p, &exitcode, 0); ::waitpid(p, &exitcode, 0);
} else if (p == 0) { }
else if (p == 0) {
::close(STDOUT_FILENO); ::close(STDOUT_FILENO);
::close(STDERR_FILENO); ::close(STDERR_FILENO);
char ttmp[64]; char ttmp[64];
@ -268,19 +273,22 @@ static void _routeCmd(const char *op,const InetAddress &target,const InetAddress
fprintf(stderr, "DEBUG: route %s -ifscope %s %s %s" ZT_EOL_S, ifscope, ((target.ss_family == AF_INET6) ? "-inet6" : "-inet"), target.toString(ttmp), via.toIpString(iptmp)); fprintf(stderr, "DEBUG: route %s -ifscope %s %s %s" ZT_EOL_S, ifscope, ((target.ss_family == AF_INET6) ? "-inet6" : "-inet"), target.toString(ttmp), via.toIpString(iptmp));
#endif #endif
::execl(ZT_BSD_ROUTE_CMD, ZT_BSD_ROUTE_CMD, op, "-ifscope", ifscope, ((target.ss_family == AF_INET6) ? "-inet6" : "-inet"), target.toString(ttmp), via.toIpString(iptmp), (const char*)0); ::execl(ZT_BSD_ROUTE_CMD, ZT_BSD_ROUTE_CMD, op, "-ifscope", ifscope, ((target.ss_family == AF_INET6) ? "-inet6" : "-inet"), target.toString(ttmp), via.toIpString(iptmp), (const char*)0);
} else { }
else {
#ifdef ZT_TRACE #ifdef ZT_TRACE
fprintf(stderr, "DEBUG: route %s %s %s %s" ZT_EOL_S, op, ((target.ss_family == AF_INET6) ? "-inet6" : "-inet"), target.toString(ttmp), via.toIpString(iptmp)); fprintf(stderr, "DEBUG: route %s %s %s %s" ZT_EOL_S, op, ((target.ss_family == AF_INET6) ? "-inet6" : "-inet"), target.toString(ttmp), via.toIpString(iptmp));
#endif #endif
::execl(ZT_BSD_ROUTE_CMD, ZT_BSD_ROUTE_CMD, op, ((target.ss_family == AF_INET6) ? "-inet6" : "-inet"), target.toString(ttmp), via.toIpString(iptmp), (const char*)0); ::execl(ZT_BSD_ROUTE_CMD, ZT_BSD_ROUTE_CMD, op, ((target.ss_family == AF_INET6) ? "-inet6" : "-inet"), target.toString(ttmp), via.toIpString(iptmp), (const char*)0);
} }
} else if ((localInterface)&&(localInterface[0])) { }
else if ((localInterface) && (localInterface[0])) {
if ((ifscope) && (ifscope[0])) { if ((ifscope) && (ifscope[0])) {
#ifdef ZT_TRACE #ifdef ZT_TRACE
fprintf(stderr, "DEBUG: route %s -ifscope %s %s %s -interface %s" ZT_EOL_S, op, ifscope, ((target.ss_family == AF_INET6) ? "-inet6" : "-inet"), target.toString(ttmp), localInterface); fprintf(stderr, "DEBUG: route %s -ifscope %s %s %s -interface %s" ZT_EOL_S, op, ifscope, ((target.ss_family == AF_INET6) ? "-inet6" : "-inet"), target.toString(ttmp), localInterface);
#endif #endif
::execl(ZT_BSD_ROUTE_CMD, ZT_BSD_ROUTE_CMD, op, "-ifscope", ifscope, ((target.ss_family == AF_INET6) ? "-inet6" : "-inet"), target.toString(ttmp), "-interface", localInterface, (const char*)0); ::execl(ZT_BSD_ROUTE_CMD, ZT_BSD_ROUTE_CMD, op, "-ifscope", ifscope, ((target.ss_family == AF_INET6) ? "-inet6" : "-inet"), target.toString(ttmp), "-interface", localInterface, (const char*)0);
} else { }
else {
#ifdef ZT_TRACE #ifdef ZT_TRACE
fprintf(stderr, "DEBUG: route %s %s %s -interface %s" ZT_EOL_S, op, ((target.ss_family == AF_INET6) ? "-inet6" : "-inet"), target.toString(ttmp), localInterface); fprintf(stderr, "DEBUG: route %s %s %s -interface %s" ZT_EOL_S, op, ((target.ss_family == AF_INET6) ? "-inet6" : "-inet"), target.toString(ttmp), localInterface);
#endif #endif
@ -318,7 +326,8 @@ static bool _winRoute(bool del,const NET_LUID &interfaceLuid,const NET_IFINDEX &
rtrow.NextHop.Ipv4.sin_family = AF_INET; rtrow.NextHop.Ipv4.sin_family = AF_INET;
rtrow.NextHop.Ipv4.sin_addr.S_un.S_addr = reinterpret_cast<const struct sockaddr_in*>(&via)->sin_addr.S_un.S_addr; rtrow.NextHop.Ipv4.sin_addr.S_un.S_addr = reinterpret_cast<const struct sockaddr_in*>(&via)->sin_addr.S_un.S_addr;
} }
} else if (target.ss_family == AF_INET6) { }
else if (target.ss_family == AF_INET6) {
rtrow.DestinationPrefix.Prefix.si_family = AF_INET6; rtrow.DestinationPrefix.Prefix.si_family = AF_INET6;
rtrow.DestinationPrefix.Prefix.Ipv6.sin6_family = AF_INET6; rtrow.DestinationPrefix.Prefix.Ipv6.sin6_family = AF_INET6;
memcpy(rtrow.DestinationPrefix.Prefix.Ipv6.sin6_addr.u.Byte, reinterpret_cast<const struct sockaddr_in6*>(&target)->sin6_addr.u.Byte, 16); memcpy(rtrow.DestinationPrefix.Prefix.Ipv6.sin6_addr.u.Byte, reinterpret_cast<const struct sockaddr_in6*>(&target)->sin6_addr.u.Byte, 16);
@ -327,7 +336,8 @@ static bool _winRoute(bool del,const NET_LUID &interfaceLuid,const NET_IFINDEX &
rtrow.NextHop.Ipv6.sin6_family = AF_INET6; rtrow.NextHop.Ipv6.sin6_family = AF_INET6;
memcpy(rtrow.NextHop.Ipv6.sin6_addr.u.Byte, reinterpret_cast<const struct sockaddr_in6*>(&via)->sin6_addr.u.Byte, 16); memcpy(rtrow.NextHop.Ipv6.sin6_addr.u.Byte, reinterpret_cast<const struct sockaddr_in6*>(&via)->sin6_addr.u.Byte, 16);
} }
} else { }
else {
return false; return false;
} }
rtrow.DestinationPrefix.PrefixLength = target.netmaskBits(); rtrow.DestinationPrefix.PrefixLength = target.netmaskBits();
@ -344,13 +354,16 @@ static bool _winRoute(bool del,const NET_LUID &interfaceLuid,const NET_IFINDEX &
rtrow.Origin = NlroManual; rtrow.Origin = NlroManual;
if (del) { if (del) {
return (DeleteIpForwardEntry2(&rtrow) == NO_ERROR); return (DeleteIpForwardEntry2(&rtrow) == NO_ERROR);
} else { }
else {
NTSTATUS r = CreateIpForwardEntry2(&rtrow); NTSTATUS r = CreateIpForwardEntry2(&rtrow);
if (r == NO_ERROR) { if (r == NO_ERROR) {
return true; return true;
} else if (r == ERROR_OBJECT_ALREADY_EXISTS) { }
else if (r == ERROR_OBJECT_ALREADY_EXISTS) {
return (SetIpForwardEntry2(&rtrow) == NO_ERROR); return (SetIpForwardEntry2(&rtrow) == NO_ERROR);
} else { }
else {
return false; return false;
} }
} }
@ -371,7 +384,8 @@ static bool _winHasRoute(const NET_LUID &interfaceLuid, const NET_IFINDEX &inter
rtrow.NextHop.Ipv4.sin_family = AF_INET; rtrow.NextHop.Ipv4.sin_family = AF_INET;
rtrow.NextHop.Ipv4.sin_addr.S_un.S_addr = reinterpret_cast<const struct sockaddr_in*>(&via)->sin_addr.S_un.S_addr; rtrow.NextHop.Ipv4.sin_addr.S_un.S_addr = reinterpret_cast<const struct sockaddr_in*>(&via)->sin_addr.S_un.S_addr;
} }
} else if (target.ss_family == AF_INET6) { }
else if (target.ss_family == AF_INET6) {
rtrow.DestinationPrefix.Prefix.si_family = AF_INET6; rtrow.DestinationPrefix.Prefix.si_family = AF_INET6;
rtrow.DestinationPrefix.Prefix.Ipv6.sin6_family = AF_INET6; rtrow.DestinationPrefix.Prefix.Ipv6.sin6_family = AF_INET6;
memcpy(rtrow.DestinationPrefix.Prefix.Ipv6.sin6_addr.u.Byte, reinterpret_cast<const struct sockaddr_in6*>(&target)->sin6_addr.u.Byte, 16); memcpy(rtrow.DestinationPrefix.Prefix.Ipv6.sin6_addr.u.Byte, reinterpret_cast<const struct sockaddr_in6*>(&target)->sin6_addr.u.Byte, 16);
@ -380,7 +394,8 @@ static bool _winHasRoute(const NET_LUID &interfaceLuid, const NET_IFINDEX &inter
rtrow.NextHop.Ipv6.sin6_family = AF_INET6; rtrow.NextHop.Ipv6.sin6_family = AF_INET6;
memcpy(rtrow.NextHop.Ipv6.sin6_addr.u.Byte, reinterpret_cast<const struct sockaddr_in6*>(&via)->sin6_addr.u.Byte, 16); memcpy(rtrow.NextHop.Ipv6.sin6_addr.u.Byte, reinterpret_cast<const struct sockaddr_in6*>(&via)->sin6_addr.u.Byte, 16);
} }
} else { }
else {
return false; return false;
} }
rtrow.DestinationPrefix.PrefixLength = target.netmaskBits(); rtrow.DestinationPrefix.PrefixLength = target.netmaskBits();
@ -391,7 +406,8 @@ static bool _winHasRoute(const NET_LUID &interfaceLuid, const NET_IFINDEX &inter
#endif // __WINDOWS__ -------------------------------------------------------- #endif // __WINDOWS__ --------------------------------------------------------
#ifndef ZT_ROUTING_SUPPORT_FOUND #ifndef ZT_ROUTING_SUPPORT_FOUND
#error "ManagedRoute.cpp has no support for managing routes on this platform! You'll need to check and see if one of the existing ones will work and make sure proper defines are set, or write one. Please do a GitHub pull request if you do this for a new OS." #error \
"ManagedRoute.cpp has no support for managing routes on this platform! You'll need to check and see if one of the existing ones will work and make sure proper defines are set, or write one. Please do a GitHub pull request if you do this for a new OS."
#endif #endif
} // anonymous namespace } // anonymous namespace
@ -404,13 +420,15 @@ ManagedRoute::ManagedRoute(const InetAddress &target,const InetAddress &via,cons
if (_via.ss_family == AF_INET) { if (_via.ss_family == AF_INET) {
_via.setPort(32); _via.setPort(32);
} else if (_via.ss_family == AF_INET6) { }
else if (_via.ss_family == AF_INET6) {
_via.setPort(128); _via.setPort(128);
} }
if (_src.ss_family == AF_INET) { if (_src.ss_family == AF_INET) {
_src.setPort(32); _src.setPort(32);
} else if (_src.ss_family == AF_INET6) { }
else if (_src.ss_family == AF_INET6) {
_src.setPort(128); _src.setPort(128);
} }
@ -449,7 +467,8 @@ bool ManagedRoute::sync()
InetAddress leftt, rightt; InetAddress leftt, rightt;
if (_target.netmaskBits() == 0) // bifurcate only the default route if (_target.netmaskBits() == 0) // bifurcate only the default route
_forkTarget(_target, leftt, rightt); _forkTarget(_target, leftt, rightt);
else leftt = _target; else
leftt = _target;
#ifdef __BSD__ // ------------------------------------------------------------ #ifdef __BSD__ // ------------------------------------------------------------
@ -476,13 +495,14 @@ bool ManagedRoute::sync()
bool hasRoute = false; bool hasRoute = false;
for (std::vector<_RTE>::iterator r(rtes.begin()); r != rtes.end(); ++r) { for (std::vector<_RTE>::iterator r(rtes.begin()); r != rtes.end(); ++r) {
hasRoute = _target == r->target && _via.ipOnly() == r->via.ipOnly() && (strcmp(r->device, _device) == 0); hasRoute = _target == r->target && _via.ipOnly() == r->via.ipOnly() && (strcmp(r->device, _device) == 0);
if (hasRoute) { break; } if (hasRoute) {
break;
}
} }
// char buf[255]; // char buf[255];
// fprintf(stderr, "hasRoute %d %s\n", !!hasRoute, _target.toString(buf)); // fprintf(stderr, "hasRoute %d %s\n", !!hasRoute, _target.toString(buf));
if (! hasRoute) { if (! hasRoute) {
if (_target && _target.netmaskBits() == 0) { // Allow Default if (_target && _target.netmaskBits() == 0) { // Allow Default
InetAddress newSystemVia; InetAddress newSystemVia;
@ -506,7 +526,6 @@ bool ManagedRoute::sync()
for (std::vector<_RTE>::iterator r(rtes.begin()); r != rtes.end(); ++r) { for (std::vector<_RTE>::iterator r(rtes.begin()); r != rtes.end(); ++r) {
if (r->via) { if (r->via) {
if (r->isDefault == 1 && (strcmp(r->device, _device) != 0)) { if (r->isDefault == 1 && (strcmp(r->device, _device) != 0)) {
// char buf[255]; // char buf[255];
// fprintf(stderr, "system device1 %s %s\n", r->via.toString(buf), r->device); // fprintf(stderr, "system device1 %s %s\n", r->via.toString(buf), r->device);
@ -517,7 +536,9 @@ bool ManagedRoute::sync()
} }
} }
if (newSystemVia) { _systemVia = newSystemVia; } if (newSystemVia) {
_systemVia = newSystemVia;
}
if (newSystemDevice[0]) { if (newSystemDevice[0]) {
Utils::scopy(_systemDevice, sizeof(_systemDevice), newSystemDevice); Utils::scopy(_systemDevice, sizeof(_systemDevice), newSystemDevice);
} }
@ -537,15 +558,14 @@ bool ManagedRoute::sync()
} }
_applied[_target] = true; _applied[_target] = true;
}
} else { else {
// Do Non-Default route commands // Do Non-Default route commands
_applied[_target] = true; _applied[_target] = true;
_routeCmd("add", leftt, _via, (const char*)0, (_via) ? (const char*)0 : _device); _routeCmd("add", leftt, _via, (const char*)0, (_via) ? (const char*)0 : _device);
} }
} }
#endif // __BSD__ ------------------------------------------------------------ #endif // __BSD__ ------------------------------------------------------------
#ifdef __LINUX__ // ---------------------------------------------------------- #ifdef __LINUX__ // ----------------------------------------------------------
@ -599,9 +619,9 @@ void ManagedRoute::remove()
_routeCmd("delete", _target, _systemVia, _systemDevice, (const char*)0); _routeCmd("delete", _target, _systemVia, _systemDevice, (const char*)0);
_routeCmd("add", _target, _systemVia, (const char*)0, (const char*)0); _routeCmd("add", _target, _systemVia, (const char*)0, (const char*)0);
} }
} else { }
else {
_routeCmd("delete", _target, _via, (const char*)0, _via ? (const char*)0 : _device); _routeCmd("delete", _target, _via, (const char*)0, _via ? (const char*)0 : _device);
} }
break; break;

View file

@ -14,25 +14,23 @@
#ifndef ZT_MANAGEDROUTE_HPP #ifndef ZT_MANAGEDROUTE_HPP
#define ZT_MANAGEDROUTE_HPP #define ZT_MANAGEDROUTE_HPP
#include "../node/AtomicCounter.hpp"
#include "../node/InetAddress.hpp"
#include "../node/SharedPtr.hpp"
#include "../node/Utils.hpp"
#include <map>
#include <stdexcept>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "../node/InetAddress.hpp"
#include "../node/Utils.hpp"
#include "../node/SharedPtr.hpp"
#include "../node/AtomicCounter.hpp"
#include <stdexcept>
#include <vector> #include <vector>
#include <map>
namespace ZeroTier { namespace ZeroTier {
/** /**
* A ZT-managed route that used C++ RAII semantics to automatically clean itself up on deallocate * A ZT-managed route that used C++ RAII semantics to automatically clean itself up on deallocate
*/ */
class ManagedRoute class ManagedRoute {
{
friend class SharedPtr<ManagedRoute>; friend class SharedPtr<ManagedRoute>;
public: public:
@ -58,14 +56,31 @@ public:
*/ */
void remove(); void remove();
inline const InetAddress &target() const { return _target; } inline const InetAddress& target() const
inline const InetAddress &via() const { return _via; } {
inline const InetAddress &src() const { return _src; } return _target;
inline const char *device() const { return _device; } }
inline const InetAddress& via() const
{
return _via;
}
inline const InetAddress& src() const
{
return _src;
}
inline const char* device() const
{
return _device;
}
private: private:
ManagedRoute(const ManagedRoute &) {} ManagedRoute(const ManagedRoute&)
inline ManagedRoute &operator=(const ManagedRoute &) { return *this; } {
}
inline ManagedRoute& operator=(const ManagedRoute&)
{
return *this;
}
InetAddress _target; InetAddress _target;
InetAddress _via; InetAddress _via;

View file

@ -12,9 +12,9 @@
/****/ /****/
#include "NeighborDiscovery.hpp" #include "NeighborDiscovery.hpp"
#include "OSUtils.hpp"
#include "../include/ZeroTierOne.h" #include "../include/ZeroTierOne.h"
#include "OSUtils.hpp"
#include <assert.h> #include <assert.h>
@ -59,9 +59,7 @@ struct _pseudo_header {
}; };
struct _option { struct _option {
_option(int optionType) _option(int optionType) : type(optionType), length(8)
: type(optionType)
, length(8)
{ {
memset(mac, 0, sizeof(mac)); memset(mac, 0, sizeof(mac));
} }
@ -72,17 +70,14 @@ struct _option {
}; };
struct _neighbor_solicitation { struct _neighbor_solicitation {
_neighbor_solicitation() _neighbor_solicitation() : type(135), code(0), checksum(0), option(1)
: type(135)
, code(0)
, checksum(0)
, option(1)
{ {
memset(&reserved, 0, sizeof(reserved)); memset(&reserved, 0, sizeof(reserved));
memset(target, 0, sizeof(target)); memset(target, 0, sizeof(target));
} }
void calculateChecksum(const sockaddr_storage &sourceIp, const sockaddr_storage &destIp) { void calculateChecksum(const sockaddr_storage& sourceIp, const sockaddr_storage& destIp)
{
_pseudo_header ph; _pseudo_header ph;
memset(&ph, 0, sizeof(_pseudo_header)); memset(&ph, 0, sizeof(_pseudo_header));
const sockaddr_in6* src = (const sockaddr_in6*)&sourceIp; const sockaddr_in6* src = (const sockaddr_in6*)&sourceIp;
@ -113,18 +108,14 @@ struct _neighbor_solicitation {
}; };
struct _neighbor_advertisement { struct _neighbor_advertisement {
_neighbor_advertisement() _neighbor_advertisement() : type(136), code(0), checksum(0), rso(0x40), option(2)
: type(136)
, code(0)
, checksum(0)
, rso(0x40)
, option(2)
{ {
memset(padding, 0, sizeof(padding)); memset(padding, 0, sizeof(padding));
memset(target, 0, sizeof(target)); memset(target, 0, sizeof(target));
} }
void calculateChecksum(const sockaddr_storage &sourceIp, const sockaddr_storage &destIp) { void calculateChecksum(const sockaddr_storage& sourceIp, const sockaddr_storage& destIp)
{
_pseudo_header ph; _pseudo_header ph;
memset(&ph, 0, sizeof(_pseudo_header)); memset(&ph, 0, sizeof(_pseudo_header));
const sockaddr_in6* src = (const sockaddr_in6*)&sourceIp; const sockaddr_in6* src = (const sockaddr_in6*)&sourceIp;
@ -155,10 +146,9 @@ struct _neighbor_advertisement {
_option option; _option option;
}; };
NeighborDiscovery::NeighborDiscovery() NeighborDiscovery::NeighborDiscovery() : _cache(256), _lastCleaned(OSUtils::now())
: _cache(256) {
, _lastCleaned(OSUtils::now()) }
{}
void NeighborDiscovery::addLocal(const sockaddr_storage& address, const MAC& mac) void NeighborDiscovery::addLocal(const sockaddr_storage& address, const MAC& mac)
{ {
@ -197,7 +187,8 @@ sockaddr_storage NeighborDiscovery::processIncomingND(const uint8_t *nd, unsigne
responseLen = sizeof(_neighbor_advertisement); responseLen = sizeof(_neighbor_advertisement);
responseDest.setTo(solicitation.option.mac, 6); responseDest.setTo(solicitation.option.mac, 6);
} }
} else if (len >= sizeof(_neighbor_advertisement) && nd[0] == 0x88) { }
else if (len >= sizeof(_neighbor_advertisement) && nd[0] == 0x88) {
_neighbor_advertisement adv; _neighbor_advertisement adv;
memcpy(&adv, nd, len); memcpy(&adv, nd, len);
InetAddress responseAddress(adv.target, 16, 0); InetAddress responseAddress(adv.target, 16, 0);
@ -235,8 +226,7 @@ MAC NeighborDiscovery::query(const MAC &localMac, const sockaddr_storage &localI
_NDEntry& e = _cache[targetAddress]; _NDEntry& e = _cache[targetAddress];
if ( (e.mac && ((now - e.lastResponseReceived) >= (ZT_ND_EXPIRE / 3))) || if ((e.mac && ((now - e.lastResponseReceived) >= (ZT_ND_EXPIRE / 3))) || (! e.mac && ((now - e.lastQuerySent) >= ZT_ND_QUERY_INTERVAL))) {
(!e.mac && ((now - e.lastQuerySent) >= ZT_ND_QUERY_INTERVAL))) {
e.lastQuerySent = now; e.lastQuerySent = now;
_neighbor_solicitation ns; _neighbor_solicitation ns;
@ -245,10 +235,12 @@ MAC NeighborDiscovery::query(const MAC &localMac, const sockaddr_storage &localI
ns.calculateChecksum(localIp, targetIp); ns.calculateChecksum(localIp, targetIp);
if (e.mac) { if (e.mac) {
queryDest = e.mac; queryDest = e.mac;
} else { }
else {
queryDest = (uint64_t)0xffffffffffffULL; queryDest = (uint64_t)0xffffffffffffULL;
} }
} else { }
else {
queryLen = 0; queryLen = 0;
queryDest.zero(); queryDest.zero();
} }
@ -256,4 +248,4 @@ MAC NeighborDiscovery::query(const MAC &localMac, const sockaddr_storage &localI
return e.mac; return e.mac;
} }
} } // namespace ZeroTier

View file

@ -15,9 +15,8 @@
#define ZT_NEIGHBORDISCOVERY_HPP #define ZT_NEIGHBORDISCOVERY_HPP
#include "../node/Hashtable.hpp" #include "../node/Hashtable.hpp"
#include "../node/MAC.hpp"
#include "../node/InetAddress.hpp" #include "../node/InetAddress.hpp"
#include "../node/MAC.hpp"
#define ZT_ND_QUERY_INTERVAL 2000 #define ZT_ND_QUERY_INTERVAL 2000
@ -25,11 +24,9 @@
#define ZT_ND_EXPIRE 600000 #define ZT_ND_EXPIRE 600000
namespace ZeroTier { namespace ZeroTier {
class NeighborDiscovery class NeighborDiscovery {
{
public: public:
NeighborDiscovery(); NeighborDiscovery();
@ -53,9 +50,10 @@ public:
MAC query(const MAC& localMac, const sockaddr_storage& localIp, const sockaddr_storage& targetIp, uint8_t* query, unsigned int& queryLen, MAC& queryDest); MAC query(const MAC& localMac, const sockaddr_storage& localIp, const sockaddr_storage& targetIp, uint8_t* query, unsigned int& queryLen, MAC& queryDest);
private: private:
struct _NDEntry struct _NDEntry {
_NDEntry() : lastQuerySent(0), lastResponseReceived(0), mac(), local(false)
{ {
_NDEntry() : lastQuerySent(0), lastResponseReceived(0), mac(), local(false) {} }
uint64_t lastQuerySent; uint64_t lastQuerySent;
uint64_t lastResponseReceived; uint64_t lastResponseReceived;
MAC mac; MAC mac;

Some files were not shown because too many files have changed in this diff Show more