From 67cb03742e09f7ad83c2edd80e0a8ffbfcfa6285 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 3 Aug 2016 14:12:38 -0700 Subject: Add tag rules and split out rule serialize/deserialize so the code can be reused. --- include/ZeroTierOne.h | 25 +++++++- node/Capability.hpp | 156 ++++++++++++++++++++++++++++++-------------------- node/Filter.cpp | 5 ++ 3 files changed, 124 insertions(+), 62 deletions(-) diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index c4696e7d..db405c08 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -525,7 +525,22 @@ enum ZT_VirtualNetworkRuleType /** * Frame size range (start-end, inclusive) */ - ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE = 49 + ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE = 49, + + /** + * Match a range of tag values (equality match if start==end) + */ + ZT_NETWORK_RULE_MATCH_TAG_VALUE_RANGE = 50, + + /** + * Match if all bits are set in a tag value + */ + ZT_NETWORK_RULE_MATCH_TAG_VALUE_BITS_ALL = 51, + + /** + * Match if any bit from a mask is set in a tag value + */ + ZT_NETWORK_RULE_MATCH_TAG_VALUE_BITS_ANY = 52 }; /** @@ -628,6 +643,14 @@ typedef struct * Ethernet packet size in host byte order (start-end, inclusive) */ uint16_t frameSize[2]; + + /** + * For matching tag values + */ + struct { + uint32_t id; + uint32_t value[2]; // only [0] is used for BITS_ALL or BITS_ANY, [0]-[1] for range + } tag; } v; } ZT_VirtualNetworkRule; diff --git a/node/Capability.hpp b/node/Capability.hpp index 6de4e0a1..82342874 100644 --- a/node/Capability.hpp +++ b/node/Capability.hpp @@ -158,21 +158,15 @@ public: int verify(const RuntimeEnvironment *RR,const Address &verifyInChain) const; template - inline void serialize(Buffer &b,const bool forSign = false) const + static inline void serializeRules(Buffer &b,const ZT_VirtualNetworkRule *rules,unsigned int ruleCount) { - if (forSign) b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL); - - b.append(_id); - b.append(_nwid); - b.append(_expiration); - - b.append((uint16_t)_ruleCount); - for(unsigned int i=0;i<_ruleCount;++i) { + b.append((uint16_t)ruleCount); + for(unsigned int i=0;i + inline void serialize(Buffer &b,const bool forSign = false) const + { + if (forSign) b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL); + + b.append(_id); + b.append(_nwid); + b.append(_expiration); + + serializeRules(b,_rules,_ruleCount); b.append((uint8_t)_maxCustodyChainLength); for(unsigned int i=0;;++i) { @@ -269,79 +287,95 @@ public: } template - inline unsigned int deserialize(const Buffer &b,unsigned int startAt = 0) + static inline void deserializeRules(const Buffer &b,unsigned int &p,ZT_VirtualNetworkRule *rules,unsigned int &ruleCount,const unsigned int maxRuleCount) { - memset(this,0,sizeof(Capability)); - - unsigned int p = startAt; - - _id = b.template at(p); p += 4; - _nwid = b.template at(p); p += 8; - _expiration = b.template at(p); p += 8; - - _ruleCount = b.template at(p); p += 2; - if (_ruleCount > ZT_MAX_CAPABILITY_RULES) + ruleCount = b.template at(p); p += 2; + if (ruleCount > maxRuleCount) throw std::runtime_error("rule count overflow"); - for(unsigned int i=0;i<_ruleCount;++i) { - _rules[i].t = (uint8_t)b[p++]; + for(unsigned int i=0;i(p); + rules[i].v.vlanId = b.template at(p); break; case ZT_NETWORK_RULE_MATCH_VLAN_PCP: - _rules[i].v.vlanPcp = (uint8_t)b[p]; + rules[i].v.vlanPcp = (uint8_t)b[p]; break; case ZT_NETWORK_RULE_MATCH_VLAN_DEI: - _rules[i].v.vlanDei = (uint8_t)b[p]; + rules[i].v.vlanDei = (uint8_t)b[p]; break; case ZT_NETWORK_RULE_MATCH_ETHERTYPE: - _rules[i].v.etherType = b.template at(p); + rules[i].v.etherType = b.template at(p); break; case ZT_NETWORK_RULE_MATCH_MAC_SOURCE: case ZT_NETWORK_RULE_MATCH_MAC_DEST: - memcpy(_rules[i].v.mac,b.field(p,6),6); + memcpy(rules[i].v.mac,b.field(p,6),6); break; case ZT_NETWORK_RULE_MATCH_IPV4_SOURCE: case ZT_NETWORK_RULE_MATCH_IPV4_DEST: - memcpy(&(_rules[i].v.ipv4.ip),b.field(p,4),4); - _rules[i].v.ipv4.mask = (uint8_t)b[p + 4]; + memcpy(&(rules[i].v.ipv4.ip),b.field(p,4),4); + rules[i].v.ipv4.mask = (uint8_t)b[p + 4]; break; case ZT_NETWORK_RULE_MATCH_IPV6_SOURCE: case ZT_NETWORK_RULE_MATCH_IPV6_DEST: - memcpy(_rules[i].v.ipv6.ip,b.field(p,16),16); - _rules[i].v.ipv6.mask = (uint8_t)b[p + 16]; + memcpy(rules[i].v.ipv6.ip,b.field(p,16),16); + rules[i].v.ipv6.mask = (uint8_t)b[p + 16]; break; case ZT_NETWORK_RULE_MATCH_IP_TOS: - _rules[i].v.ipTos = (uint8_t)b[p]; + rules[i].v.ipTos = (uint8_t)b[p]; break; case ZT_NETWORK_RULE_MATCH_IP_PROTOCOL: - _rules[i].v.ipProtocol = (uint8_t)b[p]; + rules[i].v.ipProtocol = (uint8_t)b[p]; break; case ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE: case ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE: - _rules[i].v.port[0] = b.template at(p); - _rules[i].v.port[1] = b.template at(p + 2); + rules[i].v.port[0] = b.template at(p); + rules[i].v.port[1] = b.template at(p + 2); break; case ZT_NETWORK_RULE_MATCH_CHARACTERISTICS: - _rules[i].v.characteristics[0] = b.template at(p); - _rules[i].v.characteristics[1] = b.template at(p + 8); + rules[i].v.characteristics[0] = b.template at(p); + rules[i].v.characteristics[1] = b.template at(p + 8); break; case ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE: - _rules[i].v.frameSize[0] = b.template at(p); - _rules[i].v.frameSize[0] = b.template at(p + 2); + rules[i].v.frameSize[0] = b.template at(p); + rules[i].v.frameSize[0] = b.template at(p + 2); + break; + case ZT_NETWORK_RULE_MATCH_TAG_VALUE_RANGE: + rules[i].v.tag.id = b.template at(p); + rules[i].v.tag.value[0] = b.template at(p + 4); + rules[i].v.tag.value[1] = b.template at(p + 8); + break; + case ZT_NETWORK_RULE_MATCH_TAG_VALUE_BITS_ALL: + case ZT_NETWORK_RULE_MATCH_TAG_VALUE_BITS_ANY: + rules[i].v.tag.id = b.template at(p); + rules[i].v.tag.value[0] = b.template at(p + 4); break; } p += fieldLen; } + } + + template + inline unsigned int deserialize(const Buffer &b,unsigned int startAt = 0) + { + memset(this,0,sizeof(Capability)); + + unsigned int p = startAt; + + _id = b.template at(p); p += 4; + _nwid = b.template at(p); p += 8; + _expiration = b.template at(p); p += 8; + + deserializeRules(b,p,_rules,_ruleCount,ZT_MAX_CAPABILITY_RULES); _maxCustodyChainLength = (unsigned int)b[p++]; if ((_maxCustodyChainLength < 1)||(_maxCustodyChainLength > ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH)) diff --git a/node/Filter.cpp b/node/Filter.cpp index a4de7201..d86d1a14 100644 --- a/node/Filter.cpp +++ b/node/Filter.cpp @@ -243,6 +243,11 @@ bool Filter::run( 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_TAG_VALUE_RANGE: + break; + case ZT_NETWORK_RULE_MATCH_TAG_VALUE_BITS_ALL: + case ZT_NETWORK_RULE_MATCH_TAG_VALUE_BITS_ANY: + break; } // thisSetMatches remains true if the current rule matched... or does NOT match if not bit (0x80) is 1 -- cgit v1.2.3