From f0636ffd4a86336f00bbf77a3e303def6261b518 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 29 Aug 2016 15:54:06 -0700 Subject: [PATCH] EXT_FRAME messages should always be accepted if we are the destination for a matching TEE or REDIRECT rule. --- node/IncomingPacket.cpp | 46 ++++++++++++++++++++--------------------- node/Network.cpp | 35 ++++++++++++++++--------------- node/Network.hpp | 4 ++-- 3 files changed, 43 insertions(+), 42 deletions(-) diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index 0804f04a1..c75125d34 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -596,13 +596,11 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,const SharedPtr

(comLen + ZT_PROTO_VERB_EXT_FRAME_IDX_ETHERTYPE); - const MAC to(field(comLen + ZT_PROTO_VERB_EXT_FRAME_IDX_TO,ZT_PROTO_VERB_EXT_FRAME_LEN_TO),ZT_PROTO_VERB_EXT_FRAME_LEN_TO); const MAC from(field(comLen + ZT_PROTO_VERB_EXT_FRAME_IDX_FROM,ZT_PROTO_VERB_EXT_FRAME_LEN_FROM),ZT_PROTO_VERB_EXT_FRAME_LEN_FROM); + const unsigned int frameLen = size() - (comLen + ZT_PROTO_VERB_EXT_FRAME_IDX_PAYLOAD); + const uint8_t *const frameData = (const uint8_t *)field(comLen + ZT_PROTO_VERB_EXT_FRAME_IDX_PAYLOAD,frameLen); if ((!from)||(from.isMulticast())||(from == network->mac())) { TRACE("dropped EXT_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()); @@ -610,27 +608,29 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,const SharedPtr

address(),network->id())) { - if (network->config().permitsBridging(peer->address())) { - network->learnBridgeRoute(from,peer->address()); - } else { - TRACE("dropped EXT_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()); - peer->received(_localAddress,_remoteAddress,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay - return true; - } - } else if (to != network->mac()) { - if (!network->config().permitsBridging(RR->identity.address())) { - TRACE("dropped EXT_FRAME from %s@%s(%s) to %s: I cannot bridge to %.16llx or bridging disabled on network",from.toString().c_str(),peer->address().toString().c_str(),_remoteAddress.toString().c_str(),to.toString().c_str(),network->id()); - peer->received(_localAddress,_remoteAddress,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay - return true; - } + switch (network->filterIncomingPacket(peer,RR->identity.address(),from,to,frameData,frameLen,etherType,0)) { + case 1: + if (from != MAC(peer->address(),network->id())) { + if (network->config().permitsBridging(peer->address())) { + network->learnBridgeRoute(from,peer->address()); + } else { + TRACE("dropped EXT_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()); + peer->received(_localAddress,_remoteAddress,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay + return true; + } + } else if (to != network->mac()) { + if (!network->config().permitsBridging(RR->identity.address())) { + TRACE("dropped EXT_FRAME from %s@%s(%s) to %s: I cannot bridge to %.16llx or bridging disabled on network",from.toString().c_str(),peer->address().toString().c_str(),_remoteAddress.toString().c_str(),to.toString().c_str(),network->id()); + peer->received(_localAddress,_remoteAddress,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay + return true; + } + } + // fall through -- 2 means accept regardless of bridging state + case 2: + RR->node->putFrame(network->id(),network->userPtr(),from,to,etherType,0,(const void *)frameData,frameLen); + break; } - const unsigned int frameLen = size() - (comLen + ZT_PROTO_VERB_EXT_FRAME_IDX_PAYLOAD); - const uint8_t *const frameData = (const uint8_t *)field(comLen + ZT_PROTO_VERB_EXT_FRAME_IDX_PAYLOAD,frameLen); - if (network->filterIncomingPacket(peer,RR->identity.address(),from,to,frameData,frameLen,etherType,0)) - RR->node->putFrame(network->id(),network->userPtr(),from,to,etherType,0,(const void *)frameData,frameLen); - peer->received(_localAddress,_remoteAddress,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,true); } } else { diff --git a/node/Network.cpp b/node/Network.cpp index 5fd7ac8cc..fa8cad804 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -77,7 +77,9 @@ static const char *_rtn(const ZT_VirtualNetworkRuleType rt) } static const void _dumpFilterTrace(const char *ruleName,uint8_t thisSetMatches,bool noRedirect,bool inbound,const Address &ztSource,const Address &ztDest,const MAC &macSource,const MAC &macDest,const std::vector &dlog,unsigned int frameLen,unsigned int etherType,const char *msg) { - printf("!! %c %s inbound=%d noRedirect=%d frameLen=%u etherType=%u" ZT_EOL_S, + static volatile unsigned long cnt = 0; + printf("%.6lu %c %s inbound=%d noRedirect=%d frameLen=%u etherType=%u" ZT_EOL_S, + cnt, ((thisSetMatches) ? 'Y' : '.'), ruleName, (int)inbound, @@ -86,8 +88,8 @@ static const void _dumpFilterTrace(const char *ruleName,uint8_t thisSetMatches,b etherType ); for(std::vector::const_iterator m(dlog.begin());m!=dlog.end();++m) - printf(" | %s" ZT_EOL_S,m->c_str()); - printf(" + %c %s->%s %.2x:%.2x:%.2x:%.2x:%.2x:%.2x->%.2x:%.2x:%.2x:%.2x:%.2x:%.2x" ZT_EOL_S, + printf(" | %s" ZT_EOL_S,m->c_str()); + printf(" + %c %s->%s %.2x:%.2x:%.2x:%.2x:%.2x:%.2x->%.2x:%.2x:%.2x:%.2x:%.2x:%.2x" ZT_EOL_S, ((thisSetMatches) ? 'Y' : '.'), ztSource.toString().c_str(), ztDest.toString().c_str(), @@ -105,7 +107,7 @@ static const void _dumpFilterTrace(const char *ruleName,uint8_t thisSetMatches,b (unsigned int)macDest[5] ); if (msg) - printf(" + (%s)" ZT_EOL_S,msg); + printf(" + (%s)" ZT_EOL_S,msg); } #else #define FILTER_TRACE(f,...) {} @@ -140,7 +142,7 @@ static bool _ipv6GetPayload(const uint8_t *frameData,unsigned int frameLen,unsig return false; // overflow == invalid } -// 0 == no match, -1 == match/drop, 1 == match/accept +// 0 == no match, -1 == match/drop, 1 == match/accept, 2 == match/accept even if bridged static int _doZtFilter( const RuntimeEnvironment *RR, const bool noRedirect, @@ -212,9 +214,8 @@ static int _doZtFilter( // REDIRECT as DROP since we are the destination. #ifdef ZT_RULES_ENGINE_DEBUGGING _dumpFilterTrace(_rtn(rt),thisSetMatches,noRedirect,inbound,ztSource,ztDest,macSource,macDest,dlog,frameLen,etherType,"ignored since we are the destination"); - dlog.clear(); #endif // ZT_RULES_ENGINE_DEBUGGING - thisSetMatches = 1; + return 2; // we should "super-accept" this packet since we are the TEE or REDIRECT destination } else { if (!noRedirect) { Packet outp(fwdAddr,RR->identity.address(),Packet::VERB_EXT_FRAME); @@ -580,6 +581,7 @@ bool Network::filterOutgoingPacket( m.sendCredentialsIfNeeded(RR,RR->node->now(),ztDest,_config,(const Capability *)0); return false; case 1: + case 2: if (ztDest) m.sendCredentialsIfNeeded(RR,RR->node->now(),ztDest,_config,(const Capability *)0); return true; @@ -592,6 +594,7 @@ bool Network::filterOutgoingPacket( m.sendCredentialsIfNeeded(RR,RR->node->now(),ztDest,_config,(const Capability *)0); return false; case 1: + case 2: if (ztDest) m.sendCredentialsIfNeeded(RR,RR->node->now(),ztDest,_config,&(_config.capabilities[c])); return true; @@ -601,7 +604,7 @@ bool Network::filterOutgoingPacket( return false; } -bool Network::filterIncomingPacket( +int Network::filterIncomingPacket( const SharedPtr &sourcePeer, const Address &ztDest, const MAC &macSource, @@ -620,24 +623,22 @@ bool Network::filterIncomingPacket( const unsigned int remoteTagCount = m.getAllTags(_config,remoteTagIds,remoteTagValues,ZT_MAX_NETWORK_TAGS); switch (_doZtFilter(RR,false,_config,true,sourcePeer->address(),ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,_config.rules,_config.ruleCount,_config.tags,_config.tagCount,remoteTagIds,remoteTagValues,remoteTagCount)) { - case -1: - return false; - case 1: - return true; + case -1: return 0; + case 1: return 1; + case 2: return 2; } Membership::CapabilityIterator mci(m); const Capability *c; while ((c = mci.next(_config))) { switch(_doZtFilter(RR,false,_config,false,sourcePeer->address(),ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,c->rules(),c->ruleCount(),_config.tags,_config.tagCount,remoteTagIds,remoteTagValues,remoteTagCount)) { - case -1: - return false; - case 1: - return true; + case -1: return 0; + case 1: return 1; + case 2: return 2; } } - return false; + return 0; } bool Network::subscribedToMulticastGroup(const MulticastGroup &mg,bool includeBridgedGroups) const diff --git a/node/Network.hpp b/node/Network.hpp index c5e7d570a..aa4b67f8f 100644 --- a/node/Network.hpp +++ b/node/Network.hpp @@ -124,9 +124,9 @@ public: * @param frameLen Ethernet frame payload length * @param etherType 16-bit ethernet type ID * @param vlanId 16-bit VLAN ID - * @return True if packet should be accepted locally + * @return 0 == drop, 1 == accept, 2 == accept even if bridged */ - bool filterIncomingPacket( + int filterIncomingPacket( const SharedPtr &sourcePeer, const Address &ztDest, const MAC &macSource,