diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/ZeroTierOne.h | 419 |
1 files changed, 155 insertions, 264 deletions
diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index 5126c5a2..9c295cee 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -140,39 +140,6 @@ extern "C" { #define ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH 7 /** - * Maximum number of hops in a ZeroTier circuit test - * - * This is more or less the max that can be fit in a given packet (with - * fragmentation) and only one address per hop. - */ -#define ZT_CIRCUIT_TEST_MAX_HOPS 256 - -/** - * Maximum number of addresses per hop in a circuit test - */ -#define ZT_CIRCUIT_TEST_MAX_HOP_BREADTH 8 - -/** - * Circuit test report flag: upstream peer authorized in path (e.g. by network COM) - */ -#define ZT_CIRCUIT_TEST_REPORT_FLAGS_UPSTREAM_AUTHORIZED_IN_PATH 0x0000000000000001ULL - -/** - * 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) - -/** * Maximum value for link quality (min is 0) */ #define ZT_PATH_LINK_QUALITY_MAX 0xff @@ -286,22 +253,27 @@ enum ZT_ResultCode */ ZT_RESULT_OK = 0, - // Fatal errors (>0, <1000) + /** + * Call produced no error but no action was taken + */ + ZT_RESULT_OK_IGNORED = 1, + + // Fatal errors (>100, <1000) /** * Ran out of memory */ - ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY = 1, + ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY = 100, /** * Data store is not writable or has failed */ - ZT_RESULT_FATAL_ERROR_DATA_STORE_FAILED = 2, + ZT_RESULT_FATAL_ERROR_DATA_STORE_FAILED = 101, /** * Internal error (e.g. unexpected exception indicating bug or build problem) */ - ZT_RESULT_FATAL_ERROR_INTERNAL = 3, + ZT_RESULT_FATAL_ERROR_INTERNAL = 102, // Non-fatal errors (>1000) @@ -325,7 +297,7 @@ enum ZT_ResultCode * @param x Result code * @return True if result code indicates a fatal error */ -#define ZT_ResultCode_isFatal(x) ((((int)(x)) > 0)&&(((int)(x)) < 1000)) +#define ZT_ResultCode_isFatal(x) ((((int)(x)) >= 100)&&(((int)(x)) < 1000)) /** * Status codes sent to status update callback when things happen @@ -421,6 +393,13 @@ enum ZT_Event /** * User message used with ZT_EVENT_USER_MESSAGE + * + * These are direct VL1 P2P messages for application use. Encryption and + * authentication in the ZeroTier protocol will guarantee the origin + * address and message content, but you are responsible for any other + * levels of authentication or access control that are required. Any node + * in the world can send you a user message! (Unless your network is air + * gapped.) */ typedef struct { @@ -748,24 +727,6 @@ typedef struct } v; } ZT_VirtualNetworkRule; -typedef struct -{ - /** - * 128-bit ID (GUID) of this capability - */ - uint64_t id[2]; - - /** - * Expiration time (measured vs. network config timestamp issued by controller) - */ - uint64_t expiration; - - struct { - uint64_t from; - uint64_t to; - } custody[ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH]; -} ZT_VirtualNetworkCapability; - /** * A route to be pushed on a virtual network */ @@ -1105,76 +1066,98 @@ typedef struct } ZT_PeerList; /** - * A cluster member's status + * ZeroTier core state objects + * + * All of these objects can be persisted if desired. To preserve the + * identity of a node and its address, the identity (public and secret) + * must be saved at a minimum. + * + * The reference service implementation currently persists identity, + * peer identities (for a period of time), planet, moons, and network + * configurations. Other state is treated as ephemeral. + * + * All state objects should be replicated in cluster mode. The reference + * clustering implementation uses a rumor mill algorithm in which state + * updates that are accepted with RESULT_OK (but not RESULT_OK_IGNORED) + * are flooded to all connected cluster peers. This results in updates + * being flooded across the cluster until all cluster members have the + * latest. */ -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; - +enum ZT_StateObjectType +{ /** - * Non-zero if cluster member is alive + * Null object -- ignored */ - int alive; + ZT_STATE_OBJECT_NULL = 0, /** - * X, Y, and Z coordinates of this member (if specified, otherwise zero) + * Public address and public key * - * 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. + * Object ID: this node's address if known, or 0 if unknown (first query) + * Canonical path: <HOME>/identity.public + * Persistence: required */ - int x,y,z; + ZT_STATE_OBJECT_IDENTITY_PUBLIC = 1, /** - * Cluster member's last reported load + * Full identity with secret key + * + * Object ID: this node's address if known, or 0 if unknown (first query) + * Canonical path: <HOME>/identity.secret + * Persistence: required, should be stored with restricted permissions e.g. mode 0600 on *nix */ - uint64_t load; + ZT_STATE_OBJECT_IDENTITY_SECRET = 2, /** - * Number of peers + * A peer to which this node is communicating + * + * Object ID: peer address + * Canonical path: <HOME>/peers.d/<ADDRESS> (10-digit hex address) + * Persistence: optional, can be purged at any time */ - uint64_t peers; + ZT_STATE_OBJECT_PEER = 3, /** - * Physical ZeroTier endpoints for this member (where peers are sent when directed here) + * The identity of a known peer + * + * Object ID: peer address + * Canonical path: <HOME>/iddb.d/<ADDRESS> (10-digit hex address) + * Persistence: optional, can be purged at any time, recommended ttl 30-60 days */ - struct sockaddr_storage zeroTierPhysicalEndpoints[ZT_CLUSTER_MAX_ZT_PHYSICAL_ADDRESSES]; + ZT_STATE_OBJECT_PEER_IDENTITY = 4, /** - * Number of physical ZeroTier endpoints this member is announcing + * Network configuration + * + * Object ID: peer address + * Canonical path: <HOME>/networks.d/<NETWORKID>.conf (16-digit hex ID) + * Persistence: required if network memberships should persist */ - unsigned int numZeroTierPhysicalEndpoints; -} ZT_ClusterMemberStatus; + ZT_STATE_OBJECT_NETWORK_CONFIG = 5, -/** - * ZeroTier cluster status - */ -typedef struct { /** - * My cluster member ID (a record for 'self' is included in member[]) + * The planet (there is only one per... well... planet!) + * + * Object ID: world ID of planet, or 0 if unknown (first query) + * Canonical path: <HOME>/planet + * Persistence: recommended */ - unsigned int myId; + ZT_STATE_OBJECT_PLANET = 6, /** - * Number of cluster members + * A moon (federated root set) + * + * Object ID: world ID of moon + * Canonical path: <HOME>/moons.d/<ID>.moon (16-digit hex ID) + * Persistence: required if moon memberships should persist */ - unsigned int clusterSize; + ZT_STATE_OBJECT_MOON = 7, /** - * Cluster member statuses + * IDs above this value will not be used by the core (and could be used as implementation-specific IDs) */ - ZT_ClusterMemberStatus members[ZT_CLUSTER_MAX_MEMBERS]; -} ZT_ClusterStatus; + ZT_STATE_OBJECT__MAX_ID = 255 +}; /** * An instance of a ZeroTier One node (opaque) @@ -1252,62 +1235,41 @@ typedef void (*ZT_EventCallback)( const void *); /* Event payload (if applicable) */ /** - * Function to get an object from the data store - * - * Parameters: (1) object name, (2) buffer to fill, (3) size of buffer, (4) - * index in object to start reading, (5) result parameter that must be set - * to the actual size of the object if it exists. + * Callback for storing and/or publishing state information * - * Object names can contain forward slash (/) path separators. They will - * never contain .. or backslash (\), so this is safe to map as a Unix-style - * path if the underlying storage permits. For security reasons we recommend - * returning errors if .. or \ are used. + * See ZT_StateObjectType docs for information about each state object type + * and when and if it needs to be persisted. * - * The function must return the actual number of bytes read. If the object - * doesn't exist, it should return -1. -2 should be returned on other errors - * such as errors accessing underlying storage. - * - * If the read doesn't fit in the buffer, the max number of bytes should be - * read. The caller may call the function multiple times to read the whole - * object. + * An object of length -1 is sent to indicate that an object should be + * deleted. */ -typedef long (*ZT_DataStoreGetFunction)( +typedef void (*ZT_StatePutFunction)( ZT_Node *, /* Node */ void *, /* User ptr */ void *, /* Thread ptr */ - const char *, - void *, - unsigned long, - unsigned long, - unsigned long *); + enum ZT_StateObjectType, /* State object type */ + uint64_t, /* State object ID (if applicable) */ + const void *, /* State object data */ + int); /* Length of data or -1 to delete */ /** - * Function to store an object in the data store - * - * Parameters: (1) node, (2) user ptr, (3) object name, (4) object data, - * (5) object size, (6) secure? (bool). - * - * If secure is true, the file should be set readable and writable only - * to the user running ZeroTier One. What this means is platform-specific. + * Callback for retrieving stored state information * - * Name semantics are the same as the get function. This must return zero on - * success. You can return any OS-specific error code on failure, as these - * may be visible in logs or error messages and might aid in debugging. - * - * If the data pointer is null, this must be interpreted as a delete - * operation. + * This function should return the number of bytes actually stored to the + * buffer or -1 if the state object was not found or the buffer was too + * small to store it. */ -typedef int (*ZT_DataStorePutFunction)( - ZT_Node *, - void *, +typedef int (*ZT_StateGetFunction)( + ZT_Node *, /* Node */ + void *, /* User ptr */ void *, /* Thread ptr */ - const char *, - const void *, - unsigned long, - int); + enum ZT_StateObjectType, /* State object type */ + uint64_t, /* State object ID (if applicable) */ + void *, /* Buffer to store state object data */ + unsigned int); /* Length of data buffer in bytes */ /** - * Function to send a ZeroTier packet out over the wire + * Function to send a ZeroTier packet out over the physical wire (L2/L3) * * Parameters: * (1) Node @@ -1362,9 +1324,6 @@ typedef int (*ZT_WirePacketSendFunction)( * all configured ZeroTier interfaces and check to ensure that the supplied * addresses will not result in ZeroTier traffic being sent over a ZeroTier * interface (recursion). - * - * Obviously this is not required in configurations where this can't happen, - * such as network containers or embedded. */ typedef int (*ZT_PathCheckFunction)( ZT_Node *, /* Node */ @@ -1412,14 +1371,14 @@ struct ZT_Node_Callbacks long version; /** - * REQUIRED: Function to get objects from persistent storage + * REQUIRED: Function to store and/or replicate state objects */ - ZT_DataStoreGetFunction dataStoreGetFunction; + ZT_StatePutFunction statePutFunction; /** - * REQUIRED: Function to store objects in persistent storage + * REQUIRED: Function to retrieve state objects from an object store */ - ZT_DataStorePutFunction dataStorePutFunction; + ZT_StateGetFunction stateGetFunction; /** * REQUIRED: Function to send packets over the physical wire @@ -1453,13 +1412,12 @@ struct ZT_Node_Callbacks }; /** - * Create a new ZeroTier One node + * Create a new ZeroTier node * - * Note that this can take a few seconds the first time it's called, as it - * will generate an identity. - * - * TODO: should consolidate function pointers into versioned structure for - * better API stability. + * This will attempt to load its identity via the state get function in the + * callback struct. If that fails it will generate a new identity and store + * it. Identity generation can take anywhere from a few hundred milliseconds + * to a few seconds depending on your CPU speed. * * @param node Result: pointer is set to new node instance on success * @param uptr User pointer to pass to functions/callbacks @@ -1481,6 +1439,49 @@ enum ZT_ResultCode ZT_Node_new(ZT_Node **node,void *uptr,void *tptr,const struct void ZT_Node_delete(ZT_Node *node); /** + * Notify node of an update to a state object + * + * This can be called after node startup to restore cached state objects such + * as network configurations for joined networks, planet, moons, etc. See + * the documentation of ZT_StateObjectType for more information. It's okay + * to call this for everything in the object store, but note that the node + * will automatically query for some core objects like identities so supplying + * these via this function is not necessary. + * + * Unless clustering is being implemented this function doesn't need to be + * used after startup. It could be called in response to filesystem changes + * to allow some degree of live configurability by filesystem observation. + * + * The return value of this function indicates whether the update was accepted + * as new. A return value of ZT_RESULT_OK indicates that the node gleaned new + * information from this update and that therefore (in cluster rumor mill mode) + * this update should be distributed to other members of a cluster. A return + * value of ZT_RESULT_OK_IGNORED indicates that the object did not provide any + * new information and therefore should not be propagated in a cluster. + * + * If clustering isn't being implemented the return value of this function can + * generally be ignored. + * + * ZT_RESULT_ERROR_BAD_PARAMETER can be returned if the parameter was invalid + * or not applicable. Object stores may delete the object in this case. + * + * @param node Node instance + * @param tptr Thread pointer to pass to functions/callbacks resulting from this call + * @param type State object type + * @param id State object ID + * @param data State object data + * @param len Length of state object data in bytes + * @return ZT_RESULT_OK if object was accepted or ZT_RESULT_OK_IGNORED if non-informative, error if object was invalid + */ +enum ZT_ResultCode ZT_Node_processStateUpdate( + ZT_Node *node, + void *tptr, + ZT_StateObjectType type, + uint64_t id, + const void *data, + unsigned int len); + +/** * Process a packet received from the physical wire * * @param node Node instance @@ -1766,116 +1767,6 @@ int ZT_Node_sendUserMessage(ZT_Node *node,void *tptr,uint64_t dest,uint64_t type void ZT_Node_setNetconfMaster(ZT_Node *node,void *networkConfigMasterInstance); /** - * 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); - -/** * Set trusted paths * * A trusted path is a physical network (network/bits) over which both |