summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/ZeroTierOne.h25
-rw-r--r--node/Capability.hpp156
-rw-r--r--node/Filter.cpp5
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