diff options
Diffstat (limited to 'node/Packet.hpp')
-rw-r--r-- | node/Packet.hpp | 575 |
1 files changed, 260 insertions, 315 deletions
diff --git a/node/Packet.hpp b/node/Packet.hpp index 3d95b0ba..27da6fb5 100644 --- a/node/Packet.hpp +++ b/node/Packet.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_N_PACKET_HPP @@ -34,12 +42,6 @@ #include "Utils.hpp" #include "Buffer.hpp" -#ifdef ZT_USE_SYSTEM_LZ4 -#include <lz4.h> -#else -#include "../ext/lz4/lz4.h" -#endif - /** * Protocol version -- incremented only for major changes * @@ -51,19 +53,23 @@ * + Yet another multicast redesign * + New crypto completely changes key agreement cipher * 4 - 0.6.0 ... 1.0.6 - * + New identity format based on hashcash design + * + BREAKING CHANGE: New identity format based on hashcash design * 5 - 1.1.0 ... 1.1.5 - * + Supports circuit test, proof of work, and echo + * + Supports echo * + Supports in-band world (root server definition) updates * + Clustering! (Though this will work with protocol v4 clients.) * + Otherwise backward compatible with protocol v4 * 6 - 1.1.5 ... 1.1.10 - * + Deprecate old dictionary-based network config format - * + Introduce new binary serialized network config and meta-data - * 7 - 1.1.10 -- CURRENT + * + Network configuration format revisions including binary values + * 7 - 1.1.10 ... 1.1.17 * + Introduce trusted paths for local SDN use + * 8 - 1.1.17 ... 1.2.0 + * + Multipart network configurations for large network configs + * + Tags and Capabilities + * + Inline push of CertificateOfMembership deprecated + * 9 - 1.2.0 ... CURRENT */ -#define ZT_PROTO_VERSION 7 +#define ZT_PROTO_VERSION 9 /** * Minimum supported protocol version @@ -217,12 +223,8 @@ /** * Packet buffer size (can be changed) - * - * The current value is big enough for ZT_MAX_PACKET_FRAGMENTS, the pragmatic - * packet fragment limit, times the default UDP MTU. Most packets won't be - * this big. */ -#define ZT_PROTO_MAX_PACKET_LENGTH (ZT_MAX_PACKET_FRAGMENTS * ZT_UDP_DEFAULT_PAYLOAD_MTU) +#define ZT_PROTO_MAX_PACKET_LENGTH (ZT_MAX_PACKET_FRAGMENTS * ZT_DEFAULT_PHYSMTU) /** * Minimum viable packet length (a.k.a. header length) @@ -303,6 +305,7 @@ #define ZT_PROTO_VERB_MULTICAST_GATHER_IDX_MAC (ZT_PROTO_VERB_MULTICAST_GATHER_IDX_FLAGS + 1) #define ZT_PROTO_VERB_MULTICAST_GATHER_IDX_ADI (ZT_PROTO_VERB_MULTICAST_GATHER_IDX_MAC + 6) #define ZT_PROTO_VERB_MULTICAST_GATHER_IDX_GATHER_LIMIT (ZT_PROTO_VERB_MULTICAST_GATHER_IDX_ADI + 4) +#define ZT_PROTO_VERB_MULTICAST_GATHER_IDX_COM (ZT_PROTO_VERB_MULTICAST_GATHER_IDX_GATHER_LIMIT + 4) // Note: COM, GATHER_LIMIT, and SOURCE_MAC are optional, and so are specified without size #define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID (ZT_PACKET_IDX_PAYLOAD) @@ -346,7 +349,7 @@ namespace ZeroTier { * ZeroTier packet * * Packet format: - * <[8] 64-bit random packet ID and crypto initialization vector> + * <[8] 64-bit packet ID / crypto IV / packet counter> * <[5] destination ZT address> * <[5] source ZT address> * <[1] flags/cipher/hops> @@ -357,6 +360,14 @@ namespace ZeroTier { * * Packets smaller than 28 bytes are invalid and silently discarded. * + * The 64-bit packet ID is a strongly random value used as a crypto IV. + * Its least significant 3 bits are also used as a monotonically increasing + * (and looping) counter for sending packets to a particular recipient. This + * can be used for link quality monitoring and reporting and has no crypto + * impact as it does not increase the likelihood of an IV collision. (The + * crypto we use is not sensitive to the nature of the IV, only that it does + * not repeat.) + * * The flags/cipher/hops bit field is: FFCCCHHH where C is a 3-bit cipher * selection allowing up to 7 cipher suites, F is outside-envelope flags, * and H is hop count. @@ -407,8 +418,7 @@ public: } template<unsigned int C2> - Fragment(const Buffer<C2> &b) - throw(std::out_of_range) : + Fragment(const Buffer<C2> &b) : Buffer<ZT_PROTO_MAX_PACKET_LENGTH>(b) { } @@ -426,10 +436,8 @@ public: * @param fragLen Length of fragment in bytes * @param fragNo Which fragment (>= 1, since 0 is Packet with end chopped off) * @param fragTotal Total number of fragments (including 0) - * @throws std::out_of_range Packet size would exceed buffer */ Fragment(const Packet &p,unsigned int fragStart,unsigned int fragLen,unsigned int fragNo,unsigned int fragTotal) - throw(std::out_of_range) { init(p,fragStart,fragLen,fragNo,fragTotal); } @@ -442,13 +450,11 @@ public: * @param fragLen Length of fragment in bytes * @param fragNo Which fragment (>= 1, since 0 is Packet with end chopped off) * @param fragTotal Total number of fragments (including 0) - * @throws std::out_of_range Packet size would exceed buffer */ inline void init(const Packet &p,unsigned int fragStart,unsigned int fragLen,unsigned int fragNo,unsigned int fragTotal) - throw(std::out_of_range) { if ((fragStart + fragLen) > p.size()) - throw std::out_of_range("Packet::Fragment: tried to construct fragment of packet past its length"); + throw ZT_EXCEPTION_OUT_OF_BOUNDS; setSize(fragLen + ZT_PROTO_MIN_FRAGMENT_LENGTH); // NOTE: this copies both the IV/packet ID and the destination address. @@ -523,50 +529,56 @@ public: /** * No operation (ignored, no reply) */ - VERB_NOP = 0, + VERB_NOP = 0x00, /** - * Announcement of a node's existence: + * Announcement of a node's existence and vitals: * <[1] protocol version> * <[1] software major version> * <[1] software minor version> * <[2] software revision> - * <[8] timestamp (ms since epoch)> + * <[8] timestamp for determining latency> * <[...] binary serialized identity (see Identity)> - * <[1] destination address type> - * [<[...] destination address>] - * <[8] 64-bit world ID of current world> - * <[8] 64-bit timestamp of current world> - * - * This is the only message that ever must be sent in the clear, since it - * is used to push an identity to a new peer. + * <[...] physical destination address of packet> + * <[8] 64-bit world ID of current planet> + * <[8] 64-bit timestamp of current planet> + * [... remainder if packet is encrypted using cryptField() ...] + * <[2] 16-bit number of moons> + * [<[1] 8-bit type ID of moon>] + * [<[8] 64-bit world ID of moon>] + * [<[8] 64-bit timestamp of moon>] + * [... additional moon type/ID/timestamp tuples ...] + * + * HELLO is sent in the clear as it is how peers share their identity + * public keys. A few additional fields are sent in the clear too, but + * these are things that are public info or are easy to determine. As + * of 1.2.0 we have added a few more fields, but since these could have + * the potential to be sensitive we introduced the encryption of the + * remainder of the packet. See cryptField(). Packet MAC is still + * performed of course, so authentication occurs as normal. + * + * Destination address is the actual wire address to which the packet + * was sent. See InetAddress::serialize() for format. * - * The destination address is the wire address to which this packet is - * being sent, and in OK is *also* the destination address of the OK - * packet. This can be used by the receiver to detect NAT, learn its real - * external address if behind NAT, and detect changes to its external - * address that require re-establishing connectivity. + * OK payload: + * <[8] HELLO timestamp field echo> + * <[1] protocol version> + * <[1] software major version> + * <[1] software minor version> + * <[2] software revision> + * <[...] physical destination address of packet> + * <[2] 16-bit length of world update(s) or 0 if none> + * [[...] updates to planets and/or moons] * - * Destination address types and formats (not all of these are used now): - * 0x00 - None -- no destination address data present - * 0x01 - Ethernet address -- format: <[6] Ethernet MAC> - * 0x04 - 6-byte IPv4 UDP address/port -- format: <[4] IP>, <[2] port> - * 0x06 - 18-byte IPv6 UDP address/port -- format: <[16] IP>, <[2] port> + * With the exception of the timestamp, the other fields pertain to the + * respondent who is sending OK and are not echoes. * - * OK payload: - * <[8] timestamp (echoed from original HELLO)> - * <[1] protocol version (of responder)> - * <[1] software major version (of responder)> - * <[1] software minor version (of responder)> - * <[2] software revision (of responder)> - * <[1] destination address type (for this OK, not copied from HELLO)> - * [<[...] destination address>] - * <[2] 16-bit length of world update or 0 if none> - * [[...] world update] + * Note that OK is fully encrypted so no selective cryptField() of + * potentially sensitive fields is needed. * * ERROR has no payload. */ - VERB_HELLO = 1, + VERB_HELLO = 0x01, /** * Error response: @@ -575,7 +587,7 @@ public: * <[1] error code> * <[...] error-dependent payload> */ - VERB_ERROR = 2, + VERB_ERROR = 0x02, /** * Success response: @@ -583,50 +595,43 @@ public: * <[8] in-re packet ID> * <[...] request-specific payload> */ - VERB_OK = 3, + VERB_OK = 0x03, /** * Query an identity by address: * <[5] address to look up> + * [<[...] additional addresses to look up> * * OK response payload: * <[...] binary serialized identity> + * [<[...] additional binary serialized identities>] * * If querying a cluster, duplicate OK responses may occasionally occur. - * These should be discarded. + * These must be tolerated, which is easy since they'll have info you + * already have. * - * If the address is not found, no response is generated. WHOIS requests - * will time out much like ARP requests and similar do in L2. + * If the address is not found, no response is generated. The semantics + * of WHOIS is similar to ARP and NDP in that persistent retrying can + * be performed. */ - VERB_WHOIS = 4, + VERB_WHOIS = 0x04, /** - * Meet another node at a given protocol address: + * Relay-mediated NAT traversal or firewall punching initiation: * <[1] flags (unused, currently 0)> * <[5] ZeroTier address of peer that might be found at this address> * <[2] 16-bit protocol address port> * <[1] protocol address length (4 for IPv4, 16 for IPv6)> * <[...] protocol address (network byte order)> * - * This is sent by a relaying node to initiate NAT traversal between two - * peers that are communicating by way of indirect relay. The relay will - * send this to both peers at the same time on a periodic basis, telling - * each where it might find the other on the network. + * An upstream node can send this to inform both sides of a relay of + * information they might use to establish a direct connection. * * Upon receipt a peer sends HELLO to establish a direct link. * - * Nodes should implement rate control, limiting the rate at which they - * respond to these packets to prevent their use in DDOS attacks. Nodes - * may also ignore these messages if a peer is not known or is not being - * actively communicated with. - * - * Unfortunately the physical address format in this message pre-dates - * InetAddress's serialization format. :( ZeroTier is four years old and - * yes we've accumulated a tiny bit of cruft here and there. - * * No OK or ERROR is generated. */ - VERB_RENDEZVOUS = 5, + VERB_RENDEZVOUS = 0x05, /** * ZT-to-ZT unicast ethernet frame (shortened EXT_FRAME): @@ -642,31 +647,44 @@ public: * ERROR may be generated if a membership certificate is needed for a * closed network. Payload will be network ID. */ - VERB_FRAME = 6, + VERB_FRAME = 0x06, /** * Full Ethernet frame with MAC addressing and optional fields: * <[8] 64-bit network ID> * <[1] flags> - * [<[...] certificate of network membership>] * <[6] destination MAC or all zero for destination node> * <[6] source MAC or all zero for node of origin> * <[2] 16-bit ethertype> * <[...] ethernet payload> * * Flags: - * 0x01 - Certificate of network membership is attached - * - * An extended frame carries full MAC addressing, making them a - * superset of VERB_FRAME. They're used for bridging or when we - * want to attach a certificate since FRAME does not support that. - * - * Multicast frames may not be sent as EXT_FRAME. - * - * ERROR may be generated if a membership certificate is needed for a - * closed network. Payload will be network ID. + * 0x01 - Certificate of network membership attached (DEPRECATED) + * 0x02 - Most significant bit of subtype (see below) + * 0x04 - Middle bit of subtype (see below) + * 0x08 - Least significant bit of subtype (see below) + * 0x10 - ACK requested in the form of OK(EXT_FRAME) + * + * Subtypes (0..7): + * 0x0 - Normal frame (bridging can be determined by checking MAC) + * 0x1 - TEEd outbound frame + * 0x2 - REDIRECTed outbound frame + * 0x3 - WATCHed outbound frame (TEE with ACK, ACK bit also set) + * 0x4 - TEEd inbound frame + * 0x5 - REDIRECTed inbound frame + * 0x6 - WATCHed inbound frame + * 0x7 - (reserved for future use) + * + * An extended frame carries full MAC addressing, making it a + * superset of VERB_FRAME. It is used for bridged traffic, + * redirected or observed traffic via rules, and can in theory + * be used for multicast though MULTICAST_FRAME exists for that + * purpose and has additional options and capabilities. + * + * OK payload (if ACK flag is set): + * <[8] 64-bit network ID> */ - VERB_EXT_FRAME = 7, + VERB_EXT_FRAME = 0x07, /** * ECHO request (a.k.a. ping): @@ -676,7 +694,7 @@ public: * is generated. Response to ECHO requests is optional and ECHO may be * ignored if a node detects a possible flood. */ - VERB_ECHO = 8, + VERB_ECHO = 0x08, /** * Announce interest in multicast group(s): @@ -690,77 +708,117 @@ public: * controllers and root servers. In the current network, root servers * will provide the service of final multicast cache. * - * It is recommended that NETWORK_MEMBERSHIP_CERTIFICATE pushes be sent - * along with MULTICAST_LIKE when pushing LIKEs to peers that do not - * share a network membership (such as root servers), since this can be - * used to authenticate GATHER requests and limit responses to peers - * authorized to talk on a network. (Should be an optional field here, - * but saving one or two packets every five minutes is not worth an - * ugly hack or protocol rev.) + * VERB_NETWORK_CREDENTIALS should be pushed along with this, especially + * if using upstream (e.g. root) nodes as multicast databases. This allows + * GATHERs to be authenticated. * * OK/ERROR are not generated. */ - VERB_MULTICAST_LIKE = 9, + VERB_MULTICAST_LIKE = 0x09, /** - * Network member certificate replication/push: - * <[...] serialized certificate of membership> - * [ ... additional certificates may follow ...] - * - * This is sent in response to ERROR_NEED_MEMBERSHIP_CERTIFICATE and may - * be pushed at any other time to keep exchanged certificates up to date. + * Network credentials push: + * [<[...] one or more certificates of membership>] + * <[1] 0x00, null byte marking end of COM array> + * <[2] 16-bit number of capabilities> + * <[...] one or more serialized Capability> + * <[2] 16-bit number of tags> + * <[...] one or more serialized Tags> + * <[2] 16-bit number of revocations> + * <[...] one or more serialized Revocations> + * <[2] 16-bit number of certificates of ownership> + * <[...] one or more serialized CertificateOfOwnership> + * + * This can be sent by anyone at any time to push network credentials. + * These will of course only be accepted if they are properly signed. + * Credentials can be for any number of networks. + * + * The use of a zero byte to terminate the COM section is for legacy + * backward compatiblity. Newer fields are prefixed with a length. * * OK/ERROR are not generated. */ - VERB_NETWORK_MEMBERSHIP_CERTIFICATE = 10, + VERB_NETWORK_CREDENTIALS = 0x0a, /** * Network configuration request: * <[8] 64-bit network ID> * <[2] 16-bit length of request meta-data dictionary> * <[...] string-serialized request meta-data> - * [<[8] 64-bit revision of netconf we currently have>] + * <[8] 64-bit revision of netconf we currently have> + * <[8] 64-bit timestamp of netconf we currently have> * * This message requests network configuration from a node capable of - * providing it. If the optional revision is included, a response is - * only generated if there is a newer network configuration available. + * providing it. * - * OK response payload: - * <[8] 64-bit network ID> - * <[2] 16-bit length of network configuration dictionary> - * <[...] network configuration dictionary> + * Respones to this are always whole configs intended for the recipient. + * For patches and other updates a NETWORK_CONFIG is sent instead. * - * OK returns a Dictionary (string serialized) containing the network's - * configuration and IP address assignment information for the querying - * node. It also contains a membership certificate that the querying - * node can push to other peers to demonstrate its right to speak on - * a given network. + * It would be valid and correct as of 1.2.0 to use NETWORK_CONFIG always, + * but OK(NTEWORK_CONFIG_REQUEST) should be sent for compatibility. * - * When a new network configuration is received, another config request - * should be sent with the new netconf's revision. This confirms receipt - * and also causes any subsequent changes to rapidly propagate as this - * cycle will repeat until there are no changes. This is optional but - * recommended behavior. + * OK response payload: + * <[8] 64-bit network ID> + * <[2] 16-bit length of network configuration dictionary chunk> + * <[...] network configuration dictionary (may be incomplete)> + * [ ... end of legacy single chunk response ... ] + * <[1] 8-bit flags> + * <[8] 64-bit config update ID (should never be 0)> + * <[4] 32-bit total length of assembled dictionary> + * <[4] 32-bit index of chunk> + * [ ... end signed portion ... ] + * <[1] 8-bit chunk signature type> + * <[2] 16-bit length of chunk signature> + * <[...] chunk signature> + * + * The chunk signature signs the entire payload of the OK response. + * Currently only one signature type is supported: ed25519 (1). + * + * Each config chunk is signed to prevent memory exhaustion or + * traffic crowding DOS attacks against config fragment assembly. + * + * If the packet is from the network controller it is permitted to end + * before the config update ID or other chunking related or signature + * fields. This is to support older controllers that don't include + * these fields and may be removed in the future. * * ERROR response payload: * <[8] 64-bit network ID> - * - * UNSUPPORTED_OPERATION is returned if this service is not supported, - * and OBJ_NOT_FOUND if the queried network ID was not found. */ - VERB_NETWORK_CONFIG_REQUEST = 11, + VERB_NETWORK_CONFIG_REQUEST = 0x0b, /** - * Network configuration refresh request: - * <[...] array of 64-bit network IDs> + * Network configuration data push: + * <[8] 64-bit network ID> + * <[2] 16-bit length of network configuration dictionary chunk> + * <[...] network configuration dictionary (may be incomplete)> + * <[1] 8-bit flags> + * <[8] 64-bit config update ID (should never be 0)> + * <[4] 32-bit total length of assembled dictionary> + * <[4] 32-bit index of chunk> + * [ ... end signed portion ... ] + * <[1] 8-bit chunk signature type> + * <[2] 16-bit length of chunk signature> + * <[...] chunk signature> + * + * This is a direct push variant for network config updates. It otherwise + * carries the same payload as OK(NETWORK_CONFIG_REQUEST) and has the same + * semantics. + * + * The legacy mode missing the additional chunking fields is not supported + * here. + * + * Flags: + * 0x01 - Use fast propagation * - * This can be sent by the network controller to inform a node that it - * should now make a NETWORK_CONFIG_REQUEST. + * An OK should be sent if the config is successfully received and + * accepted. * - * It does not generate an OK or ERROR message, and is treated only as - * a hint to refresh now. + * OK payload: + * <[8] 64-bit network ID> + * <[8] 64-bit config update ID> */ - VERB_NETWORK_CONFIG_REFRESH = 12, + VERB_NETWORK_CONFIG = 0x0c, /** * Request endpoints for multicast distribution: @@ -769,10 +827,10 @@ public: * <[6] MAC address of multicast group being queried> * <[4] 32-bit ADI for multicast group being queried> * <[4] 32-bit requested max number of multicast peers> - * [<[...] network certificate of membership>] + * [<[...] network certificate of membership>] * * Flags: - * 0x01 - Network certificate of membership is attached + * 0x01 - COM is attached * * This message asks a peer for additional known endpoints that have * LIKEd a given multicast group. It's sent when the sender wishes @@ -782,6 +840,9 @@ public: * More than one OK response can occur if the response is broken up across * multiple packets or if querying a clustered node. * + * The COM should be included so that upstream nodes that are not + * members of our network can validate our request. + * * OK response payload: * <[8] 64-bit network ID> * <[6] MAC address of multicast group being queried> @@ -793,13 +854,12 @@ public: * * ERROR is not generated; queries that return no response are dropped. */ - VERB_MULTICAST_GATHER = 13, + VERB_MULTICAST_GATHER = 0x0d, /** * Multicast frame: * <[8] 64-bit network ID> * <[1] flags> - * [<[...] network certificate of membership>] * [<[4] 32-bit implicit gather limit>] * [<[6] source MAC>] * <[6] destination MAC (multicast address)> @@ -808,9 +868,10 @@ public: * <[...] ethernet payload> * * Flags: - * 0x01 - Network certificate of membership is attached + * 0x01 - Network certificate of membership attached (DEPRECATED) * 0x02 - Implicit gather limit field is present * 0x04 - Source MAC is specified -- otherwise it's computed from sender + * 0x08 - Please replicate (sent to multicast replicators) * * OK and ERROR responses are optional. OK may be generated if there are * implicit gather results or if the recipient wants to send its own @@ -823,11 +884,11 @@ public: * <[6] MAC address of multicast group> * <[4] 32-bit ADI for multicast group> * <[1] flags> - * [<[...] network certficate of membership>] + * [<[...] network certficate of membership (DEPRECATED)>] * [<[...] implicit gather results if flag 0x01 is set>] * * OK flags (same bits as request flags): - * 0x01 - OK includes certificate of network membership + * 0x01 - OK includes certificate of network membership (DEPRECATED) * 0x02 - OK includes implicit gather results * * ERROR response payload: @@ -835,7 +896,7 @@ public: * <[6] multicast group MAC> * <[4] 32-bit multicast group ADI> */ - VERB_MULTICAST_FRAME = 14, + VERB_MULTICAST_FRAME = 0x0e, /** * Push of potential endpoints for direct communication: @@ -865,172 +926,42 @@ public: * be used unless they are blacklisted explicitly or unless flag 0x01 * is set. * - * Only a subset of this functionality is currently implemented: basic - * path pushing and learning. Blacklisting and trust are not fully - * implemented yet (encryption is still always used). - * * OK and ERROR are not generated. */ - VERB_PUSH_DIRECT_PATHS = 16, + VERB_PUSH_DIRECT_PATHS = 0x10, - /** - * Source-routed circuit test message: - * <[5] address of originator of circuit test> - * <[2] 16-bit flags> - * <[8] 64-bit timestamp> - * <[8] 64-bit test ID (arbitrary, set by tester)> - * <[2] 16-bit originator credential length (includes type)> - * [[1] originator credential type (for authorizing test)] - * [[...] originator credential] - * <[2] 16-bit length of additional fields> - * [[...] additional fields] - * [ ... end of signed portion of request ... ] - * <[2] 16-bit length of signature of request> - * <[...] signature of request by originator> - * <[2] 16-bit previous hop credential length (including type)> - * [[1] previous hop credential type] - * [[...] previous hop credential] - * <[...] next hop(s) in path> - * - * Flags: - * 0x01 - Report back to originator at middle hops - * 0x02 - Report back to originator at last hop - * - * Originator credential types: - * 0x01 - 64-bit network ID for which originator is controller - * - * Previous hop credential types: - * 0x01 - Certificate of network membership - * - * Path record format: - * <[1] 8-bit flags (unused, must be zero)> - * <[1] 8-bit breadth (number of next hops)> - * <[...] one or more ZeroTier addresses of next hops> - * - * The circuit test allows a device to send a message that will traverse - * the network along a specified path, with each hop optionally reporting - * back to the tester via VERB_CIRCUIT_TEST_REPORT. - * - * Each circuit test packet includes a digital signature by the originator - * of the request, as well as a credential by which that originator claims - * authorization to perform the test. Currently this signature is ed25519, - * but in the future flags might be used to indicate an alternative - * algorithm. For example, the originator might be a network controller. - * In this case the test might be authorized if the recipient is a member - * of a network controlled by it, and if the previous hop(s) are also - * members. Each hop may include its certificate of network membership. - * - * Circuit test paths consist of a series of records. When a node receives - * an authorized circuit test, it: - * - * (1) Reports back to circuit tester as flags indicate - * (2) Reads and removes the next hop from the packet's path - * (3) Sends the packet along to next hop(s), if any. - * - * It is perfectly legal for a path to contain the same hop more than - * once. In fact, this can be a very useful test to determine if a hop - * can be reached bidirectionally and if so what that connectivity looks - * like. - * - * The breadth field in source-routed path records allows a hop to forward - * to more than one recipient, allowing the tester to specify different - * forms of graph traversal in a test. - * - * There is no hard limit to the number of hops in a test, but it is - * practically limited by the maximum size of a (possibly fragmented) - * ZeroTier packet. - * - * Support for circuit tests is optional. If they are not supported, the - * node should respond with an UNSUPPORTED_OPERATION error. If a circuit - * test request is not authorized, it may be ignored or reported as - * an INVALID_REQUEST. No OK messages are generated, but TEST_REPORT - * messages may be sent (see below). - * - * ERROR packet format: - * <[8] 64-bit timestamp (echoed from original> - * <[8] 64-bit test ID (echoed from original)> - */ - VERB_CIRCUIT_TEST = 17, + // 0x11, 0x12 -- deprecated /** - * Circuit test hop report: - * <[8] 64-bit timestamp (from original test)> - * <[8] 64-bit test ID (from original test)> - * <[8] 64-bit reserved field (set to 0, currently unused)> - * <[1] 8-bit vendor ID (set to 0, currently unused)> - * <[1] 8-bit reporter protocol version> - * <[1] 8-bit reporter major version> - * <[1] 8-bit reporter minor version> - * <[2] 16-bit reporter revision> - * <[2] 16-bit reporter OS/platform> - * <[2] 16-bit reporter architecture> - * <[2] 16-bit error code (set to 0, currently unused)> - * <[8] 64-bit report flags (set to 0, currently unused)> - * <[8] 64-bit source packet ID> - * <[5] upstream ZeroTier address from which test was received> - * <[1] 8-bit source packet hop count (ZeroTier hop count)> - * <[...] local wire address on which packet was received> - * <[...] remote wire address from which packet was received> - * <[2] 16-bit length of additional fields> - * <[...] additional fields> - * <[1] 8-bit number of next hops (breadth)> - * <[...] next hop information> - * - * Next hop information record format: - * <[5] ZeroTier address of next hop> - * <[...] current best direct path address, if any, 0 if none> + * A message with arbitrary user-definable content: + * <[8] 64-bit arbitrary message type ID> + * [<[...] message payload>] * - * Circuit test reports can be sent by hops in a circuit test to report - * back results. They should include information about the sender as well - * as about the paths to which next hops are being sent. + * This can be used to send arbitrary messages over VL1. It generates no + * OK or ERROR and has no special semantics outside of whatever the user + * (via the ZeroTier core API) chooses to give it. * - * If a test report is received and no circuit test was sent, it should be - * ignored. This message generates no OK or ERROR response. + * Message type IDs less than or equal to 65535 are reserved for use by + * ZeroTier, Inc. itself. We recommend making up random ones for your own + * implementations. */ - VERB_CIRCUIT_TEST_REPORT = 18, + VERB_USER_MESSAGE = 0x14, /** - * Request proof of work: - * <[1] 8-bit proof of work type> - * <[1] 8-bit proof of work difficulty> - * <[2] 16-bit length of proof of work challenge> - * <[...] proof of work challenge> - * - * This requests that a peer perform a proof of work calucation. It can be - * sent by highly trusted peers (e.g. root servers, network controllers) - * under suspected denial of service conditions in an attempt to filter - * out "non-serious" peers and remain responsive to those proving their - * intent to actually communicate. - * - * If the peer obliges to perform the work, it does so and responds with - * an OK containing the result. Otherwise it may ignore the message or - * response with an ERROR_INVALID_REQUEST or ERROR_UNSUPPORTED_OPERATION. - * - * Proof of work type IDs: - * 0x01 - Salsa20/12+SHA512 hashcash function - * - * Salsa20/12+SHA512 is based on the following composite hash function: - * - * (1) Compute SHA512(candidate) - * (2) Use the first 256 bits of the result of #1 as a key to encrypt - * 131072 zero bytes with Salsa20/12 (with a zero IV). - * (3) Compute SHA512(the result of step #2) - * (4) Accept this candiate if the first [difficulty] bits of the result - * from step #3 are zero. Otherwise generate a new candidate and try - * again. - * - * This is performed repeatedly on candidates generated by appending the - * supplied challenge to an arbitrary nonce until a valid candidate - * is found. This chosen prepended nonce is then returned as the result - * in OK. - * - * OK payload: - * <[2] 16-bit length of result> - * <[...] computed proof of work> - * - * ERROR has no payload. + * A trace for remote debugging or diagnostics: + * <[...] null-terminated dictionary containing trace information> + * [<[...] additional null-terminated dictionaries>] + * + * This message contains a remote trace event. Remote trace events can + * be sent to observers configured at the network level for those that + * pertain directly to actiity on a network, or to global observers if + * locally configured. + * + * The instance ID is a random 64-bit value generated by each ZeroTier + * node on startup. This is helpful in identifying traces from different + * members of a cluster. */ - VERB_REQUEST_PROOF_OF_WORK = 19 + VERB_REMOTE_TRACE = 0x15 }; /** @@ -1039,40 +970,33 @@ public: enum ErrorCode { /* No error, not actually used in transit */ - ERROR_NONE = 0, + ERROR_NONE = 0x00, /* Invalid request */ - ERROR_INVALID_REQUEST = 1, + ERROR_INVALID_REQUEST = 0x01, /* Bad/unsupported protocol version */ - ERROR_BAD_PROTOCOL_VERSION = 2, + ERROR_BAD_PROTOCOL_VERSION = 0x02, /* Unknown object queried */ - ERROR_OBJ_NOT_FOUND = 3, + ERROR_OBJ_NOT_FOUND = 0x03, /* HELLO pushed an identity whose address is already claimed */ - ERROR_IDENTITY_COLLISION = 4, + ERROR_IDENTITY_COLLISION = 0x04, /* Verb or use case not supported/enabled by this node */ - ERROR_UNSUPPORTED_OPERATION = 5, + ERROR_UNSUPPORTED_OPERATION = 0x05, - /* Message to private network rejected -- no unexpired certificate on file */ - ERROR_NEED_MEMBERSHIP_CERTIFICATE = 6, + /* Network membership certificate update needed */ + ERROR_NEED_MEMBERSHIP_CERTIFICATE = 0x06, /* Tried to join network, but you're not a member */ - ERROR_NETWORK_ACCESS_DENIED_ = 7, /* extra _ to avoid Windows name conflict */ + ERROR_NETWORK_ACCESS_DENIED_ = 0x07, /* extra _ at end to avoid Windows name conflict */ /* Multicasts to this group are not wanted */ - ERROR_UNWANTED_MULTICAST = 8 + ERROR_UNWANTED_MULTICAST = 0x08 }; -//#ifdef ZT_TRACE - static const char *verbString(Verb v) - throw(); - static const char *errorString(ErrorCode e) - throw(); -//#endif - template<unsigned int C2> Packet(const Buffer<C2> &b) : Buffer<ZT_PROTO_MAX_PACKET_LENGTH>(b) @@ -1268,6 +1192,12 @@ public: /** * Get this packet's unique ID (the IV field interpreted as uint64_t) * + * Note that the least significant 3 bits of this ID will change when armor() + * is called to armor the packet for transport. This is because armor() will + * mask the last 3 bits against the send counter for QoS monitoring use prior + * to actually using the IV to encrypt and MAC the packet. Be aware of this + * when grabbing the packetId of a new packet prior to armor/send. + * * @return Packet ID */ inline uint64_t packetId() const { return at<uint64_t>(ZT_PACKET_IDX_IV); } @@ -1318,6 +1248,21 @@ public: bool dearmor(const void *key); /** + * Encrypt/decrypt a separately armored portion of a packet + * + * This is currently only used to mask portions of HELLO as an extra + * security precation since most of that message is sent in the clear. + * + * This must NEVER be used more than once in the same packet, as doing + * so will result in re-use of the same key stream. + * + * @param key 32-byte key + * @param start Start of encrypted portion + * @param len Length of encrypted portion + */ + void cryptField(const void *key,unsigned int start,unsigned int len); + + /** * Attempt to compress payload if not already (must be unencrypted) * * This requires that the payload at least contain the verb byte already |