diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/ZeroTierOne.h | 427 |
1 files changed, 314 insertions, 113 deletions
diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index 341bb767..377af63f 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -129,6 +129,21 @@ extern "C" { #define ZT_CIRCUIT_TEST_MAX_HOP_BREADTH 256 /** + * Maximum number of cluster members (and max member ID plus one) + */ +#define ZT_CLUSTER_MAX_MEMBERS 128 + +/** + * Maximum number of physical ZeroTier addresses a cluster member can report + */ +#define ZT_CLUSTER_MAX_ZT_PHYSICAL_ADDRESSES 16 + +/** + * Maximum allowed cluster message length in bytes + */ +#define ZT_CLUSTER_MAX_MESSAGE_LENGTH (1500 - 48) + +/** * A null/empty sockaddr (all zero) to signify an unspecified socket address */ extern const struct sockaddr_storage ZT_SOCKADDR_NULL; @@ -174,7 +189,17 @@ enum ZT_ResultCode /** * Network ID not valid */ - ZT_RESULT_ERROR_NETWORK_NOT_FOUND = 1000 + ZT_RESULT_ERROR_NETWORK_NOT_FOUND = 1000, + + /** + * The requested operation is not supported on this version or build + */ + ZT_RESULT_ERROR_UNSUPPORTED_OPERATION = 1001, + + /** + * The requestion operation was given a bad parameter or was called in an invalid state + */ + ZT_RESULT_ERROR_BAD_PARAMETER = 1002 }; /** @@ -256,38 +281,13 @@ enum ZT_Event ZT_EVENT_FATAL_ERROR_IDENTITY_COLLISION = 4, /** - * A more recent version was observed on the network - * - * Right now this is only triggered if a hub or rootserver reports a - * more recent version, and only once. It can be used to trigger a - * software update check. - * - * Meta-data: unsigned int[3], more recent version number - */ - ZT_EVENT_SAW_MORE_RECENT_VERSION = 5, - - /** - * A packet failed authentication - * - * Meta-data: struct sockaddr_storage containing origin address of packet - */ - ZT_EVENT_AUTHENTICATION_FAILURE = 6, - - /** - * A received packet was not valid - * - * Meta-data: struct sockaddr_storage containing origin address of packet - */ - ZT_EVENT_INVALID_PACKET = 7, - - /** * Trace (debugging) message * * These events are only generated if this is a TRACE-enabled build. * * Meta-data: C string, TRACE message */ - ZT_EVENT_TRACE = 8 + ZT_EVENT_TRACE = 5 }; /** @@ -301,6 +301,16 @@ typedef struct uint64_t address; /** + * Current world ID + */ + uint64_t worldId; + + /** + * Current world revision/timestamp + */ + uint64_t worldTimestamp; + + /** * Public identity in string-serialized form (safe to send to others) * * This pointer will remain valid as long as the node exists. @@ -415,6 +425,59 @@ enum ZT_VirtualNetworkConfigOperation }; /** + * What trust hierarchy role does this peer have? + */ +enum ZT_PeerRole { + ZT_PEER_ROLE_LEAF = 0, // ordinary node + ZT_PEER_ROLE_RELAY = 1, // relay node + ZT_PEER_ROLE_ROOT = 2 // root server +}; + +/** + * Vendor ID + */ +enum ZT_Vendor { + ZT_VENDOR_UNSPECIFIED = 0, + ZT_VENDOR_ZEROTIER = 1 +}; + +/** + * Platform type + */ +enum ZT_Platform { + ZT_PLATFORM_UNSPECIFIED = 0, + ZT_PLATFORM_LINUX = 1, + ZT_PLATFORM_WINDOWS = 2, + ZT_PLATFORM_MACOS = 3, + ZT_PLATFORM_ANDROID = 4, + ZT_PLATFORM_IOS = 5, + ZT_PLATFORM_SOLARIS_SMARTOS = 6, + ZT_PLATFORM_FREEBSD = 7, + ZT_PLATFORM_NETBSD = 8, + ZT_PLATFORM_OPENBSD = 9, + ZT_PLATFORM_RISCOS = 10, + ZT_PLATFORM_VXWORKS = 11, + ZT_PLATFORM_FREERTOS = 12, + ZT_PLATFORM_SYSBIOS = 13, + ZT_PLATFORM_HURD = 14 +}; + +/** + * Architecture type + */ +enum ZT_Architecture { + ZT_ARCHITECTURE_UNSPECIFIED = 0, + ZT_ARCHITECTURE_X86 = 1, + ZT_ARCHITECTURE_X64 = 2, + ZT_ARCHITECTURE_ARM32 = 3, + ZT_ARCHITECTURE_ARM64 = 4, + ZT_ARCHITECTURE_MIPS32 = 5, + ZT_ARCHITECTURE_MIPS64 = 6, + ZT_ARCHITECTURE_POWER32 = 7, + ZT_ARCHITECTURE_POWER64 = 8 +}; + +/** * Virtual network configuration */ typedef struct @@ -546,11 +609,6 @@ typedef struct uint64_t lastReceive; /** - * Is path fixed? (i.e. not learned, static) - */ - int fixed; - - /** * Is path active? */ int active; @@ -562,15 +620,6 @@ typedef struct } ZT_PeerPhysicalPath; /** - * What trust hierarchy role does this peer have? - */ -enum ZT_PeerRole { - ZT_PEER_ROLE_LEAF = 0, // ordinary node - ZT_PEER_ROLE_RELAY = 1, // relay node - ZT_PEER_ROLE_ROOT = 2 // root server -}; - -/** * Peer status result buffer */ typedef struct @@ -636,59 +685,6 @@ typedef struct } ZT_PeerList; /** - * Local interface trust levels - */ -typedef enum { - ZT_LOCAL_INTERFACE_ADDRESS_TRUST_NORMAL = 0, - ZT_LOCAL_INTERFACE_ADDRESS_TRUST_PRIVACY = 10, - ZT_LOCAL_INTERFACE_ADDRESS_TRUST_ULTIMATE = 20 -} ZT_LocalInterfaceAddressTrust; - -/** - * Vendor ID - */ -typedef enum { - ZT_VENDOR_UNSPECIFIED = 0, - ZT_VENDOR_ZEROTIER = 1 -} ZT_Vendor; - -/** - * Platform type - */ -typedef enum { - ZT_PLATFORM_UNSPECIFIED = 0, - ZT_PLATFORM_LINUX = 1, - ZT_PLATFORM_WINDOWS = 2, - ZT_PLATFORM_MACOS = 3, - ZT_PLATFORM_ANDROID = 4, - ZT_PLATFORM_IOS = 5, - ZT_PLATFORM_SOLARIS_SMARTOS = 6, - ZT_PLATFORM_FREEBSD = 7, - ZT_PLATFORM_NETBSD = 8, - ZT_PLATFORM_OPENBSD = 9, - ZT_PLATFORM_RISCOS = 10, - ZT_PLATFORM_VXWORKS = 11, - ZT_PLATFORM_FREERTOS = 12, - ZT_PLATFORM_SYSBIOS = 13, - ZT_PLATFORM_HURD = 14 -} ZT_Platform; - -/** - * Architecture type - */ -typedef enum { - ZT_ARCHITECTURE_UNSPECIFIED = 0, - ZT_ARCHITECTURE_X86 = 1, - ZT_ARCHITECTURE_X64 = 2, - ZT_ARCHITECTURE_ARM32 = 3, - ZT_ARCHITECTURE_ARM64 = 4, - ZT_ARCHITECTURE_MIPS32 = 5, - ZT_ARCHITECTURE_MIPS64 = 6, - ZT_ARCHITECTURE_POWER32 = 7, - ZT_ARCHITECTURE_POWER64 = 8 -} ZT_Architecture; - -/** * ZeroTier circuit test configuration and path */ typedef struct { @@ -758,9 +754,14 @@ typedef struct { */ typedef struct { /** - * Sender of report + * Sender of report (current hop) */ - uint64_t address; + uint64_t current; + + /** + * Previous hop + */ + uint64_t upstream; /** * 64-bit test ID @@ -800,7 +801,7 @@ typedef struct { /** * Remote device vendor ID */ - ZT_Vendor vendor; + enum ZT_Vendor vendor; /** * Remote device protocol compliance version @@ -825,12 +826,12 @@ typedef struct { /** * Platform / OS */ - ZT_Platform platform; + enum ZT_Platform platform; /** * System architecture */ - ZT_Architecture architecture; + enum ZT_Architecture architecture; /** * Local device address on which packet was received by reporting device @@ -875,6 +876,78 @@ typedef struct { } ZT_CircuitTestReport; /** + * A cluster member's status + */ +typedef struct { + /** + * This cluster member's ID (from 0 to 1-ZT_CLUSTER_MAX_MEMBERS) + */ + unsigned int id; + + /** + * Number of milliseconds since last 'alive' heartbeat message received via cluster backplane address + */ + unsigned int msSinceLastHeartbeat; + + /** + * Non-zero if cluster member is alive + */ + int alive; + + /** + * X, Y, and Z coordinates of this member (if specified, otherwise zero) + * + * What these mean depends on the location scheme being used for + * location-aware clustering. At present this is GeoIP and these + * will be the X, Y, and Z coordinates of the location on a spherical + * approximation of Earth where Earth's core is the origin (in km). + * They don't have to be perfect and need only be comparable with others + * to find shortest path via the standard vector distance formula. + */ + int x,y,z; + + /** + * Cluster member's last reported load + */ + uint64_t load; + + /** + * Number of peers + */ + uint64_t peers; + + /** + * Physical ZeroTier endpoints for this member (where peers are sent when directed here) + */ + struct sockaddr_storage zeroTierPhysicalEndpoints[ZT_CLUSTER_MAX_ZT_PHYSICAL_ADDRESSES]; + + /** + * Number of physical ZeroTier endpoints this member is announcing + */ + unsigned int numZeroTierPhysicalEndpoints; +} ZT_ClusterMemberStatus; + +/** + * ZeroTier cluster status + */ +typedef struct { + /** + * My cluster member ID (a record for 'self' is included in member[]) + */ + unsigned int myId; + + /** + * Number of cluster members + */ + unsigned int clusterSize; + + /** + * Cluster member statuses + */ + ZT_ClusterMemberStatus members[ZT_CLUSTER_MAX_MEMBERS]; +} ZT_ClusterStatus; + +/** * An instance of a ZeroTier One node (opaque) */ typedef void ZT_Node; @@ -1007,6 +1080,7 @@ typedef int (*ZT_DataStorePutFunction)( * (4) Remote address * (5) Packet data * (6) Packet length + * (7) Desired IP TTL or 0 to use default * * If there is only one local interface it is safe to ignore the local * interface address. Otherwise if running with multiple interfaces, the @@ -1014,17 +1088,22 @@ typedef int (*ZT_DataStorePutFunction)( * the ss_family field is zero (NULL address), a random or preferred * default interface should be used. * + * If TTL is nonzero, packets should have their IP TTL value set to this + * value if possible. If this is not possible it is acceptable to ignore + * this value and send anyway with normal or default TTL. + * * The function must return zero on success and may return any error code * on failure. Note that success does not (of course) guarantee packet * delivery. It only means that the packet appears to have been sent. */ typedef int (*ZT_WirePacketSendFunction)( - ZT_Node *, /* Node */ + ZT_Node *, /* Node */ void *, /* User ptr */ const struct sockaddr_storage *, /* Local address */ const struct sockaddr_storage *, /* Remote address */ const void *, /* Packet data */ - unsigned int); /* Packet length */ + unsigned int, /* Packet length */ + unsigned int); /* TTL or 0 to use default */ /****************************************************************************/ /* C Node API */ @@ -1043,7 +1122,6 @@ typedef int (*ZT_WirePacketSendFunction)( * @param dataStorePutFunction Function called to put objects in persistent storage * @param virtualNetworkConfigFunction Function to be called when virtual LANs are created, deleted, or their config parameters change * @param eventCallback Function to receive status updates and non-fatal error notices - * @param overrideRootTopology Alternative root server topology or NULL for default (mostly for test/debug use) * @return OK (0) or error code if a fatal error condition has occurred */ enum ZT_ResultCode ZT_Node_new( @@ -1055,8 +1133,7 @@ enum ZT_ResultCode ZT_Node_new( ZT_WirePacketSendFunction wirePacketSendFunction, ZT_VirtualNetworkFrameFunction virtualNetworkFrameFunction, ZT_VirtualNetworkConfigFunction virtualNetworkConfigFunction, - ZT_EventCallback eventCallback, - const char *overrideRootTopology); + ZT_EventCallback eventCallback); /** * Delete a node and free all resources it consumes @@ -1257,11 +1334,6 @@ void ZT_Node_freeQueryResult(ZT_Node *node,void *qr); /** * Add a local interface address * - * Local interface addresses may be added if you want remote peers - * with whom you have a trust relatinship (e.g. common network membership) - * to receive information about these endpoints as potential endpoints for - * direct communication. - * * Take care that these are never ZeroTier interface addresses, otherwise * strange things might happen or they simply won't work. * @@ -1276,11 +1348,9 @@ void ZT_Node_freeQueryResult(ZT_Node *node,void *qr); * reject bad, empty, and unusable addresses. * * @param addr Local interface address - * @param metric Local interface metric - * @param trust How much do you trust the local network under this interface? * @return Boolean: non-zero if address was accepted and added */ -int ZT_Node_addLocalInterfaceAddress(ZT_Node *node,const struct sockaddr_storage *addr,int metric,ZT_LocalInterfaceAddressTrust trust); +int ZT_Node_addLocalInterfaceAddress(ZT_Node *node,const struct sockaddr_storage *addr); /** * Clear local interface addresses @@ -1321,7 +1391,7 @@ void ZT_Node_setNetconfMaster(ZT_Node *node,void *networkConfigMasterInstance); * @param reportCallback Function to call each time a report is received * @return OK or error if, for example, test is too big for a packet or support isn't compiled in */ -ZT_ResultCode ZT_Node_circuitTestBegin(ZT_Node *node,ZT_CircuitTest *test,void (*reportCallback)(ZT_Node *,ZT_CircuitTest *,const ZT_CircuitTestReport *)); +enum ZT_ResultCode ZT_Node_circuitTestBegin(ZT_Node *node,ZT_CircuitTest *test,void (*reportCallback)(ZT_Node *, ZT_CircuitTest *,const ZT_CircuitTestReport *)); /** * Stop listening for results to a given circuit test @@ -1338,6 +1408,137 @@ ZT_ResultCode ZT_Node_circuitTestBegin(ZT_Node *node,ZT_CircuitTest *test,void ( void ZT_Node_circuitTestEnd(ZT_Node *node,ZT_CircuitTest *test); /** + * Initialize cluster operation + * + * This initializes the internal structures and state for cluster operation. + * It takes two function pointers. The first is to a function that can be + * used to send data to cluster peers (mechanism is not defined by Node), + * and the second is to a function that can be used to get the location of + * a physical address in X,Y,Z coordinate space (e.g. as cartesian coordinates + * projected from the center of the Earth). + * + * Send function takes an arbitrary pointer followed by the cluster member ID + * to send data to, a pointer to the data, and the length of the data. The + * maximum message length is ZT_CLUSTER_MAX_MESSAGE_LENGTH (65535). Messages + * must be delivered whole and may be dropped or transposed, though high + * failure rates are undesirable and can cause problems. Validity checking or + * CRC is also not required since the Node validates the authenticity of + * cluster messages using cryptogrphic methods and will silently drop invalid + * messages. + * + * Address to location function is optional and if NULL geo-handoff is not + * enabled (in this case x, y, and z in clusterInit are also unused). It + * takes an arbitrary pointer followed by a physical address and three result + * parameters for x, y, and z. It returns zero on failure or nonzero if these + * three coordinates have been set. Coordinate space is arbitrary and can be + * e.g. coordinates on Earth relative to Earth's center. These can be obtained + * from latitutde and longitude with versions of the Haversine formula. + * + * See: http://stackoverflow.com/questions/1185408/converting-from-longitude-latitude-to-cartesian-coordinates + * + * Neither the send nor the address to location function should block. If the + * address to location function does not have a location for an address, it + * should return zero and then look up the address for future use since it + * will be called again in (typically) 1-3 minutes. + * + * Note that both functions can be called from any thread from which the + * various Node functions are called, and so must be thread safe if multiple + * threads are being used. + * + * @param node Node instance + * @param myId My cluster member ID (less than or equal to ZT_CLUSTER_MAX_MEMBERS) + * @param zeroTierPhysicalEndpoints Preferred physical address(es) for ZeroTier clients to contact this cluster member (for peer redirect) + * @param numZeroTierPhysicalEndpoints Number of physical endpoints in zeroTierPhysicalEndpoints[] (max allowed: 255) + * @param x My cluster member's X location + * @param y My cluster member's Y location + * @param z My cluster member's Z location + * @param sendFunction Function to be called to send data to other cluster members + * @param sendFunctionArg First argument to sendFunction() + * @param addressToLocationFunction Function to be called to get the location of a physical address or NULL to disable geo-handoff + * @param addressToLocationFunctionArg First argument to addressToLocationFunction() + * @return OK or UNSUPPORTED_OPERATION if this Node was not built with cluster support + */ +enum ZT_ResultCode ZT_Node_clusterInit( + ZT_Node *node, + unsigned int myId, + const struct sockaddr_storage *zeroTierPhysicalEndpoints, + unsigned int numZeroTierPhysicalEndpoints, + int x, + int y, + int z, + void (*sendFunction)(void *,unsigned int,const void *,unsigned int), + void *sendFunctionArg, + int (*addressToLocationFunction)(void *,const struct sockaddr_storage *,int *,int *,int *), + void *addressToLocationFunctionArg); + +/** + * Add a member to this cluster + * + * Calling this without having called clusterInit() will do nothing. + * + * @param node Node instance + * @param memberId Member ID (must be less than or equal to ZT_CLUSTER_MAX_MEMBERS) + * @return OK or error if clustering is disabled, ID invalid, etc. + */ +enum ZT_ResultCode ZT_Node_clusterAddMember(ZT_Node *node,unsigned int memberId); + +/** + * Remove a member from this cluster + * + * Calling this without having called clusterInit() will do nothing. + * + * @param node Node instance + * @param memberId Member ID to remove (nothing happens if not present) + */ +void ZT_Node_clusterRemoveMember(ZT_Node *node,unsigned int memberId); + +/** + * Handle an incoming cluster state message + * + * The message itself contains cluster member IDs, and invalid or badly + * addressed messages will be silently discarded. + * + * Calling this without having called clusterInit() will do nothing. + * + * @param node Node instance + * @param msg Cluster message + * @param len Length of cluster message + */ +void ZT_Node_clusterHandleIncomingMessage(ZT_Node *node,const void *msg,unsigned int len); + +/** + * Get the current status of the cluster from this node's point of view + * + * Calling this without clusterInit() or without cluster support will just + * zero out the structure and show a cluster size of zero. + * + * @param node Node instance + * @param cs Cluster status structure to fill with data + */ +void ZT_Node_clusterStatus(ZT_Node *node,ZT_ClusterStatus *cs); + +/** + * Do things in the background until Node dies + * + * This function can be called from one or more background threads to process + * certain tasks in the background to improve foreground performance. It will + * not return until the Node is shut down. If threading is not enabled in + * this build it will return immediately and will do nothing. + * + * This is completely optional. If this is never called, all processing is + * done in the foreground in the various processXXXX() methods. + * + * This does NOT replace or eliminate the need to call the normal + * processBackgroundTasks() function in your main loop. This mechanism is + * used to offload the processing of expensive mssages onto background + * handler threads to prevent foreground performance degradation under + * high load. + * + * @param node Node instance + */ +void ZT_Node_backgroundThreadMain(ZT_Node *node); + +/** * Get ZeroTier One version * * @param major Result: major version |