From d637988ccf5c62c1f20233cf5704329daff61c67 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 25 Aug 2016 18:21:20 -0700 Subject: Fix chicken or egg problem in tags, and better filter debug instrumentation. --- controller/EmbeddedNetworkController.cpp | 2 +- include/ZeroTierOne.h | 6 +- node/Membership.cpp | 25 ++++-- node/Membership.hpp | 10 ++- node/Network.cpp | 136 ++++++++++++++++--------------- 5 files changed, 96 insertions(+), 83 deletions(-) diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp index 8f013464..45af30be 100644 --- a/controller/EmbeddedNetworkController.cpp +++ b/controller/EmbeddedNetworkController.cpp @@ -50,7 +50,7 @@ using json = nlohmann::json; #define ZT_NETCONF_CONTROLLER_API_VERSION 3 // Number of requests to remember in member history -#define ZT_NETCONF_DB_MEMBER_HISTORY_LENGTH 16 +#define ZT_NETCONF_DB_MEMBER_HISTORY_LENGTH 32 // Min duration between requests for an address/nwid combo to prevent floods #define ZT_NETCONF_MIN_REQUEST_PERIOD 1000 diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index 1d7620d4..a3d82adb 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -107,14 +107,14 @@ extern "C" { #define ZT_MAX_NETWORK_RULES 1024 /** - * Maximum number of per-node capabilities per network + * Maximum number of per-member capabilities per network */ #define ZT_MAX_NETWORK_CAPABILITIES 128 /** - * Maximum number of per-node tags per network + * Maximum number of per-member tags per network */ -#define ZT_MAX_NETWORK_TAGS 128 +#define ZT_MAX_NETWORK_TAGS 16 /** * Maximum number of direct network paths to a given peer diff --git a/node/Membership.cpp b/node/Membership.cpp index 8bf5b784..7ced9dcf 100644 --- a/node/Membership.cpp +++ b/node/Membership.cpp @@ -28,8 +28,12 @@ namespace ZeroTier { -bool Membership::sendCredentialsIfNeeded(const RuntimeEnvironment *RR,const uint64_t now,const Address &peerAddress,const CertificateOfMembership &com,const Capability *cap,const Tag **tags,const unsigned int tagCount) +bool Membership::sendCredentialsIfNeeded(const RuntimeEnvironment *RR,const uint64_t now,const Address &peerAddress,const NetworkConfig &nconf,const Capability *cap) { + if ((now - _lastPushAttempt) < 1000ULL) + return false; + _lastPushAttempt = now; + try { Buffer capsAndTags; @@ -50,27 +54,29 @@ bool Membership::sendCredentialsIfNeeded(const RuntimeEnvironment *RR,const uint unsigned int appendedTags = 0; const unsigned int tagCountPos = capsAndTags.size(); capsAndTags.addSize(2); - for(unsigned int i=0;iid()); + for(unsigned int i=0;ilastPushed) >= ZT_CREDENTIAL_PUSH_EVERY) { if ((capsAndTags.size() + sizeof(Tag)) > (ZT_PROTO_MAX_PACKET_LENGTH - sizeof(CertificateOfMembership))) break; - tags[i]->serialize(capsAndTags); + nconf.tags[i].serialize(capsAndTags); ts->lastPushed = now; ++appendedTags; } } capsAndTags.setAt(tagCountPos,(uint16_t)appendedTags); - if ( ((com)&&((now - _lastPushedCom) >= ZT_CREDENTIAL_PUSH_EVERY)) || (appendedCaps) || (appendedTags) ) { + const bool needCom = ((nconf.isPrivate())&&(nconf.com)&&((now - _lastPushedCom) >= ZT_CREDENTIAL_PUSH_EVERY)); + if ( (needCom) || (appendedCaps) || (appendedTags) ) { Packet outp(peerAddress,RR->identity.address(),Packet::VERB_NETWORK_CREDENTIALS); - if (com) - com.serialize(outp); + if (needCom) { + nconf.com.serialize(outp); + _lastPushedCom = now; + } outp.append((uint8_t)0x00); outp.append(capsAndTags.data(),capsAndTags.size()); outp.compress(); RR->sw->send(outp,true); - _lastPushedCom = now; return true; } } catch ( ... ) { @@ -88,8 +94,9 @@ int Membership::addCredential(const RuntimeEnvironment *RR,const CertificateOfMe const int vr = com.verify(RR); if (vr == 0) { TRACE("addCredential(CertificateOfMembership) for %s on %.16llx ACCEPTED (new)",com.issuedTo().toString().c_str(),com.networkId()); - if (com.timestamp().first > _com.timestamp().first) + if (com.timestamp().first > _com.timestamp().first) { _com = com; + } } else { TRACE("addCredential(CertificateOfMembership) for %s on %.16llx REJECTED (%d)",com.issuedTo().toString().c_str(),com.networkId(),vr); } diff --git a/node/Membership.hpp b/node/Membership.hpp index bb356902..580aa529 100644 --- a/node/Membership.hpp +++ b/node/Membership.hpp @@ -107,6 +107,7 @@ public: friend class CapabilityIterator; Membership() : + _lastPushAttempt(0), _lastPushedCom(0), _blacklistBefore(0), _com(), @@ -124,13 +125,11 @@ public: * @param RR Runtime environment * @param now Current time * @param peerAddress Address of member peer - * @param com My network certificate of membership (if any) (not the one here, but ours -- in NetworkConfig) + * @param nconf My network config * @param cap Capability to send or 0 if none - * @param tags Tags that this peer might need - * @param tagCount Number of tag IDs * @return True if we pushed something */ - bool sendCredentialsIfNeeded(const RuntimeEnvironment *RR,const uint64_t now,const Address &peerAddress,const CertificateOfMembership &com,const Capability *cap,const Tag **tags,const unsigned int tagCount); + bool sendCredentialsIfNeeded(const RuntimeEnvironment *RR,const uint64_t now,const Address &peerAddress,const NetworkConfig &nconf,const Capability *cap); /** * @param nconf Our network config @@ -270,6 +269,9 @@ public: } private: + // Last time we checked if credential push was needed + uint64_t _lastPushAttempt; + // Last time we pushed our COM to this peer uint64_t _lastPushedCom; diff --git a/node/Network.cpp b/node/Network.cpp index 5293e2f0..1267f99c 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -143,7 +143,7 @@ static int _doZtFilter( const Address &ztDest, const MAC &macSource, const MAC &macDest, - const uint8_t *frameData, + const uint8_t *const frameData, const unsigned int frameLen, const unsigned int etherType, const unsigned int vlanId, @@ -151,11 +151,9 @@ static int _doZtFilter( 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) + const uint32_t *const remoteTagIds, + const uint32_t *const remoteTagValues, + const unsigned int remoteTagCount) { // For each set of rules we start by assuming that they match (since no constraints // yields a 'match all' rule). @@ -168,30 +166,22 @@ static int _doZtFilter( for(unsigned int rn=0;rn %u",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),rules[rn].v.zt,ztSource.toInt(),(unsigned int)thisRuleMatches); break; case ZT_NETWORK_RULE_MATCH_DEST_ZEROTIER_ADDRESS: - FILTER_TRACE("%u %s param0=%.10llx",rn,_rtn(rt),rules[rn].v.zt); thisRuleMatches = (uint8_t)(rules[rn].v.zt == ztDest.toInt()); + FILTER_TRACE("%u %s %c %.10llx==%.10llx -> %u",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),rules[rn].v.zt,ztDest.toInt(),(unsigned int)thisRuleMatches); break; case ZT_NETWORK_RULE_MATCH_VLAN_ID: - FILTER_TRACE("%u %s param0=%u",rn,_rtn(rt),(unsigned int)rules[rn].v.vlanId); thisRuleMatches = (uint8_t)(rules[rn].v.vlanId == (uint16_t)vlanId); + FILTER_TRACE("%u %s %c %u==%u -> %u",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),(unsigned int)rules[rn].v.vlanId,(unsigned int)vlanId,(unsigned int)thisRuleMatches); break; case ZT_NETWORK_RULE_MATCH_VLAN_PCP: // NOT SUPPORTED YET - FILTER_TRACE("%u %s param0=%u",rn,_rtn(rt),(unsigned int)rules[rn].v.vlanPcp); thisRuleMatches = (uint8_t)(rules[rn].v.vlanPcp == 0); + FILTER_TRACE("%u %s %c %u==%u -> %u",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),(unsigned int)rules[rn].v.vlanPcp,0,(unsigned int)thisRuleMatches); break; case ZT_NETWORK_RULE_MATCH_VLAN_DEI: // NOT SUPPORTED YET - FILTER_TRACE("%u %s param0=%u",rn,_rtn(rt),(unsigned int)rules[rn].v.vlanDei); thisRuleMatches = (uint8_t)(rules[rn].v.vlanDei == 0); + FILTER_TRACE("%u %s %c %u==%u -> %u",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),(unsigned int)rules[rn].v.vlanDei,0,(unsigned int)thisRuleMatches); break; case ZT_NETWORK_RULE_MATCH_ETHERTYPE: - FILTER_TRACE("%u %s param0=%u etherType=%u",rn,_rtn(rt),(unsigned int)rules[rn].v.etherType,etherType); thisRuleMatches = (uint8_t)(rules[rn].v.etherType == (uint16_t)etherType); + FILTER_TRACE("%u %s %c %u==%u -> %u",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),(unsigned int)rules[rn].v.etherType,etherType,(unsigned int)thisRuleMatches); break; case ZT_NETWORK_RULE_MATCH_MAC_SOURCE: - FILTER_TRACE("%u %s param0=%.12llx",rn,_rtn(rt),rules[rn].v.mac); thisRuleMatches = (uint8_t)(MAC(rules[rn].v.mac,6) == macSource); + FILTER_TRACE("%u %s %c %.12llx=%.12llx -> %u",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),rules[rn].v.mac,macSource.toInt(),(unsigned int)thisRuleMatches); break; case ZT_NETWORK_RULE_MATCH_MAC_DEST: - FILTER_TRACE("%u %s param0=%.12llx",rn,_rtn(rt),rules[rn].v.mac); thisRuleMatches = (uint8_t)(MAC(rules[rn].v.mac,6) == macDest); + FILTER_TRACE("%u %s %c %.12llx=%.12llx -> %u",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),rules[rn].v.mac,macDest.toInt(),(unsigned int)thisRuleMatches); break; case ZT_NETWORK_RULE_MATCH_IPV4_SOURCE: - FILTER_TRACE("%u %s param0=%s",rn,_rtn(rt),InetAddress((const void *)&(rules[rn].v.ipv4.ip),4,rules[rn].v.ipv4.mask).toString().c_str()); 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))); + FILTER_TRACE("%u %s %c %s contains %s -> %u",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),InetAddress((const void *)&(rules[rn].v.ipv4.ip),4,rules[rn].v.ipv4.mask).toString().c_str(),InetAddress((const void *)(frameData + 12),4,0).toIpString().c_str(),(unsigned int)thisRuleMatches); } else { thisRuleMatches = 0; + FILTER_TRACE("%u %s %c [frame not IPv4] -> 0",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '=')); } break; case ZT_NETWORK_RULE_MATCH_IPV4_DEST: - FILTER_TRACE("%u %s param0=%s",rn,_rtn(rt),InetAddress((const void *)&(rules[rn].v.ipv4.ip),4,rules[rn].v.ipv4.mask).toString().c_str()); 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))); + FILTER_TRACE("%u %s %c %s contains %s -> %u",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),InetAddress((const void *)&(rules[rn].v.ipv4.ip),4,rules[rn].v.ipv4.mask).toString().c_str(),InetAddress((const void *)(frameData + 16),4,0).toIpString().c_str(),(unsigned int)thisRuleMatches); } else { thisRuleMatches = 0; + FILTER_TRACE("%u %s %c [frame not IPv4] -> 0",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '=')); } break; case ZT_NETWORK_RULE_MATCH_IPV6_SOURCE: - FILTER_TRACE("%u %s param0=%s",rn,_rtn(rt),InetAddress((const void *)rules[rn].v.ipv6.ip,16,rules[rn].v.ipv6.mask).toString().c_str()); 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))); + FILTER_TRACE("%u %s %c %s contains %s -> %u",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),InetAddress((const void *)rules[rn].v.ipv6.ip,16,rules[rn].v.ipv6.mask).toString().c_str(),InetAddress((const void *)(frameData + 8),16,0).toIpString().c_str(),(unsigned int)thisRuleMatches); } else { thisRuleMatches = 0; + FILTER_TRACE("%u %s %c [frame not IPv6] -> 0",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '=')); } break; case ZT_NETWORK_RULE_MATCH_IPV6_DEST: - FILTER_TRACE("%u %s param0=%s",rn,_rtn(rt),InetAddress((const void *)rules[rn].v.ipv6.ip,16,rules[rn].v.ipv6.mask).toString().c_str()); 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))); + FILTER_TRACE("%u %s %c %s contains %s -> %u",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),InetAddress((const void *)rules[rn].v.ipv6.ip,16,rules[rn].v.ipv6.mask).toString().c_str(),InetAddress((const void *)(frameData + 24),16,0).toIpString().c_str(),(unsigned int)thisRuleMatches); } else { thisRuleMatches = 0; + FILTER_TRACE("%u %s %c [frame not IPv6] -> 0",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '=')); } break; case ZT_NETWORK_RULE_MATCH_IP_TOS: - FILTER_TRACE("%u %s param0=%u",rn,_rtn(rt),(unsigned int)rules[rn].v.ipTos); if ((etherType == ZT_ETHERTYPE_IPV4)&&(frameLen >= 20)) { thisRuleMatches = (uint8_t)(rules[rn].v.ipTos == ((frameData[1] & 0xfc) >> 2)); + FILTER_TRACE("%u %s %c (IPv4) %u==%u -> %u",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),(unsigned int)rules[rn].v.ipTos,(unsigned int)((frameData[1] & 0xfc) >> 2),(unsigned int)thisRuleMatches); } 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)); + FILTER_TRACE("%u %s %c (IPv6) %u==%u -> %u",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),(unsigned int)rules[rn].v.ipTos,(unsigned int)((trafficClass & 0xfc) >> 2),(unsigned int)thisRuleMatches); } else { thisRuleMatches = 0; + FILTER_TRACE("%u %s %c [frame not IP] -> 0",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '=')); } break; case ZT_NETWORK_RULE_MATCH_IP_PROTOCOL: - FILTER_TRACE("%u %s param0=%u",rn,_rtn(rt),(unsigned int)rules[rn].v.ipProtocol); if ((etherType == ZT_ETHERTYPE_IPV4)&&(frameLen >= 20)) { thisRuleMatches = (uint8_t)(rules[rn].v.ipProtocol == frameData[9]); + FILTER_TRACE("%u %s %c (IPv4) %u==%u -> %u",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),(unsigned int)rules[rn].v.ipProtocol,(unsigned int)frameData[9],(unsigned int)thisRuleMatches); } 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); + FILTER_TRACE("%u %s %c (IPv6) %u==%u -> %u",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),(unsigned int)rules[rn].v.ipProtocol,proto,(unsigned int)thisRuleMatches); } else { thisRuleMatches = 0; + FILTER_TRACE("%u %s %c [invalid IPv6] -> 0",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '=')); } } else { thisRuleMatches = 0; + FILTER_TRACE("%u %s %c [frame not IP] -> 0",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '=')); } break; case ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE: @@ -359,8 +362,9 @@ static int _doZtFilter( } break; } - FILTER_TRACE("%u %s param0=%u param1=%u port==%u proto==%u etherType=%u (IPv4)",rn,_rtn(rt),(unsigned int)rules[rn].v.port[0],(unsigned int)rules[rn].v.port[1],p,(unsigned int)frameData[9],etherType); - thisRuleMatches = (p > 0) ? (uint8_t)((p >= (int)rules[rn].v.port[0])&&(p <= (int)rules[rn].v.port[1])) : (uint8_t)0; + + thisRuleMatches = (p >= 0) ? (uint8_t)((p >= (int)rules[rn].v.port[0])&&(p <= (int)rules[rn].v.port[1])) : (uint8_t)0; + FILTER_TRACE("%u %s %c (IPv4) %d in %d-%d -> %u",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),p,(int)rules[rn].v.port[0],(int)rules[rn].v.port[1],(unsigned int)thisRuleMatches); } else if (etherType == ZT_ETHERTYPE_IPV6) { unsigned int pos = 0,proto = 0; if (_ipv6GetPayload(frameData,frameLen,pos,proto)) { @@ -378,15 +382,15 @@ static int _doZtFilter( } break; } - FILTER_TRACE("%u %s param0=%u param1=%u port==%u proto=%u etherType=%u (IPv6)",rn,_rtn(rt),(unsigned int)rules[rn].v.port[0],(unsigned int)rules[rn].v.port[1],p,proto,etherType); thisRuleMatches = (p > 0) ? (uint8_t)((p >= (int)rules[rn].v.port[0])&&(p <= (int)rules[rn].v.port[1])) : (uint8_t)0; + FILTER_TRACE("%u %s %c (IPv6) %d in %d-%d -> %u",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),p,(int)rules[rn].v.port[0],(int)rules[rn].v.port[1],(unsigned int)thisRuleMatches); } else { - FILTER_TRACE("%u %s param0=%u param1=%u port=0 proto=0 etherType=%u (IPv6 parse failed)",rn,_rtn(rt),(unsigned int)rules[rn].v.port[0],(unsigned int)rules[rn].v.port[1],etherType); thisRuleMatches = 0; + FILTER_TRACE("%u %s %c [invalid IPv6] -> 0",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '=')); } } else { - FILTER_TRACE("%u %s param0=%u param1=%u port=0 proto=0 etherType=%u (not IPv4 or IPv6)",rn,_rtn(rt),(unsigned int)rules[rn].v.port[0],(unsigned int)rules[rn].v.port[1],etherType); thisRuleMatches = 0; + FILTER_TRACE("%u %s %c [frame not IP] -> 0",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '=')); } break; case ZT_NETWORK_RULE_MATCH_CHARACTERISTICS: { @@ -406,18 +410,17 @@ static int _doZtFilter( } } } - FILTER_TRACE("%u %s param0=%.16llx param1=%.16llx actual=%.16llx",rn,_rtn(rt),rules[rn].v.characteristics[0],rules[rn].v.characteristics[1],cf); thisRuleMatches = (uint8_t)((cf & rules[rn].v.characteristics[0]) == rules[rn].v.characteristics[1]); + FILTER_TRACE("%u %s %c (%.16llx & %.16llx)==%.16llx -> %u",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),cf,rules[rn].v.characteristics[0],rules[rn].v.characteristics[1],(unsigned int)thisRuleMatches); } break; case ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE: - FILTER_TRACE("%u %s param0=%u param1=%u",rn,_rtn(rt),(unsigned int)rules[rn].v.frameSize[0],(unsigned int)rules[rn].v.frameSize[1]); thisRuleMatches = (uint8_t)((frameLen >= (unsigned int)rules[rn].v.frameSize[0])&&(frameLen <= (unsigned int)rules[rn].v.frameSize[1])); + FILTER_TRACE("%u %s %c %u in %u-%u -> %u",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),frameLen,(unsigned int)rules[rn].v.frameSize[0],(unsigned int)rules[rn].v.frameSize[1],(unsigned int)thisRuleMatches); 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: { - FILTER_TRACE("%u %s param0=%u",rn,_rtn(rt),(unsigned int)rules[rn].v.tag.value); const Tag *lt = (const Tag *)0; for(unsigned int i=0;i 0",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),(unsigned int)rules[rn].v.tag.id); } else { const uint32_t *rtv = (const uint32_t *)0; for(unsigned int i=0;i 0",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),(unsigned int)rules[rn].v.tag.id); } 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); + FILTER_TRACE("%u %s %c TAG %u local:%u remote:%u sameness:%u <= %u -> %u",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),(unsigned int)rules[rn].v.tag.id,lt->value(),*rtv,sameness,(unsigned int)rules[rn].v.tag.value,thisRuleMatches); } else if (rt == ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND) { - thisRuleMatches = (uint8_t)((lt->value() & *rtv) <= rules[rn].v.tag.value); + thisRuleMatches = (uint8_t)((lt->value() & *rtv) == rules[rn].v.tag.value); + FILTER_TRACE("%u %s %c TAG %u local:%.8x & remote:%.8x == %.8x -> %u",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),(unsigned int)rules[rn].v.tag.id,lt->value(),*rtv,(unsigned int)rules[rn].v.tag.value,(unsigned int)thisRuleMatches); } else if (rt == ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR) { - thisRuleMatches = (uint8_t)((lt->value() | *rtv) <= rules[rn].v.tag.value); + thisRuleMatches = (uint8_t)((lt->value() | *rtv) == rules[rn].v.tag.value); + FILTER_TRACE("%u %s %c TAG %u local:%.8x | remote:%.8x == %.8x -> %u",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),(unsigned int)rules[rn].v.tag.id,lt->value(),*rtv,(unsigned int)rules[rn].v.tag.value,(unsigned int)thisRuleMatches); } else if (rt == ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR) { - thisRuleMatches = (uint8_t)((lt->value() ^ *rtv) <= rules[rn].v.tag.value); + thisRuleMatches = (uint8_t)((lt->value() ^ *rtv) == rules[rn].v.tag.value); + FILTER_TRACE("%u %s %c TAG %u local:%.8x ^ remote:%.8x == %.8x -> %u",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),(unsigned int)rules[rn].v.tag.id,lt->value(),*rtv,(unsigned int)rules[rn].v.tag.value,(unsigned int)thisRuleMatches); } else { // sanity check, can't really happen thisRuleMatches = 0; } - if (thisRuleMatches) { - relevantLocalTags[relevantLocalTagCount++] = lt; - } } } } break; + + default: continue; } // thisSetMatches remains true if the current rule matched (or did NOT match if NOT bit is set) - thisSetMatches &= (thisRuleMatches ^ ((rules[rn].t & 0x80) >> 7)); - - FILTER_TRACE("%u %s/%u thisRuleMatches==%u thisSetMatches==%u",rn,_rtn(rt),(unsigned int)rt,(unsigned int)thisRuleMatches,(unsigned int)thisSetMatches); + thisSetMatches &= (thisRuleMatches ^ ((rules[rn].t >> 7) & 1)); } return 0; @@ -543,31 +549,32 @@ bool Network::filterOutgoingPacket( { 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); - switch(_doZtFilter(RR,noRedirect,_config,false,ztSource,ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,_config.rules,_config.ruleCount,_config.tags,_config.tagCount,remoteTagIds,remoteTagValues,remoteTagCount,relevantLocalTags,relevantLocalTagCount)) { + switch(_doZtFilter(RR,noRedirect,_config,false,ztSource,ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,_config.rules,_config.ruleCount,_config.tags,_config.tagCount,remoteTagIds,remoteTagValues,remoteTagCount)) { case -1: + if (ztDest) + m.sendCredentialsIfNeeded(RR,RR->node->now(),ztDest,_config,(const Capability *)0); return false; case 1: if (ztDest) - m.sendCredentialsIfNeeded(RR,RR->node->now(),ztDest,_config.com,(const Capability *)0,relevantLocalTags,relevantLocalTagCount); + m.sendCredentialsIfNeeded(RR,RR->node->now(),ztDest,_config,(const Capability *)0); return true; } for(unsigned int c=0;c<_config.capabilityCount;++c) { - relevantLocalTagCount = 0; - switch (_doZtFilter(RR,noRedirect,_config,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)) { + switch (_doZtFilter(RR,noRedirect,_config,false,ztSource,ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,_config.capabilities[c].rules(),_config.capabilities[c].ruleCount(),_config.tags,_config.tagCount,remoteTagIds,remoteTagValues,remoteTagCount)) { case -1: + if (ztDest) + m.sendCredentialsIfNeeded(RR,RR->node->now(),ztDest,_config,(const Capability *)0); return false; case 1: if (ztDest) - m.sendCredentialsIfNeeded(RR,RR->node->now(),ztDest,_config.com,&(_config.capabilities[c]),relevantLocalTags,relevantLocalTagCount); + m.sendCredentialsIfNeeded(RR,RR->node->now(),ztDest,_config,&(_config.capabilities[c])); return true; } } @@ -587,15 +594,13 @@ bool Network::filterIncomingPacket( { 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); - 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,relevantLocalTags,relevantLocalTagCount)) { + 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: @@ -605,8 +610,7 @@ bool Network::filterIncomingPacket( Membership::CapabilityIterator mci(m); const Capability *c; while ((c = mci.next(_config))) { - relevantLocalTagCount = 0; - 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,relevantLocalTags,relevantLocalTagCount)) { + 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: @@ -1030,7 +1034,7 @@ void Network::_announceMulticastGroupsTo(const SharedPtr &peer,const std:: { Membership *m = _memberships.get(peer->address()); if (m) - m->sendCredentialsIfNeeded(RR,RR->node->now(),peer->address(),_config.com,(const Capability *)0,(const Tag **)0,0); + m->sendCredentialsIfNeeded(RR,RR->node->now(),peer->address(),_config,(const Capability *)0); } Packet outp(peer->address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE); -- cgit v1.2.3