浏览代码

Add tag rules and split out rule serialize/deserialize so the code can be reused.

Adam Ierymenko 9 年之前
父节点
当前提交
67cb03742e
共有 3 个文件被更改,包括 124 次插入62 次删除
  1. 24 1
      include/ZeroTierOne.h
  2. 95 61
      node/Capability.hpp
  3. 5 0
      node/Filter.cpp

+ 24 - 1
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;
 

+ 95 - 61
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))

+ 5 - 0
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