mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2024-12-21 13:57:49 +00:00
Adding signatures to multicast frames, work in progress, does not build yet
This commit is contained in:
parent
9f8069434a
commit
bcd079b70e
@ -240,7 +240,7 @@ error_no_ZT_ARCH_defined;
|
|||||||
/**
|
/**
|
||||||
* Expiration time in ms for multicast history items
|
* Expiration time in ms for multicast history items
|
||||||
*/
|
*/
|
||||||
#define ZT_MULTICAST_DEDUP_HISTORY_EXPIRE 8000
|
#define ZT_MULTICAST_DEDUP_HISTORY_EXPIRE 4000
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Number of bits to randomly "decay" in bloom filter per hop
|
* Number of bits to randomly "decay" in bloom filter per hop
|
||||||
|
@ -31,11 +31,14 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <openssl/sha.h>
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "Constants.hpp"
|
#include "Constants.hpp"
|
||||||
#include "Buffer.hpp"
|
#include "Buffer.hpp"
|
||||||
@ -46,6 +49,7 @@
|
|||||||
#include "Address.hpp"
|
#include "Address.hpp"
|
||||||
#include "SharedPtr.hpp"
|
#include "SharedPtr.hpp"
|
||||||
#include "BloomFilter.hpp"
|
#include "BloomFilter.hpp"
|
||||||
|
#include "Identity.hpp"
|
||||||
|
|
||||||
// Maximum sample size to pick during choice of multicast propagation peers
|
// Maximum sample size to pick during choice of multicast propagation peers
|
||||||
#define ZT_MULTICAST_PICK_MAX_SAMPLE_SIZE 64
|
#define ZT_MULTICAST_PICK_MAX_SAMPLE_SIZE 64
|
||||||
@ -68,10 +72,49 @@ public:
|
|||||||
typedef BloomFilter<ZT_PROTO_VERB_MULTICAST_FRAME_BLOOM_FILTER_SIZE_BITS> MulticastBloomFilter;
|
typedef BloomFilter<ZT_PROTO_VERB_MULTICAST_FRAME_BLOOM_FILTER_SIZE_BITS> MulticastBloomFilter;
|
||||||
|
|
||||||
Multicaster()
|
Multicaster()
|
||||||
|
throw()
|
||||||
{
|
{
|
||||||
memset(_multicastHistory,0,sizeof(_multicastHistory));
|
memset(_multicastHistory,0,sizeof(_multicastHistory));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a signature of a multicast packet using an identity
|
||||||
|
*
|
||||||
|
* @param id Identity to sign with (must have secret key portion)
|
||||||
|
* @param from MAC address of sender
|
||||||
|
* @param to Multicast group
|
||||||
|
* @param etherType 16-bit ethernet type
|
||||||
|
* @param data Ethernet frame data
|
||||||
|
* @param len Length of frame
|
||||||
|
* @return ECDSA signature
|
||||||
|
*/
|
||||||
|
static inline std::string signMulticastPacket(const Identity &id,const MAC &from,const MulticastGroup &to,unsigned int etherType,const void *data,unsigned int len)
|
||||||
|
{
|
||||||
|
unsigned char digest[32];
|
||||||
|
_hashMulticastPacketForSig(from,to,etherType,data,len,digest);
|
||||||
|
return id.sign(digest);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify a signature from a multicast packet
|
||||||
|
*
|
||||||
|
* @param id Identity of original signer
|
||||||
|
* @param from MAC address of sender
|
||||||
|
* @param to Multicast group
|
||||||
|
* @param etherType 16-bit ethernet type
|
||||||
|
* @param data Ethernet frame data
|
||||||
|
* @param len Length of frame
|
||||||
|
* @param signature ECDSA signature
|
||||||
|
* @param siglen Length of signature in bytes
|
||||||
|
* @return ECDSA signature
|
||||||
|
*/
|
||||||
|
static bool verifyMulticastPacket(const Identity &id,const MAC &from,const MulticastGroup &to,unsigned int etherType,const void *data,unsigned int len,const void *signature,unsigned int siglen)
|
||||||
|
{
|
||||||
|
unsigned char digest[32];
|
||||||
|
_hashMulticastPacketForSig(from,to,etherType,data,len,digest);
|
||||||
|
return id.verify(digest,signature,siglen);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the most recent LIKE time for an address in a given multicast group on a given network
|
* Update the most recent LIKE time for an address in a given multicast group on a given network
|
||||||
*
|
*
|
||||||
@ -257,6 +300,29 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline void _hashMulticastPacketForSig(const MAC &from,const MulticastGroup &to,unsigned int etherType,const void *data,unsigned int len,unsigned char *digest)
|
||||||
|
throw()
|
||||||
|
{
|
||||||
|
unsigned char zero = 0;
|
||||||
|
SHA256_CTX sha;
|
||||||
|
SHA256_Init(&sha);
|
||||||
|
uint64_t _nwid = Utils::hton(network->id());
|
||||||
|
SHA256_Update(&sha,(unsigned char *)&_nwid,sizeof(_nwid));
|
||||||
|
SHA256_Update(&sha,&zero,1);
|
||||||
|
SHA256_Update(&sha,(unsigned char *)from.data,6);
|
||||||
|
SHA256_Update(&sha,&zero,1);
|
||||||
|
SHA256_Update(&sha,(unsigned char *)mg.mac().data,6);
|
||||||
|
SHA256_Update(&sha,&zero,1);
|
||||||
|
uint32_t _adi = Utils::hton(mg.adi());
|
||||||
|
SHA256_Update(&sha,(unsigned char *)&_adi,sizeof(_adi));
|
||||||
|
SHA256_Update(&sha,&zero,1);
|
||||||
|
uint16_t _etype = Utils::hton((uint16_t)etherType);
|
||||||
|
SHA256_Update(&sha,(unsigned char *)&_etype,sizeof(_etype));
|
||||||
|
SHA256_Update(&sha,&zero,1);
|
||||||
|
SHA256_Update(&sha,(unsigned char *)data,len);
|
||||||
|
SHA256_Final(digest,&sha);
|
||||||
|
}
|
||||||
|
|
||||||
// [0] - CRC, [1] - timestamp
|
// [0] - CRC, [1] - timestamp
|
||||||
uint64_t _multicastHistory[ZT_MULTICAST_DEDUP_HISTORY_LENGTH][2];
|
uint64_t _multicastHistory[ZT_MULTICAST_DEDUP_HISTORY_LENGTH][2];
|
||||||
|
|
||||||
|
@ -112,19 +112,6 @@ public:
|
|||||||
return ((_open)||(_members.count(addr) > 0));
|
return ((_open)||(_members.count(addr) > 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Shortcut to check open(), whether MAC is ZeroTier, then isMember()
|
|
||||||
*
|
|
||||||
* @param mac MAC address to check
|
|
||||||
* @return True if MAC is allowed
|
|
||||||
*/
|
|
||||||
inline bool isAllowed(const MAC &mac) const
|
|
||||||
throw()
|
|
||||||
{
|
|
||||||
Mutex::Lock _l(_lock);
|
|
||||||
return ((_open)||((mac.isZeroTier())&&(_members.count(Address(mac)) > 0)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return True if network is open (no membership required)
|
* @return True if network is open (no membership required)
|
||||||
*/
|
*/
|
||||||
|
@ -45,8 +45,13 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Protocol version
|
* Protocol version
|
||||||
|
*
|
||||||
|
* 1 - 0.2.0 ... 0.2.5
|
||||||
|
* 2 - 0.3.0 ...
|
||||||
|
* * Added signature and originating peer to multicast frame
|
||||||
|
* * Double size of multicast frame bloom filter
|
||||||
*/
|
*/
|
||||||
#define ZT_PROTO_VERSION 1
|
#define ZT_PROTO_VERSION 2
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maximum hop count allowed by packet structure (3 bits, 0-7)
|
* Maximum hop count allowed by packet structure (3 bits, 0-7)
|
||||||
@ -123,8 +128,8 @@
|
|||||||
#define ZT_PROTO_MIN_FRAGMENT_LENGTH ZT_PACKET_FRAGMENT_IDX_PAYLOAD
|
#define ZT_PROTO_MIN_FRAGMENT_LENGTH ZT_PACKET_FRAGMENT_IDX_PAYLOAD
|
||||||
|
|
||||||
// Size of bloom filter used in multicast propagation
|
// Size of bloom filter used in multicast propagation
|
||||||
#define ZT_PROTO_VERB_MULTICAST_FRAME_BLOOM_FILTER_SIZE 32
|
#define ZT_PROTO_VERB_MULTICAST_FRAME_BLOOM_FILTER_SIZE_BITS 512
|
||||||
#define ZT_PROTO_VERB_MULTICAST_FRAME_BLOOM_FILTER_SIZE_BITS 256
|
#define ZT_PROTO_VERB_MULTICAST_FRAME_BLOOM_FILTER_SIZE_BYTES 64
|
||||||
|
|
||||||
// Field incides for parsing verbs
|
// Field incides for parsing verbs
|
||||||
#define ZT_PROTO_VERB_HELLO_IDX_PROTOCOL_VERSION (ZT_PACKET_IDX_PAYLOAD)
|
#define ZT_PROTO_VERB_HELLO_IDX_PROTOCOL_VERSION (ZT_PACKET_IDX_PAYLOAD)
|
||||||
@ -148,15 +153,18 @@
|
|||||||
#define ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID (ZT_PACKET_IDX_PAYLOAD)
|
#define ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID (ZT_PACKET_IDX_PAYLOAD)
|
||||||
#define ZT_PROTO_VERB_FRAME_IDX_ETHERTYPE (ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID + 8)
|
#define ZT_PROTO_VERB_FRAME_IDX_ETHERTYPE (ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID + 8)
|
||||||
#define ZT_PROTO_VERB_FRAME_IDX_PAYLOAD (ZT_PROTO_VERB_FRAME_IDX_ETHERTYPE + 2)
|
#define ZT_PROTO_VERB_FRAME_IDX_PAYLOAD (ZT_PROTO_VERB_FRAME_IDX_ETHERTYPE + 2)
|
||||||
#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID (ZT_PACKET_IDX_PAYLOAD)
|
#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FLAGS (ZT_PACKET_IDX_PAYLOAD)
|
||||||
#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_MULTICAST_MAC (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID + 8)
|
#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FLAGS + 1)
|
||||||
#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ADI (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_MULTICAST_MAC + 6)
|
#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SUBMITTER_ADDRESS (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID + 8)
|
||||||
#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_BLOOM (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ADI + 4)
|
#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SOURCE_MAC (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SUBMITTER_ADDRESS + 5)
|
||||||
#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_HOPS (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_BLOOM + ZT_PROTO_VERB_MULTICAST_FRAME_BLOOM_FILTER_SIZE)
|
#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DESTINATION_MAC (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SOURCE_MAC + 6)
|
||||||
#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_LOAD_FACTOR (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_HOPS + 1)
|
#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ADI (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DESTINATION_MAC + 6)
|
||||||
#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FROM_MAC (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_LOAD_FACTOR + 2)
|
#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_BLOOM_FILTER (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ADI + 4)
|
||||||
#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ETHERTYPE (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FROM_MAC + 6)
|
#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_HOP_COUNT (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_BLOOM_FILTER + 64)
|
||||||
#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PAYLOAD (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ETHERTYPE + 2)
|
#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ETHERTYPE (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_HOP_COUNT + 1)
|
||||||
|
#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PAYLOAD_LENGTH (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ETHERTYPE + 2)
|
||||||
|
#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SIGNATURE_LENGTH (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PAYLOAD_LENGTH + 2)
|
||||||
|
#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PAYLOAD (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SIGNATURE_LENGTH + 2)
|
||||||
|
|
||||||
// Field indices for parsing OK and ERROR payloads of replies
|
// Field indices for parsing OK and ERROR payloads of replies
|
||||||
#define ZT_PROTO_VERB_HELLO__OK__IDX_TIMESTAMP (ZT_PROTO_VERB_OK_IDX_PAYLOAD)
|
#define ZT_PROTO_VERB_HELLO__OK__IDX_TIMESTAMP (ZT_PROTO_VERB_OK_IDX_PAYLOAD)
|
||||||
@ -415,20 +423,8 @@ public:
|
|||||||
*/
|
*/
|
||||||
VERB_FRAME = 6,
|
VERB_FRAME = 6,
|
||||||
|
|
||||||
/* A multicast frame:
|
/* 7 - old VERB_MULTICAST_FRAME, might be reused once all old 0.2
|
||||||
* <[8] 64-bit network ID>
|
* clients are off the net. */
|
||||||
* <[6] destination multicast Ethernet address>
|
|
||||||
* <[4] multicast additional distinguishing information (ADI)>
|
|
||||||
* <[32] multicast propagation bloom filter>
|
|
||||||
* <[1] 8-bit strict propagation hop count>
|
|
||||||
* <[2] reserved, must be 0>
|
|
||||||
* <[6] source Ethernet address>
|
|
||||||
* <[2] 16-bit ethertype>
|
|
||||||
* <[...] ethernet payload>
|
|
||||||
*
|
|
||||||
* No OK or ERROR is generated.
|
|
||||||
*/
|
|
||||||
VERB_MULTICAST_FRAME = 7,
|
|
||||||
|
|
||||||
/* Announce interest in multicast group(s):
|
/* Announce interest in multicast group(s):
|
||||||
* <[8] 64-bit network ID>
|
* <[8] 64-bit network ID>
|
||||||
@ -438,7 +434,36 @@ public:
|
|||||||
*
|
*
|
||||||
* OK is generated on successful receipt.
|
* OK is generated on successful receipt.
|
||||||
*/
|
*/
|
||||||
VERB_MULTICAST_LIKE = 8
|
VERB_MULTICAST_LIKE = 8,
|
||||||
|
|
||||||
|
/* A multicast frame:
|
||||||
|
* <[1] flags, currently unused and must be 0>
|
||||||
|
* <[8] 64-bit network ID>
|
||||||
|
* <[5] ZeroTier address of original submitter of this multicast>
|
||||||
|
* <[6] source MAC address>
|
||||||
|
* <[6] destination multicast Ethernet address>
|
||||||
|
* <[4] multicast additional distinguishing information (ADI)>
|
||||||
|
* <[64] multicast propagation bloom filter>
|
||||||
|
* <[1] 8-bit propagation hop count>
|
||||||
|
* <[2] 16-bit ethertype>
|
||||||
|
* <[2] 16-bit length of payload>
|
||||||
|
* <[2] 16-bit length of signature>
|
||||||
|
* <[...] ethernet payload>
|
||||||
|
* <[...] ECDSA signature>
|
||||||
|
*
|
||||||
|
* The signature is made using the key of the original submitter, and
|
||||||
|
* can be used to authenticate the submitter for security and rate
|
||||||
|
* control purposes. Fields in the signature are: network ID, source
|
||||||
|
* MAC, destination MAC, multicast ADI, ethertype, and payload. All
|
||||||
|
* integers are hashed in big-endian byte order. A zero byte is added
|
||||||
|
* to the hash between each field.
|
||||||
|
*
|
||||||
|
* In the future flags could indicate additional fields appended to the
|
||||||
|
* end or a different signature algorithm.
|
||||||
|
*
|
||||||
|
* No OK or ERROR is generated.
|
||||||
|
*/
|
||||||
|
VERB_MULTICAST_FRAME = 9
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
119
node/Switch.cpp
119
node/Switch.cpp
@ -219,8 +219,6 @@ Switch_onRemotePacket_complete_packet_handler:
|
|||||||
qe->second.localPort = localPort;
|
qe->second.localPort = localPort;
|
||||||
qe->second.fromAddr = fromAddr;
|
qe->second.fromAddr = fromAddr;
|
||||||
}
|
}
|
||||||
if (r == PACKET_SERVICE_ATTEMPT_PEER_UNKNOWN)
|
|
||||||
_requestWhois(source);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (std::exception &ex) {
|
} catch (std::exception &ex) {
|
||||||
@ -569,17 +567,30 @@ void Switch::_propagateMulticast(const SharedPtr<Network> &network,const Address
|
|||||||
SharedPtr<Peer> propPeers[ZT_MULTICAST_PROPAGATION_BREADTH];
|
SharedPtr<Peer> propPeers[ZT_MULTICAST_PROPAGATION_BREADTH];
|
||||||
unsigned int np = _multicaster.pickNextPropagationPeers(*(_r->topology),network->id(),mg,upstream,newBloom,ZT_MULTICAST_PROPAGATION_BREADTH,propPeers,Utils::now());
|
unsigned int np = _multicaster.pickNextPropagationPeers(*(_r->topology),network->id(),mg,upstream,newBloom,ZT_MULTICAST_PROPAGATION_BREADTH,propPeers,Utils::now());
|
||||||
|
|
||||||
|
if (!np)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::string signature(Multicaster::signMulticastPacket(_r->identity,from,mg,etherType,data,len));
|
||||||
|
if (!signature.length()) {
|
||||||
|
TRACE("failure signing multicast message!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for(unsigned int i=0;i<np;++i) {
|
for(unsigned int i=0;i<np;++i) {
|
||||||
Packet outp(propPeers[i]->address(),_r->identity.address(),Packet::VERB_MULTICAST_FRAME);
|
Packet outp(propPeers[i]->address(),_r->identity.address(),Packet::VERB_MULTICAST_FRAME);
|
||||||
|
outp.append((uint8_t)0);
|
||||||
outp.append((uint64_t)network->id());
|
outp.append((uint64_t)network->id());
|
||||||
|
outp.append(_r->identity.address().data(),ZT_ADDRESS_LENGTH);
|
||||||
|
outp.append(from.data,6);
|
||||||
outp.append(mg.mac().data,6);
|
outp.append(mg.mac().data,6);
|
||||||
outp.append((uint32_t)mg.adi());
|
outp.append((uint32_t)mg.adi());
|
||||||
outp.append(newBloom.data(),ZT_PROTO_VERB_MULTICAST_FRAME_BLOOM_FILTER_SIZE);
|
outp.append(newBloom.data(),ZT_PROTO_VERB_MULTICAST_FRAME_BLOOM_FILTER_SIZE);
|
||||||
outp.append((uint8_t)mcHops);
|
outp.append((uint8_t)mcHops);
|
||||||
outp.append((unsigned char)0,2); // reserved, 0
|
|
||||||
outp.append(from.data,6);
|
|
||||||
outp.append((uint16_t)etherType);
|
outp.append((uint16_t)etherType);
|
||||||
|
outp.append((uint16_t)len);
|
||||||
|
outp.append((uint16_t)signature.length());
|
||||||
outp.append(data,len);
|
outp.append(data,len);
|
||||||
|
outp.append(signature.data(),signature.length());
|
||||||
outp.compress();
|
outp.compress();
|
||||||
send(outp,true);
|
send(outp,true);
|
||||||
}
|
}
|
||||||
@ -747,45 +758,6 @@ Switch::PacketServiceAttemptResult Switch::_tryHandleRemotePacket(Demarc::Port l
|
|||||||
TRACE("dropped FRAME from %s: unexpected exception: (unknown)",source.toString().c_str());
|
TRACE("dropped FRAME from %s: unexpected exception: (unknown)",source.toString().c_str());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Packet::VERB_MULTICAST_FRAME:
|
|
||||||
try {
|
|
||||||
SharedPtr<Network> network(_r->nc->network(packet.at<uint64_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID)));
|
|
||||||
if (network) {
|
|
||||||
if (network->isAllowed(source)) {
|
|
||||||
if (packet.size() > ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PAYLOAD) {
|
|
||||||
MulticastGroup mg(MAC(packet.field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_MULTICAST_MAC,6)),packet.at<uint32_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ADI));
|
|
||||||
unsigned int hops = packet[ZT_PROTO_VERB_MULTICAST_FRAME_IDX_HOPS];
|
|
||||||
MAC fromMac(packet.field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FROM_MAC,6));
|
|
||||||
unsigned int etherType = packet.at<uint16_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ETHERTYPE);
|
|
||||||
unsigned int payloadLen = packet.size() - ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PAYLOAD;
|
|
||||||
unsigned char *payload = packet.field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PAYLOAD,payloadLen);
|
|
||||||
|
|
||||||
if (fromMac == network->tap().mac()) {
|
|
||||||
TRACE("dropped boomerang MULTICAST_FRAME from %s",source.toString().c_str());
|
|
||||||
} if (network->isAllowed(fromMac)) {
|
|
||||||
if (_multicaster.checkAndUpdateMulticastHistory(fromMac,mg,payload,payloadLen,network->id(),now)) {
|
|
||||||
// TODO: check if allowed etherType
|
|
||||||
network->tap().put(fromMac,mg.mac(),etherType,payload,payloadLen);
|
|
||||||
} else {
|
|
||||||
TRACE("duplicate MULTICAST_FRAME from %s: %s -> %s (adi: %.8lx), %u bytes, net: %llu",source.toString().c_str(),fromMac.toString().c_str(),mg.mac().toString().c_str(),(unsigned long)mg.adi(),packet.size() - ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PAYLOAD,network->id());
|
|
||||||
}
|
|
||||||
_propagateMulticast(network,source,packet.field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_BLOOM,ZT_PROTO_VERB_MULTICAST_FRAME_BLOOM_FILTER_SIZE),mg,hops+1,fromMac,etherType,payload,payloadLen);
|
|
||||||
} else {
|
|
||||||
TRACE("dropped MULTICAST_FRAME from %s: ultimate sender %s not a member of closed network %llu",source.toString().c_str(),fromMac.toString().c_str(),network->id());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
TRACE("dropped MULTICAST_FRAME from %s: not a member of closed network %llu",source.toString().c_str(),network->id());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
TRACE("dropped MULTICAST_FRAME from %s: network %llu unknown",source.toString().c_str(),packet.at<uint64_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID));
|
|
||||||
}
|
|
||||||
} catch (std::exception &ex) {
|
|
||||||
TRACE("dropped MULTICAST_FRAME from %s: unexpected exception: %s",source.toString().c_str(),ex.what());
|
|
||||||
} catch ( ... ) {
|
|
||||||
TRACE("dropped MULTICAST_FRAME from %s: unexpected exception: (unknown)",source.toString().c_str());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Packet::VERB_MULTICAST_LIKE:
|
case Packet::VERB_MULTICAST_LIKE:
|
||||||
try {
|
try {
|
||||||
unsigned int ptr = ZT_PACKET_IDX_PAYLOAD;
|
unsigned int ptr = ZT_PACKET_IDX_PAYLOAD;
|
||||||
@ -821,6 +793,62 @@ Switch::PacketServiceAttemptResult Switch::_tryHandleRemotePacket(Demarc::Port l
|
|||||||
TRACE("dropped MULTICAST_LIKE from %s: unexpected exception: (unknown)",source.toString().c_str());
|
TRACE("dropped MULTICAST_LIKE from %s: unexpected exception: (unknown)",source.toString().c_str());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case Packet::VERB_MULTICAST_FRAME:
|
||||||
|
try {
|
||||||
|
SharedPtr<Network> network(_r->nc->network(packet.at<uint64_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID)));
|
||||||
|
if (network) {
|
||||||
|
if (network->isAllowed(source)) {
|
||||||
|
if (packet.size() > ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PAYLOAD) {
|
||||||
|
Address originalSubmitterAddress(packet.field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SUBMITTER_ADDRESS,ZT_ADDRESS_LENGTH));
|
||||||
|
if (originalSubmitterAddress == _r->identity.address()) {
|
||||||
|
TRACE("dropped boomerang MULTICAST_FRAME received from %s",source.toString().c_str());
|
||||||
|
} else {
|
||||||
|
SharedPtr<Peer> originalSubmitter(_r->topology->getPeer(originalSubmitterAddress));
|
||||||
|
if (!originalSubmitter) {
|
||||||
|
// If we don't know the original submitter, try to look them up
|
||||||
|
// and abort.
|
||||||
|
// TODO: need to rearchitect how we wait for and handle whois
|
||||||
|
// responses so they trigger a re-eval of this packet instantly.
|
||||||
|
_requestWhois(originalSubmitterAddress);
|
||||||
|
return PACKET_SERVICE_ATTEMPT_PEER_UNKNOWN;
|
||||||
|
} else {
|
||||||
|
MAC fromMac(packet.field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SOURCE_MAC,6));
|
||||||
|
MulticastGroup mg(MAC(packet.field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DESTINATION_MAC,6)),packet.at<uint32_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ADI));
|
||||||
|
unsigned int hops = packet[ZT_PROTO_VERB_MULTICAST_FRAME_IDX_HOP_COUNT];
|
||||||
|
unsigned int etherType = packet.at<uint16_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ETHERTYPE);
|
||||||
|
unsigned int datalen = packet.at<uint16_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PAYLOAD_LENGTH);
|
||||||
|
unsigned int signaturelen = packet.at<uint16_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SIGNATURE_LENGTH);
|
||||||
|
unsigned char *dataAndSignature = packet.field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PAYLOAD,datalen + signaturelen);
|
||||||
|
|
||||||
|
if (Multicaster::verifyMulticastPacket(originalSubmitter->identity(),fromMac,mg,etherType,data,datalen,dataAndSignature + datalen,signaturelen)) {
|
||||||
|
if (network->isAllowed(originalSubmitterAddress)) {
|
||||||
|
if (_multicaster.checkAndUpdateMulticastHistory(fromMac,mg,payload,payloadLen,network->id(),now)) {
|
||||||
|
// TODO: check if allowed etherType
|
||||||
|
network->tap().put(fromMac,mg.mac(),etherType,payload,payloadLen);
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
_propagateMulticast(network,source,packet.field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_BLOOM,ZT_PROTO_VERB_MULTICAST_FRAME_BLOOM_FILTER_SIZE),mg,hops+1,fromMac,etherType,payload,payloadLen);
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
TRACE("dropped MULTICAST_FRAME from %s: not a member of closed network %llu",source.toString().c_str(),network->id());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
TRACE("dropped MULTICAST_FRAME from %s: network %llu unknown or we are not a member",source.toString().c_str(),packet.at<uint64_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID));
|
||||||
|
}
|
||||||
|
} catch (std::exception &ex) {
|
||||||
|
TRACE("dropped MULTICAST_FRAME from %s: unexpected exception: %s",source.toString().c_str(),ex.what());
|
||||||
|
} catch ( ... ) {
|
||||||
|
TRACE("dropped MULTICAST_FRAME from %s: unexpected exception: (unknown)",source.toString().c_str());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
TRACE("ignored unrecognized verb %.2x from %s",(unsigned int)packet.verb(),source.toString().c_str());
|
TRACE("ignored unrecognized verb %.2x from %s",(unsigned int)packet.verb(),source.toString().c_str());
|
||||||
break;
|
break;
|
||||||
@ -828,7 +856,10 @@ Switch::PacketServiceAttemptResult Switch::_tryHandleRemotePacket(Demarc::Port l
|
|||||||
|
|
||||||
// Update peer timestamps and learn new links
|
// Update peer timestamps and learn new links
|
||||||
peer->onReceive(_r,localPort,fromAddr,latency,packet.hops(),packet.verb(),now);
|
peer->onReceive(_r,localPort,fromAddr,latency,packet.hops(),packet.verb(),now);
|
||||||
} else return PACKET_SERVICE_ATTEMPT_PEER_UNKNOWN;
|
} else {
|
||||||
|
_requestWhois(source);
|
||||||
|
return PACKET_SERVICE_ATTEMPT_PEER_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
return PACKET_SERVICE_ATTEMPT_OK;
|
return PACKET_SERVICE_ATTEMPT_OK;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user