summaryrefslogtreecommitdiff
path: root/node/IncomingPacket.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'node/IncomingPacket.cpp')
-rw-r--r--node/IncomingPacket.cpp172
1 files changed, 101 insertions, 71 deletions
diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp
index 80988130..7cbd620c 100644
--- a/node/IncomingPacket.cpp
+++ b/node/IncomingPacket.cpp
@@ -128,8 +128,15 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,const SharedPtr<Peer>
case Packet::ERROR_NEED_MEMBERSHIP_CERTIFICATE: {
SharedPtr<Network> network(RR->nc->network(at<uint64_t>(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD)));
- if (network)
- network->pushMembershipCertificate(source(),true,Utils::now());
+ if (network) {
+ SharedPtr<NetworkConfig> nconf(network->config2());
+ if (nconf) {
+ Packet outp(peer->address(),RR->identity.address(),Packet::VERB_NETWORK_MEMBERSHIP_CERTIFICATE);
+ nconf->com().serialize(outp);
+ outp.armor(peer->key(),true);
+ _fromSock->send(_remoteAddress,outp.data(),outp.size());
+ }
+ }
} break;
case Packet::ERROR_NETWORK_ACCESS_DENIED_: {
@@ -138,9 +145,9 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,const SharedPtr<Peer>
network->setAccessDenied();
} break;
- // TODO -- send and accept these to cancel multicast "LIKE"s
- //case Packet::ERROR_UNWANTED_MULTICAST: {
- //} break;
+ case Packet::ERROR_UNWANTED_MULTICAST: {
+ // TODO: unsubscribe
+ } break;
default: break;
}
@@ -330,10 +337,23 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &p
case Packet::VERB_MULTICAST_FRAME: {
unsigned int flags = (*this)[ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_FLAGS];
- if ((flags & 0x01) != 0) { // frame includes implicit gather results
- uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_NETWORK_ID);
- MulticastGroup mg(MAC(field(ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_MAC,6),6),at<uint32_t>(ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_ADI));
- _parseGatherResults(RR,peer,nwid,mg,ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_GATHER_RESULTS);
+ uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_NETWORK_ID);
+ MulticastGroup mg(MAC(field(ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_MAC,6),6),at<uint32_t>(ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_ADI));
+
+ unsigned int offset = 0;
+
+ if ((flags & 0x01) != 0) {
+ // OK(MULTICAST_FRAME) includes certificate of membership update
+ CertificateOfMembership com;
+ offset += com.deserialize(*this,ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_PAYLOAD);
+ SharedPtr<Network> network(RR->nc->network(nwid));
+ if ((network)&&(com.hasRequiredFields()))
+ network->addMembershipCertificate(com,false);
+ }
+
+ if ((flags & 0x02) != 0) {
+ // OK(MULTICAST_FRAME) includes implicit gather results
+ _parseGatherResults(RR,peer,nwid,mg,offset + ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_PAYLOAD);
}
} break;
@@ -540,13 +560,13 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,const SharedPtr<P
bool IncomingPacket::_doP5_MULTICAST_FRAME(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer)
{
- // This handles the old deprecated "P5" multicast frame, and will
- // go away once there are no longer nodes using this on the network.
- // We handle these old nodes by accepting these as simple multicasts
- // and if we are a supernode performing individual relaying of them
- // to all older nodes that expect them. This won't be too expensive
- // though since there aren't likely to be many older nodes left after
- // we do a software update.
+ /* This handles the old deprecated "P5" multicast frame, and will
+ * go away once there are no longer nodes using this on the network.
+ * We handle these old nodes by accepting these as simple multicasts
+ * and if we are a supernode performing individual relaying of them
+ * to all older nodes that expect them. This won't be too expensive
+ * though since there aren't likely to be many older nodes left after
+ * we do a software update. */
// Quick and dirty -- this is all condemned code in any case
static uint64_t p5MulticastDedupBuffer[1024];
@@ -1027,73 +1047,83 @@ bool IncomingPacket::_doMULTICAST_GATHER(const RuntimeEnvironment *RR,const Shar
bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer)
{
try {
- if (size() > ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME) {
- uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID);
- unsigned int flags = (*this)[ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FLAGS];
- unsigned int gatherLimit = at<uint32_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_GATHER_LIMIT);
-
- SharedPtr<Network> network(RR->nc->network(nwid)); // will be NULL if not a member
- if (network) {
- unsigned int comLen = 0;
- if ((flags & 0x01) != 0) {
- CertificateOfMembership com;
- comLen = com.deserialize(*this,ZT_PROTO_VERB_MULTICAST_FRAME_IDX_COM);
- if (com.hasRequiredFields())
- network->addMembershipCertificate(com,false);
- }
+ uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID);
+ unsigned int flags = (*this)[ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FLAGS];
- if (!network->isAllowed(peer->address())) {
- TRACE("dropped FRAME from %s(%s): not a member of private network %.16llx",peer->address().toString().c_str(),_remoteAddress.toString().c_str(),(unsigned long long)network->id());
- _sendErrorNeedCertificate(RR,peer,network->id());
- return true;
- }
+ SharedPtr<Network> network(RR->nc->network(nwid)); // will be NULL if not a member
+ if (network) {
+ // Offset -- size of optional fields added to position of later fields
+ unsigned int offset = 0;
- // Everything after gatherLimit is relative to the size of the
- // attached certificate, if any.
+ if ((flags & 0x01) != 0) {
+ CertificateOfMembership com;
+ offset += com.deserialize(*this,ZT_PROTO_VERB_MULTICAST_FRAME_IDX_COM);
+ if (com.hasRequiredFields())
+ network->addMembershipCertificate(com,false);
+ }
- MulticastGroup to(MAC(field(comLen + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_MAC,6),6),at<uint32_t>(comLen + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_ADI));
- MAC from(field(comLen + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SOURCE_MAC,6),6);
- unsigned int etherType = at<uint16_t>(comLen + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ETHERTYPE);
- unsigned int payloadLen = size() - (comLen + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME);
+ // Check membership after we've read any included COM, since
+ // that cert might be what we needed.
+ if (!network->isAllowed(peer->address())) {
+ TRACE("dropped MULTICAST_FRAME from %s(%s): not a member of private network %.16llx",peer->address().toString().c_str(),_remoteAddress.toString().c_str(),(unsigned long long)network->id());
+ _sendErrorNeedCertificate(RR,peer,network->id());
+ return true;
+ }
- if (payloadLen) {
- 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(),_remoteAddress.toString().c_str(),to.toString().c_str());
- return true;
- }
+ unsigned int gatherLimit = 0;
+ if ((flags & 0x02) != 0) {
+ gatherLimit = at<uint32_t>(offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_GATHER_LIMIT);
+ offset += 4;
+ }
- if ((!from)||(from.isMulticast())||(from == network->mac())) {
- TRACE("dropped MULTICAST_FRAME from %s@%s(%s) to %s: invalid source MAC",from.toString().c_str(),peer->address().toString().c_str(),_remoteAddress.toString().c_str(),to.toString().c_str());
- return true;
- }
+ MAC from;
+ if ((flags & 0x04) != 0) {
+ from.setTo(field(offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SOURCE_MAC,6),6);
+ offset += 6;
+ } else {
+ from.fromAddress(source(),nwid);
+ }
- if (from != MAC(peer->address(),network->id())) {
- if (network->permitsBridging(peer->address())) {
- network->learnBridgeRoute(from,peer->address());
- } else {
- TRACE("dropped MULTICAST_FRAME from %s@%s(%s) to %s: sender not allowed to bridge into %.16llx",from.toString().c_str(),peer->address().toString().c_str(),_remoteAddress.toString().c_str(),to.toString().c_str(),network->id());
- return true;
- }
- }
+ 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));
+ unsigned int etherType = at<uint16_t>(offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ETHERTYPE);
+ unsigned int payloadLen = size() - (offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME);
- network->tapPut(from,to.mac(),etherType,field(comLen + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME,payloadLen),payloadLen);
+ if ((payloadLen > 0)&&(payloadLen < ZT_IF_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(),_remoteAddress.toString().c_str(),to.toString().c_str());
+ return true;
+ }
+ if ((!from)||(from.isMulticast())||(from == network->mac())) {
+ TRACE("dropped MULTICAST_FRAME from %s@%s(%s) to %s: invalid source MAC",from.toString().c_str(),peer->address().toString().c_str(),_remoteAddress.toString().c_str(),to.toString().c_str());
+ return true;
}
- if (gatherLimit) {
- Packet outp(source(),RR->identity.address(),Packet::VERB_OK);
- outp.append((unsigned char)Packet::VERB_MULTICAST_FRAME);
- outp.append(packetId());
- outp.append(nwid);
- to.mac().appendTo(outp);
- outp.append((uint32_t)to.adi());
- outp.append((unsigned char)0x01); // flag 0x01 = contains gather results
- if (RR->mc->gather(peer->address(),nwid,to,outp,gatherLimit)) {
- outp.armor(peer->key(),true);
- _fromSock->send(_remoteAddress,outp.data(),outp.size());
+ if (from != MAC(peer->address(),network->id())) {
+ if (network->permitsBridging(peer->address())) {
+ network->learnBridgeRoute(from,peer->address());
+ } else {
+ TRACE("dropped MULTICAST_FRAME from %s@%s(%s) to %s: sender not allowed to bridge into %.16llx",from.toString().c_str(),peer->address().toString().c_str(),_remoteAddress.toString().c_str(),to.toString().c_str(),network->id());
+ return true;
}
}
+
+ network->tapPut(from,to.mac(),etherType,field(offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME,payloadLen),offset);
}
- }
+
+ if (gatherLimit) {
+ Packet outp(source(),RR->identity.address(),Packet::VERB_OK);
+ outp.append((unsigned char)Packet::VERB_MULTICAST_FRAME);
+ outp.append(packetId());
+ outp.append(nwid);
+ to.mac().appendTo(outp);
+ outp.append((uint32_t)to.adi());
+ outp.append((unsigned char)0x02); // flag 0x02 = contains gather results
+ if (RR->mc->gather(peer->address(),nwid,to,outp,gatherLimit)) {
+ outp.armor(peer->key(),true);
+ _fromSock->send(_remoteAddress,outp.data(),outp.size());
+ }
+ }
+ } // else ignore -- not a member of this network
peer->receive(RR,_fromSock,_remoteAddress,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,Utils::now());
} catch (std::exception &exc) {