diff options
-rw-r--r-- | include/ZeroTierOne.h | 25 | ||||
-rw-r--r-- | node/Capability.hpp | 156 | ||||
-rw-r--r-- | 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<unsigned int C> - inline void serialize(Buffer<C> &b,const bool forSign = false) const + static inline void serializeRules(Buffer<C> &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<ruleCount;++i) { // Each rule consists of its 8-bit type followed by the size of that type's // field followed by field data. The inclusion of the size will allow non-supported // rules to be ignored but still parsed. - b.append((uint8_t)_rules[i].t); - switch((ZT_VirtualNetworkRuleType)(_rules[i].t & 0x7f)) { + b.append((uint8_t)rules[i].t); + switch((ZT_VirtualNetworkRuleType)(rules[i].t & 0x7f)) { //case ZT_NETWORK_RULE_ACTION_DROP: //case ZT_NETWORK_RULE_ACTION_ACCEPT: default: @@ -183,67 +177,91 @@ public: case ZT_NETWORK_RULE_MATCH_SOURCE_ZEROTIER_ADDRESS: case ZT_NETWORK_RULE_MATCH_DEST_ZEROTIER_ADDRESS: b.append((uint8_t)5); - Address(_rules[i].v.zt).appendTo(b); + Address(rules[i].v.zt).appendTo(b); break; case ZT_NETWORK_RULE_MATCH_VLAN_ID: b.append((uint8_t)2); - b.append((uint16_t)_rules[i].v.vlanId); + b.append((uint16_t)rules[i].v.vlanId); break; case ZT_NETWORK_RULE_MATCH_VLAN_PCP: b.append((uint8_t)1); - b.append((uint8_t)_rules[i].v.vlanPcp); + b.append((uint8_t)rules[i].v.vlanPcp); break; case ZT_NETWORK_RULE_MATCH_VLAN_DEI: b.append((uint8_t)1); - b.append((uint8_t)_rules[i].v.vlanDei); + b.append((uint8_t)rules[i].v.vlanDei); break; case ZT_NETWORK_RULE_MATCH_ETHERTYPE: b.append((uint8_t)2); - b.append((uint16_t)_rules[i].v.etherType); + b.append((uint16_t)rules[i].v.etherType); break; case ZT_NETWORK_RULE_MATCH_MAC_SOURCE: case ZT_NETWORK_RULE_MATCH_MAC_DEST: b.append((uint8_t)6); - b.append(_rules[i].v.mac,6); + b.append(rules[i].v.mac,6); break; case ZT_NETWORK_RULE_MATCH_IPV4_SOURCE: case ZT_NETWORK_RULE_MATCH_IPV4_DEST: b.append((uint8_t)5); - b.append(&(_rules[i].v.ipv4.ip),4); - b.append((uint8_t)_rules[i].v.ipv4.mask); + b.append(&(rules[i].v.ipv4.ip),4); + b.append((uint8_t)rules[i].v.ipv4.mask); break; case ZT_NETWORK_RULE_MATCH_IPV6_SOURCE: case ZT_NETWORK_RULE_MATCH_IPV6_DEST: b.append((uint8_t)17); - b.append(_rules[i].v.ipv6.ip,16); - b.append((uint8_t)_rules[i].v.ipv6.mask); + b.append(rules[i].v.ipv6.ip,16); + b.append((uint8_t)rules[i].v.ipv6.mask); break; case ZT_NETWORK_RULE_MATCH_IP_TOS: b.append((uint8_t)1); - b.append((uint8_t)_rules[i].v.ipTos); + b.append((uint8_t)rules[i].v.ipTos); break; case ZT_NETWORK_RULE_MATCH_IP_PROTOCOL: b.append((uint8_t)1); - b.append((uint8_t)_rules[i].v.ipProtocol); + b.append((uint8_t)rules[i].v.ipProtocol); break; case ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE: case ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE: b.append((uint8_t)4); - b.append((uint16_t)_rules[i].v.port[0]); - b.append((uint16_t)_rules[i].v.port[1]); + b.append((uint16_t)rules[i].v.port[0]); + b.append((uint16_t)rules[i].v.port[1]); break; case ZT_NETWORK_RULE_MATCH_CHARACTERISTICS: b.append((uint8_t)16); - b.append((uint64_t)_rules[i].v.characteristics[0]); - b.append((uint64_t)_rules[i].v.characteristics[1]); + b.append((uint64_t)rules[i].v.characteristics[0]); + b.append((uint64_t)rules[i].v.characteristics[1]); break; case ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE: b.append((uint8_t)4); - b.append((uint16_t)_rules[i].v.frameSize[0]); - b.append((uint16_t)_rules[i].v.frameSize[1]); + b.append((uint16_t)rules[i].v.frameSize[0]); + b.append((uint16_t)rules[i].v.frameSize[1]); + break; + case ZT_NETWORK_RULE_MATCH_TAG_VALUE_RANGE: + b.append((uint8_t)12); + b.append((uint32_t)rules[i].v.tag.id); + b.append((uint32_t)rules[i].v.tag.value[0]); + b.append((uint32_t)rules[i].v.tag.value[1]); + break; + case ZT_NETWORK_RULE_MATCH_TAG_VALUE_BITS_ALL: + case ZT_NETWORK_RULE_MATCH_TAG_VALUE_BITS_ANY: + b.append((uint8_t)8); + b.append((uint32_t)rules[i].v.tag.id); + b.append((uint32_t)rules[i].v.tag.value[0]); break; } } + } + + template<unsigned int C> + inline void serialize(Buffer<C> &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<unsigned int C> - inline unsigned int deserialize(const Buffer<C> &b,unsigned int startAt = 0) + static inline void deserializeRules(const Buffer<C> &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<uint32_t>(p); p += 4; - _nwid = b.template at<uint64_t>(p); p += 8; - _expiration = b.template at<uint64_t>(p); p += 8; - - _ruleCount = b.template at<uint16_t>(p); p += 2; - if (_ruleCount > ZT_MAX_CAPABILITY_RULES) + ruleCount = b.template at<uint16_t>(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<ruleCount;++i) { + rules[i].t = (uint8_t)b[p++]; const unsigned int fieldLen = (unsigned int)b[p++]; - switch((ZT_VirtualNetworkRuleType)(_rules[i].t & 0x7f)) { + switch((ZT_VirtualNetworkRuleType)(rules[i].t & 0x7f)) { default: break; case ZT_NETWORK_RULE_ACTION_TEE: case ZT_NETWORK_RULE_ACTION_REDIRECT: case ZT_NETWORK_RULE_MATCH_SOURCE_ZEROTIER_ADDRESS: case ZT_NETWORK_RULE_MATCH_DEST_ZEROTIER_ADDRESS: - _rules[i].v.zt = Address(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH).toInt(); + rules[i].v.zt = Address(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH).toInt(); break; case ZT_NETWORK_RULE_MATCH_VLAN_ID: - _rules[i].v.vlanId = b.template at<uint16_t>(p); + rules[i].v.vlanId = b.template at<uint16_t>(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<uint16_t>(p); + rules[i].v.etherType = b.template at<uint16_t>(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<uint16_t>(p); - _rules[i].v.port[1] = b.template at<uint16_t>(p + 2); + rules[i].v.port[0] = b.template at<uint16_t>(p); + rules[i].v.port[1] = b.template at<uint16_t>(p + 2); break; case ZT_NETWORK_RULE_MATCH_CHARACTERISTICS: - _rules[i].v.characteristics[0] = b.template at<uint64_t>(p); - _rules[i].v.characteristics[1] = b.template at<uint64_t>(p + 8); + rules[i].v.characteristics[0] = b.template at<uint64_t>(p); + rules[i].v.characteristics[1] = b.template at<uint64_t>(p + 8); break; case ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE: - _rules[i].v.frameSize[0] = b.template at<uint16_t>(p); - _rules[i].v.frameSize[0] = b.template at<uint16_t>(p + 2); + rules[i].v.frameSize[0] = b.template at<uint16_t>(p); + rules[i].v.frameSize[0] = b.template at<uint16_t>(p + 2); + break; + case ZT_NETWORK_RULE_MATCH_TAG_VALUE_RANGE: + rules[i].v.tag.id = b.template at<uint32_t>(p); + rules[i].v.tag.value[0] = b.template at<uint32_t>(p + 4); + rules[i].v.tag.value[1] = b.template at<uint32_t>(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<uint32_t>(p); + rules[i].v.tag.value[0] = b.template at<uint32_t>(p + 4); break; } p += fieldLen; } + } + + template<unsigned int C> + inline unsigned int deserialize(const Buffer<C> &b,unsigned int startAt = 0) + { + memset(this,0,sizeof(Capability)); + + unsigned int p = startAt; + + _id = b.template at<uint32_t>(p); p += 4; + _nwid = b.template at<uint64_t>(p); p += 8; + _expiration = b.template at<uint64_t>(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 |