summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/ZeroTierOne.h419
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