diff options
Diffstat (limited to 'zto/node')
| -rw-r--r-- | zto/node/Buffer.hpp | 34 | ||||
| -rw-r--r-- | zto/node/Cluster.cpp | 4 | ||||
| -rw-r--r-- | zto/node/Constants.hpp | 33 | ||||
| -rw-r--r-- | zto/node/IncomingPacket.cpp | 204 | ||||
| -rw-r--r-- | zto/node/IncomingPacket.hpp | 2 | ||||
| -rw-r--r-- | zto/node/Network.cpp | 4 | ||||
| -rw-r--r-- | zto/node/NetworkConfig.cpp | 7 | ||||
| -rw-r--r-- | zto/node/NetworkConfig.hpp | 7 | ||||
| -rw-r--r-- | zto/node/Node.cpp | 89 | ||||
| -rw-r--r-- | zto/node/Node.hpp | 6 | ||||
| -rw-r--r-- | zto/node/Packet.cpp | 4 | ||||
| -rw-r--r-- | zto/node/Packet.hpp | 116 |
12 files changed, 71 insertions, 439 deletions
diff --git a/zto/node/Buffer.hpp b/zto/node/Buffer.hpp index ae242c7..8e6b78f 100644 --- a/zto/node/Buffer.hpp +++ b/zto/node/Buffer.hpp @@ -123,7 +123,7 @@ public: inline Buffer &operator=(const Buffer<C2> &b) throw(std::out_of_range) { - if (b._l > C) + if (unlikely(b._l > C)) throw std::out_of_range("Buffer: assignment from buffer larger than capacity"); memcpy(_b,b._b,_l = b._l); return *this; @@ -139,7 +139,7 @@ public: inline void copyFrom(const void *b,unsigned int l) throw(std::out_of_range) { - if (l > C) + if (unlikely(l > C)) throw std::out_of_range("Buffer: set from C array larger than capacity"); _l = l; memcpy(_b,b,l); @@ -148,7 +148,7 @@ public: unsigned char operator[](const unsigned int i) const throw(std::out_of_range) { - if (i >= _l) + if (unlikely(i >= _l)) throw std::out_of_range("Buffer: [] beyond end of data"); return (unsigned char)_b[i]; } @@ -156,7 +156,7 @@ public: unsigned char &operator[](const unsigned int i) throw(std::out_of_range) { - if (i >= _l) + if (unlikely(i >= _l)) throw std::out_of_range("Buffer: [] beyond end of data"); return ((unsigned char *)_b)[i]; } @@ -177,14 +177,14 @@ public: unsigned char *field(unsigned int i,unsigned int l) throw(std::out_of_range) { - if ((i + l) > _l) + if (unlikely((i + l) > _l)) throw std::out_of_range("Buffer: field() beyond end of data"); return (unsigned char *)(_b + i); } const unsigned char *field(unsigned int i,unsigned int l) const throw(std::out_of_range) { - if ((i + l) > _l) + if (unlikely((i + l) > _l)) throw std::out_of_range("Buffer: field() beyond end of data"); return (const unsigned char *)(_b + i); } @@ -200,7 +200,7 @@ public: inline void setAt(unsigned int i,const T v) throw(std::out_of_range) { - if ((i + sizeof(T)) > _l) + if (unlikely((i + sizeof(T)) > _l)) throw std::out_of_range("Buffer: setAt() beyond end of data"); #ifdef ZT_NO_TYPE_PUNNING uint8_t *p = reinterpret_cast<uint8_t *>(_b + i); @@ -223,7 +223,7 @@ public: inline T at(unsigned int i) const throw(std::out_of_range) { - if ((i + sizeof(T)) > _l) + if (unlikely((i + sizeof(T)) > _l)) throw std::out_of_range("Buffer: at() beyond end of data"); #ifdef ZT_NO_TYPE_PUNNING T v = 0; @@ -250,7 +250,7 @@ public: inline void append(const T v) throw(std::out_of_range) { - if ((_l + sizeof(T)) > C) + if (unlikely((_l + sizeof(T)) > C)) throw std::out_of_range("Buffer: append beyond capacity"); #ifdef ZT_NO_TYPE_PUNNING uint8_t *p = reinterpret_cast<uint8_t *>(_b + _l); @@ -273,7 +273,7 @@ public: inline void append(unsigned char c,unsigned int n) throw(std::out_of_range) { - if ((_l + n) > C) + if (unlikely((_l + n) > C)) throw std::out_of_range("Buffer: append beyond capacity"); for(unsigned int i=0;i<n;++i) _b[_l++] = (char)c; @@ -289,7 +289,7 @@ public: inline void append(const void *b,unsigned int l) throw(std::out_of_range) { - if ((_l + l) > C) + if (unlikely((_l + l) > C)) throw std::out_of_range("Buffer: append beyond capacity"); memcpy(_b + _l,b,l); _l += l; @@ -317,7 +317,7 @@ public: throw(std::out_of_range) { for(;;) { - if (_l >= C) + if (unlikely(_l >= C)) throw std::out_of_range("Buffer: append beyond capacity"); if (!(_b[_l++] = *(s++))) break; @@ -351,7 +351,7 @@ public: inline char *appendField(unsigned int l) throw(std::out_of_range) { - if ((_l + l) > C) + if (unlikely((_l + l) > C)) throw std::out_of_range("Buffer: append beyond capacity"); char *r = _b + _l; _l += l; @@ -369,7 +369,7 @@ public: inline void addSize(unsigned int i) throw(std::out_of_range) { - if ((i + _l) > C) + if (unlikely((i + _l) > C)) throw std::out_of_range("Buffer: setSize to larger than capacity"); _l += i; } @@ -385,7 +385,7 @@ public: inline void setSize(const unsigned int i) throw(std::out_of_range) { - if (i > C) + if (unlikely(i > C)) throw std::out_of_range("Buffer: setSize to larger than capacity"); _l = i; } @@ -401,7 +401,7 @@ public: { if (!at) return; - if (at > _l) + if (unlikely(at > _l)) throw std::out_of_range("Buffer: behead() beyond capacity"); ::memmove(_b,_b + at,_l -= at); } @@ -417,7 +417,7 @@ public: throw(std::out_of_range) { const unsigned int endr = at + length; - if (endr > _l) + if (unlikely(endr > _l)) throw std::out_of_range("Buffer: erase() range beyond end of buffer"); ::memmove(_b + at,_b + endr,_l - endr); _l -= length; diff --git a/zto/node/Cluster.cpp b/zto/node/Cluster.cpp index 4d2dea7..119aec2 100644 --- a/zto/node/Cluster.cpp +++ b/zto/node/Cluster.cpp @@ -257,7 +257,7 @@ void Cluster::handleIncomingStateMessage(const void *msg,unsigned int len) memcpy(keytmp,_key,32); for(int i=0;i<8;++i) keytmp[i] ^= reinterpret_cast<const char *>(msg)[i]; - Salsa20 s20(keytmp,256,reinterpret_cast<const char *>(msg) + 8); + Salsa20 s20(keytmp,reinterpret_cast<const char *>(msg) + 8); Utils::burn(keytmp,sizeof(keytmp)); // One-time-use Poly1305 key from first 32 bytes of Salsa20 keystream (as per DJB/NaCl "standard") @@ -956,7 +956,7 @@ void Cluster::_flush(uint16_t memberId) memcpy(keytmp,m.key,32); for(int i=0;i<8;++i) keytmp[i] ^= m.q[i]; - Salsa20 s20(keytmp,256,m.q.field(8,8)); + Salsa20 s20(keytmp,m.q.field(8,8)); Utils::burn(keytmp,sizeof(keytmp)); // One-time-use Poly1305 key from first 32 bytes of Salsa20 keystream (as per DJB/NaCl "standard") diff --git a/zto/node/Constants.hpp b/zto/node/Constants.hpp index d3c8749..3974f0e 100644 --- a/zto/node/Constants.hpp +++ b/zto/node/Constants.hpp @@ -60,6 +60,8 @@ #endif #ifdef __APPLE__ +#define likely(x) __builtin_expect((x),1) +#define unlikely(x) __builtin_expect((x),0) #include <TargetConditionals.h> #ifndef __UNIX_LIKE__ #define __UNIX_LIKE__ @@ -132,6 +134,22 @@ #include <endian.h> #endif +#if (defined(__GNUC__) && (__GNUC__ >= 3)) || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) || defined(__clang__) +#ifndef likely +#define likely(x) __builtin_expect((x),1) +#endif +#ifndef unlikely +#define unlikely(x) __builtin_expect((x),0) +#endif +#else +#ifndef likely +#define likely(x) (x) +#endif +#ifndef unlikely +#define unlikely(x) (x) +#endif +#endif + /** * Length of a ZeroTier address in bytes */ @@ -159,15 +177,12 @@ /** * Default MTU used for Ethernet tap device */ -#define ZT_IF_MTU ZT_MAX_MTU +#define ZT_DEFAULT_MTU 2800 /** - * Maximum number of packet fragments we'll support - * - * The actual spec allows 16, but this is the most we'll support right - * now. Packets with more than this many fragments are dropped. + * Maximum number of packet fragments we'll support (protocol max: 16) */ -#define ZT_MAX_PACKET_FRAGMENTS 4 +#define ZT_MAX_PACKET_FRAGMENTS 7 /** * Size of RX queue @@ -372,7 +387,7 @@ /** * Time horizon for push direct paths cutoff */ -#define ZT_PUSH_DIRECT_PATHS_CUTOFF_TIME 60000 +#define ZT_PUSH_DIRECT_PATHS_CUTOFF_TIME 30000 /** * Maximum number of direct path pushes within cutoff time @@ -381,12 +396,12 @@ * per CUTOFF_TIME milliseconds per peer to prevent this from being * useful for DOS amplification attacks. */ -#define ZT_PUSH_DIRECT_PATHS_CUTOFF_LIMIT 5 +#define ZT_PUSH_DIRECT_PATHS_CUTOFF_LIMIT 8 /** * Maximum number of paths per IP scope (e.g. global, link-local) and family (e.g. v4/v6) */ -#define ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY 4 +#define ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY 8 /** * Time horizon for VERB_NETWORK_CREDENTIALS cutoff diff --git a/zto/node/IncomingPacket.cpp b/zto/node/IncomingPacket.cpp index 126da53..9140c50 100644 --- a/zto/node/IncomingPacket.cpp +++ b/zto/node/IncomingPacket.cpp @@ -115,8 +115,6 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR,void *tPtr) case Packet::VERB_MULTICAST_GATHER: return _doMULTICAST_GATHER(RR,tPtr,peer); case Packet::VERB_MULTICAST_FRAME: return _doMULTICAST_FRAME(RR,tPtr,peer); case Packet::VERB_PUSH_DIRECT_PATHS: return _doPUSH_DIRECT_PATHS(RR,tPtr,peer); - case Packet::VERB_CIRCUIT_TEST: return _doCIRCUIT_TEST(RR,tPtr,peer); - case Packet::VERB_CIRCUIT_TEST_REPORT: return _doCIRCUIT_TEST_REPORT(RR,tPtr,peer); case Packet::VERB_USER_MESSAGE: return _doUSER_MESSAGE(RR,tPtr,peer); } } else { @@ -1125,7 +1123,7 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,void *tPtr, //TRACE("<<MC FRAME %.16llx/%s from %s@%s flags %.2x length %u",nwid,to.toString().c_str(),from.toString().c_str(),peer->address().toString().c_str(),flags,frameLen); - if ((frameLen > 0)&&(frameLen <= ZT_IF_MTU)) { + if ((frameLen > 0)&&(frameLen <= ZT_MAX_MTU)) { if (!to.mac().isMulticast()) { TRACE("dropped MULTICAST_FRAME from %s@%s(%s) to %s: destination is unicast, must use FRAME or EXT_FRAME",from.toString().c_str(),peer->address().toString().c_str(),_path->address().toString().c_str(),to.toString().c_str()); peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay @@ -1185,7 +1183,7 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,void *tPt // First, subject this to a rate limit if (!peer->rateGatePushDirectPaths(now)) { - TRACE("dropped PUSH_DIRECT_PATHS from %s(%s): circuit breaker tripped",source().toString().c_str(),_path->address().toString().c_str()); + //TRACE("dropped PUSH_DIRECT_PATHS from %s(%s): circuit breaker tripped",source().toString().c_str(),_path->address().toString().c_str()); peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_PUSH_DIRECT_PATHS,0,Packet::VERB_NOP,false); return true; } @@ -1220,7 +1218,7 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,void *tPt TRACE("attempting to contact %s at pushed direct path %s",peer->address().toString().c_str(),a.toString().c_str()); peer->attemptToContactAt(tPtr,InetAddress(),a,now,false,0); } else { - TRACE("ignoring contact for %s at %s -- too many per scope",peer->address().toString().c_str(),a.toString().c_str()); + //TRACE("ignoring contact for %s at %s -- too many per scope",peer->address().toString().c_str(),a.toString().c_str()); } } } break; @@ -1237,7 +1235,7 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,void *tPt TRACE("attempting to contact %s at pushed direct path %s",peer->address().toString().c_str(),a.toString().c_str()); peer->attemptToContactAt(tPtr,InetAddress(),a,now,false,0); } else { - TRACE("ignoring contact for %s at %s -- too many per scope",peer->address().toString().c_str(),a.toString().c_str()); + //TRACE("ignoring contact for %s at %s -- too many per scope",peer->address().toString().c_str(),a.toString().c_str()); } } } break; @@ -1252,196 +1250,6 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,void *tPt return true; } -bool IncomingPacket::_doCIRCUIT_TEST(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer) -{ - try { - const Address originatorAddress(field(ZT_PACKET_IDX_PAYLOAD,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); - SharedPtr<Peer> originator(RR->topology->getPeer(tPtr,originatorAddress)); - if (!originator) { - RR->sw->requestWhois(tPtr,originatorAddress); - return false; - } - - const unsigned int flags = at<uint16_t>(ZT_PACKET_IDX_PAYLOAD + 5); - const uint64_t timestamp = at<uint64_t>(ZT_PACKET_IDX_PAYLOAD + 7); - const uint64_t testId = at<uint64_t>(ZT_PACKET_IDX_PAYLOAD + 15); - - // Tracks total length of variable length fields, initialized to originator credential length below - unsigned int vlf; - - // Originator credentials -- right now only a network ID for which the originator is controller or is authorized by controller is allowed - const unsigned int originatorCredentialLength = vlf = at<uint16_t>(ZT_PACKET_IDX_PAYLOAD + 23); - uint64_t originatorCredentialNetworkId = 0; - if (originatorCredentialLength >= 1) { - switch((*this)[ZT_PACKET_IDX_PAYLOAD + 25]) { - case 0x01: { // 64-bit network ID, originator must be controller - if (originatorCredentialLength >= 9) - originatorCredentialNetworkId = at<uint64_t>(ZT_PACKET_IDX_PAYLOAD + 26); - } break; - default: break; - } - } - - // Add length of "additional fields," which are currently unused - vlf += at<uint16_t>(ZT_PACKET_IDX_PAYLOAD + 25 + vlf); - - // Verify signature -- only tests signed by their originators are allowed - const unsigned int signatureLength = at<uint16_t>(ZT_PACKET_IDX_PAYLOAD + 27 + vlf); - if (!originator->identity().verify(field(ZT_PACKET_IDX_PAYLOAD,27 + vlf),27 + vlf,field(ZT_PACKET_IDX_PAYLOAD + 29 + vlf,signatureLength),signatureLength)) { - TRACE("dropped CIRCUIT_TEST from %s(%s): signature by originator %s invalid",source().toString().c_str(),_path->address().toString().c_str(),originatorAddress.toString().c_str()); - peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_CIRCUIT_TEST,0,Packet::VERB_NOP,false); - return true; - } - vlf += signatureLength; - - // Save this length so we can copy the immutable parts of this test - // into the one we send along to next hops. - const unsigned int lengthOfSignedPortionAndSignature = 29 + vlf; - - // Add length of second "additional fields" section. - vlf += at<uint16_t>(ZT_PACKET_IDX_PAYLOAD + 29 + vlf); - - uint64_t reportFlags = 0; - - // Check credentials (signature already verified) - if (originatorCredentialNetworkId) { - SharedPtr<Network> network(RR->node->network(originatorCredentialNetworkId)); - if ((!network)||(!network->config().circuitTestingAllowed(originatorAddress))) { - TRACE("dropped CIRCUIT_TEST from %s(%s): originator %s specified network ID %.16llx as credential, and we don't belong to that network or originator is not allowed'",source().toString().c_str(),_path->address().toString().c_str(),originatorAddress.toString().c_str(),originatorCredentialNetworkId); - peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_CIRCUIT_TEST,0,Packet::VERB_NOP,false); - return true; - } - if (network->gate(tPtr,peer)) - reportFlags |= ZT_CIRCUIT_TEST_REPORT_FLAGS_UPSTREAM_AUTHORIZED_IN_PATH; - } else { - TRACE("dropped CIRCUIT_TEST from %s(%s): originator %s did not specify a credential or credential type",source().toString().c_str(),_path->address().toString().c_str(),originatorAddress.toString().c_str()); - peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_CIRCUIT_TEST,0,Packet::VERB_NOP,false); - return true; - } - - const uint64_t now = RR->node->now(); - - unsigned int breadth = 0; - Address nextHop[256]; // breadth is a uin8_t, so this is the max - InetAddress nextHopBestPathAddress[256]; - unsigned int remainingHopsPtr = ZT_PACKET_IDX_PAYLOAD + 33 + vlf; - if ((ZT_PACKET_IDX_PAYLOAD + 31 + vlf) < size()) { - // unsigned int nextHopFlags = (*this)[ZT_PACKET_IDX_PAYLOAD + 31 + vlf] - breadth = (*this)[ZT_PACKET_IDX_PAYLOAD + 32 + vlf]; - for(unsigned int h=0;h<breadth;++h) { - nextHop[h].setTo(field(remainingHopsPtr,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); - remainingHopsPtr += ZT_ADDRESS_LENGTH; - SharedPtr<Peer> nhp(RR->topology->getPeer(tPtr,nextHop[h])); - if (nhp) { - SharedPtr<Path> nhbp(nhp->getBestPath(now,false)); - if ((nhbp)&&(nhbp->alive(now))) - nextHopBestPathAddress[h] = nhbp->address(); - } - } - } - - // Report back to originator, depending on flags and whether we are last hop - if ( ((flags & 0x01) != 0) || ((breadth == 0)&&((flags & 0x02) != 0)) ) { - Packet outp(originatorAddress,RR->identity.address(),Packet::VERB_CIRCUIT_TEST_REPORT); - outp.append((uint64_t)timestamp); - outp.append((uint64_t)testId); - outp.append((uint64_t)0); // field reserved for future use - outp.append((uint8_t)ZT_VENDOR_ZEROTIER); - outp.append((uint8_t)ZT_PROTO_VERSION); - outp.append((uint8_t)ZEROTIER_ONE_VERSION_MAJOR); - outp.append((uint8_t)ZEROTIER_ONE_VERSION_MINOR); - outp.append((uint16_t)ZEROTIER_ONE_VERSION_REVISION); - outp.append((uint16_t)ZT_PLATFORM_UNSPECIFIED); - outp.append((uint16_t)ZT_ARCHITECTURE_UNSPECIFIED); - outp.append((uint16_t)0); // error code, currently unused - outp.append((uint64_t)reportFlags); - outp.append((uint64_t)packetId()); - peer->address().appendTo(outp); - outp.append((uint8_t)hops()); - _path->localAddress().serialize(outp); - _path->address().serialize(outp); - outp.append((uint16_t)_path->linkQuality()); - outp.append((uint8_t)breadth); - for(unsigned int h=0;h<breadth;++h) { - nextHop[h].appendTo(outp); - nextHopBestPathAddress[h].serialize(outp); // appends 0 if null InetAddress - } - RR->sw->send(tPtr,outp,true); - } - - // If there are next hops, forward the test along through the graph - if (breadth > 0) { - Packet outp(Address(),RR->identity.address(),Packet::VERB_CIRCUIT_TEST); - outp.append(field(ZT_PACKET_IDX_PAYLOAD,lengthOfSignedPortionAndSignature),lengthOfSignedPortionAndSignature); - outp.append((uint16_t)0); // no additional fields - if (remainingHopsPtr < size()) - outp.append(field(remainingHopsPtr,size() - remainingHopsPtr),size() - remainingHopsPtr); - - for(unsigned int h=0;h<breadth;++h) { - if (RR->identity.address() != nextHop[h]) { // next hops that loop back to the current hop are not valid - outp.newInitializationVector(); - outp.setDestination(nextHop[h]); - RR->sw->send(tPtr,outp,true); - } - } - } - - peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_CIRCUIT_TEST,0,Packet::VERB_NOP,false); - } catch ( ... ) { - TRACE("dropped CIRCUIT_TEST from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str()); - } - return true; -} - -bool IncomingPacket::_doCIRCUIT_TEST_REPORT(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer) -{ - try { - ZT_CircuitTestReport report; - memset(&report,0,sizeof(report)); - - report.current = peer->address().toInt(); - report.upstream = Address(field(ZT_PACKET_IDX_PAYLOAD + 52,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH).toInt(); - report.testId = at<uint64_t>(ZT_PACKET_IDX_PAYLOAD + 8); - report.timestamp = at<uint64_t>(ZT_PACKET_IDX_PAYLOAD); - report.sourcePacketId = at<uint64_t>(ZT_PACKET_IDX_PAYLOAD + 44); - report.flags = at<uint64_t>(ZT_PACKET_IDX_PAYLOAD + 36); - report.sourcePacketHopCount = (*this)[ZT_PACKET_IDX_PAYLOAD + 57]; // end of fixed length headers: 58 - report.errorCode = at<uint16_t>(ZT_PACKET_IDX_PAYLOAD + 34); - report.vendor = (enum ZT_Vendor)((*this)[ZT_PACKET_IDX_PAYLOAD + 24]); - report.protocolVersion = (*this)[ZT_PACKET_IDX_PAYLOAD + 25]; - report.majorVersion = (*this)[ZT_PACKET_IDX_PAYLOAD + 26]; - report.minorVersion = (*this)[ZT_PACKET_IDX_PAYLOAD + 27]; - report.revision = at<uint16_t>(ZT_PACKET_IDX_PAYLOAD + 28); - report.platform = (enum ZT_Platform)at<uint16_t>(ZT_PACKET_IDX_PAYLOAD + 30); - report.architecture = (enum ZT_Architecture)at<uint16_t>(ZT_PACKET_IDX_PAYLOAD + 32); - - const unsigned int receivedOnLocalAddressLen = reinterpret_cast<InetAddress *>(&(report.receivedOnLocalAddress))->deserialize(*this,ZT_PACKET_IDX_PAYLOAD + 58); - const unsigned int receivedFromRemoteAddressLen = reinterpret_cast<InetAddress *>(&(report.receivedFromRemoteAddress))->deserialize(*this,ZT_PACKET_IDX_PAYLOAD + 58 + receivedOnLocalAddressLen); - unsigned int ptr = ZT_PACKET_IDX_PAYLOAD + 58 + receivedOnLocalAddressLen + receivedFromRemoteAddressLen; - if (report.protocolVersion >= 9) { - report.receivedFromLinkQuality = at<uint16_t>(ptr); ptr += 2; - } else { - report.receivedFromLinkQuality = ZT_PATH_LINK_QUALITY_MAX; - ptr += at<uint16_t>(ptr) + 2; // this field was once an 'extended field length' reserved field, which was always set to 0 - } - - report.nextHopCount = (*this)[ptr++]; - if (report.nextHopCount > ZT_CIRCUIT_TEST_MAX_HOP_BREADTH) // sanity check, shouldn't be possible - report.nextHopCount = ZT_CIRCUIT_TEST_MAX_HOP_BREADTH; - for(unsigned int h=0;h<report.nextHopCount;++h) { - report.nextHops[h].address = Address(field(ptr,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH).toInt(); ptr += ZT_ADDRESS_LENGTH; - ptr += reinterpret_cast<InetAddress *>(&(report.nextHops[h].physicalAddress))->deserialize(*this,ptr); - } - - RR->node->postCircuitTestReport(&report); - - peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_CIRCUIT_TEST_REPORT,0,Packet::VERB_NOP,false); - } catch ( ... ) { - TRACE("dropped CIRCUIT_TEST_REPORT from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str()); - } - return true; -} - bool IncomingPacket::_doUSER_MESSAGE(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer) { try { @@ -1453,9 +1261,9 @@ bool IncomingPacket::_doUSER_MESSAGE(const RuntimeEnvironment *RR,void *tPtr,con um.length = size() - (ZT_PACKET_IDX_PAYLOAD + 8); RR->node->postEvent(tPtr,ZT_EVENT_USER_MESSAGE,reinterpret_cast<const void *>(&um)); } - peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_CIRCUIT_TEST_REPORT,0,Packet::VERB_NOP,false); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_USER_MESSAGE,0,Packet::VERB_NOP,false); } catch ( ... ) { - TRACE("dropped CIRCUIT_TEST_REPORT from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str()); + TRACE("dropped USER_MESSAGE from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str()); } return true; } diff --git a/zto/node/IncomingPacket.hpp b/zto/node/IncomingPacket.hpp index 43a1ea1..11b6071 100644 --- a/zto/node/IncomingPacket.hpp +++ b/zto/node/IncomingPacket.hpp @@ -138,8 +138,6 @@ private: bool _doMULTICAST_GATHER(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer); bool _doMULTICAST_FRAME(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer); bool _doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer); - bool _doCIRCUIT_TEST(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer); - bool _doCIRCUIT_TEST_REPORT(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer); bool _doUSER_MESSAGE(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer); void _sendErrorNeedCredentials(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer,const uint64_t nwid); diff --git a/zto/node/Network.cpp b/zto/node/Network.cpp index ee0f861..de2ea7d 100644 --- a/zto/node/Network.cpp +++ b/zto/node/Network.cpp @@ -1225,6 +1225,8 @@ void Network::requestConfiguration(void *tPtr) nconf->revision = 1; nconf->issuedTo = RR->identity.address(); nconf->flags = ZT_NETWORKCONFIG_FLAG_ENABLE_IPV6_NDP_EMULATION; + nconf->mtu = ZT_DEFAULT_MTU; + nconf->multicastLimit = 0; nconf->staticIpCount = 1; nconf->ruleCount = 14; nconf->staticIps[0] = InetAddress::makeIpv66plane(_id,RR->identity.address().toInt()); @@ -1495,7 +1497,7 @@ void Network::_externalConfig(ZT_VirtualNetworkConfig *ec) const else ec->name[0] = (char)0; ec->status = _status(); ec->type = (_config) ? (_config.isPrivate() ? ZT_NETWORK_TYPE_PRIVATE : ZT_NETWORK_TYPE_PUBLIC) : ZT_NETWORK_TYPE_PRIVATE; - ec->mtu = ZT_IF_MTU; + ec->mtu = (_config) ? _config.mtu : ZT_DEFAULT_MTU; ec->physicalMtu = ZT_UDP_DEFAULT_PAYLOAD_MTU - (ZT_PACKET_IDX_PAYLOAD + 16); ec->dhcp = 0; std::vector<Address> ab(_config.activeBridges()); diff --git a/zto/node/NetworkConfig.cpp b/zto/node/NetworkConfig.cpp index 9effe52..c39f6ca 100644 --- a/zto/node/NetworkConfig.cpp +++ b/zto/node/NetworkConfig.cpp @@ -51,6 +51,7 @@ bool NetworkConfig::toDictionary(Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d,b if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT,(uint64_t)this->multicastLimit)) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_TYPE,(uint64_t)this->type)) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_NAME,this->name)) return false; + if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_MTU,(uint64_t)this->mtu)) return false; #ifdef ZT_SUPPORT_OLD_STYLE_NETCONF if (includeLegacy) { @@ -217,6 +218,12 @@ bool NetworkConfig::fromDictionary(const Dictionary<ZT_NETWORKCONFIG_DICT_CAPACI this->multicastLimit = (unsigned int)d.getUI(ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT,0); d.get(ZT_NETWORKCONFIG_DICT_KEY_NAME,this->name,sizeof(this->name)); + this->mtu = (unsigned int)d.getUI(ZT_NETWORKCONFIG_DICT_KEY_MTU,ZT_DEFAULT_MTU); + if (this->mtu < 1280) + this->mtu = 1280; // minimum MTU allowed by IPv6 standard and others + else if (this->mtu > ZT_MAX_MTU) + this->mtu = ZT_MAX_MTU; + if (d.getUI(ZT_NETWORKCONFIG_DICT_KEY_VERSION,0) < 6) { #ifdef ZT_SUPPORT_OLD_STYLE_NETCONF char tmp2[1024]; diff --git a/zto/node/NetworkConfig.hpp b/zto/node/NetworkConfig.hpp index 7bae6a9..fdd078d 100644 --- a/zto/node/NetworkConfig.hpp +++ b/zto/node/NetworkConfig.hpp @@ -167,6 +167,8 @@ namespace ZeroTier { #define ZT_NETWORKCONFIG_DICT_KEY_TYPE "t" // text #define ZT_NETWORKCONFIG_DICT_KEY_NAME "n" +// network MTU +#define ZT_NETWORKCONFIG_DICT_KEY_MTU "mtu" // credential time max delta in ms #define ZT_NETWORKCONFIG_DICT_KEY_CREDENTIAL_TIME_MAX_DELTA "ctmd" // binary serialized certificate of membership @@ -466,6 +468,11 @@ public: uint64_t flags; /** + * Network MTU + */ + unsigned int mtu; + + /** * Maximum number of recipients per multicast (not including active bridges) */ unsigned int multicastLimit; diff --git a/zto/node/Node.cpp b/zto/node/Node.cpp index 5848d95..911c9c4 100644 --- a/zto/node/Node.cpp +++ b/zto/node/Node.cpp @@ -327,6 +327,7 @@ ZT_ResultCode Node::leave(uint64_t nwid,void **uptr,void *tptr) } else { if (uptr) *uptr = *n->second->userPtr(); + n->second->externalConfig(&ctmp); n->second->destroy(); nUserPtr = n->second->userPtr(); } @@ -502,64 +503,6 @@ void Node::setNetconfMaster(void *networkControllerInstance) RR->localNetworkController->init(RR->identity,this); } -ZT_ResultCode Node::circuitTestBegin(void *tptr,ZT_CircuitTest *test,void (*reportCallback)(ZT_Node *,ZT_CircuitTest *,const ZT_CircuitTestReport *)) -{ - if (test->hopCount > 0) { - try { - Packet outp(Address(),RR->identity.address(),Packet::VERB_CIRCUIT_TEST); - RR->identity.address().appendTo(outp); - outp.append((uint16_t)((test->reportAtEveryHop != 0) ? 0x03 : 0x02)); - outp.append((uint64_t)test->timestamp); - outp.append((uint64_t)test->testId); - outp.append((uint16_t)0); // originator credential length, updated later - if (test->credentialNetworkId) { - outp.append((uint8_t)0x01); - outp.append((uint64_t)test->credentialNetworkId); - outp.setAt<uint16_t>(ZT_PACKET_IDX_PAYLOAD + 23,(uint16_t)9); - } - outp.append((uint16_t)0); - C25519::Signature sig(RR->identity.sign(reinterpret_cast<const char *>(outp.data()) + ZT_PACKET_IDX_PAYLOAD,outp.size() - ZT_PACKET_IDX_PAYLOAD)); - outp.append((uint16_t)sig.size()); - outp.append(sig.data,(unsigned int)sig.size()); - outp.append((uint16_t)0); // originator doesn't need an extra credential, since it's the originator - for(unsigned int h=1;h<test->hopCount;++h) { - outp.append((uint8_t)0); - outp.append((uint8_t)(test->hops[h].breadth & 0xff)); - for(unsigned int a=0;a<test->hops[h].breadth;++a) - Address(test->hops[h].addresses[a]).appendTo(outp); - } - - for(unsigned int a=0;a<test->hops[0].breadth;++a) { - outp.newInitializationVector(); - outp.setDestination(Address(test->hops[0].addresses[a])); - RR->sw->send(tptr,outp,true); - } - } catch ( ... ) { - return ZT_RESULT_FATAL_ERROR_INTERNAL; // probably indicates FIFO too big for packet - } - } - - { - test->_internalPtr = reinterpret_cast<void *>(reportCallback); - Mutex::Lock _l(_circuitTests_m); - if (std::find(_circuitTests.begin(),_circuitTests.end(),test) == _circuitTests.end()) - _circuitTests.push_back(test); - } - - return ZT_RESULT_OK; -} - -void Node::circuitTestEnd(ZT_CircuitTest *test) -{ - Mutex::Lock _l(_circuitTests_m); - for(;;) { - std::vector< ZT_CircuitTest * >::iterator ct(std::find(_circuitTests.begin(),_circuitTests.end(),test)); - if (ct == _circuitTests.end()) - break; - else _circuitTests.erase(ct); - } -} - ZT_ResultCode Node::clusterInit( unsigned int myId, const struct sockaddr_storage *zeroTierPhysicalEndpoints, @@ -714,20 +657,6 @@ uint64_t Node::prng() return z + y; } -void Node::postCircuitTestReport(const ZT_CircuitTestReport *report) -{ - std::vector< ZT_CircuitTest * > toNotify; - { - Mutex::Lock _l(_circuitTests_m); - for(std::vector< ZT_CircuitTest * >::iterator i(_circuitTests.begin());i!=_circuitTests.end();++i) { - if ((*i)->testId == report->testId) - toNotify.push_back(*i); - } - } - for(std::vector< ZT_CircuitTest * >::iterator i(toNotify.begin());i!=toNotify.end();++i) - (reinterpret_cast<void (*)(ZT_Node *,ZT_CircuitTest *,const ZT_CircuitTestReport *)>((*i)->_internalPtr))(reinterpret_cast<ZT_Node *>(this),*i,report); -} - void Node::setTrustedPaths(const struct sockaddr_storage *networks,const uint64_t *ids,unsigned int count) { RR->topology->setTrustedPaths(reinterpret_cast<const InetAddress *>(networks),ids,count); @@ -1069,22 +998,6 @@ void ZT_Node_setNetconfMaster(ZT_Node *node,void *networkControllerInstance) } catch ( ... ) {} } -enum ZT_ResultCode ZT_Node_circuitTestBegin(ZT_Node *node,void *tptr,ZT_CircuitTest *test,void (*reportCallback)(ZT_Node *,ZT_CircuitTest *,const ZT_CircuitTestReport *)) -{ - try { - return reinterpret_cast<ZeroTier::Node *>(node)->circuitTestBegin(tptr,test,reportCallback); - } catch ( ... ) { - return ZT_RESULT_FATAL_ERROR_INTERNAL; - } -} - -void ZT_Node_circuitTestEnd(ZT_Node *node,ZT_CircuitTest *test) -{ - try { - reinterpret_cast<ZeroTier::Node *>(node)->circuitTestEnd(test); - } catch ( ... ) {} -} - enum ZT_ResultCode ZT_Node_clusterInit( ZT_Node *node, unsigned int myId, diff --git a/zto/node/Node.hpp b/zto/node/Node.hpp index 9558716..57b5489 100644 --- a/zto/node/Node.hpp +++ b/zto/node/Node.hpp @@ -117,8 +117,6 @@ public: void clearLocalInterfaceAddresses(); int sendUserMessage(void *tptr,uint64_t dest,uint64_t typeId,const void *data,unsigned int len); void setNetconfMaster(void *networkControllerInstance); - ZT_ResultCode circuitTestBegin(void *tptr,ZT_CircuitTest *test,void (*reportCallback)(ZT_Node *,ZT_CircuitTest *,const ZT_CircuitTestReport *)); - void circuitTestEnd(ZT_CircuitTest *test); ZT_ResultCode clusterInit( unsigned int myId, const struct sockaddr_storage *zeroTierPhysicalEndpoints, @@ -219,7 +217,6 @@ public: inline bool externalPathLookup(void *tPtr,const Address &ztaddr,int family,InetAddress &addr) { return ( (_cb.pathLookupFunction) ? (_cb.pathLookupFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,ztaddr.toInt(),family,reinterpret_cast<struct sockaddr_storage *>(&addr)) != 0) : false ); } uint64_t prng(); - void postCircuitTestReport(const ZT_CircuitTestReport *report); void setTrustedPaths(const struct sockaddr_storage *networks,const uint64_t *ids,unsigned int count); World planet() const; @@ -309,9 +306,6 @@ private: std::vector< std::pair< uint64_t, SharedPtr<Network> > > _networks; Mutex _networks_m; - std::vector< ZT_CircuitTest * > _circuitTests; - Mutex _circuitTests_m; - std::vector<InetAddress> _directPaths; Mutex _directPaths_m; diff --git a/zto/node/Packet.cpp b/zto/node/Packet.cpp index d60a3a3..6e1b36a 100644 --- a/zto/node/Packet.cpp +++ b/zto/node/Packet.cpp @@ -320,6 +320,7 @@ union LZ4_streamDecode_u { #define FORCE_INLINE static inline #endif +#if 0 #if (defined(__GNUC__) && (__GNUC__ >= 3)) || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) || defined(__clang__) # define expect(expr,value) (__builtin_expect ((expr),(value)) ) #else @@ -328,6 +329,7 @@ union LZ4_streamDecode_u { #define likely(expr) expect((expr) != 0, 1) #define unlikely(expr) expect((expr) != 0, 0) +#endif /*-************************************ * Memory routines @@ -1080,8 +1082,6 @@ const char *Packet::verbString(Verb v) case VERB_MULTICAST_GATHER: return "MULTICAST_GATHER"; case VERB_MULTICAST_FRAME: return "MULTICAST_FRAME"; case VERB_PUSH_DIRECT_PATHS: return "PUSH_DIRECT_PATHS"; - case VERB_CIRCUIT_TEST: return "CIRCUIT_TEST"; - case VERB_CIRCUIT_TEST_REPORT: return "CIRCUIT_TEST_REPORT"; case VERB_USER_MESSAGE: return "USER_MESSAGE"; } return "(unknown)"; diff --git a/zto/node/Packet.hpp b/zto/node/Packet.hpp index 1de679e..a76d418 100644 --- a/zto/node/Packet.hpp +++ b/zto/node/Packet.hpp @@ -61,7 +61,7 @@ * 4 - 0.6.0 ... 1.0.6 * + 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 @@ -954,119 +954,7 @@ public: */ 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 length of additional fields> - * [[...] additional fields] - * <[...] next hop(s) in path> - * - * Flags: - * 0x01 - Report back to originator at all hops - * 0x02 - Report back to originator at last hop - * - * Originator credential types: - * 0x01 - 64-bit network ID for which originator is controller - * - * 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 = 0x11, - - /** - * Circuit test hop report: - * <[8] 64-bit timestamp (echoed from original test)> - * <[8] 64-bit test ID (echoed 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 software major version> - * <[1] 8-bit reporter software minor version> - * <[2] 16-bit reporter software revision> - * <[2] 16-bit reporter OS/platform or 0 if not specified> - * <[2] 16-bit reporter architecture or 0 if not specified> - * <[2] 16-bit error code (set to 0, currently unused)> - * <[8] 64-bit report flags> - * <[8] 64-bit packet ID of received CIRCUIT_TEST packet> - * <[5] upstream ZeroTier address from which CIRCUIT_TEST was received> - * <[1] 8-bit packet hop count of received CIRCUIT_TEST> - * <[...] local wire address on which packet was received> - * <[...] remote wire address from which packet was received> - * <[2] 16-bit path link quality of path over which packet was received> - * <[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> - * - * Report flags: - * 0x1 - Upstream peer in circuit test path allowed in path (e.g. network COM valid) - * - * 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. - * - * If a test report is received and no circuit test was sent, it should be - * ignored. This message generates no OK or ERROR response. - */ - VERB_CIRCUIT_TEST_REPORT = 0x12, + // 0x11, 0x12 -- deprecated /** * A message with arbitrary user-definable content: |
