Loads of refactoring, integration of new version of Trace.

This commit is contained in:
Adam Ierymenko 2020-01-23 13:05:33 -08:00
parent e6273b3300
commit 33bb61c63d
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3
52 changed files with 1603 additions and 910 deletions

View file

@ -44,7 +44,7 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons
// LF record masking key is the first 32 bytes of SHA512(controller private key) in hex,
// hiding record values from anything but the controller or someone who has its key.
uint8_t sha384pk[48];
_myId.hash(sha384pk,true);
_myId.hashWithPrivate(sha384pk);
char maskingKey [128];
Utils::hex(sha384pk,32,maskingKey);

View file

@ -46,7 +46,6 @@
#include <mutex>
#include <map>
#include <vector>
#include <set>
#include <memory>
#include <atomic>

View file

@ -495,7 +495,7 @@ func createAPIServer(basePath string, node *Node) (*http.Server, *http.Server, e
Port: tcpBindAddr.Port,
})
if err != nil {
node.log.Printf("ERROR: unable to start API HTTP server at TCP bind address %s: %s (continuing anyway)", tcpBindAddr.String(), err.Error())
node.infoLog.Printf("ERROR: unable to start API HTTP server at TCP bind address %s: %s (named socket listener startd, continuing anyway)", tcpBindAddr.String(), err.Error())
} else {
tcpHttpServer = &http.Server{
MaxHeaderBytes: 4096,

View file

@ -57,7 +57,7 @@ type LocalConfigSettings struct {
// PortMapping enables uPnP and NAT-PMP support
PortMapping bool `json:"portMapping"`
// LogSizeMax is the maximum size of the log in kilobytes or 0 for no limit and -1 to disable logging
// LogSizeMax is the maximum size of the infoLog in kilobytes or 0 for no limit and -1 to disable logging
LogSizeMax int `json:"logSizeMax"`
// IP/port to bind for TCP access to control API (disabled if null)

View file

@ -203,7 +203,7 @@ func (n *Network) LocalSettings() NetworkLocalSettings {
// MulticastSubscribe subscribes to a multicast group
func (n *Network) MulticastSubscribe(mg *MulticastGroup) {
n.node.log.Printf("%.16x joined multicast group %s", uint64(n.id), mg.String())
n.node.infoLog.Printf("%.16x joined multicast group %s", uint64(n.id), mg.String())
k := mg.key()
n.multicastSubscriptionsLock.Lock()
if _, have := n.multicastSubscriptions[k]; have {
@ -217,7 +217,7 @@ func (n *Network) MulticastSubscribe(mg *MulticastGroup) {
// MulticastUnsubscribe removes a subscription to a multicast group
func (n *Network) MulticastUnsubscribe(mg *MulticastGroup) {
n.node.log.Printf("%.16x left multicast group %s", uint64(n.id), mg.String())
n.node.infoLog.Printf("%.16x left multicast group %s", uint64(n.id), mg.String())
n.multicastSubscriptionsLock.Lock()
delete(n.multicastSubscriptions, mg.key())
n.multicastSubscriptionsLock.Unlock()
@ -311,7 +311,7 @@ func (n *Network) updateConfig(nc *NetworkConfig, ls *NetworkLocalSettings) {
k := ipNetToKey(&ip)
wantAssignedIPs[k] = true
if _, have := haveAssignedIPs[k]; !have {
n.node.log.Printf("%.16x adding managed IP %s", uint64(n.id), ip.String())
n.node.infoLog.Printf("%.16x adding managed IP %s", uint64(n.id), ip.String())
_ = n.tap.AddIP(&ip)
}
}
@ -319,7 +319,7 @@ func (n *Network) updateConfig(nc *NetworkConfig, ls *NetworkLocalSettings) {
}
for k, ip := range haveAssignedIPs {
if _, want := wantAssignedIPs[k]; !want {
n.node.log.Printf("%.16x removing managed IP %s", uint64(n.id), ip.String())
n.node.infoLog.Printf("%.16x removing managed IP %s", uint64(n.id), ip.String())
_ = n.tap.RemoveIP(ip)
}
}
@ -340,7 +340,7 @@ func (n *Network) updateConfig(nc *NetworkConfig, ls *NetworkLocalSettings) {
k := r.key()
wantManagedRoutes[k] = true
if _, have := haveManagedRoutes[k]; !have {
n.node.log.Printf("%.16x adding managed route %s", uint64(n.id), r.String())
n.node.infoLog.Printf("%.16x adding managed route %s", uint64(n.id), r.String())
_ = n.tap.AddRoute(&r)
}
}
@ -348,7 +348,7 @@ func (n *Network) updateConfig(nc *NetworkConfig, ls *NetworkLocalSettings) {
}
for k, r := range haveManagedRoutes {
if _, want := wantManagedRoutes[k]; !want {
n.node.log.Printf("%.16x removing managed route %s", uint64(n.id), r.String())
n.node.infoLog.Printf("%.16x removing managed route %s", uint64(n.id), r.String())
_ = n.tap.RemoveRoute(r)
}
}

View file

@ -24,6 +24,7 @@ import (
"encoding/hex"
"errors"
"fmt"
"io"
"io/ioutil"
"log"
"math/rand"
@ -82,28 +83,52 @@ var (
nodesByUserPtrLock sync.RWMutex
)
// Node is an instance of the ZeroTier core node and related C++ I/O code
// Node is an instance of a virtual port on the global switch.
type Node struct {
// networks contains networks we have joined, and networksByMAC by their local MAC address
networks map[NetworkID]*Network
networksByMAC map[MAC]*Network // locked by networksLock
networksLock sync.RWMutex
interfaceAddresses map[string]net.IP // physical external IPs on the machine
// interfaceAddresses are physical IPs assigned to the local machine (detected, not configured)
interfaceAddresses map[string]net.IP
interfaceAddressesLock sync.Mutex
// online and running are atomic flags set to control and monitor background tasks
online uint32
running uint32
basePath string
peersPath string
networksPath string
localConfigPath string
// localConfig is the current state of local.conf
localConfig LocalConfig
localConfigLock sync.RWMutex
logW *sizeLimitWriter
log *log.Logger
// logs for information, errors, and trace output
infoLogW *sizeLimitWriter
errLogW *sizeLimitWriter
traceLogW io.Writer
infoLog *log.Logger
errLog *log.Logger
traceLog *log.Logger
// gn is the instance of GoNode, the Go wrapper and multithreaded I/O engine
gn *C.ZT_GoNode
// zn is the underlying instance of the ZeroTier core
zn *C.ZT_Node
// id is the identity of this node
id *Identity
// HTTP server instances: one for a named socket (Unix domain or Windows named pipe) and one on a local TCP socket
namedSocketApiServer *http.Server
tcpApiServer *http.Server
// runWaitGroup is used to wait for all node goroutines on shutdown
runWaitGroup sync.WaitGroup
}
@ -141,13 +166,18 @@ func NewNode(basePath string) (n *Node, err error) {
}
if n.localConfig.Settings.LogSizeMax >= 0 {
n.logW, err = sizeLimitWriterOpen(path.Join(basePath, "node.log"))
n.infoLogW, err = sizeLimitWriterOpen(path.Join(basePath, "info.log"))
if err != nil {
return
}
n.log = log.New(n.logW, "", log.LstdFlags)
n.errLogW, err = sizeLimitWriterOpen(path.Join(basePath, "error.log"))
if err != nil {
return
}
n.infoLog = log.New(n.infoLogW, "", log.LstdFlags)
n.errLog = log.New(n.errLogW, "", log.LstdFlags)
} else {
n.log = nullLogger
n.infoLog = nullLogger
}
if n.localConfig.Settings.PortSearch {
@ -159,7 +189,7 @@ func NewNode(basePath string) (n *Node, err error) {
portCheckCount++
if checkPort(n.localConfig.Settings.PrimaryPort) {
if n.localConfig.Settings.PrimaryPort != origPort {
n.log.Printf("primary port %d unavailable, found port %d and saved in local.conf", origPort, n.localConfig.Settings.PrimaryPort)
n.infoLog.Printf("primary port %d unavailable, found port %d and saved in local.conf", origPort, n.localConfig.Settings.PrimaryPort)
}
break
}
@ -177,11 +207,11 @@ func NewNode(basePath string) (n *Node, err error) {
portCheckCount++
if checkPort(n.localConfig.Settings.SecondaryPort) {
if n.localConfig.Settings.SecondaryPort != origPort {
n.log.Printf("secondary port %d unavailable, found port %d (port search enabled)", origPort, n.localConfig.Settings.SecondaryPort)
n.infoLog.Printf("secondary port %d unavailable, found port %d (port search enabled)", origPort, n.localConfig.Settings.SecondaryPort)
}
break
}
n.log.Printf("secondary port %d unavailable, trying a random port (port search enabled)", n.localConfig.Settings.SecondaryPort)
n.infoLog.Printf("secondary port %d unavailable, trying a random port (port search enabled)", n.localConfig.Settings.SecondaryPort)
if portCheckCount <= 64 {
n.localConfig.Settings.SecondaryPort = unassignedPrivilegedPorts[randomUInt()%uint(len(unassignedPrivilegedPorts))]
} else {
@ -200,14 +230,14 @@ func NewNode(basePath string) (n *Node, err error) {
}
if n.localConfig.Settings.SecondaryPort > 0 && n.localConfig.Settings.SecondaryPort < 65536 {
if !checkPort(n.localConfig.Settings.SecondaryPort) {
n.log.Printf("WARNING: unable to bind secondary port %d",n.localConfig.Settings.SecondaryPort)
n.infoLog.Printf("WARNING: unable to bind secondary port %d", n.localConfig.Settings.SecondaryPort)
}
}
}
n.namedSocketApiServer, n.tcpApiServer, err = createAPIServer(basePath, n)
if err != nil {
n.log.Printf("FATAL: unable to start API server: %s", err.Error())
n.infoLog.Printf("FATAL: unable to start API server: %s", err.Error())
return nil, err
}
@ -215,21 +245,21 @@ func NewNode(basePath string) (n *Node, err error) {
nodesByUserPtr[uintptr(unsafe.Pointer(n))] = n
nodesByUserPtrLock.Unlock()
// Instantiate GoNode and friends from the land of C/C++
cPath := C.CString(basePath)
n.gn = C.ZT_GoNode_new(cPath, C.uintptr_t(uintptr(unsafe.Pointer(n))))
C.free(unsafe.Pointer(cPath))
if n.gn == nil {
n.log.Println("FATAL: node initialization failed")
n.infoLog.Println("FATAL: node initialization failed")
nodesByUserPtrLock.Lock()
delete(nodesByUserPtr, uintptr(unsafe.Pointer(n)))
nodesByUserPtrLock.Unlock()
return nil, ErrNodeInitFailed
}
n.zn = (*C.ZT_Node)(C.ZT_GoNode_getNode(n.gn))
n.id, err = newIdentityFromCIdentity(C.ZT_Node_identity(unsafe.Pointer(n.zn)))
if err != nil {
n.log.Printf("FATAL: error obtaining node's identity")
n.infoLog.Printf("FATAL: error obtaining node's identity")
nodesByUserPtrLock.Lock()
delete(nodesByUserPtr, uintptr(unsafe.Pointer(n)))
nodesByUserPtrLock.Unlock()
@ -237,6 +267,8 @@ func NewNode(basePath string) (n *Node, err error) {
return nil, err
}
// Background maintenance goroutine that handles polling for local network changes, cleaning internal data
// structures, syncing local config changes, and numerous other things that must happen from time to time.
n.runWaitGroup.Add(1)
go func() {
defer n.runWaitGroup.Done()
@ -296,7 +328,7 @@ func NewNode(basePath string) (n *Node, err error) {
interfaceAddressesChanged = true
ipCstr := C.CString(ipn.String())
for pn, p := range ports {
n.log.Printf("UDP binding to port %d on interface %s", p, astr)
n.infoLog.Printf("UDP binding to port %d on interface %s", p, astr)
primary := C.int(0)
if pn == 0 {
primary = 1
@ -311,7 +343,7 @@ func NewNode(basePath string) (n *Node, err error) {
interfaceAddressesChanged = true
ipCstr := C.CString(ipn.String())
for _, p := range ports {
n.log.Printf("UDP closing socket bound to port %d on interface %s", p, astr)
n.infoLog.Printf("UDP closing socket bound to port %d on interface %s", p, astr)
C.ZT_GoNode_phyStopListen(n.gn, nil, ipCstr, C.int(p))
}
C.free(unsafe.Pointer(ipCstr))
@ -360,9 +392,9 @@ func NewNode(basePath string) (n *Node, err error) {
}
}
// Trim log if it's gone over its size limit
if n.localConfig.Settings.LogSizeMax > 0 && n.logW != nil {
_ = n.logW.trim(n.localConfig.Settings.LogSizeMax*1024, 0.5, true)
// Trim infoLog if it's gone over its size limit
if n.localConfig.Settings.LogSizeMax > 0 && n.infoLogW != nil {
_ = n.infoLogW.trim(n.localConfig.Settings.LogSizeMax*1024, 0.5, true)
}
n.localConfigLock.RUnlock()
@ -440,16 +472,16 @@ func (n *Node) SetLocalConfig(lc *LocalConfig) (restartRequired bool, err error)
restartRequired = true
}
if lc.Settings.LogSizeMax < 0 {
n.log = nullLogger
_ = n.logW.Close()
n.logW = nil
} else if n.logW != nil {
n.logW, err = sizeLimitWriterOpen(path.Join(n.basePath, "service.log"))
n.infoLog = nullLogger
_ = n.infoLogW.Close()
n.infoLogW = nil
} else if n.infoLogW != nil {
n.infoLogW, err = sizeLimitWriterOpen(path.Join(n.basePath, "service.infoLog"))
if err == nil {
n.log = log.New(n.logW, "", log.LstdFlags)
n.infoLog = log.New(n.infoLogW, "", log.LstdFlags)
} else {
n.log = nullLogger
n.logW = nil
n.infoLog = nullLogger
n.infoLogW = nil
}
}
@ -458,12 +490,12 @@ func (n *Node) SetLocalConfig(lc *LocalConfig) (restartRequired bool, err error)
return
}
// Join joins a network
// Join a network.
// If tap is nil, the default system tap for this OS/platform is used (if available).
func (n *Node) Join(nwid NetworkID, settings *NetworkLocalSettings, tap Tap) (*Network, error) {
n.networksLock.RLock()
if nw, have := n.networks[nwid]; have {
n.log.Printf("join network %.16x ignored: already a member", nwid)
n.infoLog.Printf("join network %.16x ignored: already a member", nwid)
if settings != nil {
nw.SetLocalSettings(settings)
}
@ -476,13 +508,13 @@ func (n *Node) Join(nwid NetworkID, settings *NetworkLocalSettings, tap Tap) (*N
}
ntap := C.ZT_GoNode_join(n.gn, C.uint64_t(nwid))
if ntap == nil {
n.log.Printf("join network %.16x failed: tap device failed to initialize (check drivers / kernel modules)", uint64(nwid))
n.infoLog.Printf("join network %.16x failed: tap device failed to initialize (check drivers / kernel modules)", uint64(nwid))
return nil, ErrTapInitFailed
}
nw, err := newNetwork(n, nwid, &nativeTap{tap: unsafe.Pointer(ntap), enabled: 1})
if err != nil {
n.log.Printf("join network %.16x failed: network failed to initialize: %s", nwid, err.Error())
n.infoLog.Printf("join network %.16x failed: network failed to initialize: %s", nwid, err.Error())
C.ZT_GoNode_leave(n.gn, C.uint64_t(nwid))
return nil, err
}
@ -496,14 +528,14 @@ func (n *Node) Join(nwid NetworkID, settings *NetworkLocalSettings, tap Tap) (*N
return nw, nil
}
// Leave leaves a network
// Leave a network.
func (n *Node) Leave(nwid NetworkID) error {
n.log.Printf("leaving network %.16x", nwid)
n.networksLock.Lock()
nw := n.networks[nwid]
delete(n.networks, nwid)
n.networksLock.Unlock()
if nw != nil {
n.infoLog.Printf("leaving network %.16x", nwid)
nw.leaving()
}
C.ZT_GoNode_leave(n.gn, C.uint64_t(nwid))
@ -668,7 +700,7 @@ func (n *Node) stateObjectGet(objType int, id [2]uint64) ([]byte, bool) {
func (n *Node) handleTrace(traceMessage string) {
if len(traceMessage) > 0 {
n.log.Print("TRACE: " + traceMessage)
n.infoLog.Print("TRACE: " + traceMessage)
}
}

View file

@ -19,6 +19,25 @@
#ifndef ZT_ZEROTIER_API_H
#define ZT_ZEROTIER_API_H
/* ZT_PACKED_STRUCT encloses structs whose contents should be bit-packed.
* Nearly all compilers support this. These macros detect the compiler and
* define it correctly for gcc/icc/clang or MSC. */
#ifndef ZT_PACKED_STRUCT
#if defined(__GCC__) || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1) || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2) || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) || defined(__INTEL_COMPILER) || defined(__clang__)
#define ZT_PACKED_STRUCT(D) D __attribute__((packed))
#define ZT_PACKED_STRUCT_START
#define ZT_PACKED_STRUCT_END __attribute__((packed))
#endif
#ifdef _MSC_VER
#define ZT_PACKED_STRUCT(D) __pragma(pack(push,1)) D __pragma(pack(pop))
#define ZT_PACKED_STRUCT_START __pragma(pack(push,1))
#define ZT_PACKED_STRUCT_END __pragma(pack(pop))
#endif
#endif
#ifndef ZT_PACKED_STRUCT
#error Missing a macro to define ZT_PACKED_STRUCT for your compiler.
#endif
#ifdef __cplusplus
#include <cstdint>
extern "C" {
@ -26,26 +45,21 @@ extern "C" {
#include <stdint.h>
#endif
/* For struct sockaddr_storage, which is referenced here. */
#if defined(_WIN32) || defined(_WIN64)
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <Windows.h>
#else /* not Windows */
#else
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#endif /* Windows or not */
#endif
/* This symbol may be defined in a build environment or before including this
* header if you need to prepend something to function specifications. */
#ifndef ZT_SDK_API
#define ZT_SDK_API
#endif
/****************************************************************************/
/* Core constants */
/****************************************************************************/
/**
@ -174,13 +188,6 @@ extern "C" {
*/
#define ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH 7
/**
* Maximum number of multicast group subscriptions on a local virtual network interface
*
* This coincides with many operating systems' maximum values and is rather huge.
*/
#define ZT_MAX_MULTICAST_SUBSCRIPTIONS 1024
/* Rule specification contants **********************************************/
/**
@ -269,7 +276,310 @@ extern "C" {
#define ZT_RULE_PACKET_CHARACTERISTICS_TCP_FIN 0x0000000000000001ULL
/****************************************************************************/
/* Structures and other types */
/**
* Credential type IDs
*
* These are mostly used internally but are declared here so they can be used
* in trace messages.
*/
enum ZT_CredentialType
{
ZT_CREDENTIAL_TYPE_NULL = 0,
ZT_CREDENTIAL_TYPE_COM = 1,
ZT_CREDENTIAL_TYPE_CAPABILITY = 2,
ZT_CREDENTIAL_TYPE_TAG = 3,
ZT_CREDENTIAL_TYPE_COO = 4,
ZT_CREDENTIAL_TYPE_REVOCATION = 6
};
/* Trace events are sent and received as packed structures of a fixed size.
* Normally we don't use this form of brittle encoding but in this case the
* performance benefit is non-trivial as events are generated in critical
* areas of the code.
*
* NOTE: all integer fields larger than one byte are stored in big-endian
* "network" byte order in these structures. */
/**
* Flag indicating that VL1 tracing should be generated
*/
#define ZT_TRACE_FLAG_VL1 0x01
/**
* Flag indicating that VL2 (virtual network) tracing should be generated
*/
#define ZT_TRACE_FLAG_VL2 0x02
/**
* Flag indicating that VL2 network filter tracing should be generated (separate because this can be very verbose)
*/
#define ZT_TRACE_FLAG_VL2_FILTER 0x04
/**
* Flag indicating that VL2 multicast propagation should be reported
*/
#define ZT_TRACE_FLAG_VL2_MULTICAST 0x08
/**
* Trace event types
*
* All trace event structures start with a size and type.
*/
enum ZT_TraceEventType
{
/* VL1 events related to the peer-to-peer layer */
ZT_TRACE_VL1_RESETTING_PATHS_IN_SCOPE = 1,
ZT_TRACE_VL1_TRYING_NEW_PATH = 2,
ZT_TRACE_VL1_LEARNED_NEW_PATH = 3,
ZT_TRACE_VL1_INCOMING_PACKET_DROPPED = 4,
/* VL2 events relate to virtual networks, packet filtering, and authentication */
ZT_TRACE_VL2_OUTGOING_FRAME_DROPPED = 100,
ZT_TRACE_VL2_INCOMING_FRAME_DROPPED = 101,
ZT_TRACE_VL2_NETWORK_CONFIG_REQUESTED = 102,
ZT_TRACE_VL2_NETWORK_FILTER = 103
};
/**
* Trace VL1 packet drop reasons
*/
enum ZT_TracePacketDropReason
{
ZT_TRACE_PACKET_DROP_REASON_UNSPECIFIED = 0,
ZT_TRACE_PACKET_DROP_REASON_PEER_TOO_OLD = 1,
ZT_TRACE_PACKET_DROP_REASON_MALFORMED_PACKET = 2,
ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED = 3,
ZT_TRACE_PACKET_DROP_REASON_RATE_LIMIT_EXCEEDED = 4,
ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT = 5,
ZT_TRACE_PACKET_DROP_REASON_INVALID_COMPRESSED_DATA = 6,
ZT_TRACE_PACKET_DROP_REASON_UNRECOGNIZED_VERB = 7
};
/**
* Trace VL2 frame drop reasons
*/
enum ZT_TraceFrameDropReason
{
ZT_TRACE_FRAME_DROP_REASON_UNSPECIFIED = 0,
ZT_TRACE_FRAME_DROP_REASON_BRIDGING_NOT_ALLOWED_REMOTE = 1,
ZT_TRACE_FRAME_DROP_REASON_BRIDGING_NOT_ALLOWED_LOCAL = 2,
ZT_TRACE_FRAME_DROP_REASON_MULTICAST_DISABLED = 3,
ZT_TRACE_FRAME_DROP_REASON_BROADCAST_DISABLED = 4,
ZT_TRACE_FRAME_DROP_REASON_FILTER_BLOCKED = 5,
ZT_TRACE_FRAME_DROP_REASON_FILTER_BLOCKED_AT_BRIDGE_REPLICATION = 6,
ZT_TRACE_FRAME_DROP_REASON_PERMISSION_DENIED = 7
};
/**
* Address types for ZT_TraceEventPathAddress
*
* These are currently the same as the types in Endpoint.hpp and should remain so
* if possible for consistency. Not all of these are used (yet?) but they are defined
* for possible future use and the structure is sized to support them.
*/
enum ZT_TraceEventPathAddressType
{
ZT_TRACE_EVENT_PATH_TYPE_NIL = 0, /* none/empty */
ZT_TRACE_EVENT_PATH_TYPE_INETADDR_V4 = 1, /* 4-byte IPv4 */
ZT_TRACE_EVENT_PATH_TYPE_INETADDR_V6 = 2, /* 16-byte IPv6 */
ZT_TRACE_EVENT_PATH_TYPE_DNSNAME = 3, /* C string */
ZT_TRACE_EVENT_PATH_TYPE_ZEROTIER = 4, /* 5-byte ZeroTier + 48-byte identity hash */
ZT_TRACE_EVENT_PATH_TYPE_URL = 5, /* C string */
ZT_TRACE_EVENT_PATH_TYPE_ETHERNET = 6 /* 6-byte Ethernet */
};
/**
* Reasons for trying new paths
*/
enum ZT_TraceTryingNewPathReason
{
ZT_TRACE_TRYING_NEW_PATH_REASON_PACKET_RECEIVED_FROM_UNKNOWN_PATH = 1,
ZT_TRACE_TRYING_NEW_PATH_REASON_RECEIVED_PUSH_DIRECT_PATHS = 2,
ZT_TRACE_TRYING_NEW_PATH_REASON_RENDEZVOUS = 3
};
/**
* Reasons for credential rejection
*/
enum ZT_TraceCredentialRejectionReason
{
ZT_TRACE_CREDENTIAL_REJECTION_REASON_SIGNATURE_VERIFICATION_FAILED = 1,
ZT_TRACE_CREDENTIAL_REJECTION_REASON_REVOKED = 2,
ZT_TRACE_CREDENTIAL_REJECTION_REASON_OLDER_THAN_LATEST = 3,
ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID = 4
};
/**
* Physical path address from a trace event
*
* This is a special packed address format that roughly mirrors Endpoint in the core
* and is designed to support both present and future address types.
*/
ZT_PACKED_STRUCT(struct ZT_TraceEventPathAddress
{
uint8_t type; /* ZT_TraceEventPathAddressType */
uint8_t address[63]; /* Type-dependent address: 4-byte IPv4, 16-byte IPV6, etc. */
uint16_t port; /* UDP/TCP port for address types for which this is meaningful */
});
/**
* Header for all trace events
*
* All packet types begin with these fields in this order.
*/
ZT_PACKED_STRUCT(struct ZT_TraceEvent
{
uint16_t evSize; /* sizeof(ZT_TraceEvent_XX structure) (inclusive size in bytes) */
uint16_t evType; /* ZT_TraceEventType */
});
/* Temporary macros to make it easier to declare all ZT_TraceEvent's sub-types */
#define _ZT_TRACE_EVENT_STRUCT_START(e) ZT_PACKED_STRUCT_START struct ZT_TraceEvent_##e { \
uint16_t evSize; \
uint16_t evType;
#define _ZT_TRACE_EVENT_STRUCT_END() } ZT_PACKED_STRUCT_END;
/**
* Node is resetting all paths in a given address scope
*
* This happens when the node detects and external surface IP addressing change
* via a trusted (usually root) peer. It's used to renegotiate links when nodes
* move around on the network.
*/
_ZT_TRACE_EVENT_STRUCT_START(VL1_RESETTING_PATHS_IN_SCOPE)
uint64_t reporter; /* ZeroTier address that triggered the reset */
uint8_t reporterIdentityHash[48]; /* full identity hash of triggering node's identity */
struct ZT_TraceEventPathAddress from; /* physical origin of triggering packet */
struct ZT_TraceEventPathAddress oldExternal; /* previous detected external address */
struct ZT_TraceEventPathAddress newExternal; /* new detected external address */
uint8_t scope; /* IP scope being reset */
_ZT_TRACE_EVENT_STRUCT_END()
/**
* Node is trying a new path
*
* Paths are tried in response to PUSH_DIRECT_PATHS, RENDEZVOUS, and other places
* we might hear of them. A node tries a path by sending a trial message to it.
*/
_ZT_TRACE_EVENT_STRUCT_START(VL1_TRYING_NEW_PATH)
uint64_t address; /* short address of node we're trying to reach */
uint8_t identityHash[48]; /* identity hash of node we're trying to reach */
struct ZT_TraceEventPathAddress physicalAddress; /* physical address being tried */
struct ZT_TraceEventPathAddress triggerAddress; /* physical origin of triggering packet */
uint64_t triggeringPacketId; /* packet ID of triggering packet */
uint8_t triggeringPacketVerb; /* packet verb of triggering packet */
uint64_t triggeredByAddress; /* short address of node triggering attempt */
uint8_t triggeredByIdentityHash[48]; /* full identity hash of node triggering attempt */
uint8_t reason; /* ZT_TraceTryingNewPathReason */
_ZT_TRACE_EVENT_STRUCT_END()
/**
* Node has learned a new path to another node
*/
_ZT_TRACE_EVENT_STRUCT_START(VL1_LEARNED_NEW_PATH)
uint64_t packetId; /* packet ID of confirming packet */
uint64_t address; /* short address of learned peer */
uint8_t identityHash[48]; /* full identity hash of learned peer */
struct ZT_TraceEventPathAddress physicalAddress; /* physical address learned */
struct ZT_TraceEventPathAddress replaced; /* if non-empty, an older address that was replaced */
_ZT_TRACE_EVENT_STRUCT_END()
/**
* An incoming packet was dropped at the VL1 level
*
* This indicates a packet that passed MAC check but was dropped for some other
* reason such as rate limits, being malformed, etc.
*/
_ZT_TRACE_EVENT_STRUCT_START(VL1_INCOMING_PACKET_DROPPED)
uint64_t packetId; /* packet ID of failed packet */
uint64_t networkId; /* VL2 network ID or 0 if unrelated to a network or unknown */
uint64_t address; /* short address that sent packet */
uint8_t identityHash[48]; /* full identity hash of sending node */
struct ZT_TraceEventPathAddress physicalAddress; /* physical origin address of packet */
uint8_t hops; /* hop count of packet */
uint8_t verb; /* packet verb */
uint8_t reason; /* ZT_TracePacketDropReason */
_ZT_TRACE_EVENT_STRUCT_END()
/**
* Node declined to send a packet read from a local network port/tap
*/
_ZT_TRACE_EVENT_STRUCT_START(VL2_OUTGOING_FRAME_DROPPED)
uint64_t networkId; /* network ID */
uint64_t sourceMac; /* source MAC address */
uint64_t destMac; /* destination MAC address */
uint16_t etherType; /* Ethernet type of frame */
uint16_t frameLength; /* length of dropped frame */
uint8_t frameHead[64]; /* first up to 64 bytes of dropped frame */
uint8_t reason; /* ZT_TraceFrameDropReason */
_ZT_TRACE_EVENT_STRUCT_END()
/**
* An incoming frame was dropped
*/
_ZT_TRACE_EVENT_STRUCT_START(VL2_INCOMING_FRAME_DROPPED)
uint64_t packetId; /* VL1 packet ID */
uint64_t networkId; /* VL2 network ID */
uint64_t sourceMac; /* 48-bit source MAC */
uint64_t destMac; /* 48-bit destination MAC */
uint64_t address; /* short address of sending peer */
struct ZT_TraceEventPathAddress physicalAddress; /* physical source address of packet */
uint8_t hops; /* hop count of packet */
uint16_t frameLength; /* length of frame in bytes */
uint8_t frameHead[64]; /* first up to 64 bytes of dropped frame */
uint8_t verb; /* packet verb indicating how frame was sent */
uint8_t credentialRequestSent; /* if non-zero a request for credentials was sent */
uint8_t reason; /* ZT_TraceFrameDropReason */
_ZT_TRACE_EVENT_STRUCT_END()
/**
* Node is requesting a new network config and certificate from a network controller
*/
_ZT_TRACE_EVENT_STRUCT_START(VL2_NETWORK_CONFIG_REQUESTED)
uint64_t networkId; /* VL2 network ID */
_ZT_TRACE_EVENT_STRUCT_END()
/**
* Network filter trace results
*
* These are generated when filter tracing is enabled to allow filters to be debugged.
* Format for rule set logs is documented elsewhere.
*/
_ZT_TRACE_EVENT_STRUCT_START(VL2_NETWORK_FILTER)
uint64_t networkId; /* VL2 network ID */
uint8_t primaryRuleSetLog[512]; /* primary rule set log */
uint8_t matchingCapabilityRuleSetLog[512]; /* capability rule set log (if any) */
uint32_t matchingCapabilityId; /* capability ID or 0 if none */
int64_t matchingCapabilityTimestamp; /* capability timestamp or 0 if none */
uint64_t source; /* source ZeroTier address */
uint64_t dest; /* destination ZeroTier address */
uint64_t sourceMac; /* packet source MAC */
uint64_t destMac; /* packet destination MAC */
uint16_t frameLength; /* length of filtered frame */
uint8_t frameHead[64]; /* first up to 64 bytes of filtered frame */
uint16_t etherType; /* frame Ethernet type */
uint16_t vlanId; /* frame VLAN ID (currently unused, always 0) */
uint8_t noTee; /* if true noTee flag was set in filter */
uint8_t inbound; /* direction: 1 for inbound, 0 for outbound */
int8_t accept; /* 0: drop, 1: accept, 2: "super-accept" */
_ZT_TRACE_EVENT_STRUCT_END()
/**
* An incoming credential from a peer was rejected
*/
_ZT_TRACE_EVENT_STRUCT_START(VL2_CREDENTIAL_REJECTED)
uint64_t networkId; /* VL2 network ID */
uint64_t address; /* short address of sender */
uint32_t credentialId; /* credential ID */
int64_t credentialTimestamp; /* credential timestamp */
uint8_t credentialType; /* credential type */
uint8_t reason; /* ZT_TraceCredentialRejectionReason */
_ZT_TRACE_EVENT_STRUCT_END()
#undef _ZT_TRACE_EVENT_STRUCT_START
#undef _ZT_TRACE_EVENT_STRUCT_END
/****************************************************************************/
/**
@ -390,7 +700,7 @@ enum ZT_Event
* These events are only generated if this is a TRACE-enabled build.
* This is for local debug traces, not remote trace diagnostics.
*
* Meta-data: C string, TRACE message
* Meta-data: struct of type ZT_Trace_*
*/
ZT_EVENT_TRACE = 5,
@ -1164,8 +1474,6 @@ enum ZT_StateObjectType
*/
typedef void ZT_Node;
/****************************************************************************/
/* Callbacks used by Node API */
/****************************************************************************/
/**
@ -1357,8 +1665,6 @@ typedef int (*ZT_PathLookupFunction)(
struct sockaddr_storage *); /* Result buffer */
/****************************************************************************/
/* C Node API */
/****************************************************************************/
/**
* Structure for configuring ZeroTier core callback functions
@ -1735,6 +2041,8 @@ ZT_SDK_API void ZT_Node_setController(ZT_Node *node,void *networkConfigMasterIns
*/
ZT_SDK_API enum ZT_ResultCode ZT_Node_setPhysicalPathConfiguration(ZT_Node *node,const struct sockaddr_storage *pathNetwork,const ZT_PhysicalPathConfiguration *pathConfig);
/****************************************************************************/
/**
* Generate a new identity
*
@ -1844,6 +2152,8 @@ ZT_SDK_API void ZT_Identity_hash(const ZT_Identity *id,uint8_t h[48],int include
*/
ZT_SDK_API void ZT_Identity_delete(ZT_Identity *id);
/****************************************************************************/
/**
* Get ZeroTier One version
*

View file

@ -20,7 +20,7 @@
namespace ZeroTier {
#ifdef ZT_NO_TYPE_PUNNING
#ifdef ZT_NO_UNALIGNED_ACCESS
static inline uint32_t readuint32_t(const void *in)
{
uint32_t v = ((const uint8_t *)in)[0];
@ -161,7 +161,7 @@ void AES::_ctrSW(const uint8_t iv[16],const void *in,unsigned int len,void *out)
while (len >= 16) {
_encryptSW((const uint8_t *)ctr,(uint8_t *)cenc);
ctr[1] = Utils::hton(++bctr);
#ifdef ZT_NO_TYPE_PUNNING
#ifdef ZT_NO_UNALIGNED_ACCESS
for(unsigned int k=0;k<16;++k)
*(o++) = *(i++) ^ ((uint8_t *)cenc)[k];
#else
@ -339,7 +339,7 @@ void AES::_gmacSW(const uint8_t iv[12],const uint8_t *in,unsigned int len,uint8_
uint64_t y0 = 0,y1 = 0;
while (len >= 16) {
#ifdef ZT_NO_TYPE_PUNNING
#ifdef ZT_NO_UNALIGNED_ACCESS
for(unsigned int i=0;i<8;++i) ((uint8_t *)&y0)[i] ^= *(in++);
for(unsigned int i=0;i<8;++i) ((uint8_t *)&y1)[i] ^= *(in++);
#else
@ -369,7 +369,7 @@ void AES::_gmacSW(const uint8_t iv[12],const uint8_t *in,unsigned int len,uint8_
((uint8_t *)iv2)[14] = 0;
((uint8_t *)iv2)[15] = 1;
_encryptSW((const uint8_t *)iv2,(uint8_t *)iv2);
#ifdef ZT_NO_TYPE_PUNNING
#ifdef ZT_NO_UNALIGNED_ACCESS
for(unsigned int i=0;i<8;++i) out[i] = ((const uint8_t *)&y0)[i] ^ ((const uint8_t *)iv2)[i];
for(unsigned int i=8;i<16;++i) out[i] = ((const uint8_t *)&y1)[i-8] ^ ((const uint8_t *)iv2)[i];
#else

View file

@ -145,7 +145,7 @@ public:
{
const unsigned int s = (unsigned int)ii & ZT_BUF_MEM_MASK;
ii += 2;
#ifdef ZT_NO_TYPE_PUNNING
#ifdef ZT_NO_UNALIGNED_ACCESS
return (
((uint16_t)data[s] << 8U) |
(uint16_t)data[s + 1]);
@ -164,7 +164,7 @@ public:
{
const unsigned int s = (unsigned int)ii & ZT_BUF_MEM_MASK;
ii += 4;
#ifdef ZT_NO_TYPE_PUNNING
#ifdef ZT_NO_UNALIGNED_ACCESS
return (
((uint32_t)data[s] << 24U) |
((uint32_t)data[s + 1] << 16U) |
@ -185,7 +185,7 @@ public:
{
const unsigned int s = (unsigned int)ii & ZT_BUF_MEM_MASK;
ii += 8;
#ifdef ZT_NO_TYPE_PUNNING
#ifdef ZT_NO_UNALIGNED_ACCESS
return (
((uint64_t)data[s] << 56U) |
((uint64_t)data[s + 1] << 48U) |
@ -340,7 +340,7 @@ public:
{
const unsigned int s = ((unsigned int)ii) & ZT_BUF_MEM_MASK;
ii += 2;
#ifdef ZT_NO_TYPE_PUNNING
#ifdef ZT_NO_UNALIGNED_ACCESS
data[s] = (uint8_t)(n >> 8U);
data[s + 1] = (uint8_t)n;
#else
@ -358,7 +358,7 @@ public:
{
const unsigned int s = ((unsigned int)ii) & ZT_BUF_MEM_MASK;
ii += 4;
#ifdef ZT_NO_TYPE_PUNNING
#ifdef ZT_NO_UNALIGNED_ACCESS
data[s] = (uint8_t)(n >> 24U);
data[s + 1] = (uint8_t)(n >> 16U);
data[s + 2] = (uint8_t)(n >> 8U);
@ -378,7 +378,7 @@ public:
{
const unsigned int s = ((unsigned int)ii) & ZT_BUF_MEM_MASK;
ii += 8;
#ifdef ZT_NO_TYPE_PUNNING
#ifdef ZT_NO_UNALIGNED_ACCESS
data[s] = (uint8_t)(n >> 56U);
data[s + 1] = (uint8_t)(n >> 48U);
data[s + 2] = (uint8_t)(n >> 40U);

View file

@ -25,7 +25,7 @@
#include "Constants.hpp"
#include "Utils.hpp"
#if defined(__GNUC__) && (!defined(ZT_NO_TYPE_PUNNING))
#if defined(__GNUC__) && (!defined(ZT_NO_UNALIGNED_ACCESS))
#define ZT_VAR_MAY_ALIAS __attribute__((__may_alias__))
#else
#define ZT_VAR_MAY_ALIAS
@ -171,7 +171,7 @@ public:
{
if (unlikely((i + sizeof(T)) > _l))
throw ZT_EXCEPTION_OUT_OF_BOUNDS;
#ifdef ZT_NO_TYPE_PUNNING
#ifdef ZT_NO_UNALIGNED_ACCESS
uint8_t *p = reinterpret_cast<uint8_t *>(_b + i);
for(unsigned int x=1;x<=sizeof(T);++x)
*(p++) = (uint8_t)(v >> (8 * (sizeof(T) - x)));
@ -193,7 +193,7 @@ public:
{
if (unlikely((i + sizeof(T)) > _l))
throw ZT_EXCEPTION_OUT_OF_BOUNDS;
#ifdef ZT_NO_TYPE_PUNNING
#ifdef ZT_NO_UNALIGNED_ACCESS
T v = 0;
const uint8_t *p = reinterpret_cast<const uint8_t *>(_b + i);
for(unsigned int x=0;x<sizeof(T);++x) {
@ -219,7 +219,7 @@ public:
{
if (unlikely((_l + sizeof(T)) > C))
throw ZT_EXCEPTION_OUT_OF_BOUNDS;
#ifdef ZT_NO_TYPE_PUNNING
#ifdef ZT_NO_UNALIGNED_ACCESS
uint8_t *p = reinterpret_cast<uint8_t *>(_b + _l);
for(unsigned int x=1;x<=sizeof(T);++x)
*(p++) = (uint8_t)(v >> (8 * (sizeof(T) - x)));

View file

@ -73,6 +73,7 @@ set(core_src
SHA512.cpp
Switch.cpp
Topology.cpp
Trace.cpp
Utils.cpp
)

View file

@ -58,7 +58,7 @@ class Capability : public Credential
friend class Credential;
public:
static ZT_ALWAYS_INLINE Credential::Type credentialType() { return Credential::CREDENTIAL_TYPE_CAPABILITY; }
static ZT_ALWAYS_INLINE ZT_CredentialType credentialType() { return ZT_CREDENTIAL_TYPE_CAPABILITY; }
ZT_ALWAYS_INLINE Capability() :
_nwid(0),

View file

@ -69,7 +69,7 @@ class CertificateOfMembership : public Credential
friend class Credential;
public:
static inline Credential::Type credentialType() { return Credential::CREDENTIAL_TYPE_COM; }
static ZT_ALWAYS_INLINE ZT_CredentialType credentialType() { return ZT_CREDENTIAL_TYPE_COM; }
/**
* Reserved qualifier IDs
@ -101,7 +101,7 @@ public:
/**
* Create an empty certificate of membership
*/
inline CertificateOfMembership() :
ZT_ALWAYS_INLINE CertificateOfMembership() :
_qualifierCount(0),
_signatureLength(0) {}
@ -113,7 +113,7 @@ public:
* @param nwid Network ID
* @param issuedTo Certificate recipient
*/
inline CertificateOfMembership(uint64_t timestamp,uint64_t timestampMaxDelta,uint64_t nwid,const Address &issuedTo)
ZT_ALWAYS_INLINE CertificateOfMembership(uint64_t timestamp,uint64_t timestampMaxDelta,uint64_t nwid,const Address &issuedTo)
{
_qualifiers[0].id = COM_RESERVED_ID_TIMESTAMP;
_qualifiers[0].value = timestamp;
@ -135,22 +135,22 @@ public:
* @param startAt Position to start in buffer
*/
template<unsigned int C>
inline CertificateOfMembership(const Buffer<C> &b,unsigned int startAt = 0) { deserialize(b,startAt); }
ZT_ALWAYS_INLINE CertificateOfMembership(const Buffer<C> &b,unsigned int startAt = 0) { deserialize(b,startAt); }
/**
* @return True if there's something here
*/
inline operator bool() const { return (_qualifierCount != 0); }
ZT_ALWAYS_INLINE operator bool() const { return (_qualifierCount != 0); }
/**
* @return Credential ID, always 0 for COMs
*/
inline uint32_t id() const { return 0; }
ZT_ALWAYS_INLINE uint32_t id() const { return 0; }
/**
* @return Timestamp for this cert and maximum delta for timestamp
*/
inline int64_t timestamp() const
ZT_ALWAYS_INLINE int64_t timestamp() const
{
for(unsigned int i=0;i<_qualifierCount;++i) {
if (_qualifiers[i].id == COM_RESERVED_ID_TIMESTAMP)
@ -162,7 +162,7 @@ public:
/**
* @return Address to which this cert was issued
*/
inline Address issuedTo() const
ZT_ALWAYS_INLINE Address issuedTo() const
{
for(unsigned int i=0;i<_qualifierCount;++i) {
if (_qualifiers[i].id == COM_RESERVED_ID_ISSUED_TO)
@ -174,7 +174,7 @@ public:
/**
* @return Network ID for which this cert was issued
*/
inline uint64_t networkId() const
ZT_ALWAYS_INLINE uint64_t networkId() const
{
for(unsigned int i=0;i<_qualifierCount;++i) {
if (_qualifiers[i].id == COM_RESERVED_ID_NETWORK_ID)
@ -192,7 +192,7 @@ public:
* @param value Qualifier value
* @param maxDelta Qualifier maximum allowed difference (absolute value of difference)
*/
inline void setQualifier(uint64_t id,uint64_t value,uint64_t maxDelta)
ZT_ALWAYS_INLINE void setQualifier(uint64_t id,uint64_t value,uint64_t maxDelta)
{
_signedBy.zero();
for(unsigned int i=0;i<_qualifierCount;++i) {
@ -211,7 +211,7 @@ public:
}
}
inline void setQualifier(ReservedId id,uint64_t value,uint64_t maxDelta) { setQualifier((uint64_t)id,value,maxDelta); }
ZT_ALWAYS_INLINE void setQualifier(ReservedId id,uint64_t value,uint64_t maxDelta) { setQualifier((uint64_t)id,value,maxDelta); }
/**
* Compare two certificates for parameter agreement
@ -226,7 +226,7 @@ public:
* @param other Cert to compare with
* @return True if certs agree and 'other' may be communicated with
*/
inline bool agreesWith(const CertificateOfMembership &other) const
ZT_ALWAYS_INLINE bool agreesWith(const CertificateOfMembership &other) const
{
unsigned int myidx = 0;
unsigned int otheridx = 0;
@ -268,7 +268,7 @@ public:
* @param with Identity to sign with, must include private key
* @return True if signature was successful
*/
inline bool sign(const Identity &with)
ZT_ALWAYS_INLINE bool sign(const Identity &with)
{
uint64_t buf[ZT_NETWORK_COM_MAX_QUALIFIERS * 3];
unsigned int ptr = 0;
@ -294,17 +294,12 @@ public:
* @param RR Runtime environment for looking up peers
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
*/
inline Credential::VerifyResult verify(const RuntimeEnvironment *RR,void *tPtr) const { return _verify(RR,tPtr,*this); }
/**
* @return True if signed
*/
inline bool isSigned() const { return (_signedBy); }
ZT_ALWAYS_INLINE Credential::VerifyResult verify(const RuntimeEnvironment *RR,void *tPtr) const { return _verify(RR,tPtr,*this); }
/**
* @return Address that signed this certificate or null address if none
*/
inline const Address &signedBy() const { return _signedBy; }
ZT_ALWAYS_INLINE const Address &signedBy() const { return _signedBy; }
template<unsigned int C>
inline void serialize(Buffer<C> &b) const
@ -369,7 +364,7 @@ public:
return (p - startAt);
}
inline bool operator==(const CertificateOfMembership &c) const
ZT_ALWAYS_INLINE bool operator==(const CertificateOfMembership &c) const
{
if (_signedBy != c._signedBy)
return false;
@ -385,7 +380,7 @@ public:
}
return (memcmp(_signature,c._signature,_signatureLength) == 0);
}
inline bool operator!=(const CertificateOfMembership &c) const { return (!(*this == c)); }
ZT_ALWAYS_INLINE bool operator!=(const CertificateOfMembership &c) const { return (!(*this == c)); }
private:
struct _Qualifier

View file

@ -46,7 +46,7 @@ class CertificateOfOwnership : public Credential
friend class Credential;
public:
static inline Credential::Type credentialType() { return Credential::CREDENTIAL_TYPE_COO; }
static ZT_ALWAYS_INLINE ZT_CredentialType credentialType() { return ZT_CREDENTIAL_TYPE_COO; }
enum Thing
{
@ -56,12 +56,12 @@ public:
THING_IPV6_ADDRESS = 3
};
inline CertificateOfOwnership()
ZT_ALWAYS_INLINE CertificateOfOwnership()
{
memset(reinterpret_cast<void *>(this),0,sizeof(CertificateOfOwnership));
}
inline CertificateOfOwnership(const uint64_t nwid,const int64_t ts,const Address &issuedTo,const uint32_t id)
ZT_ALWAYS_INLINE CertificateOfOwnership(const uint64_t nwid,const int64_t ts,const Address &issuedTo,const uint32_t id)
{
memset(reinterpret_cast<void *>(this),0,sizeof(CertificateOfOwnership));
_networkId = nwid;
@ -70,19 +70,19 @@ public:
_issuedTo = issuedTo;
}
inline uint64_t networkId() const { return _networkId; }
inline int64_t timestamp() const { return _ts; }
inline uint32_t id() const { return _id; }
inline const Address &issuedTo() const { return _issuedTo; }
inline const Address &signer() const { return _signedBy; }
inline const uint8_t *signature() const { return _signature; }
inline unsigned int signatureLength() const { return _signatureLength; }
ZT_ALWAYS_INLINE uint64_t networkId() const { return _networkId; }
ZT_ALWAYS_INLINE int64_t timestamp() const { return _ts; }
ZT_ALWAYS_INLINE uint32_t id() const { return _id; }
ZT_ALWAYS_INLINE const Address &issuedTo() const { return _issuedTo; }
ZT_ALWAYS_INLINE const Address &signer() const { return _signedBy; }
ZT_ALWAYS_INLINE const uint8_t *signature() const { return _signature; }
ZT_ALWAYS_INLINE unsigned int signatureLength() const { return _signatureLength; }
inline unsigned int thingCount() const { return (unsigned int)_thingCount; }
inline Thing thingType(const unsigned int i) const { return (Thing)_thingTypes[i]; }
inline const uint8_t *thingValue(const unsigned int i) const { return _thingValues[i]; }
ZT_ALWAYS_INLINE unsigned int thingCount() const { return (unsigned int)_thingCount; }
ZT_ALWAYS_INLINE Thing thingType(const unsigned int i) const { return (Thing)_thingTypes[i]; }
ZT_ALWAYS_INLINE const uint8_t *thingValue(const unsigned int i) const { return _thingValues[i]; }
inline bool owns(const InetAddress &ip) const
ZT_ALWAYS_INLINE bool owns(const InetAddress &ip) const
{
if (ip.ss_family == AF_INET)
return this->_owns(THING_IPV4_ADDRESS,&(reinterpret_cast<const struct sockaddr_in *>(&ip)->sin_addr.s_addr),4);
@ -91,14 +91,14 @@ public:
return false;
}
inline bool owns(const MAC &mac) const
ZT_ALWAYS_INLINE bool owns(const MAC &mac) const
{
uint8_t tmp[6];
mac.copyTo(tmp,6);
return this->_owns(THING_MAC_ADDRESS,tmp,6);
}
inline void addThing(const InetAddress &ip)
ZT_ALWAYS_INLINE void addThing(const InetAddress &ip)
{
if (_thingCount >= ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS) return;
if (ip.ss_family == AF_INET) {
@ -112,7 +112,7 @@ public:
}
}
inline void addThing(const MAC &mac)
ZT_ALWAYS_INLINE void addThing(const MAC &mac)
{
if (_thingCount >= ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS) return;
_thingTypes[_thingCount] = THING_MAC_ADDRESS;
@ -124,7 +124,7 @@ public:
* @param signer Signing identity, must have private key
* @return True if signature was successful
*/
inline bool sign(const Identity &signer)
ZT_ALWAYS_INLINE bool sign(const Identity &signer)
{
if (signer.hasPrivate()) {
Buffer<sizeof(CertificateOfOwnership) + 64> tmp;
@ -136,7 +136,7 @@ public:
return false;
}
inline Credential::VerifyResult verify(const RuntimeEnvironment *RR,void *tPtr) const { return _verify(RR,tPtr,*this); }
ZT_ALWAYS_INLINE Credential::VerifyResult verify(const RuntimeEnvironment *RR,void *tPtr) const { return _verify(RR,tPtr,*this); }
template<unsigned int C>
inline void serialize(Buffer<C> &b,const bool forSign = false) const
@ -206,13 +206,13 @@ public:
}
// Provides natural sort order by ID
inline bool operator<(const CertificateOfOwnership &coo) const { return (_id < coo._id); }
ZT_ALWAYS_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 { return (memcmp(this,&coo,sizeof(CertificateOfOwnership)) != 0); }
ZT_ALWAYS_INLINE bool operator==(const CertificateOfOwnership &coo) const { return (memcmp(this,&coo,sizeof(CertificateOfOwnership)) == 0); }
ZT_ALWAYS_INLINE bool operator!=(const CertificateOfOwnership &coo) const { return (memcmp(this,&coo,sizeof(CertificateOfOwnership)) != 0); }
private:
inline bool _owns(const Thing &t,const void *v,unsigned int l) const
ZT_ALWAYS_INLINE bool _owns(const Thing &t,const void *v,unsigned int l) const
{
for(unsigned int i=0,j=_thingCount;i<j;++i) {
if (_thingTypes[i] == (uint8_t)t) {

View file

@ -118,18 +118,18 @@
/**
* Period between keepalives sent to paths if no other traffic has been sent
*
* See https://conferences.sigcomm.org/imc/2010/papers/p260.pdf for
* some real world data on NAT UDP timeouts. From the paper: "the
* lowest measured timeout when a binding has seen bidirectional
* traffic is 54 sec." 30 seconds is faster than really necessary.
*/
#define ZT_PATH_KEEPALIVE_PERIOD 30000
#define ZT_PATH_KEEPALIVE_PERIOD 20000
/**
* Timeout for path aliveness (measured from last receive)
* Timeout for path alive-ness (measured from last receive)
*/
#define ZT_PATH_ACTIVITY_TIMEOUT ((ZT_PATH_KEEPALIVE_PERIOD * 2) + 5000)
#define ZT_PATH_ALIVE_TIMEOUT ((ZT_PATH_KEEPALIVE_PERIOD * 2) + 5000)
/**
* Timeout for path active-ness (measured from last receive)
*/
#define ZT_PATH_ACTIVITY_TIMEOUT (ZT_PATH_KEEPALIVE_PERIOD + 5000)
/**
* Delay between full HELLO messages between peers
@ -137,12 +137,12 @@
#define ZT_PEER_PING_PERIOD 60000
/**
* Timeout for overall peer activity (measured from last receive)
* Timeout for peer alive-ness (measured from last receive)
*/
#define ZT_PEER_ALIVE_TIMEOUT ((ZT_PEER_PING_PERIOD * 2) + 5000)
/**
* Timeout for overall peer activity (measured from last receive)
* Timeout for peer active-ness (measured from last receive)
*/
#define ZT_PEER_ACTIVITY_TIMEOUT (ZT_PEER_PING_PERIOD + 5000)

View file

@ -40,19 +40,6 @@ class RuntimeEnvironment;
class Credential
{
public:
/**
* Do not change type code IDs -- these are used in Revocation objects and elsewhere
*/
enum Type
{
CREDENTIAL_TYPE_NULL = 0,
CREDENTIAL_TYPE_COM = 1, // CertificateOfMembership
CREDENTIAL_TYPE_CAPABILITY = 2,
CREDENTIAL_TYPE_TAG = 3,
CREDENTIAL_TYPE_COO = 4, // CertificateOfOwnership
CREDENTIAL_TYPE_REVOCATION = 6
};
/**
* Result of verify() operations
*/

View file

@ -19,12 +19,13 @@ bool Endpoint::operator==(const Endpoint &ep) const
{
if (_t == ep._t) {
switch(_t) {
case INETADDR: return (inetAddr() == ep.inetAddr());
default: return true;
case INETADDR_V4:
case INETADDR_V6: return (inetAddr() == ep.inetAddr());
case DNSNAME: return ((_v.dns.port == ep._v.dns.port)&&(strcmp(_v.dns.name,ep._v.dns.name) == 0));
case ZEROTIER: return ((_v.zt.a == ep._v.zt.a)&&(memcmp(_v.zt.idh,ep._v.zt.idh,sizeof(_v.zt.idh)) == 0));
case URL: return (strcmp(_v.url,ep._v.url) == 0);
case ETHERNET: return (_v.eth == ep._v.eth);
default: return true;
}
}
return false;
@ -37,7 +38,9 @@ bool Endpoint::operator<(const Endpoint &ep) const
} else if (_t == ep._t) {
int ncmp;
switch(_t) {
case INETADDR: return (inetAddr() < ep.inetAddr());
case INETADDR_V4:
case INETADDR_V6:
return (inetAddr() < ep.inetAddr());
case DNSNAME:
ncmp = strcmp(_v.dns.name,ep._v.dns.name);
return ((ncmp < 0) ? true : (ncmp == 0)&&(_v.dns.port < ep._v.dns.port));
@ -58,7 +61,8 @@ int Endpoint::marshal(uint8_t data[ZT_ENDPOINT_MARSHAL_SIZE_MAX]) const
Utils::storeBigEndian(data + 3,(int16_t)_l[1]);
Utils::storeBigEndian(data + 5,(int16_t)_l[2]);
switch(_t) {
case INETADDR:
case INETADDR_V4:
case INETADDR_V6:
return 7 + reinterpret_cast<const InetAddress *>(&_v.sa)->marshal(data+1);
case DNSNAME:
p = 7;
@ -116,7 +120,8 @@ int Endpoint::unmarshal(const uint8_t *restrict data,const int len)
switch(_t) {
case NIL:
return 7;
case INETADDR:
case INETADDR_V4:
case INETADDR_V6:
return 7 + reinterpret_cast<InetAddress *>(&_v.sa)->unmarshal(data+7,len-7);
case DNSNAME:
if (len < 10)

View file

@ -41,11 +41,12 @@ public:
enum Type
{
NIL = 0, // NIL value
INETADDR = 1, // InetAddress (v4 or v6)
DNSNAME = 2, // DNS name and port that resolves to InetAddress
ZEROTIER = 3, // ZeroTier Address (for relaying and meshy behavior)
URL = 4, // URL for http/https/ws/etc. (not implemented yet)
ETHERNET = 5, // 48-bit LAN-local Ethernet address
INETADDR_V4 = 1, // IPv4
INETADDR_V6 = 2, // IPv6
DNSNAME = 3, // DNS name and port that resolves to InetAddress
ZEROTIER = 4, // ZeroTier Address (for relaying and meshy behavior)
URL = 5, // URL for http/https/ws/etc. (not implemented yet)
ETHERNET = 6, // 48-bit LAN-local Ethernet address
UNRECOGNIZED = 255 // Unrecognized endpoint type encountered in stream
};
@ -56,13 +57,12 @@ public:
ZT_ALWAYS_INLINE Endpoint(const Endpoint &ep)
{
memcpy(reinterpret_cast<void *>(this),&ep,sizeof(Endpoint));
memcpy(reinterpret_cast<void *>(this),reinterpret_cast<const void *>(&ep),sizeof(Endpoint));
}
explicit ZT_ALWAYS_INLINE Endpoint(const InetAddress &sa) :
_t(INETADDR)
explicit ZT_ALWAYS_INLINE Endpoint(const InetAddress &sa)
{
_v.sa = sa;
*this = sa;
}
ZT_ALWAYS_INLINE Endpoint(const Address &zt,const uint8_t identityHash[ZT_IDENTITY_HASH_SIZE]) :
@ -93,7 +93,17 @@ public:
ZT_ALWAYS_INLINE Endpoint &operator=(const InetAddress &sa)
{
_t = INETADDR;
switch(sa.ss_family) {
case AF_INET:
_t = INETADDR_V4;
break;
case AF_INET6:
_t = INETADDR_V6;
break;
default:
_t = NIL;
return *this;
}
_v.sa = sa;
return *this;
}
@ -101,7 +111,7 @@ public:
/**
* @return InetAddress or NIL if not of this type
*/
ZT_ALWAYS_INLINE const InetAddress &inetAddr() const { return (_t == INETADDR) ? *reinterpret_cast<const InetAddress *>(&_v.sa) : InetAddress::NIL; }
ZT_ALWAYS_INLINE const InetAddress &inetAddr() const { return ((_t == INETADDR_V4)||(_t == INETADDR_V6)) ? *reinterpret_cast<const InetAddress *>(&_v.sa) : InetAddress::NIL; }
/**
* @return DNS name or empty string if not of this type
@ -156,14 +166,14 @@ private:
int _l[3]; // X,Y,Z location in kilometers from the nearest gravitational center of mass
union {
struct sockaddr_storage sa;
ZT_PACKED_STRUCT(struct {
struct {
uint16_t port;
char name[ZT_ENDPOINT_MAX_NAME_SIZE];
}) dns;
ZT_PACKED_STRUCT(struct {
} dns;
struct {
uint64_t a;
uint8_t idh[ZT_IDENTITY_HASH_SIZE];
}) zt;
} zt;
char url[ZT_ENDPOINT_MAX_NAME_SIZE];
uint64_t eth;
} _v;

View file

@ -89,6 +89,7 @@ void Identity::generate(const Type t)
_type = t;
_hasPrivate = true;
_hash[0] = 0; // force hash recompute
char *const genmem = new char[ZT_IDENTITY_GEN_MEMORY];
do {
@ -142,24 +143,13 @@ bool Identity::locallyValidate() const
return false;
}
bool Identity::hash(uint8_t h[48],const bool includePrivate) const
void Identity::hashWithPrivate(uint8_t h[48]) const
{
switch(_type) {
case C25519:
if ((_hasPrivate)&&(includePrivate))
SHA384(h,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN,_priv.c25519,ZT_C25519_PRIVATE_KEY_LEN);
else SHA384(h,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN);
return true;
case P384:
if ((_hasPrivate)&&(includePrivate))
SHA384(h,&_pub,sizeof(_pub),&_priv,sizeof(_priv));
else SHA384(h,&_pub,sizeof(_pub));
return true;
case C25519: SHA384(h,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN,_priv.c25519,ZT_C25519_PRIVATE_KEY_LEN); break;
case P384: SHA384(h,&_pub,sizeof(_pub),&_priv,sizeof(_priv)); break;
default: memset(h,0,48);
}
return false;
}
unsigned int Identity::sign(const void *data,unsigned int len,void *sig,unsigned int siglen) const
@ -293,6 +283,7 @@ char *Identity::toString(bool includePrivate,char buf[ZT_IDENTITY_STRING_BUFFER_
bool Identity::fromString(const char *str)
{
_hasPrivate = false;
_hash[0] = 0; // force hash recompute
if (!str) {
_address.zero();
@ -386,6 +377,97 @@ bool Identity::fromString(const char *str)
return true;
}
int Identity::marshal(uint8_t data[ZT_IDENTITY_MARSHAL_SIZE_MAX],const bool includePrivate) const
{
_address.copyTo(data,ZT_ADDRESS_LENGTH);
switch(_type) {
case C25519:
data[ZT_ADDRESS_LENGTH] = (uint8_t)C25519;
memcpy(data + ZT_ADDRESS_LENGTH + 1,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN);
if ((includePrivate)&&(_hasPrivate)) {
data[ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN] = ZT_C25519_PRIVATE_KEY_LEN;
memcpy(data + ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1,_priv.c25519,ZT_C25519_PRIVATE_KEY_LEN);
return (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1 + ZT_C25519_PRIVATE_KEY_LEN);
}
data[ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN] = 0;
return (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1);
case P384:
data[ZT_ADDRESS_LENGTH] = (uint8_t)P384;
memcpy(data + ZT_ADDRESS_LENGTH + 1,&_pub,ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE);
if ((includePrivate)&&(_hasPrivate)) {
data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE] = ZT_C25519_PRIVATE_KEY_LEN + ZT_ECC384_PRIVATE_KEY_SIZE;
memcpy(data + ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1,&_priv,ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE);
data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE] = 0;
return (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE + 1);
}
data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE] = 0;
data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1] = 0;
return (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 2);
}
return -1;
}
int Identity::unmarshal(const uint8_t *data,const int len)
{
if (len < (ZT_ADDRESS_LENGTH + 1))
return -1;
_hash[0] = 0; // force hash recompute
unsigned int privlen;
switch((_type = (Type)data[ZT_ADDRESS_LENGTH])) {
case C25519:
if (len < (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1))
return -1;
memcpy(_pub.c25519,data + ZT_ADDRESS_LENGTH + 1,ZT_C25519_PUBLIC_KEY_LEN);
privlen = data[ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN];
if (privlen == ZT_C25519_PRIVATE_KEY_LEN) {
if (len < (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1 + ZT_C25519_PRIVATE_KEY_LEN))
return -1;
_hasPrivate = true;
memcpy(_priv.c25519,data + ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1,ZT_C25519_PRIVATE_KEY_LEN);
return (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1 + ZT_C25519_PRIVATE_KEY_LEN);
} else if (privlen == 0) {
_hasPrivate = false;
return (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1);
}
break;
case P384:
if (len < (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 2))
return -1;
memcpy(&_pub,data + ZT_ADDRESS_LENGTH + 1,ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE);
privlen = data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE];
if (privlen == ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE) {
if (len < (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE + 1))
return -1;
_hasPrivate = true;
memcpy(&_priv,data + ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1,ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE);
privlen = data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE];
if (len < (int)(privlen + (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE + 1)))
return -1;
return (int)(privlen + (unsigned int)(ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE + 1));
} else if (privlen == 0) {
_hasPrivate = false;
return (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 2);
}
break;
}
return -1;
}
void Identity::_computeHash()
{
switch(_type) {
case C25519: SHA384(_hash,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN); break;
case P384: SHA384(_hash,&_pub,sizeof(_pub)); break;
default: memset(_hash,0,48);
}
}
} // namespace ZeroTier
extern "C" {
@ -473,7 +555,9 @@ uint64_t ZT_Identity_address(const ZT_Identity *id)
void ZT_Identity_hash(const ZT_Identity *id,uint8_t h[48],int includePrivate)
{
reinterpret_cast<const ZeroTier::Identity *>(id)->hash(h,includePrivate != 0);
if (includePrivate)
reinterpret_cast<const ZeroTier::Identity *>(id)->hashWithPrivate(h);
else memcpy(h,reinterpret_cast<const ZeroTier::Identity *>(id)->hash(),48);
}
ZT_SDK_API void ZT_Identity_delete(ZT_Identity *id)

View file

@ -101,12 +101,21 @@ public:
ZT_ALWAYS_INLINE bool hasPrivate() const { return _hasPrivate; }
/**
* This generates a SHA384 hash of this identity's keys.
*
* @param h Buffer to receive SHA384 of public key(s)
* @param includePrivate If true, hash private key(s) as well
* @return 384-bit/48-byte hash of this identity's public key(s)
*/
bool hash(uint8_t h[48],bool includePrivate = false) const;
ZT_ALWAYS_INLINE const uint8_t *hash() const
{
if (_hash[0] == 0)
const_cast<Identity *>(this)->_computeHash();
return reinterpret_cast<const uint8_t *>(_hash);
}
/**
* Compute a hash of this identity's public and private keys
*
* @param h Buffer to store SHA384 hash
*/
void hashWithPrivate(uint8_t h[48]) const;
/**
* Sign a message with this identity (private key required)
@ -311,91 +320,15 @@ public:
ZT_ALWAYS_INLINE unsigned long hashCode() const { return ((unsigned long)_address.toInt() + (unsigned long)_pub.c25519[0] + (unsigned long)_pub.c25519[1] + (unsigned long)_pub.c25519[2]); }
// Marshal interface ///////////////////////////////////////////////////////
static ZT_ALWAYS_INLINE int marshalSizeMax() { return ZT_IDENTITY_MARSHAL_SIZE_MAX; }
inline int marshal(uint8_t data[ZT_IDENTITY_MARSHAL_SIZE_MAX],const bool includePrivate = false) const
{
_address.copyTo(data,ZT_ADDRESS_LENGTH);
switch(_type) {
case C25519:
data[ZT_ADDRESS_LENGTH] = (uint8_t)C25519;
memcpy(data + ZT_ADDRESS_LENGTH + 1,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN);
if ((includePrivate)&&(_hasPrivate)) {
data[ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN] = ZT_C25519_PRIVATE_KEY_LEN;
memcpy(data + ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1,_priv.c25519,ZT_C25519_PRIVATE_KEY_LEN);
return (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1 + ZT_C25519_PRIVATE_KEY_LEN);
}
data[ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN] = 0;
return (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1);
case P384:
data[ZT_ADDRESS_LENGTH] = (uint8_t)P384;
memcpy(data + ZT_ADDRESS_LENGTH + 1,&_pub,ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE);
if ((includePrivate)&&(_hasPrivate)) {
data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE] = ZT_C25519_PRIVATE_KEY_LEN + ZT_ECC384_PRIVATE_KEY_SIZE;
memcpy(data + ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1,&_priv,ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE);
data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE] = 0;
return (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE + 1);
}
data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE] = 0;
data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1] = 0;
return (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 2);
}
return -1;
}
inline int unmarshal(const uint8_t *restrict data,const int len)
{
if (len < (ZT_ADDRESS_LENGTH + 1))
return -1;
unsigned int privlen;
switch((_type = (Type)data[ZT_ADDRESS_LENGTH])) {
case C25519:
if (len < (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1))
return -1;
memcpy(_pub.c25519,data + ZT_ADDRESS_LENGTH + 1,ZT_C25519_PUBLIC_KEY_LEN);
privlen = data[ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN];
if (privlen == ZT_C25519_PRIVATE_KEY_LEN) {
if (len < (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1 + ZT_C25519_PRIVATE_KEY_LEN))
return -1;
_hasPrivate = true;
memcpy(_priv.c25519,data + ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1,ZT_C25519_PRIVATE_KEY_LEN);
return (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1 + ZT_C25519_PRIVATE_KEY_LEN);
} else if (privlen == 0) {
_hasPrivate = false;
return (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1);
}
break;
case P384:
if (len < (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 2))
return -1;
memcpy(&_pub,data + ZT_ADDRESS_LENGTH + 1,ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE);
privlen = data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE];
if (privlen == ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE) {
if (len < (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE + 1))
return -1;
_hasPrivate = true;
memcpy(&_priv,data + ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1,ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE);
privlen = data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE];
if (len < (int)(privlen + (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE + 1)))
return -1;
return (int)(privlen + (unsigned int)(ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE + 1));
} else if (privlen == 0) {
_hasPrivate = false;
return (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 2);
}
break;
}
return -1;
}
////////////////////////////////////////////////////////////////////////////
int marshal(uint8_t data[ZT_IDENTITY_MARSHAL_SIZE_MAX],bool includePrivate = false) const;
int unmarshal(const uint8_t *data,int len);
private:
void _computeHash(); // recompute _hash
Address _address;
uint64_t _hash[6]; // hash of public key memo-ized for performance, recalculated when _hash[0] == 0
Type _type; // _type determines which fields in _priv and _pub are used
bool _hasPrivate;
ZT_PACKED_STRUCT(struct { // don't re-order these

View file

@ -35,9 +35,6 @@
namespace ZeroTier {
namespace {
//////////////////////////////////////////////////////////////////////////////
// Implementation of each protocol verb //
//////////////////////////////////////////////////////////////////////////////
void _sendErrorNeedCredentials(IncomingPacket &pkt,const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer,const uint64_t nwid,const SharedPtr<Path> &path)
{
@ -65,11 +62,11 @@ ZT_ALWAYS_INLINE bool _doHELLO(IncomingPacket &pkt,const RuntimeEnvironment *con
unsigned int ptr = ZT_PROTO_VERB_HELLO_IDX_IDENTITY + id.deserialize(pkt,ZT_PROTO_VERB_HELLO_IDX_IDENTITY);
if (protoVersion < ZT_PROTO_VERSION_MIN) {
RR->t->incomingPacketDroppedHELLO(tPtr,path,pid,fromAddress,"protocol version too old");
RR->t->incomingPacketDropped(tPtr,pid,0,id,path->address(),pkt.hops(),Packet::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_PEER_TOO_OLD);
return true;
}
if (fromAddress != id.address()) {
RR->t->incomingPacketDroppedHELLO(tPtr,path,pid,fromAddress,"identity/address mismatch");
RR->t->incomingPacketDropped(tPtr,pid,0,id,path->address(),pkt.hops(),Packet::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_MALFORMED_PACKET);
return true;
}
@ -87,18 +84,13 @@ ZT_ALWAYS_INLINE bool _doHELLO(IncomingPacket &pkt,const RuntimeEnvironment *con
uint8_t key[ZT_PEER_SECRET_KEY_LENGTH];
if (RR->identity.agree(id,key)) {
if (pkt.dearmor(key)) { // ensure packet is authentic, otherwise drop
RR->t->incomingPacketDroppedHELLO(tPtr,path,pid,fromAddress,"address collision");
Packet outp(id.address(),RR->identity.address(),Packet::VERB_ERROR);
outp.append((uint8_t)Packet::VERB_HELLO);
outp.append((uint64_t)pid);
outp.append((uint8_t)Packet::ERROR_IDENTITY_COLLISION);
outp.armor(key,true);
path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now());
RR->t->incomingPacketDropped(tPtr,pid,0,id,path->address(),pkt.hops(),Packet::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_MALFORMED_PACKET);
// TODO: we handle identity collisions differently now
} else {
RR->t->incomingPacketMessageAuthenticationFailure(tPtr,path,pid,fromAddress,pkt.hops(),"invalid MAC");
RR->t->incomingPacketDropped(tPtr,pid,0,id,path->address(),pkt.hops(),Packet::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);
}
} else {
RR->t->incomingPacketMessageAuthenticationFailure(tPtr,path,pid,fromAddress,pkt.hops(),"invalid identity");
RR->t->incomingPacketDropped(tPtr,pid,0,id,path->address(),pkt.hops(),Packet::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_MALFORMED_PACKET);
}
return true;
@ -106,7 +98,7 @@ ZT_ALWAYS_INLINE bool _doHELLO(IncomingPacket &pkt,const RuntimeEnvironment *con
// Identity is the same as the one we already have -- check packet integrity
if (!pkt.dearmor(peer->key())) {
RR->t->incomingPacketMessageAuthenticationFailure(tPtr,path,pid,fromAddress,pkt.hops(),"invalid MAC");
RR->t->incomingPacketDropped(tPtr,pid,0,id,path->address(),pkt.hops(),Packet::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);
return true;
}
@ -118,30 +110,30 @@ ZT_ALWAYS_INLINE bool _doHELLO(IncomingPacket &pkt,const RuntimeEnvironment *con
// Sanity check: this basically can't happen
if (alreadyAuthenticated) {
RR->t->incomingPacketDroppedHELLO(tPtr,path,pid,fromAddress,"illegal alreadyAuthenticated state");
RR->t->incomingPacketDropped(tPtr,pid,0,id,path->address(),pkt.hops(),Packet::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_UNSPECIFIED);
return true;
}
// Check rate limits
if (!RR->node->rateGateIdentityVerification(now,path->address())) {
RR->t->incomingPacketDroppedHELLO(tPtr,path,pid,fromAddress,"rate limit exceeded");
RR->t->incomingPacketDropped(tPtr,pid,0,id,path->address(),pkt.hops(),Packet::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_RATE_LIMIT_EXCEEDED);
return true;
}
// Check packet integrity and MAC (this is faster than locallyValidate() so do it first to filter out total crap)
SharedPtr<Peer> newPeer(new Peer(RR));
if (!newPeer->init(RR->identity,id)) {
RR->t->incomingPacketDroppedHELLO(tPtr,path,pid,fromAddress,"error initializing peer");
RR->t->incomingPacketDropped(tPtr,pid,0,id,path->address(),pkt.hops(),Packet::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_UNSPECIFIED);
return true;
}
if (!pkt.dearmor(newPeer->key())) {
RR->t->incomingPacketMessageAuthenticationFailure(tPtr,path,pid,fromAddress,pkt.hops(),"invalid MAC");
RR->t->incomingPacketDropped(tPtr,pid,0,id,path->address(),pkt.hops(),Packet::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);
return true;
}
// Check that identity's address is valid as per the derivation function
if (!id.locallyValidate()) {
RR->t->incomingPacketDroppedHELLO(tPtr,path,pid,fromAddress,"invalid identity");
RR->t->incomingPacketDropped(tPtr,pid,0,id,path->address(),pkt.hops(),Packet::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT);
return true;
}
@ -158,7 +150,7 @@ ZT_ALWAYS_INLINE bool _doHELLO(IncomingPacket &pkt,const RuntimeEnvironment *con
if (ptr < pkt.size()) {
ptr += externalSurfaceAddress.deserialize(pkt,ptr);
if ((externalSurfaceAddress)&&(pkt.hops() == 0))
RR->sa->iam(tPtr,id.address(),path->localSocket(),path->address(),externalSurfaceAddress,RR->topology->isRoot(id),now);
RR->sa->iam(tPtr,id,path->localSocket(),path->address(),externalSurfaceAddress,RR->topology->isRoot(id),now);
}
}
@ -270,7 +262,7 @@ ZT_ALWAYS_INLINE bool _doOK(IncomingPacket &pkt,const RuntimeEnvironment *const
InetAddress externalSurfaceAddress;
externalSurfaceAddress.deserialize(pkt,ZT_PROTO_VERB_HELLO__OK__IDX_REVISION + 2);
if (externalSurfaceAddress)
RR->sa->iam(tPtr,peer->address(),path->localSocket(),path->address(),externalSurfaceAddress,RR->topology->isRoot(peer->identity()),RR->node->now());
RR->sa->iam(tPtr,peer->identity(),path->localSocket(),path->address(),externalSurfaceAddress,RR->topology->isRoot(peer->identity()),RR->node->now());
}
}
@ -388,6 +380,7 @@ ZT_ALWAYS_INLINE bool _doFRAME(IncomingPacket &pkt,const RuntimeEnvironment *con
RR->node->putFrame(tPtr,nwid,network->userPtr(),sourceMac,network->mac(),etherType,0,(const void *)frameData,frameLen);
}
} else {
RR->t->incomingNetworkFrameDropped(tPtr,nwid,MAC(),MAC(),peer->identity(),path->address(),pkt.hops(),0,nullptr,Packet::VERB_FRAME,true,ZT_TRACE_FRAME_DROP_REASON_PERMISSION_DENIED);
_sendErrorNeedCredentials(pkt,RR,tPtr,peer,nwid,path);
return false;
}
@ -412,7 +405,7 @@ ZT_ALWAYS_INLINE bool _doEXT_FRAME(IncomingPacket &pkt,const RuntimeEnvironment
}
if (!network->gate(tPtr,peer)) {
RR->t->incomingNetworkAccessDenied(tPtr,network,path,pkt.packetId(),pkt.size(),peer->address(),Packet::VERB_EXT_FRAME,true);
RR->t->incomingNetworkFrameDropped(tPtr,nwid,MAC(),MAC(),peer->identity(),path->address(),pkt.hops(),0,nullptr,Packet::VERB_EXT_FRAME,true,ZT_TRACE_FRAME_DROP_REASON_PERMISSION_DENIED);
_sendErrorNeedCredentials(pkt,RR,tPtr,peer,nwid,path);
return false;
}
@ -435,19 +428,19 @@ ZT_ALWAYS_INLINE bool _doEXT_FRAME(IncomingPacket &pkt,const RuntimeEnvironment
if (network->config().permitsBridging(peer->address())) {
network->learnBridgeRoute(from,peer->address());
} else {
RR->t->incomingNetworkFrameDropped(tPtr,network,path,pkt.packetId(),pkt.size(),peer->address(),Packet::VERB_EXT_FRAME,from,to,"bridging not allowed (remote)");
RR->t->incomingNetworkFrameDropped(tPtr,nwid,from,to,peer->identity(),path->address(),pkt.hops(),(uint16_t)frameLen,frameData,Packet::VERB_EXT_FRAME,true,ZT_TRACE_FRAME_DROP_REASON_BRIDGING_NOT_ALLOWED_REMOTE);
peer->received(tPtr,path,pkt.hops(),pkt.packetId(),pkt.payloadLength(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,nwid);
return true;
}
} else if (to != network->mac()) {
if (to.isMulticast()) {
if (network->config().multicastLimit == 0) {
RR->t->incomingNetworkFrameDropped(tPtr,network,path,pkt.packetId(),pkt.size(),peer->address(),Packet::VERB_EXT_FRAME,from,to,"multicast disabled");
RR->t->incomingNetworkFrameDropped(tPtr,nwid,from,to,peer->identity(),path->address(),pkt.hops(),(uint16_t)frameLen,frameData,Packet::VERB_EXT_FRAME,true,ZT_TRACE_FRAME_DROP_REASON_MULTICAST_DISABLED);
peer->received(tPtr,path,pkt.hops(),pkt.packetId(),pkt.payloadLength(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,nwid);
return true;
}
} else if (!network->config().permitsBridging(RR->identity.address())) {
RR->t->incomingNetworkFrameDropped(tPtr,network,path,pkt.packetId(),pkt.size(),peer->address(),Packet::VERB_EXT_FRAME,from,to,"bridging not allowed (local)");
RR->t->incomingNetworkFrameDropped(tPtr,nwid,from,to,peer->identity(),path->address(),pkt.hops(),(uint16_t)frameLen,frameData,Packet::VERB_EXT_FRAME,true,ZT_TRACE_FRAME_DROP_REASON_BRIDGING_NOT_ALLOWED_LOCAL);
peer->received(tPtr,path,pkt.hops(),pkt.packetId(),pkt.payloadLength(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,nwid);
return true;
}
@ -733,6 +726,7 @@ ZT_ALWAYS_INLINE bool _doUSER_MESSAGE(IncomingPacket &pkt,const RuntimeEnvironme
bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR,void *tPtr)
{
const Address sourceAddress(source());
const SharedPtr<Peer> peer(RR->topology->get(tPtr,sourceAddress));
try {
// Check for trusted paths or unencrypted HELLOs (HELLO is the only packet sent in the clear)
@ -746,7 +740,8 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR,void *tPtr)
if (RR->topology->shouldInboundPathBeTrusted(_path->address(),tpid)) {
trusted = true;
} else {
RR->t->incomingPacketMessageAuthenticationFailure(tPtr,_path,packetId(),sourceAddress,hops(),"path not trusted");
if (peer)
RR->t->incomingPacketDropped(tPtr,packetId(),0,peer->identity(),_path->address(),hops(),Packet::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);
return true;
}
} else if ((c == ZT_PROTO_CIPHER_SUITE__POLY1305_NONE)&&(verb() == Packet::VERB_HELLO)) {
@ -754,25 +749,30 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR,void *tPtr)
return _doHELLO(*this,RR,tPtr,false,_path);
}
const SharedPtr<Peer> peer(RR->topology->get(tPtr,sourceAddress));
if (peer) {
if (!peer) {
RR->sw->requestWhois(tPtr,RR->node->now(),sourceAddress);
return false;
}
if (!trusted) {
if (!dearmor(peer->key())) {
RR->t->incomingPacketMessageAuthenticationFailure(tPtr,_path,packetId(),sourceAddress,hops(),"invalid MAC");
RR->t->incomingPacketDropped(tPtr,packetId(),0,peer->identity(),_path->address(),hops(),Packet::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);
return true;
}
}
if (!uncompress()) {
RR->t->incomingPacketInvalid(tPtr,_path,packetId(),sourceAddress,hops(),Packet::VERB_NOP,"LZ4 decompression failed");
RR->t->incomingPacketDropped(tPtr,packetId(),0,peer->identity(),_path->address(),hops(),Packet::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_INVALID_COMPRESSED_DATA);
return true;
}
const Packet::Verb v = verb();
bool r = true;
switch(v) {
//case Packet::VERB_NOP:
default: // ignore unknown verbs, but if they pass auth check they are "received"
default: // ignore unknown verbs, but if they pass auth check they are "received" and considered NOPs by peer->receive()
RR->t->incomingPacketDropped(tPtr,packetId(),0,peer->identity(),_path->address(),hops(),Packet::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_UNRECOGNIZED_VERB);
// fall through
case Packet::VERB_NOP:
peer->received(tPtr,_path,hops(),packetId(),payloadLength(),v,0,Packet::VERB_NOP,0);
break;
case Packet::VERB_HELLO: r = _doHELLO(*this,RR,tPtr,true,_path); break;
@ -791,17 +791,12 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR,void *tPtr)
case Packet::VERB_USER_MESSAGE: r = _doUSER_MESSAGE(*this,RR,tPtr,peer,_path); break;
}
return r;
} else {
RR->sw->requestWhois(tPtr,RR->node->now(),sourceAddress);
return false;
}
} catch (int ztExcCode) {
RR->t->incomingPacketInvalid(tPtr,_path,packetId(),sourceAddress,hops(),verb(),"unexpected exception in tryDecode()");
} catch ( ... ) {}
if (peer)
RR->t->incomingPacketDropped(tPtr,packetId(),0,peer->identity(),_path->address(),hops(),Packet::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_UNSPECIFIED);
return true;
} catch ( ... ) {
RR->t->incomingPacketInvalid(tPtr,_path,packetId(),sourceAddress,hops(),verb(),"unexpected exception in tryDecode()");
return true;
}
}
} // namespace ZeroTier

View file

@ -419,6 +419,37 @@ public:
}
}
/**
* Fill out a ZT_TraceEventPathAddress from this InetAddress
*
* @param ta ZT_TraceEventPathAddress to fill
*/
ZT_ALWAYS_INLINE void forTrace(ZT_TraceEventPathAddress &ta) const
{
uint32_t tmp;
switch(ss_family) {
default:
memset(&ta,0,sizeof(ZT_TraceEventPathAddress));
break;
case AF_INET:
ta.type = ZT_TRACE_EVENT_PATH_TYPE_INETADDR_V4;
tmp = (uint32_t)(reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr);
ta.address[0] = reinterpret_cast<const uint8_t *>(&tmp)[0];
ta.address[1] = reinterpret_cast<const uint8_t *>(&tmp)[1];
ta.address[2] = reinterpret_cast<const uint8_t *>(&tmp)[2];
ta.address[3] = reinterpret_cast<const uint8_t *>(&tmp)[3];
memset(ta.address + 4,0,sizeof(ta.address) - 4);
ta.port = reinterpret_cast<const struct sockaddr_in *>(this)->sin_port;
break;
case AF_INET6:
ta.type = ZT_TRACE_EVENT_PATH_TYPE_INETADDR_V6;
memcpy(ta.address,reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr,16);
memset(ta.address + 16,0,sizeof(ta.address) - 16);
ta.port = reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_port;
break;
}
}
/**
* Set to null/zero
*/

View file

@ -101,7 +101,7 @@ union LZ4_streamDecode_u {
#define HEAPMODE 0
#endif
#ifdef ZT_NO_TYPE_PUNNING
#ifdef ZT_NO_UNALIGNED_ACCESS
#define LZ4_FORCE_MEMORY_ACCESS 0
#else
#define LZ4_FORCE_MEMORY_ACCESS 2

View file

@ -46,8 +46,8 @@ int Locator::marshal(uint8_t data[ZT_LOCATOR_MARSHAL_SIZE_MAX],const bool exclud
int p = 8;
if (_ts > 0) {
data[p++] = (uint8_t)(_endpointCount >> 8U);
data[p++] = (uint8_t)_endpointCount;
Utils::storeBigEndian(data + p,(uint16_t)_endpointCount);
p += 2;
for (unsigned int i = 0; i < _endpointCount; ++i) {
int tmp = _at[i].marshal(data + p);
if (tmp < 0)
@ -56,11 +56,14 @@ int Locator::marshal(uint8_t data[ZT_LOCATOR_MARSHAL_SIZE_MAX],const bool exclud
}
if (!excludeSignature) {
data[p++] = (uint8_t)(_signatureLength >> 8U);
data[p++] = (uint8_t)_signatureLength;
Utils::storeBigEndian(data + p,(uint16_t)_signatureLength);
p += 2;
memcpy(data + p,_signature,_signatureLength);
p += (int)_signatureLength;
}
Utils::storeBigEndian(data + p,_flags);
p += 2;
}
return p;
@ -75,9 +78,8 @@ int Locator::unmarshal(const uint8_t *restrict data,const int len)
int p = 8;
if (_ts > 0) {
unsigned int ec = (int)data[p++];
ec <<= 8U;
ec |= data[p++];
const unsigned int ec = Utils::loadBigEndian<uint16_t>(data + p);
p += 2;
if (ec > ZT_LOCATOR_MAX_ENDPOINTS)
return -1;
_endpointCount = ec;
@ -90,9 +92,8 @@ int Locator::unmarshal(const uint8_t *restrict data,const int len)
if ((p + 2) > len)
return -1;
unsigned int sl = data[p++];
sl <<= 8U;
sl |= data[p++];
const unsigned int sl = Utils::loadBigEndian<uint16_t>(data + p);
p += 2;
if (sl > ZT_SIGNATURE_BUFFER_SIZE)
return -1;
_signatureLength = sl;
@ -100,6 +101,11 @@ int Locator::unmarshal(const uint8_t *restrict data,const int len)
return -1;
memcpy(_signature,data + p,sl);
p += (int)sl;
if ((p + 2) > len)
return -1;
_flags = Utils::loadBigEndian<uint16_t>(data + p);
p += 2;
} else {
_ts = 0;
}

View file

@ -23,7 +23,7 @@
#include "Identity.hpp"
#define ZT_LOCATOR_MAX_ENDPOINTS 8
#define ZT_LOCATOR_MARSHAL_SIZE_MAX (8 + 2 + (ZT_ENDPOINT_MARSHAL_SIZE_MAX * ZT_LOCATOR_MAX_ENDPOINTS) + 2 + ZT_SIGNATURE_BUFFER_SIZE)
#define ZT_LOCATOR_MARSHAL_SIZE_MAX (8 + 2 + (ZT_ENDPOINT_MARSHAL_SIZE_MAX * ZT_LOCATOR_MAX_ENDPOINTS) + 2 + 2 + ZT_SIGNATURE_BUFFER_SIZE)
namespace ZeroTier {
@ -120,6 +120,7 @@ private:
unsigned int _endpointCount;
unsigned int _signatureLength;
Endpoint _at[ZT_LOCATOR_MAX_ENDPOINTS];
uint16_t _flags;
uint8_t _signature[ZT_SIGNATURE_BUFFER_SIZE];
};

View file

@ -20,7 +20,6 @@
#include "Switch.hpp"
#include "Packet.hpp"
#include "Node.hpp"
#include "Trace.hpp"
namespace ZeroTier {
@ -102,17 +101,24 @@ void Membership::pushCredentials(const RuntimeEnvironment *RR,void *tPtr,const i
_lastPushedCredentials = now;
}
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const CertificateOfMembership &com)
void Membership::clean(const int64_t now,const NetworkConfig &nconf)
{
_cleanCredImpl<Tag>(nconf,_remoteTags);
_cleanCredImpl<Capability>(nconf,_remoteCaps);
_cleanCredImpl<CertificateOfOwnership>(nconf,_remoteCoos);
}
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const CertificateOfMembership &com)
{
const int64_t newts = com.timestamp();
if (newts <= _comRevocationThreshold) {
RR->t->credentialRejected(tPtr,com,"revoked");
RR->t->credentialRejected(tPtr,com.networkId(),sourcePeerIdentity.address(),com.id(),com.timestamp(),ZT_CREDENTIAL_TYPE_COM,ZT_TRACE_CREDENTIAL_REJECTION_REASON_REVOKED);
return ADD_REJECTED;
}
const int64_t oldts = _com.timestamp();
if (newts < oldts) {
RR->t->credentialRejected(tPtr,com,"old");
RR->t->credentialRejected(tPtr,com.networkId(),sourcePeerIdentity.address(),com.id(),com.timestamp(),ZT_CREDENTIAL_TYPE_COM,ZT_TRACE_CREDENTIAL_REJECTION_REASON_OLDER_THAN_LATEST);
return ADD_REJECTED;
}
if ((newts == oldts)&&(_com == com))
@ -120,27 +126,34 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
switch(com.verify(RR,tPtr)) {
default:
RR->t->credentialRejected(tPtr,com,"invalid");
RR->t->credentialRejected(tPtr,com.networkId(),sourcePeerIdentity.address(),com.id(),com.timestamp(),ZT_CREDENTIAL_TYPE_COM,ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
return Membership::ADD_REJECTED;
case Credential::VERIFY_OK:
_com = com;
return ADD_ACCEPTED_NEW;
case Credential::VERIFY_BAD_SIGNATURE:
RR->t->credentialRejected(tPtr,com,"invalid");
RR->t->credentialRejected(tPtr,com.networkId(),sourcePeerIdentity.address(),com.id(),com.timestamp(),ZT_CREDENTIAL_TYPE_COM,ZT_TRACE_CREDENTIAL_REJECTION_REASON_SIGNATURE_VERIFICATION_FAILED);
return ADD_REJECTED;
case Credential::VERIFY_NEED_IDENTITY:
return ADD_DEFERRED_FOR_WHOIS;
}
}
// Template out addCredential() for many cred types to avoid copypasta
// 3/5 of the credential types have identical addCredential() code
template<typename C>
static Membership::AddCredentialResult _addCredImpl(Hashtable<uint32_t,C> &remoteCreds,const Hashtable<uint64_t,int64_t> &revocations,const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const C &cred)
static ZT_ALWAYS_INLINE Membership::AddCredentialResult _addCredImpl(
Hashtable<uint32_t,C> &remoteCreds,
const Hashtable<uint64_t,int64_t> &revocations,
const RuntimeEnvironment *const RR,
void *const tPtr,
const Identity &sourcePeerIdentity,
const NetworkConfig &nconf,
const C &cred)
{
C *rc = remoteCreds.get(cred.id());
if (rc) {
if (rc->timestamp() > cred.timestamp()) {
RR->t->credentialRejected(tPtr,cred,"old");
RR->t->credentialRejected(tPtr,nconf.networkId,sourcePeerIdentity.address(),cred.id(),cred.timestamp(),C::credentialType(),ZT_TRACE_CREDENTIAL_REJECTION_REASON_OLDER_THAN_LATEST);
return Membership::ADD_REJECTED;
}
if (*rc == cred)
@ -149,13 +162,13 @@ static Membership::AddCredentialResult _addCredImpl(Hashtable<uint32_t,C> &remot
const int64_t *const rt = revocations.get(Membership::credentialKey(C::credentialType(),cred.id()));
if ((rt)&&(*rt >= cred.timestamp())) {
RR->t->credentialRejected(tPtr,cred,"revoked");
RR->t->credentialRejected(tPtr,nconf.networkId,sourcePeerIdentity.address(),cred.id(),cred.timestamp(),C::credentialType(),ZT_TRACE_CREDENTIAL_REJECTION_REASON_REVOKED);
return Membership::ADD_REJECTED;
}
switch(cred.verify(RR,tPtr)) {
default:
RR->t->credentialRejected(tPtr,cred,"invalid");
RR->t->credentialRejected(tPtr,nconf.networkId,sourcePeerIdentity.address(),cred.id(),cred.timestamp(),C::credentialType(),ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
return Membership::ADD_REJECTED;
case 0:
if (!rc)
@ -166,30 +179,29 @@ static Membership::AddCredentialResult _addCredImpl(Hashtable<uint32_t,C> &remot
return Membership::ADD_DEFERRED_FOR_WHOIS;
}
}
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const Tag &tag) { return _addCredImpl<Tag>(_remoteTags,_revocations,RR,tPtr,sourcePeerIdentity,nconf,tag); }
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const Capability &cap) { return _addCredImpl<Capability>(_remoteCaps,_revocations,RR,tPtr,sourcePeerIdentity,nconf,cap); }
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const CertificateOfOwnership &coo) { return _addCredImpl<CertificateOfOwnership>(_remoteCoos,_revocations,RR,tPtr,sourcePeerIdentity,nconf,coo); }
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 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 Identity &sourcePeerIdentity,const NetworkConfig &nconf,const Revocation &rev)
{
int64_t *rt;
switch(rev.verify(RR,tPtr)) {
default:
RR->t->credentialRejected(tPtr,rev,"invalid");
RR->t->credentialRejected(tPtr,nconf.networkId,sourcePeerIdentity.address(),rev.id(),0,ZT_CREDENTIAL_TYPE_REVOCATION,ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
return ADD_REJECTED;
case 0: {
const Credential::Type ct = rev.type();
const ZT_CredentialType ct = rev.typeBeingRevoked();
switch(ct) {
case Credential::CREDENTIAL_TYPE_COM:
case ZT_CREDENTIAL_TYPE_COM:
if (rev.threshold() > _comRevocationThreshold) {
_comRevocationThreshold = rev.threshold();
return ADD_ACCEPTED_NEW;
}
return ADD_ACCEPTED_REDUNDANT;
case Credential::CREDENTIAL_TYPE_CAPABILITY:
case Credential::CREDENTIAL_TYPE_TAG:
case Credential::CREDENTIAL_TYPE_COO:
case ZT_CREDENTIAL_TYPE_CAPABILITY:
case ZT_CREDENTIAL_TYPE_TAG:
case ZT_CREDENTIAL_TYPE_COO:
rt = &(_revocations[credentialKey(ct,rev.credentialId())]);
if (*rt < rev.threshold()) {
*rt = rev.threshold();
@ -198,7 +210,7 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
}
return ADD_ACCEPTED_REDUNDANT;
default:
RR->t->credentialRejected(tPtr,rev,"invalid");
RR->t->credentialRejected(tPtr,nconf.networkId,sourcePeerIdentity.address(),rev.id(),0,ZT_CREDENTIAL_TYPE_REVOCATION,ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
return ADD_REJECTED;
}
}
@ -207,11 +219,42 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
}
}
void Membership::clean(const int64_t now,const NetworkConfig &nconf)
bool Membership::_isUnspoofableAddress(const NetworkConfig &nconf,const InetAddress &ip) const
{
_cleanCredImpl<Tag>(nconf,_remoteTags);
_cleanCredImpl<Capability>(nconf,_remoteCaps);
_cleanCredImpl<CertificateOfOwnership>(nconf,_remoteCoos);
if ((ip.isV6())&&(nconf.ndpEmulation())) {
const InetAddress sixpl(InetAddress::makeIpv66plane(nconf.networkId,nconf.issuedTo.toInt()));
for(unsigned int i=0;i<nconf.staticIpCount;++i) {
if (nconf.staticIps[i].ipsEqual(sixpl)) {
bool prefixMatches = true;
for(unsigned int j=0;j<5;++j) { // check for match on /40
if ((((const struct sockaddr_in6 *)&ip)->sin6_addr.s6_addr)[j] != (((const struct sockaddr_in6 *)&sixpl)->sin6_addr.s6_addr)[j]) {
prefixMatches = false;
break;
}
}
if (prefixMatches)
return true;
break;
}
}
const InetAddress rfc4193(InetAddress::makeIpv6rfc4193(nconf.networkId,nconf.issuedTo.toInt()));
for(unsigned int i=0;i<nconf.staticIpCount;++i) {
if (nconf.staticIps[i].ipsEqual(rfc4193)) {
bool prefixMatches = true;
for(unsigned int j=0;j<11;++j) { // check for match on /88
if ((((const struct sockaddr_in6 *)&ip)->sin6_addr.s6_addr)[j] != (((const struct sockaddr_in6 *)&rfc4193)->sin6_addr.s6_addr)[j]) {
prefixMatches = false;
break;
}
}
if (prefixMatches)
return true;
break;
}
}
}
return false;
}
} // namespace ZeroTier

View file

@ -25,8 +25,6 @@
#include "Revocation.hpp"
#include "NetworkConfig.hpp"
#define ZT_MEMBERSHIP_CRED_ID_UNUSED 0xffffffffffffffffULL
namespace ZeroTier {
class RuntimeEnvironment;
@ -61,7 +59,7 @@ public:
* @param peerAddress Address of member peer (the one that this Membership describes)
* @param nconf My network config
*/
void pushCredentials(const RuntimeEnvironment *RR,void *tPtr,const int64_t now,const Address &peerAddress,const NetworkConfig &nconf);
void pushCredentials(const RuntimeEnvironment *RR,void *tPtr,int64_t now,const Address &peerAddress,const NetworkConfig &nconf);
/**
* @return Time we last pushed credentials to this member
@ -94,8 +92,8 @@ public:
{
if (_isUnspoofableAddress(nconf,r))
return true;
uint32_t *k = (uint32_t *)0;
CertificateOfOwnership *v = (CertificateOfOwnership *)0;
uint32_t *k = nullptr;
CertificateOfOwnership *v = nullptr;
Hashtable< uint32_t,CertificateOfOwnership >::Iterator i(*(const_cast< Hashtable< uint32_t,CertificateOfOwnership> *>(&_remoteCoos)));
while (i.next(k,v)) {
if (_isCredentialTimestampValid(nconf,*v)&&(v->owns(r)))
@ -117,12 +115,6 @@ public:
return (((t)&&(_isCredentialTimestampValid(nconf,*t))) ? t : (Tag *)0);
}
AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const CertificateOfMembership &com);
AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const Tag &tag);
AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const Capability &cap);
AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const CertificateOfOwnership &coo);
AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const Revocation &rev);
/**
* Clean internal databases of stale entries
*
@ -134,70 +126,20 @@ public:
/**
* Generates a key for 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 ZT_ALWAYS_INLINE uint64_t credentialKey(const ZT_CredentialType &t,const uint32_t i) { return (((uint64_t)t << 32U) | (uint64_t)i); }
/**
* @return Bytes received so far
*/
ZT_ALWAYS_INLINE uint64_t receivedBytes() const { return _received; }
/**
* @return Bytes sent so far
*/
ZT_ALWAYS_INLINE uint64_t sentBytes() const { return _sent; }
/**
* @param bytes Bytes received
*/
ZT_ALWAYS_INLINE void logReceivedBytes(const unsigned int bytes) { _received = (uint64_t)bytes; }
/**
* @param bytes Bytes sent
*/
ZT_ALWAYS_INLINE void logSentBytes(const unsigned int bytes) { _sent = (uint64_t)bytes; }
AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const CertificateOfMembership &com);
AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const Tag &tag);
AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const Capability &cap);
AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const CertificateOfOwnership &coo);
AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const Revocation &rev);
private:
// This returns true if a resource is an IPv6 NDP-emulated address. These embed the ZT
// address of the peer and therefore cannot be spoofed, causing peerOwnsAddress() to
// always return true for them. A certificate is not required for these.
ZT_ALWAYS_INLINE bool _isUnspoofableAddress(const NetworkConfig &nconf,const MAC &m) const { return false; }
ZT_ALWAYS_INLINE bool _isUnspoofableAddress(const NetworkConfig &nconf,const InetAddress &ip) const
{
if ((ip.isV6())&&(nconf.ndpEmulation())) {
const InetAddress sixpl(InetAddress::makeIpv66plane(nconf.networkId,nconf.issuedTo.toInt()));
for(unsigned int i=0;i<nconf.staticIpCount;++i) {
if (nconf.staticIps[i].ipsEqual(sixpl)) {
bool prefixMatches = true;
for(unsigned int j=0;j<5;++j) { // check for match on /40
if ((((const struct sockaddr_in6 *)&ip)->sin6_addr.s6_addr)[j] != (((const struct sockaddr_in6 *)&sixpl)->sin6_addr.s6_addr)[j]) {
prefixMatches = false;
break;
}
}
if (prefixMatches)
return true;
break;
}
}
const InetAddress rfc4193(InetAddress::makeIpv6rfc4193(nconf.networkId,nconf.issuedTo.toInt()));
for(unsigned int i=0;i<nconf.staticIpCount;++i) {
if (nconf.staticIps[i].ipsEqual(rfc4193)) {
bool prefixMatches = true;
for(unsigned int j=0;j<11;++j) { // check for match on /88
if ((((const struct sockaddr_in6 *)&ip)->sin6_addr.s6_addr)[j] != (((const struct sockaddr_in6 *)&rfc4193)->sin6_addr.s6_addr)[j]) {
prefixMatches = false;
break;
}
}
if (prefixMatches)
return true;
break;
}
}
}
return false;
}
bool _isUnspoofableAddress(const NetworkConfig &nconf,const InetAddress &ip) const;
// This compares the remote credential's timestamp to the timestamp in our network config
// plus or minus the permitted maximum timestamp delta.
@ -213,10 +155,10 @@ private:
}
template<typename C>
inline void _cleanCredImpl(const NetworkConfig &nconf,Hashtable<uint32_t,C> &remoteCreds)
ZT_ALWAYS_INLINE void _cleanCredImpl(const NetworkConfig &nconf,Hashtable<uint32_t,C> &remoteCreds)
{
uint32_t *k = (uint32_t *)0;
C *v = (C *)0;
uint32_t *k = nullptr;
C *v = nullptr;
typename Hashtable<uint32_t,C>::Iterator i(remoteCreds);
while (i.next(k,v)) {
if (!_isCredentialTimestampValid(nconf,*v))
@ -233,12 +175,6 @@ private:
// Time we last pushed credentials
int64_t _lastPushedCredentials;
// Number of Ethernet frame bytes received
uint64_t _received;
// Number of Ethernet frame bytes sent
uint64_t _sent;
// Remote member's latest network COM
CertificateOfMembership _com;
@ -256,8 +192,8 @@ public:
public:
ZT_ALWAYS_INLINE CapabilityIterator(Membership &m,const NetworkConfig &nconf) :
_hti(m._remoteCaps),
_k((uint32_t *)0),
_c((Capability *)0),
_k(nullptr),
_c(nullptr),
_m(m),
_nconf(nconf)
{
@ -269,7 +205,7 @@ public:
if (_m._isCredentialTimestampValid(_nconf,*_c))
return _c;
}
return (Capability *)0;
return nullptr;
}
private:

View file

@ -11,12 +11,8 @@
*/
/****/
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include "../include/ZeroTierDebug.h"
#include "Constants.hpp"
#include "Network.hpp"
@ -28,7 +24,6 @@
#include "Buffer.hpp"
#include "Packet.hpp"
#include "NetworkController.hpp"
#include "Node.hpp"
#include "Peer.hpp"
#include "Trace.hpp"
#include "ScopedPtr.hpp"
@ -40,7 +35,7 @@ namespace ZeroTier {
namespace {
// Returns true if packet appears valid; pos and proto will be set
static bool _ipv6GetPayload(const uint8_t *frameData,unsigned int frameLen,unsigned int &pos,unsigned int &proto)
bool _ipv6GetPayload(const uint8_t *frameData,unsigned int frameLen,unsigned int &pos,unsigned int &proto)
{
if (frameLen < 40)
return false;
@ -77,7 +72,7 @@ enum _doZtFilterResult
DOZTFILTER_SUPER_ACCEPT
};
static _doZtFilterResult _doZtFilter(
_doZtFilterResult _doZtFilter(
const RuntimeEnvironment *RR,
Trace::RuleResultLog &rrl,
const NetworkConfig &nconf,
@ -108,14 +103,14 @@ static _doZtFilterResult _doZtFilter(
rrl.clear();
for(unsigned int rn=0;rn<ruleCount;++rn) {
const ZT_VirtualNetworkRuleType rt = (ZT_VirtualNetworkRuleType)(rules[rn].t & 0x3f);
const ZT_VirtualNetworkRuleType rt = (ZT_VirtualNetworkRuleType)(rules[rn].t & 0x3fU);
// First check if this is an ACTION
if ((unsigned int)rt <= (unsigned int)ZT_NETWORK_RULE_ACTION__MAX_ID) {
if (thisSetMatches) {
switch(rt) {
case ZT_NETWORK_RULE_ACTION_PRIORITY:
qosBucket = (rules[rn].v.qosBucket >= 0 || rules[rn].v.qosBucket <= 8) ? rules[rn].v.qosBucket : 4; // 4 = default bucket (no priority)
qosBucket = (rules[rn].v.qosBucket >= 0 && rules[rn].v.qosBucket <= 8) ? rules[rn].v.qosBucket : 4; // 4 = default bucket (no priority)
return DOZTFILTER_ACCEPT;
case ZT_NETWORK_RULE_ACTION_DROP:
@ -180,7 +175,7 @@ static _doZtFilterResult _doZtFilter(
// Circuit breaker: no need to evaluate an AND if the set's match state
// is currently false since anything AND false is false.
if ((!thisSetMatches)&&(!(rules[rn].t & 0x40))) {
if ((!thisSetMatches)&&(!(rules[rn].t & 0x40U))) {
rrl.logSkipped(rn,thisSetMatches);
continue;
}
@ -245,7 +240,7 @@ static _doZtFilterResult _doZtFilter(
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]));
} 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] << 4U) & 0xf0U) | ((frameData[1] >> 4U) & 0x0fU)) & rules[rn].v.ipTos.mask;
thisRuleMatches = (uint8_t)((tosMasked >= rules[rn].v.ipTos.value[0])&&(tosMasked <= rules[rn].v.ipTos.value[1]));
} else {
thisRuleMatches = 0;
@ -271,7 +266,7 @@ static _doZtFilterResult _doZtFilter(
case ZT_NETWORK_RULE_MATCH_ICMP:
if ((etherType == ZT_ETHERTYPE_IPV4)&&(frameLen >= 20)) {
if (frameData[9] == 0x01) { // IP protocol == ICMP
const unsigned int ihl = (frameData[0] & 0xf) * 4;
const unsigned int ihl = (frameData[0] & 0xfU) * 4;
if (frameLen >= (ihl + 2)) {
if (rules[rn].v.icmp.type == frameData[ihl]) {
if ((rules[rn].v.icmp.flags & 0x01) != 0) {
@ -314,7 +309,7 @@ static _doZtFilterResult _doZtFilter(
case ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE:
case ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE:
if ((etherType == ZT_ETHERTYPE_IPV4)&&(frameLen >= 20)) {
const unsigned int headerLen = 4 * (frameData[0] & 0xf);
const unsigned int headerLen = 4 * (frameData[0] & 0xfU);
int p = -1;
switch(frameData[9]) { // IP protocol number
// All these start with 16-bit source and destination port in that order
@ -324,7 +319,7 @@ static _doZtFilterResult _doZtFilter(
case 0x88: // UDPLite
if (frameLen > (headerLen + 4)) {
unsigned int pos = headerLen + ((rt == ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE) ? 2 : 0);
p = (int)frameData[pos++] << 8;
p = (int)(frameData[pos++] << 8U);
p |= (int)frameData[pos];
}
break;
@ -343,7 +338,7 @@ static _doZtFilterResult _doZtFilter(
case 0x88: // UDPLite
if (frameLen > (pos + 4)) {
if (rt == ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE) pos += 2;
p = (int)frameData[pos++] << 8;
p = (int)(frameData[pos++] << 8U);
p |= (int)frameData[pos];
}
break;
@ -402,15 +397,15 @@ static _doZtFilterResult _doZtFilter(
}
cf |= ownershipVerificationMask;
if ((etherType == ZT_ETHERTYPE_IPV4)&&(frameLen >= 20)&&(frameData[9] == 0x06)) {
const unsigned int headerLen = 4 * (frameData[0] & 0xf);
const unsigned int headerLen = 4 * (frameData[0] & 0xfU);
cf |= (uint64_t)frameData[headerLen + 13];
cf |= (((uint64_t)(frameData[headerLen + 12] & 0x0f)) << 8);
cf |= (((uint64_t)(frameData[headerLen + 12] & 0x0fU)) << 8U);
} else if (etherType == ZT_ETHERTYPE_IPV6) {
unsigned int pos = 0,proto = 0;
if (_ipv6GetPayload(frameData,frameLen,pos,proto)) {
if ((proto == 0x06)&&(frameLen > (pos + 14))) {
cf |= (uint64_t)frameData[pos + 13];
cf |= (((uint64_t)(frameData[pos + 12] & 0x0f)) << 8);
cf |= (((uint64_t)(frameData[pos + 12] & 0x0fU)) << 8U);
}
}
}
@ -491,15 +486,15 @@ static _doZtFilterResult _doZtFilter(
} break;
case ZT_NETWORK_RULE_MATCH_INTEGER_RANGE: {
uint64_t integer = 0;
const unsigned int bits = (rules[rn].v.intRange.format & 63) + 1;
const unsigned int bits = (rules[rn].v.intRange.format & 63U) + 1;
const unsigned int bytes = ((bits + 8 - 1) / 8); // integer ceiling of division by 8
if ((rules[rn].v.intRange.format & 0x80) == 0) {
if ((rules[rn].v.intRange.format & 0x80U) == 0) {
// Big-endian
unsigned int idx = rules[rn].v.intRange.idx + (8 - bytes);
const unsigned int eof = idx + bytes;
if (eof <= frameLen) {
while (idx < eof) {
integer <<= 8;
integer <<= 8U;
integer |= frameData[idx++];
}
}
@ -510,8 +505,8 @@ static _doZtFilterResult _doZtFilter(
const unsigned int eof = idx + bytes;
if (eof <= frameLen) {
while (idx < eof) {
integer >>= 8;
integer |= ((uint64_t)frameData[idx++]) << 56;
integer >>= 8U;
integer |= ((uint64_t)frameData[idx++]) << 56U;
}
}
integer >>= (64 - bits);
@ -528,9 +523,9 @@ static _doZtFilterResult _doZtFilter(
rrl.log(rn,thisRuleMatches,thisSetMatches);
if ((rules[rn].t & 0x40))
thisSetMatches |= (thisRuleMatches ^ ((rules[rn].t >> 7) & 1));
else thisSetMatches &= (thisRuleMatches ^ ((rules[rn].t >> 7) & 1));
if ((rules[rn].t & 0x40U))
thisSetMatches |= (thisRuleMatches ^ ((rules[rn].t >> 7U) & 1U));
else thisSetMatches &= (thisRuleMatches ^ ((rules[rn].t >> 7U) & 1U));
}
return DOZTFILTER_NO_MATCH;
@ -622,10 +617,10 @@ bool Network::filterOutgoingPacket(
const unsigned int vlanId,
uint8_t &qosBucket)
{
Trace::RuleResultLog rrl,crrl;
Address ztFinalDest(ztDest);
int localCapabilityIndex = -1;
int accept = 0;
Trace::RuleResultLog rrl,crrl;
Address cc;
unsigned int ccLength = 0;
bool ccWatch = false;
@ -674,8 +669,7 @@ bool Network::filterOutgoingPacket(
} break;
case DOZTFILTER_DROP:
//if (_config.remoteTraceTarget)
// RR->t->networkFilter(tPtr,*this,rrl,(Trace::RuleResultLog *)0,(Capability *)0,ztSource,ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,noTee,false,0);
RR->t->networkFilter(tPtr,_id,rrl.l,nullptr,0,0,ztSource,ztDest,macSource,macDest,(uint16_t)frameLen,frameData,(uint16_t)etherType,(uint16_t)vlanId,noTee,false,0);
return false;
case DOZTFILTER_REDIRECT: // interpreted as ACCEPT but ztFinalDest will have been changed in _doZtFilter()
@ -688,10 +682,7 @@ bool Network::filterOutgoingPacket(
break;
}
if (accept) {
if (membership)
membership->logSentBytes(frameLen);
if (accept != 0) {
if ((!noTee)&&(cc)) {
Packet outp(cc,RR->identity.address(),Packet::VERB_EXT_FRAME);
outp.append(_id);
@ -715,19 +706,19 @@ bool Network::filterOutgoingPacket(
outp.compress();
RR->sw->send(tPtr,outp,true);
//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);
return false; // DROP locally, since we redirected
} else {
//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);
return true;
// DROP locally since we redirected
accept = 0;
}
} else {
//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);
return false;
}
if (localCapabilityIndex >= 0) {
const Capability &cap = _config.capabilities[localCapabilityIndex];
RR->t->networkFilter(tPtr,_id,rrl.l,crrl.l,cap.id(),cap.timestamp(),ztSource,ztDest,macSource,macDest,(uint16_t)frameLen,frameData,(uint16_t)etherType,(uint16_t)vlanId,noTee,false,accept);
} else {
RR->t->networkFilter(tPtr,_id,rrl.l,nullptr,0,0,ztSource,ztDest,macSource,macDest,(uint16_t)frameLen,frameData,(uint16_t)etherType,(uint16_t)vlanId,noTee,false,accept);
}
return (accept != 0);
}
int Network::filterIncomingPacket(
@ -810,8 +801,6 @@ int Network::filterIncomingPacket(
}
if (accept) {
membership.logReceivedBytes(frameLen);
if (cc) {
Packet outp(cc,RR->identity.address(),Packet::VERB_EXT_FRAME);
outp.append(_id);
@ -846,6 +835,24 @@ int Network::filterIncomingPacket(
return accept;
}
void Network::multicastSubscribe(void *tPtr,const MulticastGroup &mg)
{
Mutex::Lock l(_myMulticastGroups_l);
if (!std::binary_search(_myMulticastGroups.begin(),_myMulticastGroups.end(),mg)) {
_myMulticastGroups.insert(std::upper_bound(_myMulticastGroups.begin(),_myMulticastGroups.end(),mg),mg);
Mutex::Lock l2(_memberships_l);
_announceMulticastGroups(tPtr,true);
}
}
void Network::multicastUnsubscribe(const MulticastGroup &mg)
{
Mutex::Lock l(_myMulticastGroups_l);
std::vector<MulticastGroup>::iterator i(std::lower_bound(_myMulticastGroups.begin(),_myMulticastGroups.end(),mg));
if ( (i != _myMulticastGroups.end()) && (*i == mg) )
_myMulticastGroups.erase(i);
}
uint64_t Network::handleConfigChunk(void *tPtr,const uint64_t packetId,const Address &source,const Buffer<ZT_PROTO_MAX_PACKET_LENGTH> &chunk,unsigned int ptr)
{
if (_destroyed)
@ -861,11 +868,11 @@ uint64_t Network::handleConfigChunk(void *tPtr,const uint64_t packetId,const Add
{
Mutex::Lock l1(_config_l);
_IncomingConfigChunk *c = (_IncomingConfigChunk *)0;
_IncomingConfigChunk *c = nullptr;
uint64_t chunkId = 0;
unsigned long totalLength,chunkIndex;
if (ptr < chunk.size()) {
const bool fastPropagate = ((chunk[ptr++] & 0x01) != 0);
const bool fastPropagate = ((chunk[ptr++] & 0x01U) != 0);
configUpdateId = chunk.at<uint64_t>(ptr); ptr += 8;
totalLength = chunk.at<uint32_t>(ptr); ptr += 4;
chunkIndex = chunk.at<uint32_t>(ptr); ptr += 4;
@ -906,8 +913,8 @@ uint64_t Network::handleConfigChunk(void *tPtr,const uint64_t packetId,const Add
// New properly verified chunks can be flooded "virally" through the network
if (fastPropagate) {
Mutex::Lock l2(_memberships_l);
Address *a = (Address *)0;
Membership *m = (Membership *)0;
Address *a = nullptr;
Membership *m = nullptr;
Hashtable<Address,Membership>::Iterator i(_memberships);
while (i.next(a,m)) {
if ((*a != source)&&(*a != controller())) {
@ -1102,7 +1109,31 @@ void Network::learnBridgeRoute(const MAC &mac,const Address &addr)
}
}
Membership::AddCredentialResult Network::addCredential(void *tPtr,const Address &sentFrom,const Revocation &rev)
Membership::AddCredentialResult Network::addCredential(void *tPtr,const Identity &sourcePeerIdentity,const CertificateOfMembership &com)
{
if (com.networkId() != _id)
return Membership::ADD_REJECTED;
Mutex::Lock _l(_memberships_l);
return _memberships[com.issuedTo()].addCredential(RR,tPtr,sourcePeerIdentity,_config,com);
}
Membership::AddCredentialResult Network::addCredential(void *tPtr,const Identity &sourcePeerIdentity,const Capability &cap)
{
if (cap.networkId() != _id)
return Membership::ADD_REJECTED;
Mutex::Lock _l(_memberships_l);
return _memberships[cap.issuedTo()].addCredential(RR,tPtr,sourcePeerIdentity,_config,cap);
}
Membership::AddCredentialResult Network::addCredential(void *tPtr,const Identity &sourcePeerIdentity,const Tag &tag)
{
if (tag.networkId() != _id)
return Membership::ADD_REJECTED;
Mutex::Lock _l(_memberships_l);
return _memberships[tag.issuedTo()].addCredential(RR,tPtr,sourcePeerIdentity,_config,tag);
}
Membership::AddCredentialResult Network::addCredential(void *tPtr,const Identity &sourcePeerIdentity,const Revocation &rev)
{
if (rev.networkId() != _id)
return Membership::ADD_REJECTED;
@ -1110,14 +1141,14 @@ Membership::AddCredentialResult Network::addCredential(void *tPtr,const Address
Mutex::Lock l1(_memberships_l);
Membership &m = _memberships[rev.target()];
const Membership::AddCredentialResult result = m.addCredential(RR,tPtr,_config,rev);
const Membership::AddCredentialResult result = m.addCredential(RR,tPtr,sourcePeerIdentity,_config,rev);
if ((result == Membership::ADD_ACCEPTED_NEW)&&(rev.fastPropagate())) {
Address *a = (Address *)0;
Membership *m = (Membership *)0;
Address *a = nullptr;
Membership *m = nullptr;
Hashtable<Address,Membership>::Iterator i(_memberships);
while (i.next(a,m)) {
if ((*a != sentFrom)&&(*a != rev.signer())) {
if ((*a != sourcePeerIdentity.address())&&(*a != rev.signer())) {
Packet outp(*a,RR->identity.address(),Packet::VERB_NETWORK_CREDENTIALS);
outp.append((uint8_t)0x00); // no COM
outp.append((uint16_t)0); // no capabilities
@ -1133,15 +1164,44 @@ Membership::AddCredentialResult Network::addCredential(void *tPtr,const Address
return result;
}
Membership::AddCredentialResult Network::addCredential(void *tPtr,const Identity &sourcePeerIdentity,const CertificateOfOwnership &coo)
{
if (coo.networkId() != _id)
return Membership::ADD_REJECTED;
Mutex::Lock _l(_memberships_l);
return _memberships[coo.issuedTo()].addCredential(RR,tPtr,sourcePeerIdentity,_config,coo);
}
void Network::pushCredentialsNow(void *tPtr,const Address &to,const int64_t now)
{
Mutex::Lock _l(_memberships_l);
_memberships[to].pushCredentials(RR,tPtr,now,to,_config);
}
void Network::destroy()
{
_memberships_l.lock();
_config_l.lock();
_destroyed = true;
_config_l.unlock();
_memberships_l.unlock();
}
void Network::externalConfig(ZT_VirtualNetworkConfig *ec) const
{
Mutex::Lock _l(_config_l);
_externalConfig(ec);
}
void Network::_requestConfiguration(void *tPtr)
{
if (_destroyed)
return;
if ((_id >> 56) == 0xff) {
if ((_id & 0xffffff) == 0) {
const uint16_t startPortRange = (uint16_t)((_id >> 40) & 0xffff);
const uint16_t endPortRange = (uint16_t)((_id >> 24) & 0xffff);
if ((_id >> 56U) == 0xff) {
if ((_id & 0xffffffU) == 0) {
const uint16_t startPortRange = (uint16_t)((_id >> 40U) & 0xffff);
const uint16_t endPortRange = (uint16_t)((_id >> 24U) & 0xffff);
if (endPortRange >= startPortRange) {
ScopedPtr<NetworkConfig> nconf(new NetworkConfig());
@ -1158,7 +1218,7 @@ void Network::_requestConfiguration(void *tPtr)
nconf->staticIps[0] = InetAddress::makeIpv66plane(_id,RR->identity.address().toInt());
// Drop everything but IPv6
nconf->rules[0].t = (uint8_t)ZT_NETWORK_RULE_MATCH_ETHERTYPE | 0x80; // NOT
nconf->rules[0].t = (uint8_t)ZT_NETWORK_RULE_MATCH_ETHERTYPE | 0x80U; // NOT
nconf->rules[0].v.etherType = 0x86dd; // IPv6
nconf->rules[1].t = (uint8_t)ZT_NETWORK_RULE_ACTION_DROP;
@ -1170,7 +1230,7 @@ void Network::_requestConfiguration(void *tPtr)
// Allow destination ports within range
nconf->rules[4].t = (uint8_t)ZT_NETWORK_RULE_MATCH_IP_PROTOCOL;
nconf->rules[4].v.ipProtocol = 0x11; // UDP
nconf->rules[5].t = (uint8_t)ZT_NETWORK_RULE_MATCH_IP_PROTOCOL | 0x40; // OR
nconf->rules[5].t = (uint8_t)ZT_NETWORK_RULE_MATCH_IP_PROTOCOL | 0x40U; // OR
nconf->rules[5].v.ipProtocol = 0x06; // TCP
nconf->rules[6].t = (uint8_t)ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE;
nconf->rules[6].v.port[0] = startPortRange;
@ -1178,7 +1238,7 @@ void Network::_requestConfiguration(void *tPtr)
nconf->rules[7].t = (uint8_t)ZT_NETWORK_RULE_ACTION_ACCEPT;
// Allow non-SYN TCP packets to permit non-connection-initiating traffic
nconf->rules[8].t = (uint8_t)ZT_NETWORK_RULE_MATCH_CHARACTERISTICS | 0x80; // NOT
nconf->rules[8].t = (uint8_t)ZT_NETWORK_RULE_MATCH_CHARACTERISTICS | 0x80U; // NOT
nconf->rules[8].v.characteristics = ZT_RULE_PACKET_CHARACTERISTICS_TCP_SYN;
nconf->rules[9].t = (uint8_t)ZT_NETWORK_RULE_ACTION_ACCEPT;
@ -1208,16 +1268,16 @@ void Network::_requestConfiguration(void *tPtr)
} else {
this->setNotFound();
}
} else if ((_id & 0xff) == 0x01) {
} else if ((_id & 0xffU) == 0x01) {
// 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 networkHub = (_id >> 8) & 0xffffffffffULL;
const uint64_t networkHub = (_id >> 8U) & 0xffffffffffULL;
uint8_t ipv4[4];
ipv4[0] = (uint8_t)((_id >> 48) & 0xff);
ipv4[1] = (uint8_t)((myAddress >> 16) & 0xff);
ipv4[2] = (uint8_t)((myAddress >> 8) & 0xff);
ipv4[3] = (uint8_t)(myAddress & 0xff);
ipv4[0] = (uint8_t)(_id >> 48U);
ipv4[1] = (uint8_t)(myAddress >> 16U);
ipv4[2] = (uint8_t)(myAddress >> 8U);
ipv4[3] = (uint8_t)myAddress;
char v4ascii[24];
Utils::decimal(ipv4[0],v4ascii);
@ -1282,7 +1342,7 @@ void Network::_requestConfiguration(void *tPtr)
rmd->add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_FLAGS,(uint64_t)0);
rmd->add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_RULES_ENGINE_REV,(uint64_t)ZT_RULES_ENGINE_REVISION);
RR->t->networkConfigRequestSent(tPtr,*this,ctrl);
RR->t->networkConfigRequestSent(tPtr,_id);
if (ctrl == RR->identity.address()) {
if (RR->localNetworkController) {

View file

@ -58,7 +58,7 @@ public:
/**
* Compute primary controller device ID from network ID
*/
static inline Address controllerFor(uint64_t nwid) { return Address(nwid >> 24); }
static ZT_ALWAYS_INLINE Address controllerFor(uint64_t nwid) { return Address(nwid >> 24U); }
/**
* Construct a new network
@ -76,14 +76,14 @@ public:
~Network();
inline uint64_t id() const { return _id; }
inline Address controller() const { return Address(_id >> 24); }
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 { return _status(); }
inline const NetworkConfig &config() const { return _config; }
inline const MAC &mac() const { return _mac; }
ZT_ALWAYS_INLINE uint64_t id() const { return _id; }
ZT_ALWAYS_INLINE Address controller() const { return Address(_id >> 24); }
ZT_ALWAYS_INLINE bool multicastEnabled() const { return (_config.multicastLimit > 0); }
ZT_ALWAYS_INLINE bool hasConfig() const { return (_config); }
ZT_ALWAYS_INLINE uint64_t lastConfigUpdate() const { return _lastConfigUpdate; }
ZT_ALWAYS_INLINE ZT_VirtualNetworkStatus status() const { return _status(); }
ZT_ALWAYS_INLINE const NetworkConfig &config() const { return _config; }
ZT_ALWAYS_INLINE const MAC &mac() const { return _mac; }
/**
* Apply filters to an outgoing packet
@ -107,15 +107,15 @@ public:
*/
bool filterOutgoingPacket(
void *tPtr,
const bool noTee,
bool noTee,
const Address &ztSource,
const Address &ztDest,
const MAC &macSource,
const MAC &macDest,
const uint8_t *frameData,
const unsigned int frameLen,
const unsigned int etherType,
const unsigned int vlanId,
unsigned int frameLen,
unsigned int etherType,
unsigned int vlanId,
uint8_t &qosBucket);
/**
@ -144,9 +144,9 @@ public:
const MAC &macSource,
const MAC &macDest,
const uint8_t *frameData,
const unsigned int frameLen,
const unsigned int etherType,
const unsigned int vlanId);
unsigned int frameLen,
unsigned int etherType,
unsigned int vlanId);
/**
* Check whether we are subscribed to a multicast group
@ -155,7 +155,7 @@ public:
* @param includeBridgedGroups If true, also check groups we've learned via bridging
* @return True if this network endpoint / peer is a member
*/
inline bool subscribedToMulticastGroup(const MulticastGroup &mg,const bool includeBridgedGroups) const
ZT_ALWAYS_INLINE bool subscribedToMulticastGroup(const MulticastGroup &mg,const bool includeBridgedGroups) const
{
Mutex::Lock l(_myMulticastGroups_l);
if (std::binary_search(_myMulticastGroups.begin(),_myMulticastGroups.end(),mg))
@ -171,28 +171,14 @@ public:
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param mg New multicast group
*/
inline void multicastSubscribe(void *tPtr,const MulticastGroup &mg)
{
Mutex::Lock l(_myMulticastGroups_l);
if (!std::binary_search(_myMulticastGroups.begin(),_myMulticastGroups.end(),mg)) {
_myMulticastGroups.insert(std::upper_bound(_myMulticastGroups.begin(),_myMulticastGroups.end(),mg),mg);
Mutex::Lock l2(_memberships_l);
_announceMulticastGroups(tPtr,true);
}
}
void multicastSubscribe(void *tPtr,const MulticastGroup &mg);
/**
* Unsubscribe from a multicast group
*
* @param mg Multicast group
*/
inline void multicastUnsubscribe(const MulticastGroup &mg)
{
Mutex::Lock l(_myMulticastGroups_l);
std::vector<MulticastGroup>::iterator i(std::lower_bound(_myMulticastGroups.begin(),_myMulticastGroups.end(),mg));
if ( (i != _myMulticastGroups.end()) && (*i == mg) )
_myMulticastGroups.erase(i);
}
void multicastUnsubscribe(const MulticastGroup &mg);
/**
* Handle an inbound network config chunk
@ -208,7 +194,7 @@ public:
* @param ptr Index of chunk and related fields in packet
* @return Update ID if update was fully assembled and accepted or 0 otherwise
*/
uint64_t handleConfigChunk(void *tPtr,const uint64_t packetId,const Address &source,const Buffer<ZT_PROTO_MAX_PACKET_LENGTH> &chunk,unsigned int ptr);
uint64_t handleConfigChunk(void *tPtr,uint64_t packetId,const Address &source,const Buffer<ZT_PROTO_MAX_PACKET_LENGTH> &chunk,unsigned int ptr);
/**
* Set network configuration
@ -227,12 +213,12 @@ public:
/**
* Set netconf failure to 'access denied' -- called in IncomingPacket when controller reports this
*/
inline void setAccessDenied() { _netconfFailure = NETCONF_FAILURE_ACCESS_DENIED; }
ZT_ALWAYS_INLINE void setAccessDenied() { _netconfFailure = NETCONF_FAILURE_ACCESS_DENIED; }
/**
* Set netconf failure to 'not found' -- called by IncomingPacket when controller reports this
*/
inline void setNotFound() { _netconfFailure = NETCONF_FAILURE_NOT_FOUND; }
ZT_ALWAYS_INLINE void setNotFound() { _netconfFailure = NETCONF_FAILURE_NOT_FOUND; }
/**
* Determine whether this peer is permitted to communicate on this network
@ -245,7 +231,7 @@ public:
/**
* Do periodic cleanup and housekeeping tasks
*/
void doPeriodicTasks(void *tPtr,const int64_t now);
void doPeriodicTasks(void *tPtr,int64_t now);
/**
* Find the node on this network that has this MAC behind it (if any)
@ -253,18 +239,13 @@ public:
* @param mac MAC address
* @return ZeroTier address of bridge to this MAC
*/
inline Address findBridgeTo(const MAC &mac) const
ZT_ALWAYS_INLINE Address findBridgeTo(const MAC &mac) const
{
Mutex::Lock _l(_remoteBridgeRoutes_l);
const Address *const br = _remoteBridgeRoutes.get(mac);
return ((br) ? *br : Address());
}
/**
* @return True if QoS is in effect for this network
*/
inline bool qosEnabled() { return false; }
/**
* Set a bridge route
*
@ -280,7 +261,7 @@ public:
* @param mg Multicast group
* @param now Current time
*/
inline void learnBridgedMulticastGroup(void *tPtr,const MulticastGroup &mg,int64_t now)
ZT_ALWAYS_INLINE void learnBridgedMulticastGroup(void *tPtr,const MulticastGroup &mg,int64_t now)
{
Mutex::Lock l(_myMulticastGroups_l);
_multicastGroupsBehindMe.set(mg,now);
@ -289,51 +270,27 @@ public:
/**
* Validate a credential and learn it if it passes certificate and other checks
*/
inline Membership::AddCredentialResult addCredential(void *tPtr,const CertificateOfMembership &com)
{
if (com.networkId() != _id)
return Membership::ADD_REJECTED;
Mutex::Lock _l(_memberships_l);
return _memberships[com.issuedTo()].addCredential(RR,tPtr,_config,com);
}
Membership::AddCredentialResult addCredential(void *tPtr,const Identity &sourcePeerIdentity,const CertificateOfMembership &com);
/**
* Validate a credential and learn it if it passes certificate and other checks
*/
inline Membership::AddCredentialResult addCredential(void *tPtr,const Capability &cap)
{
if (cap.networkId() != _id)
return Membership::ADD_REJECTED;
Mutex::Lock _l(_memberships_l);
return _memberships[cap.issuedTo()].addCredential(RR,tPtr,_config,cap);
}
Membership::AddCredentialResult addCredential(void *tPtr,const Identity &sourcePeerIdentity,const Capability &cap);
/**
* Validate a credential and learn it if it passes certificate and other checks
*/
inline Membership::AddCredentialResult addCredential(void *tPtr,const Tag &tag)
{
if (tag.networkId() != _id)
return Membership::ADD_REJECTED;
Mutex::Lock _l(_memberships_l);
return _memberships[tag.issuedTo()].addCredential(RR,tPtr,_config,tag);
}
Membership::AddCredentialResult addCredential(void *tPtr,const Identity &sourcePeerIdentity,const Tag &tag);
/**
* Validate a credential and learn it if it passes certificate and other checks
*/
Membership::AddCredentialResult addCredential(void *tPtr,const Address &sentFrom,const Revocation &rev);
Membership::AddCredentialResult addCredential(void *tPtr,const Identity &sourcePeerIdentity,const Revocation &rev);
/**
* Validate a credential and learn it if it passes certificate and other checks
*/
inline Membership::AddCredentialResult addCredential(void *tPtr,const CertificateOfOwnership &coo)
{
if (coo.networkId() != _id)
return Membership::ADD_REJECTED;
Mutex::Lock _l(_memberships_l);
return _memberships[coo.issuedTo()].addCredential(RR,tPtr,_config,coo);
}
Membership::AddCredentialResult addCredential(void *tPtr,const Identity &sourcePeerIdentity,const CertificateOfOwnership &coo);
/**
* Force push credentials (COM, etc.) to a peer now
@ -342,11 +299,7 @@ public:
* @param to Destination peer address
* @param now Current time
*/
inline void pushCredentialsNow(void *tPtr,const Address &to,const int64_t now)
{
Mutex::Lock _l(_memberships_l);
_memberships[to].pushCredentials(RR,tPtr,now,to,_config);
}
void pushCredentialsNow(void *tPtr,const Address &to,int64_t now);
/**
* Push credentials if we haven't done so in a long time
@ -355,7 +308,7 @@ public:
* @param to Destination peer address
* @param now Current time
*/
inline void pushCredentialsIfNeeded(void *tPtr,const Address &to,const int64_t now)
ZT_ALWAYS_INLINE void pushCredentialsIfNeeded(void *tPtr,const Address &to,const int64_t now)
{
const int64_t tout = std::min(_config.credentialTimeMaxDelta,(int64_t)ZT_PEER_ACTIVITY_TIMEOUT);
Mutex::Lock _l(_memberships_l);
@ -370,25 +323,14 @@ public:
* This sets the network to completely remove itself on delete. This also prevents the
* call of the normal port shutdown event on delete.
*/
inline void destroy()
{
_memberships_l.lock();
_config_l.lock();
_destroyed = true;
_config_l.unlock();
_memberships_l.unlock();
}
void destroy();
/**
* Get this network's config for export via the ZT core API
*
* @param ec Buffer to fill with externally-visible network configuration
*/
inline void externalConfig(ZT_VirtualNetworkConfig *ec) const
{
Mutex::Lock _l(_config_l);
_externalConfig(ec);
}
void externalConfig(ZT_VirtualNetworkConfig *ec) const;
/**
* Iterate through memberships
@ -396,7 +338,7 @@ public:
* @param f Function of (const Address,const Membership)
*/
template<typename F>
inline void eachMember(F f)
ZT_ALWAYS_INLINE void eachMember(F f)
{
Mutex::Lock ml(_memberships_l);
Hashtable<Address,Membership>::Iterator i(_memberships);
@ -411,13 +353,12 @@ public:
/**
* @return Externally usable pointer-to-pointer exported via the core API
*/
inline void **userPtr() { return &_uPtr; }
ZT_ALWAYS_INLINE void **userPtr() { return &_uPtr; }
private:
void _requestConfiguration(void *tPtr);
ZT_VirtualNetworkStatus _status() const;
void _externalConfig(ZT_VirtualNetworkConfig *ec) const; // assumes _lock is locked
bool _gate(const SharedPtr<Peer> &peer);
void _announceMulticastGroups(void *tPtr,bool force);
void _announceMulticastGroupsTo(void *tPtr,const Address &peer,const std::vector<MulticastGroup> &allMulticastGroups);
std::vector<MulticastGroup> _allMulticastGroups() const;
@ -433,11 +374,11 @@ private:
Hashtable< MAC,Address > _remoteBridgeRoutes; // remote addresses where given MACs are reachable (for tracking devices behind remote bridges)
NetworkConfig _config;
uint64_t _lastConfigUpdate;
volatile uint64_t _lastConfigUpdate;
struct _IncomingConfigChunk
{
inline _IncomingConfigChunk() : ts(0),updateId(0),haveChunks(0),haveBytes(0),data() {}
ZT_ALWAYS_INLINE _IncomingConfigChunk() : ts(0),updateId(0),haveChunks(0),haveBytes(0),data() {}
uint64_t ts;
uint64_t updateId;
uint64_t haveChunkIds[ZT_NETWORK_MAX_UPDATE_CHUNKS];

View file

@ -33,10 +33,6 @@
namespace ZeroTier {
/****************************************************************************/
/* Public Node interface (C++, exposed via CAPI bindings) */
/****************************************************************************/
Node::Node(void *uPtr,void *tPtr,const struct ZT_Node_Callbacks *callbacks,int64_t now) :
_RR(this),
RR(&_RR),
@ -437,7 +433,7 @@ ZT_PeerList *Node::peers() const
p->address = (*pi)->address().toInt();
identities[pl->peerCount] = (*pi)->identity(); // need to make a copy in case peer gets deleted
p->identity = &identities[pl->peerCount];
(*pi)->identity().hash(p->identityHash,false);
memcpy(p->identityHash,(*pi)->identity().hash(),sizeof(p->identityHash));
if ((*pi)->remoteVersionKnown()) {
p->versionMajor = (int)(*pi)->remoteVersionMajor();
p->versionMinor = (int)(*pi)->remoteVersionMinor();

View file

@ -264,7 +264,7 @@ public:
* @param remoteAddress Remote address
* @return True if path should be used
*/
bool shouldUsePathForZeroTierTraffic(void *tPtr,const Identity &id,const int64_t localSocket,const InetAddress &remoteAddress);
bool shouldUsePathForZeroTierTraffic(void *tPtr,const Identity &id,int64_t localSocket,const InetAddress &remoteAddress);
/**
* Query callback for a physical address for a peer

View file

@ -28,18 +28,15 @@
//
#ifndef __GCC__
#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1) || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2) || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1) || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2) || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) || defined(__INTEL_COMPILER) || defined(__clang__)
#define __GCC__
#endif
#endif
#if !defined(__GCC__) && !defined (__clang__) && !defined(__INTEL_COMPILER)
#define ZT_PACKED_STRUCT(D) __pragma(pack(push,1)) D __pragma(pack(pop))
#ifdef _MSC_VER
#pragma warning(disable : 4290)
#pragma warning(disable : 4996)
#pragma warning(disable : 4101)
#else
#define ZT_PACKED_STRUCT(D) D __attribute__((packed))
#endif
#if defined(_WIN32) || defined(_WIN64)
@ -98,8 +95,8 @@
// Avoid unaligned type casts on all but x86/x64 architecture.
#if (!(defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_AMD64) || defined(_M_X64) || defined(i386) || defined(__i386) || defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(_M_IX86) || defined(__X86__) || defined(_X86_) || defined(__I86__) || defined(__INTEL__) || defined(__386)))
#ifndef ZT_NO_TYPE_PUNNING
#define ZT_NO_TYPE_PUNNING
#ifndef ZT_NO_UNALIGNED_ACCESS
#define ZT_NO_UNALIGNED_ACCESS
#endif
#endif

View file

@ -66,7 +66,7 @@ bool Packet::dearmor(const void *key)
s20.crypt12(ZERO_KEY,macKey,sizeof(macKey));
uint64_t mac[2];
poly1305(mac,payload,payloadLen,macKey);
#ifdef ZT_NO_TYPE_PUNNING
#ifdef ZT_NO_UNALIGNED_ACCESS
if (!Utils::secureEq(mac,data + ZT_PACKET_IDX_MAC,8))
return false;
#else

View file

@ -111,7 +111,14 @@ public:
*
* @param now Current time
*/
ZT_ALWAYS_INLINE bool alive(const int64_t now) const { return ((now - _lastIn) < ZT_PATH_ACTIVITY_TIMEOUT); }
ZT_ALWAYS_INLINE bool alive(const int64_t now) const { return ((now - _lastIn) < ZT_PATH_ALIVE_TIMEOUT); }
/**
* Check if path is considered active
*
* @param now Current time
*/
ZT_ALWAYS_INLINE bool active(const int64_t now) const { return ((now - _lastIn) < ZT_PATH_ACTIVITY_TIMEOUT); }
/**
* @return Physical address

View file

@ -92,9 +92,7 @@ void Peer::received(
if ((_paths[i]->address().ss_family == path->address().ss_family) &&
(_paths[i]->localSocket() == path->localSocket()) && // TODO: should be localInterface when multipath is integrated
(_paths[i]->address().ipsEqual2(path->address()))) {
// If this is another path to the same place, swap it out as the
// one we just received from may replace an old one but don't
// learn it as a new path.
// Replace older path if everything is the same except the port number.
_paths[i] = path;
goto path_check_done;
} else {
@ -130,7 +128,7 @@ path_check_done:
_lastAttemptedP2PInit = now;
InetAddress addr;
if (_bootstrap.type() == Endpoint::INETADDR)
if ((_bootstrap.type() == Endpoint::INETADDR_V4)||(_bootstrap.type() == Endpoint::INETADDR_V6))
sendHELLO(tPtr,-1,_bootstrap.inetAddr(),now);
if (RR->node->externalPathLookup(tPtr,_id,-1,addr)) {
if (RR->node->shouldUsePathForZeroTierTraffic(tPtr,_id,-1,addr))
@ -256,7 +254,7 @@ void Peer::ping(void *tPtr,int64_t now,const bool pingAllAddressTypes)
return;
}
if (_bootstrap.type() == Endpoint::INETADDR)
if ((_bootstrap.type() == Endpoint::INETADDR_V4)||(_bootstrap.type() == Endpoint::INETADDR_V6))
sendHELLO(tPtr,-1,_bootstrap.inetAddr(),now);
SharedPtr<Peer> r(RR->topology->root());

View file

@ -70,7 +70,7 @@ typedef struct poly1305_state_internal_t {
unsigned char final;
} poly1305_state_internal_t;
#if defined(ZT_NO_TYPE_PUNNING) || (__BYTE_ORDER != __LITTLE_ENDIAN)
#if defined(ZT_NO_UNALIGNED_ACCESS) || (__BYTE_ORDER != __LITTLE_ENDIAN)
static inline unsigned long long U8TO64(const unsigned char *p)
{
return
@ -87,7 +87,7 @@ static inline unsigned long long U8TO64(const unsigned char *p)
#define U8TO64(p) (*reinterpret_cast<const unsigned long long *>(p))
#endif
#if defined(ZT_NO_TYPE_PUNNING) || (__BYTE_ORDER != __LITTLE_ENDIAN)
#if defined(ZT_NO_UNALIGNED_ACCESS) || (__BYTE_ORDER != __LITTLE_ENDIAN)
static inline void U64TO8(unsigned char *p, unsigned long long v)
{
p[0] = (v ) & 0xff;

View file

@ -44,7 +44,7 @@ class Revocation : public Credential
friend class Credential;
public:
static ZT_ALWAYS_INLINE Credential::Type credentialType() { return Credential::CREDENTIAL_TYPE_REVOCATION; }
static ZT_ALWAYS_INLINE ZT_CredentialType credentialType() { return ZT_CREDENTIAL_TYPE_REVOCATION; }
ZT_ALWAYS_INLINE Revocation() :
_id(0),
@ -54,7 +54,7 @@ public:
_flags(0),
_target(),
_signedBy(),
_type(Credential::CREDENTIAL_TYPE_NULL),
_type(ZT_CREDENTIAL_TYPE_NULL),
_signatureLength(0)
{
}
@ -68,7 +68,7 @@ public:
* @param tgt Target node whose credential(s) are being revoked
* @param ct Credential type being revoked
*/
ZT_ALWAYS_INLINE Revocation(const uint32_t i,const uint64_t nwid,const uint32_t cid,const uint64_t thr,const uint64_t fl,const Address &tgt,const Credential::Type ct) :
ZT_ALWAYS_INLINE Revocation(const uint32_t i,const uint64_t nwid,const uint32_t cid,const uint64_t thr,const uint64_t fl,const Address &tgt,const ZT_CredentialType ct) :
_id(i),
_credentialId(cid),
_networkId(nwid),
@ -87,7 +87,7 @@ public:
ZT_ALWAYS_INLINE int64_t threshold() const { return _threshold; }
ZT_ALWAYS_INLINE const Address &target() const { return _target; }
ZT_ALWAYS_INLINE const Address &signer() const { return _signedBy; }
ZT_ALWAYS_INLINE Credential::Type type() const { return _type; }
ZT_ALWAYS_INLINE ZT_CredentialType typeBeingRevoked() const { return _type; }
ZT_ALWAYS_INLINE const uint8_t *signature() const { return _signature; }
ZT_ALWAYS_INLINE unsigned int signatureLength() const { return _signatureLength; }
ZT_ALWAYS_INLINE bool fastPropagate() const { return ((_flags & ZT_REVOCATION_FLAG_FAST_PROPAGATE) != 0); }
@ -160,7 +160,7 @@ public:
_flags = b.template at<uint64_t>(p); p += 8;
_target.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); p += ZT_ADDRESS_LENGTH;
_signedBy.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); p += ZT_ADDRESS_LENGTH;
_type = (Credential::Type)b[p++];
_type = (ZT_CredentialType)b[p++];
if (b[p++] == 1) {
_signatureLength = b.template at<uint16_t>(p);
@ -186,7 +186,7 @@ private:
uint64_t _flags;
Address _target;
Address _signedBy;
Credential::Type _type;
ZT_CredentialType _type;
unsigned int _signatureLength;
uint8_t _signature[ZT_SIGNATURE_BUFFER_SIZE];
};

View file

@ -235,64 +235,6 @@ public:
}
return curr_cnt ? subtotal / (float)curr_cnt : 0;
}
/**
* @return The sample standard deviation of element values
*/
inline float stddev() { return sqrt(variance()); }
/**
* @return The variance of element values
*/
inline float variance()
{
size_t iterator = begin;
float cached_mean = mean();
size_t curr_cnt = count();
T sum_of_squared_deviations = 0;
for (size_t i=0; i<curr_cnt; i++) {
iterator = (iterator + S - 1) % curr_cnt;
float deviation = (buf[i] - cached_mean);
sum_of_squared_deviations += (T)(deviation*deviation);
}
float variance = (float)sum_of_squared_deviations / (float)(S - 1);
return variance;
}
/**
* @return The number of elements of zero value
*/
inline size_t zeroCount()
{
size_t iterator = begin;
size_t zeros = 0;
size_t curr_cnt = count();
for (size_t i=0; i<curr_cnt; i++) {
iterator = (iterator + S - 1) % curr_cnt;
if (*(buf + iterator) == 0) {
zeros++;
}
}
return zeros;
}
/**
* @param value Value to match against in buffer
* @return The number of values held in the ring buffer which match a given value
*/
inline size_t countValue(T value)
{
size_t iterator = begin;
size_t cnt = 0;
size_t curr_cnt = count();
for (size_t i=0; i<curr_cnt; i++) {
iterator = (iterator + S - 1) % curr_cnt;
if (*(buf + iterator) == value) {
cnt++;
}
}
return cnt;
}
};
} // namespace ZeroTier

View file

@ -218,7 +218,7 @@ void HMACSHA384(const uint8_t key[32],const void *msg,const unsigned int msglen,
uint64_t kInPadded[16]; // input padded key
uint64_t outer[22]; // output padded key | H(input padded key | msg)
#ifdef ZT_NO_TYPE_PUNNING
#ifdef ZT_NO_UNALIGNED_ACCESS
for(int i=0;i<32;++i) ((uint8_t *)kInPadded)[i] = key[i] ^ 0x36;
for(int i=4;i<16;++i) kInPadded[i] = 0x3636363636363636ULL;
for(int i=0;i<32;++i) ((uint8_t *)outer)[i] = key[i] ^ 0x5c;

View file

@ -32,12 +32,6 @@
#define ZT_HMACSHA384_LEN 48
#define ZT_PROTO_KBKDF_LABEL_KEY_USE_HMAC_SHA_384 'H'
#define ZT_PROTO_KBKDF_LABEL_KEY_USE_AES_GMAC_SIV_K1 '1'
#define ZT_PROTO_KBKDF_LABEL_KEY_USE_AES_GMAC_SIV_K2 '2'
#define ZT_PROTO_KBKDF_LABEL_KEY_USE_AES_GMAC_SIV_K3 '3'
#define ZT_PROTO_KBKDF_LABEL_KEY_USE_AES_GMAC_SIV_K4 '4'
namespace ZeroTier {
#ifdef __APPLE__
@ -108,7 +102,7 @@ void SHA384(void *digest,const void *data0,unsigned int len0,const void *data1,u
* @param msglen Length of message
* @param mac Buffer to fill with result
*/
void HMACSHA384(const uint8_t key[32],const void *msg,const unsigned int msglen,uint8_t mac[48]);
void HMACSHA384(const uint8_t key[32],const void *msg,unsigned int msglen,uint8_t mac[48]);
/**
* Compute KBKDF (key-based key derivation function) using HMAC-SHA-384 as a PRF
@ -119,7 +113,7 @@ void HMACSHA384(const uint8_t key[32],const void *msg,const unsigned int msglen,
* @param iter Key iteration for generation of multiple keys for the same label/context
* @param out Output to receive derived key
*/
void KBKDFHMACSHA384(const uint8_t key[32],const char label,const char context,const uint32_t iter,uint8_t out[32]);
void KBKDFHMACSHA384(const uint8_t key[32],char label,char context,uint32_t iter,uint8_t out[32]);
} // namespace ZeroTier

View file

@ -19,7 +19,7 @@
#if __BYTE_ORDER == __LITTLE_ENDIAN
#ifdef ZT_NO_TYPE_PUNNING
#ifdef ZT_NO_UNALIGNED_ACCESS
// 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) )
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); }
@ -27,7 +27,7 @@ static inline void U32TO8_LITTLE(uint8_t *const c,const uint32_t v) { c[0] = (ui
// Fast version that just does 32-bit load/store
#define U8TO32_LITTLE(p) (*((const uint32_t *)((const void *)(p))))
#define U32TO8_LITTLE(c,v) *((uint32_t *)((void *)(c))) = (v)
#endif // ZT_NO_TYPE_PUNNING
#endif // ZT_NO_UNALIGNED_ACCESS
#else // __BYTE_ORDER == __BIG_ENDIAN (we don't support anything else... does MIDDLE_ENDIAN even still exist?)

View file

@ -25,7 +25,7 @@
#include "Trace.hpp"
// 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 300000
namespace ZeroTier {
@ -53,11 +53,7 @@ SelfAwareness::SelfAwareness(const RuntimeEnvironment *renv) :
{
}
SelfAwareness::~SelfAwareness()
{
}
void SelfAwareness::iam(void *tPtr,const Address &reporter,const int64_t receivedOnLocalSocket,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,bool trusted,int64_t now)
void SelfAwareness::iam(void *tPtr,const Identity &reporter,const int64_t receivedOnLocalSocket,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,bool trusted,int64_t now)
{
const InetAddress::IpScope scope = myPhysicalAddress.ipScope();
@ -65,12 +61,10 @@ void SelfAwareness::iam(void *tPtr,const Address &reporter,const int64_t receive
return;
Mutex::Lock l(_phy_l);
PhySurfaceEntry &entry = _phy[PhySurfaceKey(reporter,receivedOnLocalSocket,reporterPhysicalAddress,scope)];
PhySurfaceEntry &entry = _phy[PhySurfaceKey(reporter.address(),receivedOnLocalSocket,reporterPhysicalAddress,scope)];
if ( (trusted) && ((now - entry.ts) < ZT_SELFAWARENESS_ENTRY_TIMEOUT) && (!entry.mySurface.ipsEqual(myPhysicalAddress)) ) {
// Changes to external surface reported by trusted peers causes path reset in this scope
RR->t->resettingPathsInScope(tPtr,reporter,reporterPhysicalAddress,myPhysicalAddress,scope);
entry.mySurface = myPhysicalAddress;
entry.ts = now;
entry.trusted = trusted;
@ -80,10 +74,10 @@ void SelfAwareness::iam(void *tPtr,const Address &reporter,const int64_t receive
// Don't use 'entry' after this since hash table gets modified.
{
Hashtable< PhySurfaceKey,PhySurfaceEntry >::Iterator i(_phy);
PhySurfaceKey *k = (PhySurfaceKey *)0;
PhySurfaceEntry *e = (PhySurfaceEntry *)0;
PhySurfaceKey *k = nullptr;
PhySurfaceEntry *e = nullptr;
while (i.next(k,e)) {
if ((k->reporterPhysicalAddress != reporterPhysicalAddress)&&(k->scope == scope))
if ((k->scope == scope)&&(k->reporterPhysicalAddress != reporterPhysicalAddress))
_phy.erase(*k);
}
}
@ -91,6 +85,8 @@ void SelfAwareness::iam(void *tPtr,const Address &reporter,const int64_t receive
// Reset all paths within this scope and address family
_ResetWithinScope rset(tPtr,now,myPhysicalAddress.ss_family,(InetAddress::IpScope)scope);
RR->topology->eachPeer<_ResetWithinScope &>(rset);
RR->t->resettingPathsInScope(tPtr,reporter,reporterPhysicalAddress,entry.mySurface,myPhysicalAddress,scope);
} else {
// Otherwise just update DB to use to determine external surface info
entry.mySurface = myPhysicalAddress;
@ -111,35 +107,6 @@ void SelfAwareness::clean(int64_t now)
}
}
bool SelfAwareness::symmetricNat(const int64_t now) const
{
Hashtable< InetAddress,std::pair< std::set<int>,std::set<int64_t> > > ipToPortsAndLocalSockets(16);
{
Mutex::Lock l(_phy_l);
Hashtable<PhySurfaceKey,PhySurfaceEntry>::Iterator i(const_cast<SelfAwareness *>(this)->_phy);
PhySurfaceKey *k = nullptr;
PhySurfaceEntry *e = nullptr;
while (i.next(k,e)) {
if ((now - e->ts) < ZT_SELFAWARENESS_ENTRY_TIMEOUT) {
std::pair< std::set<int>,std::set<int64_t> > &ii = ipToPortsAndLocalSockets[e->mySurface.ipOnly()];
ii.first.insert(e->mySurface.port());
if (k->receivedOnLocalSocket != -1)
ii.second.insert(k->receivedOnLocalSocket);
}
}
}
Hashtable< InetAddress,std::pair< std::set<int>,std::set<int64_t> > >::Iterator i(ipToPortsAndLocalSockets);
InetAddress *k = nullptr;
std::pair< std::set<int>,std::set<int64_t> > *v = nullptr;
while (i.next(k,v)) {
if (v->first.size() > v->second.size()) // more external ports than local sockets for a given external IP
return true;
}
return false;
}
std::multimap<unsigned long,InetAddress> SelfAwareness::externalAddresses(const int64_t now) const
{
std::multimap<unsigned long,InetAddress> r;

View file

@ -24,6 +24,7 @@
namespace ZeroTier {
class Identity;
class RuntimeEnvironment;
/**
@ -35,19 +36,18 @@ class SelfAwareness
{
public:
explicit SelfAwareness(const RuntimeEnvironment *renv);
~SelfAwareness();
/**
* Called when a remote peer informs us of our external network address
*
* @param reporter ZeroTier address of reporting peer
* @param reporter Identity of reporting peer
* @param receivedOnLocalAddress Local address on which report was received
* @param reporterPhysicalAddress Physical address that reporting peer seems to have
* @param myPhysicalAddress Physical address that peer says we have
* @param trusted True if this peer is trusted as an authority to inform us of external address changes
* @param now Current time
*/
void iam(void *tPtr,const Address &reporter,int64_t receivedOnLocalSocket,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,bool trusted,int64_t now);
void iam(void *tPtr,const Identity &reporter,int64_t receivedOnLocalSocket,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,bool trusted,int64_t now);
/**
* Clean up database periodically
@ -56,14 +56,6 @@ public:
*/
void clean(int64_t now);
/**
* Check whether this node appears to be behind a symmetric NAT
*
* @param now Current time
* @return True if it looks like we're behind a symmetric NAT
*/
bool symmetricNat(int64_t now) const;
/**
* Get external address consensus, which is the statistical "mode" of external addresses.
*

View file

@ -211,7 +211,7 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr<Network> &network,const
bool fromBridged;
if ((fromBridged = (from != network->mac()))) {
if (!network->config().permitsBridging(RR->identity.address())) {
RR->t->outgoingNetworkFrameDropped(tPtr,network,from,to,etherType,vlanId,len,"not a bridge");
RR->t->outgoingNetworkFrameDropped(tPtr,network,from,to,etherType,vlanId,len,ZT_TRACE_FRAME_DROP_REASON_BRIDGING_NOT_ALLOWED_LOCAL);
return;
}
}
@ -235,7 +235,7 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr<Network> &network,const
multicastGroup = MulticastGroup::deriveMulticastGroupForAddressResolution(InetAddress(((const unsigned char *)data) + 24,4,0));
} else if (!network->config().enableBroadcast()) {
// 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,ZT_TRACE_FRAME_DROP_REASON_BROADCAST_DISABLED);
return;
}
} else if ((etherType == ZT_ETHERTYPE_IPV6)&&(len >= (40 + 8 + 16))) {
@ -323,7 +323,7 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr<Network> &network,const
// Check this after NDP emulation, since that has to be allowed in exactly this case
if (network->config().multicastLimit == 0) {
RR->t->outgoingNetworkFrameDropped(tPtr,network,from,to,etherType,vlanId,len,"multicast disabled");
RR->t->outgoingNetworkFrameDropped(tPtr,network,from,to,etherType,vlanId,len,ZT_TRACE_FRAME_DROP_REASON_MULTICAST_DISABLED);
return;
}
@ -336,7 +336,7 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr<Network> &network,const
// First pass sets noTee to false, but noTee is set to true in OutboundMulticast to prevent duplicates.
if (!network->filterOutgoingPacket(tPtr,false,RR->identity.address(),Address(),from,to,(const uint8_t *)data,len,etherType,vlanId,qosBucket)) {
RR->t->outgoingNetworkFrameDropped(tPtr,network,from,to,etherType,vlanId,len,"filter blocked");
RR->t->outgoingNetworkFrameDropped(tPtr,network,from,to,etherType,vlanId,len,ZT_TRACE_FRAME_DROP_REASON_FILTER_BLOCKED);
return;
}
@ -365,7 +365,7 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr<Network> &network,const
SharedPtr<Peer> toPeer(RR->topology->get(tPtr,toZT));
if (!network->filterOutgoingPacket(tPtr,false,RR->identity.address(),toZT,from,to,(const uint8_t *)data,len,etherType,vlanId,qosBucket)) {
RR->t->outgoingNetworkFrameDropped(tPtr,network,from,to,etherType,vlanId,len,"filter blocked");
RR->t->outgoingNetworkFrameDropped(tPtr,network,from,to,etherType,vlanId,len,ZT_TRACE_FRAME_DROP_REASON_FILTER_BLOCKED);
return;
}
@ -392,7 +392,7 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr<Network> &network,const
// for each ZT destination are also done below. This is the same rationale
// and design as for multicast.
if (!network->filterOutgoingPacket(tPtr,false,RR->identity.address(),Address(),from,to,(const uint8_t *)data,len,etherType,vlanId,qosBucket)) {
RR->t->outgoingNetworkFrameDropped(tPtr,network,from,to,etherType,vlanId,len,"filter blocked");
RR->t->outgoingNetworkFrameDropped(tPtr,network,from,to,etherType,vlanId,len,ZT_TRACE_FRAME_DROP_REASON_FILTER_BLOCKED);
return;
}
@ -442,7 +442,7 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr<Network> &network,const
outp.append((uint16_t)etherType);
outp.append(data,len);
} 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,ZT_TRACE_FRAME_DROP_REASON_FILTER_BLOCKED_AT_BRIDGE_REPLICATION);
}
}
}

View file

@ -52,7 +52,7 @@ class Tag : public Credential
friend class Credential;
public:
static ZT_ALWAYS_INLINE Credential::Type credentialType() { return Credential::CREDENTIAL_TYPE_TAG; }
static ZT_ALWAYS_INLINE ZT_CredentialType credentialType() { return ZT_CREDENTIAL_TYPE_TAG; }
ZT_ALWAYS_INLINE Tag() :
_id(0),

282
node/Trace.cpp Normal file
View file

@ -0,0 +1,282 @@
/*
* Copyright (c)2013-2020 ZeroTier, Inc.
*
* Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file in the project's root directory.
*
* Change Date: 2024-01-01
*
* On the date above, in accordance with the Business Source License, use
* of this software will be governed by version 2.0 of the Apache License.
*/
/****/
#include "Trace.hpp"
#include "RuntimeEnvironment.hpp"
#include "Node.hpp"
#include "Peer.hpp"
// Macro to avoid calling hton() on values known at compile time.
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define CONST_TO_BE_UINT16(x) ((uint16_t)((uint16_t)((uint16_t)(x) << 8U) | (uint16_t)((uint16_t)(x) >> 8U)))
#else
#define CONST_TO_BE_UINT16(x) ((uint16_t)(x))
#endif
namespace ZeroTier {
Trace::Trace(const RuntimeEnvironment *renv) :
RR(renv),
_vl1(false),
_vl2(false),
_vl2Filter(false),
_vl2Multicast(false),
_eventBufSize(0)
{
}
void Trace::_resettingPathsInScope(
void *const tPtr,
const Identity &reporter,
const InetAddress &from,
const InetAddress &oldExternal,
const InetAddress &newExternal,
const InetAddress::IpScope scope)
{
ZT_TraceEvent_VL1_RESETTING_PATHS_IN_SCOPE ev;
ev.evSize = CONST_TO_BE_UINT16(sizeof(ev));
ev.evType = CONST_TO_BE_UINT16(ZT_TRACE_VL1_RESETTING_PATHS_IN_SCOPE);
from.forTrace(ev.from);
oldExternal.forTrace(ev.oldExternal);
newExternal.forTrace(ev.newExternal);
ev.scope = (uint8_t)scope;
RR->node->postEvent(tPtr,ZT_EVENT_TRACE,&ev);
}
void Trace::_tryingNewPath(
void *const tPtr,
const Identity &trying,
const InetAddress &physicalAddress,
const InetAddress &triggerAddress,
uint64_t triggeringPacketId,
uint8_t triggeringPacketVerb,
uint64_t triggeredByAddress,
const uint8_t *triggeredByIdentityHash,
ZT_TraceTryingNewPathReason reason)
{
ZT_TraceEvent_VL1_TRYING_NEW_PATH ev;
ev.evSize = CONST_TO_BE_UINT16(sizeof(ev));
ev.evType = CONST_TO_BE_UINT16(ZT_TRACE_VL1_TRYING_NEW_PATH);
ev.address = Utils::hton(trying.address().toInt());
memcpy(ev.identityHash,trying.hash(),48);
physicalAddress.forTrace(ev.physicalAddress);
triggerAddress.forTrace(ev.triggerAddress);
ev.triggeringPacketId = Utils::hton(triggeringPacketId);
ev.triggeringPacketVerb = triggeringPacketVerb;
ev.triggeredByAddress = Utils::hton(triggeredByAddress);
if (triggeredByIdentityHash)
memcpy(ev.triggeredByIdentityHash,triggeredByIdentityHash,48);
else memset(ev.triggeredByIdentityHash,0,48);
ev.reason = (uint8_t)reason;
RR->node->postEvent(tPtr,ZT_EVENT_TRACE,&ev);
}
void Trace::_learnedNewPath(
void *const tPtr,
uint64_t packetId,
const Identity &peerIdentity,
const InetAddress &physicalAddress,
const InetAddress &replaced)
{
ZT_TraceEvent_VL1_LEARNED_NEW_PATH ev;
ev.evSize = CONST_TO_BE_UINT16(sizeof(ev));
ev.evType = CONST_TO_BE_UINT16(ZT_TRACE_VL1_LEARNED_NEW_PATH);
ev.packetId = Utils::hton(packetId);
ev.address = Utils::hton(peerIdentity.address().toInt());
memcpy(ev.identityHash,peerIdentity.hash(),48);
physicalAddress.forTrace(ev.physicalAddress);
replaced.forTrace(ev.replaced);
RR->node->postEvent(tPtr,ZT_EVENT_TRACE,&ev);
}
void Trace::_incomingPacketDropped(
void *const tPtr,
uint64_t packetId,
uint64_t networkId,
const Identity &peerIdentity,
const InetAddress &physicalAddress,
uint8_t hops,
uint8_t verb,
ZT_TracePacketDropReason reason)
{
ZT_TraceEvent_VL1_INCOMING_PACKET_DROPPED ev;
ev.evSize = CONST_TO_BE_UINT16(sizeof(ev));
ev.evType = CONST_TO_BE_UINT16(ZT_TRACE_VL1_INCOMING_PACKET_DROPPED);
ev.packetId = Utils::hton(packetId);
ev.networkId = Utils::hton(networkId);
ev.address = Utils::hton(peerIdentity.address().toInt());
memcpy(ev.identityHash,peerIdentity.hash(),48);
physicalAddress.forTrace(ev.physicalAddress);
ev.hops = hops;
ev.verb = verb;
ev.reason = (uint8_t)reason;
RR->node->postEvent(tPtr,ZT_EVENT_TRACE,&ev);
}
void Trace::_outgoingNetworkFrameDropped(
void *const tPtr,
uint64_t networkId,
const MAC &sourceMac,
const MAC &destMac,
uint16_t etherType,
uint16_t frameLength,
const uint8_t *frameData,
ZT_TraceFrameDropReason reason)
{
ZT_TraceEvent_VL2_OUTGOING_FRAME_DROPPED ev;
ev.evSize = CONST_TO_BE_UINT16(sizeof(ev));
ev.evType = CONST_TO_BE_UINT16(ZT_TRACE_VL2_OUTGOING_FRAME_DROPPED);
ev.networkId = Utils::hton(networkId);
ev.sourceMac = Utils::hton(sourceMac.toInt());
ev.destMac = Utils::hton(destMac.toInt());
ev.etherType = Utils::hton(etherType);
ev.frameLength = Utils::hton(frameLength);
if (frameData) {
unsigned int l = frameLength;
if (l > sizeof(ev.frameHead))
l = sizeof(ev.frameHead);
memcpy(ev.frameHead,frameData,l);
memset(ev.frameHead + l,0,sizeof(ev.frameHead) - l);
}
ev.reason = (uint8_t)reason;
RR->node->postEvent(tPtr,ZT_EVENT_TRACE,&ev);
}
void Trace::_incomingNetworkFrameDropped(
void *const tPtr,
uint64_t networkId,
const MAC &sourceMac,
const MAC &destMac,
const Identity &peerIdentity,
const InetAddress &physicalAddress,
uint8_t hops,
uint16_t frameLength,
const uint8_t *frameData,
uint8_t verb,
bool credentialRequestSent,
ZT_TraceFrameDropReason reason)
{
ZT_TraceEvent_VL2_INCOMING_FRAME_DROPPED ev;
ev.evSize = CONST_TO_BE_UINT16(sizeof(ev));
ev.evType = CONST_TO_BE_UINT16(ZT_TRACE_VL2_INCOMING_FRAME_DROPPED);
ev.networkId = Utils::hton(networkId);
ev.sourceMac = Utils::hton(sourceMac.toInt());
ev.destMac = Utils::hton(destMac.toInt());
ev.address = Utils::hton(peerIdentity.address().toInt());
physicalAddress.forTrace(ev.physicalAddress);
ev.hops = hops;
ev.frameLength = Utils::hton(frameLength);
if (frameData) {
unsigned int l = frameLength;
if (l > sizeof(ev.frameHead))
l = sizeof(ev.frameHead);
memcpy(ev.frameHead,frameData,l);
memset(ev.frameHead + l,0,sizeof(ev.frameHead) - l);
}
ev.verb = verb;
ev.credentialRequestSent = (uint8_t)credentialRequestSent;
ev.reason = (uint8_t)reason;
RR->node->postEvent(tPtr,ZT_EVENT_TRACE,&ev);
}
void Trace::_networkConfigRequestSent(
void *const tPtr,
uint64_t networkId)
{
ZT_TraceEvent_VL2_NETWORK_CONFIG_REQUESTED ev;
ev.evSize = CONST_TO_BE_UINT16(sizeof(ev));
ev.evType = CONST_TO_BE_UINT16(ZT_TRACE_VL2_NETWORK_CONFIG_REQUESTED);
ev.networkId = Utils::hton(networkId);
RR->node->postEvent(tPtr,ZT_EVENT_TRACE,&ev);
}
void Trace::_networkFilter(
void *const tPtr,
uint64_t networkId,
const uint8_t primaryRuleSetLog[512],
const uint8_t matchingCapabilityRuleSetLog[512],
uint32_t matchingCapabilityId,
int64_t matchingCapabilityTimestamp,
const Address &source,
const Address &dest,
const MAC &sourceMac,
const MAC &destMac,
uint16_t frameLength,
const uint8_t *frameData,
uint16_t etherType,
uint16_t vlanId,
bool noTee,
bool inbound,
int accept)
{
ZT_TraceEvent_VL2_NETWORK_FILTER ev;
ev.evSize = CONST_TO_BE_UINT16(sizeof(ev));
ev.evType = CONST_TO_BE_UINT16(ZT_TRACE_VL2_NETWORK_FILTER);
ev.networkId = Utils::hton(networkId);
memcpy(ev.primaryRuleSetLog,primaryRuleSetLog,sizeof(ev.primaryRuleSetLog));
if (matchingCapabilityRuleSetLog)
memcpy(ev.matchingCapabilityRuleSetLog,matchingCapabilityRuleSetLog,sizeof(ev.matchingCapabilityRuleSetLog));
else memset(ev.matchingCapabilityRuleSetLog,0,sizeof(ev.matchingCapabilityRuleSetLog));
ev.matchingCapabilityId = Utils::hton(matchingCapabilityId);
ev.matchingCapabilityTimestamp = Utils::hton(matchingCapabilityTimestamp);
ev.source = Utils::hton(source.toInt());
ev.dest = Utils::hton(dest.toInt());
ev.sourceMac = Utils::hton(sourceMac.toInt());
ev.destMac = Utils::hton(destMac.toInt());
ev.frameLength = Utils::hton(frameLength);
if (frameData) {
unsigned int l = frameLength;
if (l > sizeof(ev.frameHead))
l = sizeof(ev.frameHead);
memcpy(ev.frameHead,frameData,l);
memset(ev.frameHead + l,0,sizeof(ev.frameHead) - l);
}
ev.etherType = Utils::hton(etherType);
ev.vlanId = Utils::hton(vlanId);
ev.noTee = (uint8_t)noTee;
ev.inbound = (uint8_t)inbound;
ev.accept = (int8_t)accept;
RR->node->postEvent(tPtr,ZT_EVENT_TRACE,&ev);
}
void Trace::_credentialRejected(
void *const tPtr,
uint64_t networkId,
const Address &address,
uint32_t credentialId,
int64_t credentialTimestamp,
uint8_t credentialType,
ZT_TraceCredentialRejectionReason reason)
{
ZT_TraceEvent_VL2_CREDENTIAL_REJECTED ev;
ev.evSize = CONST_TO_BE_UINT16(sizeof(ev));
ev.evType = CONST_TO_BE_UINT16(ZT_TRACE_VL2_NETWORK_FILTER);
ev.networkId = Utils::hton(networkId);
ev.address = Utils::hton(address.toInt());
ev.credentialId = Utils::hton(credentialId);
ev.credentialTimestamp = Utils::hton(credentialTimestamp);
ev.credentialType = credentialType;
ev.reason = (uint8_t)reason;
RR->node->postEvent(tPtr,ZT_EVENT_TRACE,&ev);
}
} // namespace ZeroTier

View file

@ -14,29 +14,26 @@
#ifndef ZT_TRACE_HPP
#define ZT_TRACE_HPP
#include <cstdio>
#include <cstdint>
#include <cstring>
#include <cstdlib>
#include <vector>
#include "Constants.hpp"
#include "SharedPtr.hpp"
#include "Packet.hpp"
#include "Credential.hpp"
#include "InetAddress.hpp"
#include "Dictionary.hpp"
#include "Mutex.hpp"
#include "Hashtable.hpp"
#include "Packet.hpp"
#include "InetAddress.hpp"
#include "Address.hpp"
#include "MAC.hpp"
namespace ZeroTier {
class RuntimeEnvironment;
class Address;
class Identity;
class Peer;
class Path;
class Network;
class MAC;
class CertificateOfMembership;
class CertificateOfOwnership;
class Revocation;
@ -50,117 +47,265 @@ struct NetworkConfig;
class Trace
{
public:
class RuleResultLog
struct RuleResultLog
{
public:
ZT_ALWAYS_INLINE RuleResultLog() { this->clear(); }
uint8_t l[ZT_MAX_NETWORK_RULES / 2]; // ZT_MAX_NETWORK_RULES 4-bit fields
ZT_ALWAYS_INLINE void log(const unsigned int rn,const uint8_t thisRuleMatches,const uint8_t thisSetMatches) { _l[rn >> 1U] |= ( ((thisRuleMatches + 1U) << 2U) | (thisSetMatches + 1U) ) << ((rn & 1U) << 2U); }
ZT_ALWAYS_INLINE void logSkipped(const unsigned int rn,const uint8_t thisSetMatches) { _l[rn >> 1U] |= (thisSetMatches + 1U) << ((rn & 1U) << 2U); }
ZT_ALWAYS_INLINE void clear() { memset(_l,0,sizeof(_l)); }
ZT_ALWAYS_INLINE const uint8_t *data() const { return _l; }
ZT_ALWAYS_INLINE unsigned int sizeBytes() const { return (ZT_MAX_NETWORK_RULES / 2); }
private:
uint8_t _l[ZT_MAX_NETWORK_RULES / 2];
ZT_ALWAYS_INLINE void log(const unsigned int rn,const uint8_t thisRuleMatches,const uint8_t thisSetMatches)
{
l[rn >> 1U] |= ( ((thisRuleMatches + 1U) << 2U) | (thisSetMatches + 1U) ) << ((rn & 1U) << 2U);
}
ZT_ALWAYS_INLINE void logSkipped(const unsigned int rn,const uint8_t thisSetMatches)
{
l[rn >> 1U] |= (thisSetMatches + 1U) << ((rn & 1U) << 2U);
}
ZT_ALWAYS_INLINE void clear()
{
memset(l,0,sizeof(l));
}
};
inline Trace(const RuntimeEnvironment *renv)
{
}
explicit Trace(const RuntimeEnvironment *renv);
inline void resettingPathsInScope(void *const tPtr,const Address &reporter,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,const InetAddress::IpScope scope)
{
}
inline void peerConfirmingUnknownPath(void *const tPtr,const uint64_t networkId,Peer &peer,const SharedPtr<Path> &path,const uint64_t packetId,const Packet::Verb verb)
{
}
inline void peerLinkNowRedundant(void *const tPtr,Peer &peer)
{
}
inline void peerLinkNoLongerRedundant(void *const tPtr,Peer &peer)
{
}
inline void peerLinkAggregateStatistics(void *const tPtr,Peer &peer)
{
}
inline void peerLearnedNewPath(void *const tPtr,const uint64_t networkId,Peer &peer,const SharedPtr<Path> &newPath,const uint64_t packetId)
{
}
inline void incomingPacketMessageAuthenticationFailure(void *const tPtr,const SharedPtr<Path> &path,const uint64_t packetId,const Address &source,const unsigned int hops,const char *reason)
{
}
inline void incomingPacketInvalid(void *const tPtr,const SharedPtr<Path> &path,const uint64_t packetId,const Address &source,const unsigned int hops,const Packet::Verb verb,const char *reason)
{
}
inline void incomingPacketDroppedHELLO(void *const tPtr,const SharedPtr<Path> &path,const uint64_t packetId,const Address &source,const char *reason)
{
}
inline 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)
{
}
inline 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)
{
}
inline 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)
{
}
inline void networkConfigRequestSent(void *const tPtr,const Network &network,const Address &controller)
{
}
inline void networkFilter(
ZT_ALWAYS_INLINE void resettingPathsInScope(
void *const tPtr,
const Network &network,
const RuleResultLog &primaryRuleSetLog,
const RuleResultLog *const matchingCapabilityRuleSetLog,
const Capability *const matchingCapability,
const Address &ztSource,
const Address &ztDest,
const MAC &macSource,
const MAC &macDest,
const uint8_t *const frameData,
const unsigned int frameLen,
const unsigned int etherType,
const unsigned int vlanId,
const bool noTee,
const bool inbound,
const int accept)
const Identity &reporter,
const InetAddress &from,
const InetAddress &oldExternal,
const InetAddress &newExternal,
const InetAddress::IpScope scope)
{
if (_vl1) _resettingPathsInScope(tPtr,reporter,from,oldExternal,newExternal,scope);
}
inline void credentialRejected(void *const tPtr,const CertificateOfMembership &c,const char *reason)
ZT_ALWAYS_INLINE void tryingNewPath(
void *const tPtr,
const Identity &trying,
const InetAddress &physicalAddress,
const InetAddress &triggerAddress,
uint64_t triggeringPacketId,
uint8_t triggeringPacketVerb,
uint64_t triggeredByAddress,
const uint8_t *triggeredByIdentityHash,
ZT_TraceTryingNewPathReason reason)
{
if (_vl1) _tryingNewPath(tPtr,trying,physicalAddress,triggerAddress,triggeringPacketId,triggeringPacketVerb,triggeredByAddress,triggeredByIdentityHash,reason);
}
inline void credentialRejected(void *const tPtr,const CertificateOfOwnership &c,const char *reason)
ZT_ALWAYS_INLINE void learnedNewPath(
void *const tPtr,
uint64_t packetId,
const Identity &peerIdentity,
const InetAddress &physicalAddress,
const InetAddress &replaced)
{
if (_vl1) _learnedNewPath(tPtr,packetId,peerIdentity,physicalAddress,replaced);
}
inline void credentialRejected(void *const tPtr,const Capability &c,const char *reason)
ZT_ALWAYS_INLINE void incomingPacketDropped(
void *const tPtr,
uint64_t packetId,
uint64_t networkId,
const Identity &peerIdentity,
const InetAddress &physicalAddress,
uint8_t hops,
uint8_t verb,
const ZT_TracePacketDropReason reason)
{
if (_vl1) _incomingPacketDropped(tPtr,packetId,networkId,peerIdentity,physicalAddress,hops,verb,reason);
}
inline void credentialRejected(void *const tPtr,const Tag &c,const char *reason)
ZT_ALWAYS_INLINE void outgoingNetworkFrameDropped(
void *const tPtr,
uint64_t networkId,
const MAC &sourceMac,
const MAC &destMac,
uint16_t etherType,
uint16_t frameLength,
const uint8_t *frameData,
ZT_TraceFrameDropReason reason)
{
if (_vl2) _outgoingNetworkFrameDropped(tPtr,networkId,sourceMac,destMac,etherType,frameLength,frameData,reason);
}
inline void credentialRejected(void *const tPtr,const Revocation &c,const char *reason)
ZT_ALWAYS_INLINE void incomingNetworkFrameDropped(
void *const tPtr,
uint64_t networkId,
const MAC &sourceMac,
const MAC &destMac,
const Identity &peerIdentity,
const InetAddress &physicalAddress,
uint8_t hops,
uint16_t frameLength,
const uint8_t *frameData,
uint8_t verb,
bool credentialRequestSent,
ZT_TraceFrameDropReason reason)
{
if (_vl2) _incomingNetworkFrameDropped(tPtr,networkId,sourceMac,destMac,peerIdentity,physicalAddress,hops,frameLength,frameData,verb,credentialRequestSent,reason);
}
ZT_ALWAYS_INLINE void networkConfigRequestSent(
void *const tPtr,
uint64_t networkId)
{
if (_vl2) _networkConfigRequestSent(tPtr,networkId);
}
ZT_ALWAYS_INLINE void networkFilter(
void *const tPtr,
uint64_t networkId,
const uint8_t primaryRuleSetLog[512],
const uint8_t matchingCapabilityRuleSetLog[512],
uint32_t matchingCapabilityId,
int64_t matchingCapabilityTimestamp,
const Address &source,
const Address &dest,
const MAC &sourceMac,
const MAC &destMac,
uint16_t frameLength,
const uint8_t *frameData,
uint16_t etherType,
uint16_t vlanId,
bool noTee,
bool inbound,
int accept)
{
if (_vl2Filter) {
_networkFilter(
tPtr,
networkId,
primaryRuleSetLog,
matchingCapabilityRuleSetLog,
matchingCapabilityId,
matchingCapabilityTimestamp,
source,
dest,
sourceMac,
destMac,
frameLength,
frameData,
etherType,
vlanId,
noTee,
inbound,
accept);
}
}
ZT_ALWAYS_INLINE void credentialRejected(
void *const tPtr,
uint64_t networkId,
const Address &address,
uint32_t credentialId,
int64_t credentialTimestamp,
uint8_t credentialType,
ZT_TraceCredentialRejectionReason reason)
{
if (_vl2) _credentialRejected(tPtr,networkId,address,credentialId,credentialTimestamp,credentialType,reason);
}
private:
void _resettingPathsInScope(
void *tPtr,
const Identity &reporter,
const InetAddress &from,
const InetAddress &oldExternal,
const InetAddress &newExternal,
InetAddress::IpScope scope);
void _tryingNewPath(
void *tPtr,
const Identity &trying,
const InetAddress &physicalAddress,
const InetAddress &triggerAddress,
uint64_t triggeringPacketId,
uint8_t triggeringPacketVerb,
uint64_t triggeredByAddress,
const uint8_t *triggeredByIdentityHash,
ZT_TraceTryingNewPathReason reason);
void _learnedNewPath(
void *tPtr,
uint64_t packetId,
const Identity &peerIdentity,
const InetAddress &physicalAddress,
const InetAddress &replaced);
void _incomingPacketDropped(
void *tPtr,
uint64_t packetId,
uint64_t networkId,
const Identity &peerIdentity,
const InetAddress &physicalAddress,
uint8_t hops,
uint8_t verb,
ZT_TracePacketDropReason reason);
void _outgoingNetworkFrameDropped(
void *tPtr,
uint64_t networkId,
const MAC &sourceMac,
const MAC &destMac,
uint16_t etherType,
uint16_t frameLength,
const uint8_t *frameData,
ZT_TraceFrameDropReason reason);
void _incomingNetworkFrameDropped(
void *const tPtr,
uint64_t networkId,
const MAC &sourceMac,
const MAC &destMac,
const Identity &peerIdentity,
const InetAddress &physicalAddress,
uint8_t hops,
uint16_t frameLength,
const uint8_t *frameData,
uint8_t verb,
bool credentialRequestSent,
ZT_TraceFrameDropReason reason);
void _networkConfigRequestSent(
void *tPtr,
uint64_t networkId);
void _networkFilter(
void *tPtr,
uint64_t networkId,
const uint8_t primaryRuleSetLog[512],
const uint8_t matchingCapabilityRuleSetLog[512],
uint32_t matchingCapabilityId,
int64_t matchingCapabilityTimestamp,
const Address &source,
const Address &dest,
const MAC &sourceMac,
const MAC &destMac,
uint16_t frameLength,
const uint8_t *frameData,
uint16_t etherType,
uint16_t vlanId,
bool noTee,
bool inbound,
int accept);
void _credentialRejected(
void *tPtr,
uint64_t networkId,
const Address &address,
uint32_t credentialId,
int64_t credentialTimestamp,
uint8_t credentialType,
ZT_TraceCredentialRejectionReason reason);
const RuntimeEnvironment *const RR;
volatile bool _vl1,_vl2,_vl2Filter,_vl2Multicast;
struct _MonitoringPeer
{
int64_t _timeSet;
unsigned int _traceTypes;
SharedPtr<Peer> peer;
Mutex lock;
};
uint8_t _eventBuf[8192]; // must be less than ZT_PROTO_MAX_PACKET_LENGTH
unsigned int _eventBufSize;
std::vector<_MonitoringPeer> _monitoringPeers;
RWMutex _monitoringPeers_l;
};
} // namespace ZeroTier

View file

@ -331,7 +331,7 @@ uint64_t random()
l.lock();
const uint64_t result = ROL64(s1 * 5,7) * 9;
const uint64_t t = s1 << 17;
const uint64_t t = s1 << 17U;
s2 ^= s0;
s3 ^= s1;
s1 ^= s2;

View file

@ -395,7 +395,7 @@ static ZT_ALWAYS_INLINE T ntoh(T n) { return n; }
template<typename I>
static ZT_ALWAYS_INLINE I loadBigEndian(const void *const p)
{
#ifdef ZT_NO_TYPE_PUNNING
#ifdef ZT_NO_UNALIGNED_ACCESS
I x = (I)0;
for(unsigned int k=0;k<sizeof(I);++k) {
#if __BYTE_ORDER == __LITTLE_ENDIAN
@ -413,7 +413,7 @@ static ZT_ALWAYS_INLINE I loadBigEndian(const void *const p)
template<typename I>
static ZT_ALWAYS_INLINE void storeBigEndian(void *const p,const I i)
{
#ifdef ZT_NO_TYPE_PUNNING
#ifdef ZT_NO_UNALIGNED_ACCESS
for(unsigned int k=0;k<sizeof(I);++k) {
#if __BYTE_ORDER == __LITTLE_ENDIAN
reinterpret_cast<uint8_t *>(p)[k] = reinterpret_cast<const uint8_t *>(&i)[(sizeof(I)-1)-k];
@ -422,7 +422,7 @@ static ZT_ALWAYS_INLINE void storeBigEndian(void *const p,const I i)
#endif
}
#else
*reinterpret_cast<I *>(p) = Utils::hton(i);
*reinterpret_cast<I *>(p) = hton(i);
#endif
}

View file

@ -24,6 +24,10 @@
#include <fcntl.h>
#endif
#ifdef __GCC__
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
namespace ZeroTier {
unsigned int OSUtils::ztsnprintf(char *buf,unsigned int len,const char *fmt,...)

View file

@ -203,7 +203,7 @@ public:
* @param quot Zero or more quote characters
* @return Vector of tokens
*/
static std::vector<std::string> split(const char *s,const char *const sep,const char *esc,const char *quot);
static std::vector<std::string> split(const char *s,const char *sep,const char *esc,const char *quot);
/**
* Write a block of data to disk, replacing any current file contents
@ -222,9 +222,9 @@ public:
#ifndef OMIT_JSON_SUPPORT
static nlohmann::json jsonParse(const std::string &buf);
static std::string jsonDump(const nlohmann::json &j,int indentation = 1);
static uint64_t jsonInt(const nlohmann::json &jv,const uint64_t dfl);
static uint64_t jsonIntHex(const nlohmann::json &jv,const uint64_t dfl);
static bool jsonBool(const nlohmann::json &jv,const bool dfl);
static uint64_t jsonInt(const nlohmann::json &jv,uint64_t dfl);
static uint64_t jsonIntHex(const nlohmann::json &jv,uint64_t dfl);
static bool jsonBool(const nlohmann::json &jv,bool dfl);
static std::string jsonString(const nlohmann::json &jv,const char *dfl);
#endif // OMIT_JSON_SUPPORT
};