|
|
|
|
@ -22,19 +22,313 @@
|
|
|
|
|
#include <math.h> |
|
|
|
|
|
|
|
|
|
#include "Constants.hpp" |
|
|
|
|
#include "../version.h" |
|
|
|
|
#include "Network.hpp" |
|
|
|
|
#include "RuntimeEnvironment.hpp" |
|
|
|
|
#include "MAC.hpp" |
|
|
|
|
#include "Address.hpp" |
|
|
|
|
#include "InetAddress.hpp" |
|
|
|
|
#include "Switch.hpp" |
|
|
|
|
#include "Packet.hpp" |
|
|
|
|
#include "Buffer.hpp" |
|
|
|
|
#include "Packet.hpp" |
|
|
|
|
#include "NetworkController.hpp" |
|
|
|
|
#include "Node.hpp" |
|
|
|
|
#include "Peer.hpp" |
|
|
|
|
|
|
|
|
|
#include "../version.h" |
|
|
|
|
|
|
|
|
|
namespace ZeroTier { |
|
|
|
|
|
|
|
|
|
// Returns true if packet appears valid; pos and proto will be set
|
|
|
|
|
static bool _ipv6GetPayload(const uint8_t *frameData,unsigned int frameLen,unsigned int &pos,unsigned int &proto) |
|
|
|
|
{ |
|
|
|
|
if (frameLen < 40) |
|
|
|
|
return false; |
|
|
|
|
pos = 40; |
|
|
|
|
proto = frameData[6]; |
|
|
|
|
while (pos <= frameLen) { |
|
|
|
|
switch(proto) { |
|
|
|
|
case 0: // hop-by-hop options
|
|
|
|
|
case 43: // routing
|
|
|
|
|
case 60: // destination options
|
|
|
|
|
case 135: // mobility options
|
|
|
|
|
if ((pos + 8) > frameLen) |
|
|
|
|
return false; // invalid!
|
|
|
|
|
proto = frameData[pos]; |
|
|
|
|
pos += ((unsigned int)frameData[pos + 1] * 8) + 8; |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
//case 44: // fragment -- we currently can't parse these and they are deprecated in IPv6 anyway
|
|
|
|
|
//case 50:
|
|
|
|
|
//case 51: // IPSec ESP and AH -- we have to stop here since this is encrypted stuff
|
|
|
|
|
default: |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return false; // overflow == invalid
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static bool _doZtFilter( |
|
|
|
|
const RuntimeEnvironment *RR, |
|
|
|
|
const uint64_t nwid, |
|
|
|
|
const bool inbound, |
|
|
|
|
const Address &ztSource, |
|
|
|
|
const Address &ztDest, |
|
|
|
|
const MAC &macSource, |
|
|
|
|
const MAC &macDest, |
|
|
|
|
const uint8_t *frameData, |
|
|
|
|
const unsigned int frameLen, |
|
|
|
|
const unsigned int etherType, |
|
|
|
|
const unsigned int vlanId, |
|
|
|
|
const ZT_VirtualNetworkRule *rules, |
|
|
|
|
const unsigned int ruleCount, |
|
|
|
|
const Tag *localTags, |
|
|
|
|
const unsigned int localTagCount, |
|
|
|
|
const uint32_t *remoteTagIds, |
|
|
|
|
const uint32_t *remoteTagValues, |
|
|
|
|
const unsigned int remoteTagCount, |
|
|
|
|
const Tag **relevantLocalTags, // pointer array must be at least [localTagCount] in size
|
|
|
|
|
unsigned int &relevantLocalTagCount) |
|
|
|
|
{ |
|
|
|
|
// For each set of rules we start by assuming that they match (since no constraints
|
|
|
|
|
// yields a 'match all' rule).
|
|
|
|
|
uint8_t thisSetMatches = 1; |
|
|
|
|
|
|
|
|
|
for(unsigned int rn=0;rn<ruleCount;++rn) { |
|
|
|
|
const ZT_VirtualNetworkRuleType rt = (ZT_VirtualNetworkRuleType)(rules[rn].t & 0x7f); |
|
|
|
|
uint8_t thisRuleMatches = 0; |
|
|
|
|
|
|
|
|
|
switch(rt) { |
|
|
|
|
// Actions -------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
case ZT_NETWORK_RULE_ACTION_DROP: |
|
|
|
|
if (thisSetMatches) { |
|
|
|
|
return false; |
|
|
|
|
} else { |
|
|
|
|
thisSetMatches = 1; // continue parsing next set of rules
|
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case ZT_NETWORK_RULE_ACTION_ACCEPT: |
|
|
|
|
if (thisSetMatches) { |
|
|
|
|
return true; |
|
|
|
|
} else { |
|
|
|
|
thisSetMatches = 1; // continue parsing next set of rules
|
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case ZT_NETWORK_RULE_ACTION_TEE: |
|
|
|
|
case ZT_NETWORK_RULE_ACTION_REDIRECT: { |
|
|
|
|
Packet outp(Address(rules[rn].v.zt),RR->identity.address(),Packet::VERB_EXT_FRAME); |
|
|
|
|
outp.append(nwid); |
|
|
|
|
outp.append((uint8_t)((rt == ZT_NETWORK_RULE_ACTION_REDIRECT) ? 0x04 : 0x02)); |
|
|
|
|
macDest.appendTo(outp); |
|
|
|
|
macSource.appendTo(outp); |
|
|
|
|
outp.append((uint16_t)etherType); |
|
|
|
|
outp.append(frameData,frameLen); |
|
|
|
|
outp.compress(); |
|
|
|
|
RR->sw->send(outp,true,nwid); |
|
|
|
|
|
|
|
|
|
if (rt == ZT_NETWORK_RULE_ACTION_REDIRECT) { |
|
|
|
|
return false; |
|
|
|
|
} else { |
|
|
|
|
thisSetMatches = 1; // TEE does not terminate parsing
|
|
|
|
|
} |
|
|
|
|
} break; |
|
|
|
|
|
|
|
|
|
// Rules ---------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
case ZT_NETWORK_RULE_MATCH_SOURCE_ZEROTIER_ADDRESS: |
|
|
|
|
thisRuleMatches = (uint8_t)(rules[rn].v.zt == ztSource.toInt()); |
|
|
|
|
break; |
|
|
|
|
case ZT_NETWORK_RULE_MATCH_DEST_ZEROTIER_ADDRESS: |
|
|
|
|
thisRuleMatches = (uint8_t)(rules[rn].v.zt == ztDest.toInt()); |
|
|
|
|
break; |
|
|
|
|
case ZT_NETWORK_RULE_MATCH_VLAN_ID: |
|
|
|
|
thisRuleMatches = (uint8_t)(rules[rn].v.vlanId == (uint16_t)vlanId); |
|
|
|
|
break; |
|
|
|
|
case ZT_NETWORK_RULE_MATCH_VLAN_PCP: |
|
|
|
|
// NOT SUPPORTED YET
|
|
|
|
|
thisRuleMatches = (uint8_t)(rules[rn].v.vlanPcp == 0); |
|
|
|
|
break; |
|
|
|
|
case ZT_NETWORK_RULE_MATCH_VLAN_DEI: |
|
|
|
|
// NOT SUPPORTED YET
|
|
|
|
|
thisRuleMatches = (uint8_t)(rules[rn].v.vlanDei == 0); |
|
|
|
|
break; |
|
|
|
|
case ZT_NETWORK_RULE_MATCH_ETHERTYPE: |
|
|
|
|
thisRuleMatches = (uint8_t)(rules[rn].v.etherType == (uint16_t)etherType); |
|
|
|
|
break; |
|
|
|
|
case ZT_NETWORK_RULE_MATCH_MAC_SOURCE: |
|
|
|
|
thisRuleMatches = (uint8_t)(MAC(rules[rn].v.mac,6) == macSource); |
|
|
|
|
break; |
|
|
|
|
case ZT_NETWORK_RULE_MATCH_MAC_DEST: |
|
|
|
|
thisRuleMatches = (uint8_t)(MAC(rules[rn].v.mac,6) == macDest); |
|
|
|
|
break; |
|
|
|
|
case ZT_NETWORK_RULE_MATCH_IPV4_SOURCE: |
|
|
|
|
if ((etherType == ZT_ETHERTYPE_IPV4)&&(frameLen >= 20)) { |
|
|
|
|
thisRuleMatches = (uint8_t)(InetAddress((const void *)&(rules[rn].v.ipv4.ip),4,rules[rn].v.ipv4.mask).containsAddress(InetAddress((const void *)(frameData + 12),4,0))); |
|
|
|
|
} else { |
|
|
|
|
thisRuleMatches = 0; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case ZT_NETWORK_RULE_MATCH_IPV4_DEST: |
|
|
|
|
if ((etherType == ZT_ETHERTYPE_IPV4)&&(frameLen >= 20)) { |
|
|
|
|
thisRuleMatches = (uint8_t)(InetAddress((const void *)&(rules[rn].v.ipv4.ip),4,rules[rn].v.ipv4.mask).containsAddress(InetAddress((const void *)(frameData + 16),4,0))); |
|
|
|
|
} else { |
|
|
|
|
thisRuleMatches = 0; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case ZT_NETWORK_RULE_MATCH_IPV6_SOURCE: |
|
|
|
|
if ((etherType == ZT_ETHERTYPE_IPV6)&&(frameLen >= 40)) { |
|
|
|
|
thisRuleMatches = (uint8_t)(InetAddress((const void *)rules[rn].v.ipv6.ip,16,rules[rn].v.ipv6.mask).containsAddress(InetAddress((const void *)(frameData + 8),16,0))); |
|
|
|
|
} else { |
|
|
|
|
thisRuleMatches = 0; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case ZT_NETWORK_RULE_MATCH_IPV6_DEST: |
|
|
|
|
if ((etherType == ZT_ETHERTYPE_IPV6)&&(frameLen >= 40)) { |
|
|
|
|
thisRuleMatches = (uint8_t)(InetAddress((const void *)rules[rn].v.ipv6.ip,16,rules[rn].v.ipv6.mask).containsAddress(InetAddress((const void *)(frameData + 24),16,0))); |
|
|
|
|
} else { |
|
|
|
|
thisRuleMatches = 0; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case ZT_NETWORK_RULE_MATCH_IP_TOS: |
|
|
|
|
if ((etherType == ZT_ETHERTYPE_IPV4)&&(frameLen >= 20)) { |
|
|
|
|
thisRuleMatches = (uint8_t)(rules[rn].v.ipTos == ((frameData[1] & 0xfc) >> 2)); |
|
|
|
|
} else if ((etherType == ZT_ETHERTYPE_IPV6)&&(frameLen >= 40)) { |
|
|
|
|
const uint8_t trafficClass = ((frameData[0] << 4) & 0xf0) | ((frameData[1] >> 4) & 0x0f); |
|
|
|
|
thisRuleMatches = (uint8_t)(rules[rn].v.ipTos == ((trafficClass & 0xfc) >> 2)); |
|
|
|
|
} else { |
|
|
|
|
thisRuleMatches = 0; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case ZT_NETWORK_RULE_MATCH_IP_PROTOCOL: |
|
|
|
|
if ((etherType == ZT_ETHERTYPE_IPV4)&&(frameLen >= 20)) { |
|
|
|
|
thisRuleMatches = (uint8_t)(rules[rn].v.ipProtocol == frameData[9]); |
|
|
|
|
} else if (etherType == ZT_ETHERTYPE_IPV6) { |
|
|
|
|
unsigned int pos = 0,proto = 0; |
|
|
|
|
if (_ipv6GetPayload(frameData,frameLen,pos,proto)) { |
|
|
|
|
thisRuleMatches = (uint8_t)(rules[rn].v.ipProtocol == (uint8_t)proto); |
|
|
|
|
} else { |
|
|
|
|
thisRuleMatches = 0; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
thisRuleMatches = 0; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE: |
|
|
|
|
case ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE: |
|
|
|
|
if ((etherType == ZT_ETHERTYPE_IPV4)&&(frameLen >= 20)) { |
|
|
|
|
const unsigned int headerLen = 4 * (frameData[0] & 0xf); |
|
|
|
|
int p = -1; |
|
|
|
|
switch(frameData[9]) { // IP protocol number
|
|
|
|
|
// All these start with 16-bit source and destination port in that order
|
|
|
|
|
case 0x06: // TCP
|
|
|
|
|
case 0x11: // UDP
|
|
|
|
|
case 0x84: // SCTP
|
|
|
|
|
case 0x88: // UDPLite
|
|
|
|
|
if (frameLen > (headerLen + 4)) { |
|
|
|
|
unsigned int pos = headerLen + ((rt == ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE) ? 2 : 0); |
|
|
|
|
p = (int)frameData[pos++] << 8; |
|
|
|
|
p |= (int)frameData[pos]; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
thisRuleMatches = (p > 0) ? (uint8_t)((p >= (int)rules[rn].v.port[0])&&(p <= (int)rules[rn].v.port[1])) : (uint8_t)0; |
|
|
|
|
} else if (etherType == ZT_ETHERTYPE_IPV6) { |
|
|
|
|
unsigned int pos = 0,proto = 0; |
|
|
|
|
if (_ipv6GetPayload(frameData,frameLen,pos,proto)) { |
|
|
|
|
int p = -1; |
|
|
|
|
switch(proto) { // IP protocol number
|
|
|
|
|
// All these start with 16-bit source and destination port in that order
|
|
|
|
|
case 0x06: // TCP
|
|
|
|
|
case 0x11: // UDP
|
|
|
|
|
case 0x84: // SCTP
|
|
|
|
|
case 0x88: // UDPLite
|
|
|
|
|
if (frameLen > (pos + 4)) { |
|
|
|
|
if (rt == ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE) pos += 2; |
|
|
|
|
p = (int)frameData[pos++] << 8; |
|
|
|
|
p |= (int)frameData[pos]; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
thisRuleMatches = (p > 0) ? (uint8_t)((p >= (int)rules[rn].v.port[0])&&(p <= (int)rules[rn].v.port[1])) : (uint8_t)0; |
|
|
|
|
} else { |
|
|
|
|
thisRuleMatches = 0; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
thisRuleMatches = 0; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case ZT_NETWORK_RULE_MATCH_CHARACTERISTICS: { |
|
|
|
|
uint64_t cf = (inbound) ? ZT_RULE_PACKET_CHARACTERISTICS_INBOUND : 0ULL; |
|
|
|
|
if ((etherType == ZT_ETHERTYPE_IPV4)&&(frameLen >= 20)&&(frameData[9] == 0x06)) { |
|
|
|
|
const unsigned int headerLen = 4 * (frameData[0] & 0xf); |
|
|
|
|
cf |= (uint64_t)frameData[headerLen + 13]; |
|
|
|
|
cf |= (((uint64_t)(frameData[headerLen + 12] & 0x0f)) << 8); |
|
|
|
|
} else if (etherType == ZT_ETHERTYPE_IPV6) { |
|
|
|
|
unsigned int pos = 0,proto = 0; |
|
|
|
|
if (_ipv6GetPayload(frameData,frameLen,pos,proto)) { |
|
|
|
|
if ((proto == 0x06)&&(frameLen > (pos + 14))) { |
|
|
|
|
cf |= (uint64_t)frameData[pos + 13]; |
|
|
|
|
cf |= (((uint64_t)(frameData[pos + 12] & 0x0f)) << 8); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
thisRuleMatches = (uint8_t)((cf & rules[rn].v.characteristics[0]) == rules[rn].v.characteristics[1]); |
|
|
|
|
} break; |
|
|
|
|
case ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE: |
|
|
|
|
thisRuleMatches = (uint8_t)((frameLen >= (unsigned int)rules[rn].v.frameSize[0])&&(frameLen <= (unsigned int)rules[rn].v.frameSize[1])); |
|
|
|
|
break; |
|
|
|
|
case ZT_NETWORK_RULE_MATCH_TAGS_SAMENESS: |
|
|
|
|
case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND: |
|
|
|
|
case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR: |
|
|
|
|
case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR: { |
|
|
|
|
const Tag *lt = (const Tag *)0; |
|
|
|
|
for(unsigned int i=0;i<localTagCount;++i) { |
|
|
|
|
if (rules[rn].v.tag.id == localTags[i].id()) { |
|
|
|
|
lt = &(localTags[i]); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (!lt) { |
|
|
|
|
thisRuleMatches = 0; |
|
|
|
|
} else { |
|
|
|
|
const uint32_t *rtv = (const uint32_t *)0; |
|
|
|
|
for(unsigned int i=0;i<remoteTagCount;++i) { |
|
|
|
|
if (rules[rn].v.tag.id == remoteTagIds[i]) { |
|
|
|
|
rtv = &(remoteTagValues[i]); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (!rtv) { |
|
|
|
|
thisRuleMatches = 0; |
|
|
|
|
} else { |
|
|
|
|
if (rt == ZT_NETWORK_RULE_MATCH_TAGS_SAMENESS) { |
|
|
|
|
const uint32_t sameness = (lt->value() > *rtv) ? (lt->value() - *rtv) : (*rtv - lt->value()); |
|
|
|
|
thisRuleMatches = (uint8_t)(sameness <= rules[rn].v.tag.value); |
|
|
|
|
} else if (rt == ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND) { |
|
|
|
|
thisRuleMatches = (uint8_t)((lt->value() & *rtv) <= rules[rn].v.tag.value); |
|
|
|
|
} else if (rt == ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR) { |
|
|
|
|
thisRuleMatches = (uint8_t)((lt->value() | *rtv) <= rules[rn].v.tag.value); |
|
|
|
|
} else if (rt == ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR) { |
|
|
|
|
thisRuleMatches = (uint8_t)((lt->value() ^ *rtv) <= rules[rn].v.tag.value); |
|
|
|
|
} else { // sanity check, can't really happen
|
|
|
|
|
thisRuleMatches = 0; |
|
|
|
|
} |
|
|
|
|
if (thisRuleMatches) { |
|
|
|
|
relevantLocalTags[relevantLocalTagCount++] = lt; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// thisSetMatches remains true if the current rule matched... or does NOT match if not bit (0x80) is 1
|
|
|
|
|
thisSetMatches &= (thisRuleMatches ^ ((rules[rn].t & 0x80) >> 7)); |
|
|
|
|
|
|
|
|
|
//TRACE("[%u] %u result==%u set==%u",rn,(unsigned int)rt,(unsigned int)thisRuleMatches,(unsigned int)thisSetMatches);
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const ZeroTier::MulticastGroup Network::BROADCAST(ZeroTier::MAC(0xffffffffffffULL),0); |
|
|
|
|
|
|
|
|
|
Network::Network(const RuntimeEnvironment *renv,uint64_t nwid,void *uptr) : |
|
|
|
|
@ -100,6 +394,96 @@ Network::~Network()
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool Network::filterOutgoingPacket( |
|
|
|
|
const Address &ztSource, |
|
|
|
|
const Address &ztDest, |
|
|
|
|
const MAC &macSource, |
|
|
|
|
const MAC &macDest, |
|
|
|
|
const uint8_t *frameData, |
|
|
|
|
const unsigned int frameLen, |
|
|
|
|
const unsigned int etherType, |
|
|
|
|
const unsigned int vlanId) |
|
|
|
|
{ |
|
|
|
|
uint32_t remoteTagIds[ZT_MAX_NETWORK_TAGS]; |
|
|
|
|
uint32_t remoteTagValues[ZT_MAX_NETWORK_TAGS]; |
|
|
|
|
const Tag *relevantLocalTags[ZT_MAX_NETWORK_TAGS]; |
|
|
|
|
unsigned int relevantLocalTagCount = 0; |
|
|
|
|
|
|
|
|
|
Mutex::Lock _l(_lock); |
|
|
|
|
|
|
|
|
|
Membership &m = _memberships[ztDest]; |
|
|
|
|
const unsigned int remoteTagCount = m.getAllTags(_config,remoteTagIds,remoteTagValues,ZT_MAX_NETWORK_TAGS); |
|
|
|
|
|
|
|
|
|
if (_doZtFilter( |
|
|
|
|
RR, |
|
|
|
|
_id, |
|
|
|
|
false, |
|
|
|
|
ztSource, |
|
|
|
|
ztDest, |
|
|
|
|
macSource, |
|
|
|
|
macDest, |
|
|
|
|
frameData, |
|
|
|
|
frameLen, |
|
|
|
|
etherType, |
|
|
|
|
vlanId, |
|
|
|
|
_config.rules, |
|
|
|
|
_config.ruleCount, |
|
|
|
|
_config.tags, |
|
|
|
|
_config.tagCount, |
|
|
|
|
remoteTagIds, |
|
|
|
|
remoteTagValues, |
|
|
|
|
remoteTagCount, |
|
|
|
|
relevantLocalTags, |
|
|
|
|
relevantLocalTagCount |
|
|
|
|
)) { |
|
|
|
|
m.sendCredentialsIfNeeded(RR,RR->node->now(),ztDest,_config.com,(const Capability *)0,relevantLocalTags,relevantLocalTagCount); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for(unsigned int c=0;c<_config.capabilityCount;++c) { |
|
|
|
|
relevantLocalTagCount = 0; |
|
|
|
|
if (_doZtFilter( |
|
|
|
|
RR, |
|
|
|
|
_id, |
|
|
|
|
false, |
|
|
|
|
ztSource, |
|
|
|
|
ztDest, |
|
|
|
|
macSource, |
|
|
|
|
macDest, |
|
|
|
|
frameData, |
|
|
|
|
frameLen, |
|
|
|
|
etherType, |
|
|
|
|
vlanId, |
|
|
|
|
_config.capabilities[c].rules(), |
|
|
|
|
_config.capabilities[c].ruleCount(), |
|
|
|
|
_config.tags, |
|
|
|
|
_config.tagCount, |
|
|
|
|
remoteTagIds, |
|
|
|
|
remoteTagValues, |
|
|
|
|
remoteTagCount, |
|
|
|
|
relevantLocalTags, |
|
|
|
|
relevantLocalTagCount |
|
|
|
|
)) { |
|
|
|
|
m.sendCredentialsIfNeeded(RR,RR->node->now(),ztDest,_config.com,&(_config.capabilities[c]),relevantLocalTags,relevantLocalTagCount); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool Network::filterIncomingPacket( |
|
|
|
|
const SharedPtr<Peer> &sourcePeer, |
|
|
|
|
const Address &ztDest, |
|
|
|
|
const MAC &macSource, |
|
|
|
|
const MAC &macDest, |
|
|
|
|
const uint8_t *frameData, |
|
|
|
|
const unsigned int frameLen, |
|
|
|
|
const unsigned int etherType, |
|
|
|
|
const unsigned int vlanId) |
|
|
|
|
{ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool Network::subscribedToMulticastGroup(const MulticastGroup &mg,bool includeBridgedGroups) const |
|
|
|
|
{ |
|
|
|
|
Mutex::Lock _l(_lock); |
|
|
|
|
@ -267,6 +651,16 @@ void Network::clean()
|
|
|
|
|
_multicastGroupsBehindMe.erase(*mg); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
{ |
|
|
|
|
Address *a = (Address *)0; |
|
|
|
|
Membership *m = (Membership *)0; |
|
|
|
|
Hashtable<Address,Membership>::Iterator i(_memberships); |
|
|
|
|
while (i.next(a,m)) { |
|
|
|
|
if ((now - m->clean(now)) > ZT_MEMBERSHIP_EXPIRATION_TIME) |
|
|
|
|
_memberships.erase(*a); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Network::learnBridgeRoute(const MAC &mac,const Address &addr) |
|
|
|
|
|