Add capability for P2P multicast propagation, and some cleanup.
This commit is contained in:
parent
98bbb84a63
commit
debd5a5c5e
15 changed files with 119 additions and 257 deletions
|
@ -28,6 +28,8 @@
|
|||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "../version.h"
|
||||
#include "../include/ZeroTierOne.h"
|
||||
|
||||
|
@ -168,13 +170,14 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,void *tPtr,const Shar
|
|||
break;
|
||||
|
||||
case Packet::ERROR_IDENTITY_COLLISION:
|
||||
// FIXME: for federation this will need a payload with a signature or something.
|
||||
// This is a trusted upstream telling us our 5-digit ID is taken. This
|
||||
// causes the node to generate another.
|
||||
if (RR->topology->isUpstream(peer->identity()))
|
||||
RR->node->postEvent(tPtr,ZT_EVENT_FATAL_ERROR_IDENTITY_COLLISION);
|
||||
break;
|
||||
|
||||
case Packet::ERROR_NEED_MEMBERSHIP_CERTIFICATE: {
|
||||
// Peers can send this in response to frames if they do not have a recent enough COM from us
|
||||
// Peers can send this to ask for a cert for a network.
|
||||
networkId = at<uint64_t>(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD);
|
||||
const SharedPtr<Network> network(RR->node->network(networkId));
|
||||
const int64_t now = RR->node->now();
|
||||
|
@ -1000,18 +1003,16 @@ bool IncomingPacket::_doMULTICAST_GATHER(const RuntimeEnvironment *RR,void *tPtr
|
|||
|
||||
bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer)
|
||||
{
|
||||
const uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID);
|
||||
const unsigned int flags = (*this)[ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FLAGS];
|
||||
unsigned int offset = ZT_PACKET_IDX_PAYLOAD;
|
||||
const uint64_t nwid = at<uint64_t>(offset); offset += 8;
|
||||
const unsigned int flags = (*this)[offset]; ++offset;
|
||||
|
||||
const SharedPtr<Network> network(RR->node->network(nwid));
|
||||
if (network) {
|
||||
// Offset -- size of optional fields added to position of later fields
|
||||
unsigned int offset = 0;
|
||||
|
||||
if ((flags & 0x01) != 0) {
|
||||
// This is deprecated but may still be sent by old peers
|
||||
CertificateOfMembership com;
|
||||
offset += com.deserialize(*this,ZT_PROTO_VERB_MULTICAST_FRAME_IDX_COM);
|
||||
offset += com.deserialize(*this,offset);
|
||||
if (com)
|
||||
network->addCredential(tPtr,com);
|
||||
}
|
||||
|
@ -1023,60 +1024,87 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,void *tPtr,
|
|||
|
||||
unsigned int gatherLimit = 0;
|
||||
if ((flags & 0x02) != 0) {
|
||||
gatherLimit = at<uint32_t>(offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_GATHER_LIMIT);
|
||||
offset += 4;
|
||||
gatherLimit = at<uint32_t>(offset); offset += 4;
|
||||
}
|
||||
|
||||
MAC from;
|
||||
if ((flags & 0x04) != 0) {
|
||||
from.setTo(field(offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SOURCE_MAC,6),6);
|
||||
offset += 6;
|
||||
from.setTo(field(offset,6),6); offset += 6;
|
||||
} else {
|
||||
from.fromAddress(peer->address(),nwid);
|
||||
}
|
||||
|
||||
const MulticastGroup to(MAC(field(offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_MAC,6),6),at<uint32_t>(offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_ADI));
|
||||
const unsigned int etherType = at<uint16_t>(offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ETHERTYPE);
|
||||
const unsigned int frameLen = size() - (offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME);
|
||||
const unsigned int recipientsOffset = offset;
|
||||
std::list<Address> recipients;
|
||||
if ((flags & 0x08) != 0) {
|
||||
const unsigned int rc = at<uint16_t>(offset); offset += 2;
|
||||
for(unsigned int i=0;i<rc;++i) {
|
||||
const Address a(field(offset,5),5);
|
||||
if ((a != peer->address())&&(a != RR->identity.address())) {
|
||||
recipients.push_back(a);
|
||||
}
|
||||
offset += 5;
|
||||
}
|
||||
}
|
||||
const unsigned int afterRecipientsOffset = offset;
|
||||
|
||||
const MulticastGroup to(MAC(field(offset,6),6),at<uint32_t>(offset + 6)); offset += 10;
|
||||
const unsigned int etherType = at<uint16_t>(offset); offset += 2;
|
||||
const unsigned int frameLen = size() - offset;
|
||||
|
||||
if (network->config().multicastLimit == 0) {
|
||||
RR->t->incomingNetworkFrameDropped(tPtr,network,_path,packetId(),size(),peer->address(),Packet::VERB_MULTICAST_FRAME,from,to.mac(),"multicast disabled");
|
||||
peer->received(tPtr,_path,hops(),packetId(),payloadLength(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,false,nwid);
|
||||
peer->received(tPtr,_path,hops(),packetId(),payloadLength(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,true,nwid);
|
||||
return true;
|
||||
}
|
||||
if (!to.mac().isMulticast()) {
|
||||
RR->t->incomingPacketInvalid(tPtr,_path,packetId(),source(),hops(),Packet::VERB_MULTICAST_FRAME,"destination not multicast");
|
||||
peer->received(tPtr,_path,hops(),packetId(),payloadLength(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,true,nwid);
|
||||
return true;
|
||||
}
|
||||
if ((!from)||(from.isMulticast())||(from == network->mac())) {
|
||||
RR->t->incomingPacketInvalid(tPtr,_path,packetId(),source(),hops(),Packet::VERB_MULTICAST_FRAME,"invalid source MAC");
|
||||
peer->received(tPtr,_path,hops(),packetId(),payloadLength(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,true,nwid);
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((frameLen > 0)&&(frameLen <= ZT_MAX_MTU)) {
|
||||
if (!to.mac().isMulticast()) {
|
||||
RR->t->incomingPacketInvalid(tPtr,_path,packetId(),source(),hops(),Packet::VERB_MULTICAST_FRAME,"destination not multicast");
|
||||
peer->received(tPtr,_path,hops(),packetId(),payloadLength(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,true,nwid); // trustEstablished because COM is okay
|
||||
return true;
|
||||
}
|
||||
if ((!from)||(from.isMulticast())||(from == network->mac())) {
|
||||
RR->t->incomingPacketInvalid(tPtr,_path,packetId(),source(),hops(),Packet::VERB_MULTICAST_FRAME,"invalid source MAC");
|
||||
peer->received(tPtr,_path,hops(),packetId(),payloadLength(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,true,nwid); // trustEstablished because COM is okay
|
||||
return true;
|
||||
}
|
||||
|
||||
const uint8_t *const frameData = (const uint8_t *)field(offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME,frameLen);
|
||||
|
||||
if ((flags & 0x08)&&(network->config().isMulticastReplicator(RR->identity.address())))
|
||||
RR->mc->send(tPtr,RR->node->now(),network,peer->address(),to,from,etherType,frameData,frameLen);
|
||||
|
||||
if (from != MAC(peer->address(),nwid)) {
|
||||
if (network->config().permitsBridging(peer->address())) {
|
||||
network->learnBridgeRoute(from,peer->address());
|
||||
} else {
|
||||
RR->t->incomingNetworkFrameDropped(tPtr,network,_path,packetId(),size(),peer->address(),Packet::VERB_MULTICAST_FRAME,from,to.mac(),"bridging not allowed (remote)");
|
||||
peer->received(tPtr,_path,hops(),packetId(),payloadLength(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,true,nwid); // trustEstablished because COM is okay
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (network->filterIncomingPacket(tPtr,peer,RR->identity.address(),from,to.mac(),frameData,frameLen,etherType,0) > 0)
|
||||
const uint8_t *const frameData = ((const uint8_t *)unsafeData()) + offset;
|
||||
if (network->filterIncomingPacket(tPtr,peer,RR->identity.address(),from,to.mac(),frameData,frameLen,etherType,0) > 0) {
|
||||
RR->node->putFrame(tPtr,nwid,network->userPtr(),from,to.mac(),etherType,0,(const void *)frameData,frameLen);
|
||||
}
|
||||
}
|
||||
|
||||
if (gatherLimit) {
|
||||
if (!recipients.empty()) {
|
||||
const std::vector<Address> anchors = network->config().anchors();
|
||||
const bool amAnchor = (std::find(anchors.begin(),anchors.end(),RR->identity.address()) != anchors.end());
|
||||
|
||||
for(std::list<Address>::iterator ra(recipients.begin());ra!=recipients.end();) {
|
||||
SharedPtr<Peer> recipient(RR->topology->getPeer(tPtr,*ra));
|
||||
if ((recipient)&&((recipient->remoteVersionProtocol() < 10)||(amAnchor))) {
|
||||
Packet outp(*ra,RR->identity.address(),Packet::VERB_MULTICAST_FRAME);
|
||||
outp.append(field(ZT_PACKET_IDX_PAYLOAD,recipientsOffset - ZT_PACKET_IDX_PAYLOAD),recipientsOffset - ZT_PACKET_IDX_PAYLOAD);
|
||||
outp.append(field(afterRecipientsOffset,size() - afterRecipientsOffset),size() - afterRecipientsOffset);
|
||||
RR->sw->send(tPtr,outp,true);
|
||||
recipients.erase(ra++);
|
||||
} else ++ra;
|
||||
}
|
||||
|
||||
if (!recipients.empty()) {
|
||||
Packet outp(recipients.front(),RR->identity.address(),Packet::VERB_MULTICAST_FRAME);
|
||||
recipients.pop_front();
|
||||
outp.append(field(ZT_PACKET_IDX_PAYLOAD,recipientsOffset - ZT_PACKET_IDX_PAYLOAD),recipientsOffset - ZT_PACKET_IDX_PAYLOAD);
|
||||
if (!recipients.empty()) {
|
||||
outp.append((uint16_t)recipients.size());
|
||||
for(std::list<Address>::iterator ra(recipients.begin());ra!=recipients.end();++ra)
|
||||
ra->appendTo(outp);
|
||||
}
|
||||
outp.append(field(afterRecipientsOffset,size() - afterRecipientsOffset),size() - afterRecipientsOffset);
|
||||
RR->sw->send(tPtr,outp,true);
|
||||
}
|
||||
}
|
||||
|
||||
if (gatherLimit) { // DEPRECATED but still supported
|
||||
Packet outp(source(),RR->identity.address(),Packet::VERB_OK);
|
||||
outp.append((unsigned char)Packet::VERB_MULTICAST_FRAME);
|
||||
outp.append(packetId());
|
||||
|
@ -1091,12 +1119,11 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,void *tPtr,
|
|||
}
|
||||
|
||||
peer->received(tPtr,_path,hops(),packetId(),payloadLength(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,true,nwid);
|
||||
return true;
|
||||
} else {
|
||||
_sendErrorNeedCredentials(RR,tPtr,peer,nwid);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue