diff options
Diffstat (limited to 'node')
-rw-r--r-- | node/Multicaster.cpp | 2 | ||||
-rw-r--r-- | node/Multicaster.hpp | 2 | ||||
-rw-r--r-- | node/PacketDecoder.cpp | 64 | ||||
-rw-r--r-- | node/Peer.hpp | 30 | ||||
-rw-r--r-- | node/Switch.cpp | 17 |
5 files changed, 71 insertions, 44 deletions
diff --git a/node/Multicaster.cpp b/node/Multicaster.cpp index 89204346..3348f4c1 100644 --- a/node/Multicaster.cpp +++ b/node/Multicaster.cpp @@ -25,6 +25,8 @@ * LLC. Start here: http://www.zerotier.com/ */ +#include <stdio.h> + #include "Constants.hpp" #include "Multicaster.hpp" #include "Utils.hpp" diff --git a/node/Multicaster.hpp b/node/Multicaster.hpp index 861fc65e..16ae7218 100644 --- a/node/Multicaster.hpp +++ b/node/Multicaster.hpp @@ -177,7 +177,7 @@ public: uint64_t aint = a.toInt() + _bloomNonce; const unsigned int bit = (unsigned int)(aint ^ (aint >> 13) ^ (aint >> 26) ^ (aint >> 39)) & 0x1fff; unsigned char *const bbyte = _bloom + (bit >> 3); // note: bloom filter size == 1024 is hard-coded here - const unsigned char bmask = 0x80 >> (bit & 7); + const unsigned char bmask = 1 << (bit & 7); if ((*bbyte & bmask)) return true; else *bbyte |= bmask; diff --git a/node/PacketDecoder.cpp b/node/PacketDecoder.cpp index 0533ebda..be7acf8d 100644 --- a/node/PacketDecoder.cpp +++ b/node/PacketDecoder.cpp @@ -25,6 +25,10 @@ * LLC. Start here: http://www.zerotier.com/ */ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + #include "../version.h" #include "Constants.hpp" @@ -463,23 +467,27 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared return false; } + // These fields change unsigned int depth = at<uint16_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_DEPTH); - unsigned char *fifo = field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_FIFO,ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_FIFO); - unsigned char *bloom = field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_BLOOM,ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_BLOOM); - uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID); - uint16_t bloomNonce = at<uint16_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_BLOOM_NONCE); - unsigned int prefixBits = (*this)[ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_PREFIX_BITS]; - unsigned int prefix = (*this)[ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_PREFIX]; - uint64_t guid = at<uint64_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_GUID); - MAC sourceMac(field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SOURCE_MAC,ZT_PROTO_VERB_MULTICAST_FRAME_LEN_SOURCE_MAC)); - MulticastGroup dest(MAC(field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_MAC,ZT_PROTO_VERB_MULTICAST_FRAME_LEN_DEST_MAC)),at<uint32_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_ADI)); - unsigned int etherType = at<uint16_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ETHERTYPE); - unsigned int frameLen = at<uint16_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME_LEN); - unsigned char *frame = field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME,frameLen); - unsigned int signatureLen = at<uint16_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME + frameLen); - unsigned char *signature = field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME + frameLen + 2,signatureLen); - - unsigned int signedPartLen = (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME - ZT_PROTO_VERB_MULTICAST_FRAME_IDX__START_OF_SIGNED_PORTION) + frameLen; + unsigned char *const fifo = field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_FIFO,ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_FIFO); + unsigned char *const bloom = field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_BLOOM,ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_BLOOM); + + // These fields don't -- they're signed by the original sender + // const unsigned int flags = (*this)[ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FLAGS]; + const uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID); + const uint16_t bloomNonce = at<uint16_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_BLOOM_NONCE); + const unsigned int prefixBits = (*this)[ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_PREFIX_BITS]; + const unsigned int prefix = (*this)[ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_PREFIX]; + const uint64_t guid = at<uint64_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_GUID); + const MAC sourceMac(field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SOURCE_MAC,ZT_PROTO_VERB_MULTICAST_FRAME_LEN_SOURCE_MAC)); + const MulticastGroup dest(MAC(field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_MAC,ZT_PROTO_VERB_MULTICAST_FRAME_LEN_DEST_MAC)),at<uint32_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_ADI)); + const unsigned int etherType = at<uint16_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ETHERTYPE); + const unsigned int frameLen = at<uint16_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME_LEN); + const unsigned char *const frame = field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME,frameLen); + const unsigned int signatureLen = at<uint16_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME + frameLen); + const unsigned char *const signature = field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME + frameLen + 2,signatureLen); + + const unsigned int signedPartLen = (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME - ZT_PROTO_VERB_MULTICAST_FRAME_IDX__START_OF_SIGNED_PORTION) + frameLen; if (!originPeer->identity().verify(field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX__START_OF_SIGNED_PORTION,signedPartLen),signedPartLen,signature,signatureLen)) { TRACE("dropped MULTICAST_FRAME from %s(%s): failed signature verification, claims to be from %s",source().toString().c_str(),_remoteAddress.toString().c_str(),origin.toString().c_str()); return true; @@ -491,6 +499,7 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared _r->demarc->send(Demarc::ANY_PORT,ZT_DEFAULTS.multicastTraceWatcher,mct,strlen(mct),-1); #endif + // Security check to prohibit multicasts that are really Ethernet unicasts if (!dest.mac().isMulticast()) { TRACE("dropped MULTICAST_FRAME from %s(%s): %s is not a multicast/broadcast address",source().toString().c_str(),_remoteAddress.toString().c_str(),dest.mac().toString().c_str()); return true; @@ -564,15 +573,20 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared // New FIFO with room for one extra, since head will be next hop unsigned char newFifo[ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_FIFO + ZT_ADDRESS_LENGTH]; unsigned char *newFifoPtr = newFifo; - unsigned char *const newFifoEnd = newFifoPtr + sizeof(newFifo); - for(unsigned int i=0;i<ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_FIFO;) { - unsigned int j = i; - i += ZT_ADDRESS_LENGTH; - unsigned char zm = 0; - while (j != i) - zm |= (*(newFifoPtr++) = fifo[j++]); - if (!zm) // stop at zero address - break; + unsigned char *const newFifoEnd = newFifo + sizeof(newFifo); + + // Copy old FIFO into new buffer, terminating at first NULL address + for(unsigned char *f=fifo,*const fifoEnd=(fifo + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_FIFO);f!=fifoEnd;) { + unsigned char *nf = newFifoPtr; + unsigned char *e = nf + ZT_ADDRESS_LENGTH; + unsigned char *ftmp = f; + unsigned char zeroCheckMask = 0; + while (nf != e) + zeroCheckMask |= (*(nf++) = *(ftmp++)); + if (zeroCheckMask) { + f = ftmp; + newFifoPtr = nf; + } else break; } // Add any next hops we know about to FIFO diff --git a/node/Peer.hpp b/node/Peer.hpp index e9b24bd8..5ef8c97d 100644 --- a/node/Peer.hpp +++ b/node/Peer.hpp @@ -162,7 +162,7 @@ public: /** * @return Last successfully sent firewall opener */ - uint64_t lastFirewallOpener() const + inline uint64_t lastFirewallOpener() const throw() { return std::max(_ipv4p.lastFirewallOpener,_ipv6p.lastFirewallOpener); @@ -171,7 +171,7 @@ public: /** * @return Time of last direct packet receive */ - uint64_t lastDirectReceive() const + inline uint64_t lastDirectReceive() const throw() { return std::max(_ipv4p.lastReceive,_ipv6p.lastReceive); @@ -180,7 +180,7 @@ public: /** * @return Time of last direct packet send */ - uint64_t lastDirectSend() const + inline uint64_t lastDirectSend() const throw() { return std::max(_ipv4p.lastSend,_ipv6p.lastSend); @@ -189,7 +189,7 @@ public: /** * @return Time of most recent unicast frame received */ - uint64_t lastUnicastFrame() const + inline uint64_t lastUnicastFrame() const throw() { return _lastUnicastFrame; @@ -198,7 +198,7 @@ public: /** * @return Time of most recent multicast frame received */ - uint64_t lastMulticastFrame() const + inline uint64_t lastMulticastFrame() const throw() { return _lastMulticastFrame; @@ -207,7 +207,7 @@ public: /** * @return Time of most recent frame of any kind (unicast or multicast) */ - uint64_t lastFrame() const + inline uint64_t lastFrame() const throw() { return std::max(_lastUnicastFrame,_lastMulticastFrame); @@ -216,16 +216,28 @@ public: /** * @return Time we last announced state TO this peer, such as multicast LIKEs */ - uint64_t lastAnnouncedTo() const + inline uint64_t lastAnnouncedTo() const throw() { return _lastAnnouncedTo; } /** + * Set the time of last announcement + * + * @param t Time, typically current + */ + inline void setLastAnnouncedTo(const uint64_t t) + throw() + { + _lastAnnouncedTo = t; + _dirty = true; + } + + /** * @return Lowest of measured latencies of all paths or 0 if unknown */ - unsigned int latency() const + inline unsigned int latency() const throw() { if (_ipv4p.latency) { @@ -241,7 +253,7 @@ public: * @param addr Remote address * @param latency Latency measurment */ - void setLatency(const InetAddress &addr,unsigned int latency) + inline void setLatency(const InetAddress &addr,unsigned int latency) { if (addr == _ipv4p.addr) { _ipv4p.latency = latency; diff --git a/node/Switch.cpp b/node/Switch.cpp index 896c6435..b1e5f624 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -107,27 +107,27 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c mg = MulticastGroup::deriveMulticastGroupForAddressResolution(InetAddress(data.field(24,4),4,0)); } - unsigned int mcid = ++_multicastIdCounter & 0xffffff; - uint16_t bloomNonce = (uint16_t)_r->prng->next32(); // doesn't need to be cryptographically strong + const unsigned int mcid = ++_multicastIdCounter & 0xffffff; + const uint16_t bloomNonce = (uint16_t)(_r->prng->next32() & 0xffff); // doesn't need to be cryptographically strong unsigned char bloom[ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_BLOOM]; unsigned char fifo[ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_FIFO + ZT_ADDRESS_LENGTH]; + unsigned char *const fifoEnd = fifo + sizeof(fifo); + const unsigned int signedPartLen = (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME - ZT_PROTO_VERB_MULTICAST_FRAME_IDX__START_OF_SIGNED_PORTION) + data.size(); + const SharedPtr<Peer> supernode(_r->topology->getBestSupernode()); for(unsigned int prefix=0,np=((unsigned int)2 << (network->multicastPrefixBits() - 1));prefix<np;++prefix) { memset(bloom,0,sizeof(bloom)); unsigned char *fifoPtr = fifo; - unsigned char *fifoEnd = fifo + sizeof(fifo); - _r->mc->getNextHops(network->id(),mg,Multicaster::AddToPropagationQueue(&fifoPtr,fifoEnd,bloom,bloomNonce,_r->identity.address(),network->multicastPrefixBits(),prefix)); while (fifoPtr != fifoEnd) *(fifoPtr++) = (unsigned char)0; Address firstHop(fifo,ZT_ADDRESS_LENGTH); // fifo is +1 in size, with first element being used here if (!firstHop) { - SharedPtr<Peer> sn(_r->topology->getBestSupernode()); - if (sn) - firstHop = sn->address(); - else break; + if (supernode) + firstHop = supernode->address(); + else continue; } Packet outp(firstHop,_r->identity.address(),Packet::VERB_MULTICAST_FRAME); @@ -150,7 +150,6 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c outp.append((uint16_t)data.size()); outp.append(data); - unsigned int signedPartLen = (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME - ZT_PROTO_VERB_MULTICAST_FRAME_IDX__START_OF_SIGNED_PORTION) + data.size(); C25519::Signature sig(_r->identity.sign(outp.field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX__START_OF_SIGNED_PORTION,signedPartLen),signedPartLen)); outp.append((uint16_t)sig.size()); outp.append(sig.data,sig.size()); |