瀏覽代碼

Broke down and added an OR to the rules engine. It is now possible to have a series of MATCHes that are ORed.

Adam Ierymenko 8 年之前
父節點
當前提交
e53f63ca87
共有 4 個文件被更改,包括 193 次插入292 次删除
  1. 140 142
      controller/EmbeddedNetworkController.cpp
  2. 32 131
      include/ZeroTierOne.h
  3. 9 9
      node/Capability.hpp
  4. 12 10
      node/Network.cpp

+ 140 - 142
controller/EmbeddedNetworkController.cpp

@@ -127,7 +127,9 @@ static json _renderRule(ZT_VirtualNetworkRule &rule)
 {
 {
 	char tmp[128];
 	char tmp[128];
 	json r = json::object();
 	json r = json::object();
-	switch((rule.t) & 0x7f) {
+	const ZT_VirtualNetworkRuleType rt = (ZT_VirtualNetworkRuleType)(rule.t & 0x3f);
+
+	switch(rt) {
 		case ZT_NETWORK_RULE_ACTION_DROP:
 		case ZT_NETWORK_RULE_ACTION_DROP:
 			r["type"] = "ACTION_DROP";
 			r["type"] = "ACTION_DROP";
 			break;
 			break;
@@ -154,146 +156,136 @@ static json _renderRule(ZT_VirtualNetworkRule &rule)
 		case ZT_NETWORK_RULE_ACTION_DEBUG_LOG:
 		case ZT_NETWORK_RULE_ACTION_DEBUG_LOG:
 			r["type"] = "ACTION_DEBUG_LOG";
 			r["type"] = "ACTION_DEBUG_LOG";
 			break;
 			break;
-		case ZT_NETWORK_RULE_MATCH_SOURCE_ZEROTIER_ADDRESS:
-			r["type"] = "MATCH_SOURCE_ZEROTIER_ADDRESS";
-			r["not"] = ((rule.t & 0x80) != 0);
-			r["zt"] = Address(rule.v.zt).toString();
-			break;
-		case ZT_NETWORK_RULE_MATCH_DEST_ZEROTIER_ADDRESS:
-			r["type"] = "MATCH_DEST_ZEROTIER_ADDRESS";
-			r["not"] = ((rule.t & 0x80) != 0);
-			r["zt"] = Address(rule.v.zt).toString();
-			break;
-		case ZT_NETWORK_RULE_MATCH_VLAN_ID:
-			r["type"] = "MATCH_VLAN_ID";
-			r["not"] = ((rule.t & 0x80) != 0);
-			r["vlanId"] = (unsigned int)rule.v.vlanId;
-			break;
-		case ZT_NETWORK_RULE_MATCH_VLAN_PCP:
-			r["type"] = "MATCH_VLAN_PCP";
-			r["not"] = ((rule.t & 0x80) != 0);
-			r["vlanPcp"] = (unsigned int)rule.v.vlanPcp;
-			break;
-		case ZT_NETWORK_RULE_MATCH_VLAN_DEI:
-			r["type"] = "MATCH_VLAN_DEI";
-			r["not"] = ((rule.t & 0x80) != 0);
-			r["vlanDei"] = (unsigned int)rule.v.vlanDei;
-			break;
-		case ZT_NETWORK_RULE_MATCH_ETHERTYPE:
-			r["type"] = "MATCH_ETHERTYPE";
-			r["not"] = ((rule.t & 0x80) != 0);
-			r["etherType"] = (unsigned int)rule.v.etherType;
-			break;
-		case ZT_NETWORK_RULE_MATCH_MAC_SOURCE:
-			r["type"] = "MATCH_MAC_SOURCE";
-			r["not"] = ((rule.t & 0x80) != 0);
-			Utils::snprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)rule.v.mac[0],(unsigned int)rule.v.mac[1],(unsigned int)rule.v.mac[2],(unsigned int)rule.v.mac[3],(unsigned int)rule.v.mac[4],(unsigned int)rule.v.mac[5]);
-			r["mac"] = tmp;
-			break;
-		case ZT_NETWORK_RULE_MATCH_MAC_DEST:
-			r["type"] = "MATCH_MAC_DEST";
-			r["not"] = ((rule.t & 0x80) != 0);
-			Utils::snprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)rule.v.mac[0],(unsigned int)rule.v.mac[1],(unsigned int)rule.v.mac[2],(unsigned int)rule.v.mac[3],(unsigned int)rule.v.mac[4],(unsigned int)rule.v.mac[5]);
-			r["mac"] = tmp;
-			break;
-		case ZT_NETWORK_RULE_MATCH_IPV4_SOURCE:
-			r["type"] = "MATCH_IPV4_SOURCE";
-			r["not"] = ((rule.t & 0x80) != 0);
-			r["ip"] = InetAddress(&(rule.v.ipv4.ip),4,(unsigned int)rule.v.ipv4.mask).toString();
-			break;
-		case ZT_NETWORK_RULE_MATCH_IPV4_DEST:
-			r["type"] = "MATCH_IPV4_DEST";
-			r["not"] = ((rule.t & 0x80) != 0);
-			r["ip"] = InetAddress(&(rule.v.ipv4.ip),4,(unsigned int)rule.v.ipv4.mask).toString();
-			break;
-		case ZT_NETWORK_RULE_MATCH_IPV6_SOURCE:
-			r["type"] = "MATCH_IPV6_SOURCE";
-			r["not"] = ((rule.t & 0x80) != 0);
-			r["ip"] = InetAddress(rule.v.ipv6.ip,16,(unsigned int)rule.v.ipv6.mask).toString();
-			break;
-		case ZT_NETWORK_RULE_MATCH_IPV6_DEST:
-			r["type"] = "MATCH_IPV6_DEST";
-			r["not"] = ((rule.t & 0x80) != 0);
-			r["ip"] = InetAddress(rule.v.ipv6.ip,16,(unsigned int)rule.v.ipv6.mask).toString();
+		default:
 			break;
 			break;
-		case ZT_NETWORK_RULE_MATCH_IP_TOS:
-			r["type"] = "MATCH_IP_TOS";
-			r["not"] = ((rule.t & 0x80) != 0);
-			r["ipTos"] = (unsigned int)rule.v.ipTos;
-			break;
-		case ZT_NETWORK_RULE_MATCH_IP_PROTOCOL:
-			r["type"] = "MATCH_IP_PROTOCOL";
-			r["not"] = ((rule.t & 0x80) != 0);
-			r["ipProtocol"] = (unsigned int)rule.v.ipProtocol;
-			break;
-		case ZT_NETWORK_RULE_MATCH_ICMP:
-			r["type"] = "MATCH_ICMP";
-			r["not"] = ((rule.t & 0x80) != 0);
-			r["type"] = (unsigned int)rule.v.icmp.type;
-			if ((rule.v.icmp.flags & 0x01) != 0)
-				r["code"] = (unsigned int)rule.v.icmp.code;
-			else r["code"] = json();
-			break;
-		case ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE:
-			r["type"] = "MATCH_IP_SOURCE_PORT_RANGE";
-			r["not"] = ((rule.t & 0x80) != 0);
-			r["start"] = (unsigned int)rule.v.port[0];
-			r["end"] = (unsigned int)rule.v.port[1];
-			break;
-		case ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE:
-			r["type"] = "MATCH_IP_DEST_PORT_RANGE";
-			r["not"] = ((rule.t & 0x80) != 0);
-			r["start"] = (unsigned int)rule.v.port[0];
-			r["end"] = (unsigned int)rule.v.port[1];
-			break;
-		case ZT_NETWORK_RULE_MATCH_CHARACTERISTICS:
-			r["type"] = "MATCH_CHARACTERISTICS";
-			r["not"] = ((rule.t & 0x80) != 0);
-			Utils::snprintf(tmp,sizeof(tmp),"%.16llx",rule.v.characteristics);
-			r["mask"] = tmp;
-			break;
-		case ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE:
-			r["type"] = "MATCH_FRAME_SIZE_RANGE";
-			r["not"] = ((rule.t & 0x80) != 0);
-			r["start"] = (unsigned int)rule.v.frameSize[0];
-			r["end"] = (unsigned int)rule.v.frameSize[1];
-			break;
-		case ZT_NETWORK_RULE_MATCH_RANDOM:
-			r["type"] = "MATCH_RANDOM";
-			r["not"] = ((rule.t & 0x80) != 0);
-			r["probability"] = (unsigned long)rule.v.randomProbability;
-			break;
-		case ZT_NETWORK_RULE_MATCH_TAGS_DIFFERENCE:
-			r["type"] = "MATCH_TAGS_DIFFERENCE";
-			r["not"] = ((rule.t & 0x80) != 0);
-			r["id"] = rule.v.tag.id;
-			r["value"] = rule.v.tag.value;
-			break;
-		case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND:
-			r["type"] = "MATCH_TAGS_BITWISE_AND";
-			r["not"] = ((rule.t & 0x80) != 0);
-			r["id"] = rule.v.tag.id;
-			r["value"] = rule.v.tag.value;
-			break;
-		case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR:
-			r["type"] = "MATCH_TAGS_BITWISE_OR";
-			r["not"] = ((rule.t & 0x80) != 0);
-			r["id"] = rule.v.tag.id;
-			r["value"] = rule.v.tag.value;
-			break;
-		case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR:
-			r["type"] = "MATCH_TAGS_BITWISE_XOR";
-			r["not"] = ((rule.t & 0x80) != 0);
-			r["id"] = rule.v.tag.id;
-			r["value"] = rule.v.tag.value;
-			break;
-		case ZT_NETWORK_RULE_MATCH_TAGS_EQUAL:
-			r["type"] = "MATCH_TAGS_EQUAL";
+	}
+
+	if (r.size() == 0) {
+		switch(rt) {
+			case ZT_NETWORK_RULE_MATCH_SOURCE_ZEROTIER_ADDRESS:
+				r["type"] = "MATCH_SOURCE_ZEROTIER_ADDRESS";
+				r["zt"] = Address(rule.v.zt).toString();
+				break;
+			case ZT_NETWORK_RULE_MATCH_DEST_ZEROTIER_ADDRESS:
+				r["type"] = "MATCH_DEST_ZEROTIER_ADDRESS";
+				r["zt"] = Address(rule.v.zt).toString();
+				break;
+			case ZT_NETWORK_RULE_MATCH_VLAN_ID:
+				r["type"] = "MATCH_VLAN_ID";
+				r["vlanId"] = (unsigned int)rule.v.vlanId;
+				break;
+			case ZT_NETWORK_RULE_MATCH_VLAN_PCP:
+				r["type"] = "MATCH_VLAN_PCP";
+				r["vlanPcp"] = (unsigned int)rule.v.vlanPcp;
+				break;
+			case ZT_NETWORK_RULE_MATCH_VLAN_DEI:
+				r["type"] = "MATCH_VLAN_DEI";
+				r["vlanDei"] = (unsigned int)rule.v.vlanDei;
+				break;
+			case ZT_NETWORK_RULE_MATCH_MAC_SOURCE:
+				r["type"] = "MATCH_MAC_SOURCE";
+				Utils::snprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)rule.v.mac[0],(unsigned int)rule.v.mac[1],(unsigned int)rule.v.mac[2],(unsigned int)rule.v.mac[3],(unsigned int)rule.v.mac[4],(unsigned int)rule.v.mac[5]);
+				r["mac"] = tmp;
+				break;
+			case ZT_NETWORK_RULE_MATCH_MAC_DEST:
+				r["type"] = "MATCH_MAC_DEST";
+				Utils::snprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)rule.v.mac[0],(unsigned int)rule.v.mac[1],(unsigned int)rule.v.mac[2],(unsigned int)rule.v.mac[3],(unsigned int)rule.v.mac[4],(unsigned int)rule.v.mac[5]);
+				r["mac"] = tmp;
+				break;
+			case ZT_NETWORK_RULE_MATCH_IPV4_SOURCE:
+				r["type"] = "MATCH_IPV4_SOURCE";
+				r["ip"] = InetAddress(&(rule.v.ipv4.ip),4,(unsigned int)rule.v.ipv4.mask).toString();
+				break;
+			case ZT_NETWORK_RULE_MATCH_IPV4_DEST:
+				r["type"] = "MATCH_IPV4_DEST";
+				r["ip"] = InetAddress(&(rule.v.ipv4.ip),4,(unsigned int)rule.v.ipv4.mask).toString();
+				break;
+			case ZT_NETWORK_RULE_MATCH_IPV6_SOURCE:
+				r["type"] = "MATCH_IPV6_SOURCE";
+				r["ip"] = InetAddress(rule.v.ipv6.ip,16,(unsigned int)rule.v.ipv6.mask).toString();
+				break;
+			case ZT_NETWORK_RULE_MATCH_IPV6_DEST:
+				r["type"] = "MATCH_IPV6_DEST";
+				r["ip"] = InetAddress(rule.v.ipv6.ip,16,(unsigned int)rule.v.ipv6.mask).toString();
+				break;
+			case ZT_NETWORK_RULE_MATCH_IP_TOS:
+				r["type"] = "MATCH_IP_TOS";
+				r["ipTos"] = (unsigned int)rule.v.ipTos;
+				break;
+			case ZT_NETWORK_RULE_MATCH_IP_PROTOCOL:
+				r["type"] = "MATCH_IP_PROTOCOL";
+				r["ipProtocol"] = (unsigned int)rule.v.ipProtocol;
+				break;
+			case ZT_NETWORK_RULE_MATCH_ETHERTYPE:
+				r["type"] = "MATCH_ETHERTYPE";
+				r["etherType"] = (unsigned int)rule.v.etherType;
+				break;
+			case ZT_NETWORK_RULE_MATCH_ICMP:
+				r["type"] = "MATCH_ICMP";
+				r["type"] = (unsigned int)rule.v.icmp.type;
+				if ((rule.v.icmp.flags & 0x01) != 0)
+					r["code"] = (unsigned int)rule.v.icmp.code;
+				else r["code"] = json();
+				break;
+			case ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE:
+				r["type"] = "MATCH_IP_SOURCE_PORT_RANGE";
+				r["start"] = (unsigned int)rule.v.port[0];
+				r["end"] = (unsigned int)rule.v.port[1];
+				break;
+			case ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE:
+				r["type"] = "MATCH_IP_DEST_PORT_RANGE";
+				r["start"] = (unsigned int)rule.v.port[0];
+				r["end"] = (unsigned int)rule.v.port[1];
+				break;
+			case ZT_NETWORK_RULE_MATCH_CHARACTERISTICS:
+				r["type"] = "MATCH_CHARACTERISTICS";
+				Utils::snprintf(tmp,sizeof(tmp),"%.16llx",rule.v.characteristics);
+				r["mask"] = tmp;
+				break;
+			case ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE:
+				r["type"] = "MATCH_FRAME_SIZE_RANGE";
+				r["start"] = (unsigned int)rule.v.frameSize[0];
+				r["end"] = (unsigned int)rule.v.frameSize[1];
+				break;
+			case ZT_NETWORK_RULE_MATCH_RANDOM:
+				r["type"] = "MATCH_RANDOM";
+				r["probability"] = (unsigned long)rule.v.randomProbability;
+				break;
+			case ZT_NETWORK_RULE_MATCH_TAGS_DIFFERENCE:
+				r["type"] = "MATCH_TAGS_DIFFERENCE";
+				r["id"] = rule.v.tag.id;
+				r["value"] = rule.v.tag.value;
+				break;
+			case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND:
+				r["type"] = "MATCH_TAGS_BITWISE_AND";
+				r["id"] = rule.v.tag.id;
+				r["value"] = rule.v.tag.value;
+				break;
+			case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR:
+				r["type"] = "MATCH_TAGS_BITWISE_OR";
+				r["id"] = rule.v.tag.id;
+				r["value"] = rule.v.tag.value;
+				break;
+			case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR:
+				r["type"] = "MATCH_TAGS_BITWISE_XOR";
+				r["id"] = rule.v.tag.id;
+				r["value"] = rule.v.tag.value;
+				break;
+			case ZT_NETWORK_RULE_MATCH_TAGS_EQUAL:
+				r["type"] = "MATCH_TAGS_EQUAL";
+				r["id"] = rule.v.tag.id;
+				r["value"] = rule.v.tag.value;
+				break;
+			default:
+				break;
+		}
+
+		if (r.size() > 0) {
 			r["not"] = ((rule.t & 0x80) != 0);
 			r["not"] = ((rule.t & 0x80) != 0);
-			r["id"] = rule.v.tag.id;
-			r["value"] = rule.v.tag.value;
-			break;
+			r["or"] = ((rule.t & 0x40) != 0);
+		}
 	}
 	}
+
 	return r;
 	return r;
 }
 }
 
 
@@ -301,11 +293,16 @@ static bool _parseRule(json &r,ZT_VirtualNetworkRule &rule)
 {
 {
 	if (!r.is_object())
 	if (!r.is_object())
 		return false;
 		return false;
+
 	const std::string t(_jS(r["type"],""));
 	const std::string t(_jS(r["type"],""));
 	memset(&rule,0,sizeof(ZT_VirtualNetworkRule));
 	memset(&rule,0,sizeof(ZT_VirtualNetworkRule));
+
 	if (_jB(r["not"],false))
 	if (_jB(r["not"],false))
 		rule.t = 0x80;
 		rule.t = 0x80;
 	else rule.t = 0x00;
 	else rule.t = 0x00;
+	if (_jB(r["or"],false))
+		rule.t |= 0x40;
+
 	if (t == "ACTION_DROP") {
 	if (t == "ACTION_DROP") {
 		rule.t |= ZT_NETWORK_RULE_ACTION_DROP;
 		rule.t |= ZT_NETWORK_RULE_ACTION_DROP;
 		return true;
 		return true;
@@ -352,10 +349,6 @@ static bool _parseRule(json &r,ZT_VirtualNetworkRule &rule)
 		rule.t |= ZT_NETWORK_RULE_MATCH_VLAN_DEI;
 		rule.t |= ZT_NETWORK_RULE_MATCH_VLAN_DEI;
 		rule.v.vlanDei = (uint8_t)(_jI(r["vlanDei"],0ULL) & 0xffULL);
 		rule.v.vlanDei = (uint8_t)(_jI(r["vlanDei"],0ULL) & 0xffULL);
 		return true;
 		return true;
-	} else if (t == "MATCH_ETHERTYPE") {
-		rule.t |= ZT_NETWORK_RULE_MATCH_ETHERTYPE;
-		rule.v.etherType = (uint16_t)(_jI(r["etherType"],0ULL) & 0xffffULL);
-		return true;
 	} else if (t == "MATCH_MAC_SOURCE") {
 	} else if (t == "MATCH_MAC_SOURCE") {
 		rule.t |= ZT_NETWORK_RULE_MATCH_MAC_SOURCE;
 		rule.t |= ZT_NETWORK_RULE_MATCH_MAC_SOURCE;
 		const std::string mac(_jS(r["mac"],"0"));
 		const std::string mac(_jS(r["mac"],"0"));
@@ -402,6 +395,10 @@ static bool _parseRule(json &r,ZT_VirtualNetworkRule &rule)
 		rule.t |= ZT_NETWORK_RULE_MATCH_IP_PROTOCOL;
 		rule.t |= ZT_NETWORK_RULE_MATCH_IP_PROTOCOL;
 		rule.v.ipProtocol = (uint8_t)(_jI(r["ipProtocol"],0ULL) & 0xffULL);
 		rule.v.ipProtocol = (uint8_t)(_jI(r["ipProtocol"],0ULL) & 0xffULL);
 		return true;
 		return true;
+	} else if (t == "MATCH_ETHERTYPE") {
+		rule.t |= ZT_NETWORK_RULE_MATCH_ETHERTYPE;
+		rule.v.etherType = (uint16_t)(_jI(r["etherType"],0ULL) & 0xffffULL);
+		return true;
 	} else if (t == "MATCH_ICMP") {
 	} else if (t == "MATCH_ICMP") {
 		rule.t |= ZT_NETWORK_RULE_MATCH_ICMP;
 		rule.t |= ZT_NETWORK_RULE_MATCH_ICMP;
 		rule.v.icmp.type = (uint8_t)(_jI(r["type"],0ULL) & 0xffULL);
 		rule.v.icmp.type = (uint8_t)(_jI(r["type"],0ULL) & 0xffULL);
@@ -470,6 +467,7 @@ static bool _parseRule(json &r,ZT_VirtualNetworkRule &rule)
 		rule.v.tag.value = (uint32_t)(_jI(r["value"],0ULL) & 0xffffffffULL);
 		rule.v.tag.value = (uint32_t)(_jI(r["value"],0ULL) & 0xffffffffULL);
 		return true;
 		return true;
 	}
 	}
+
 	return false;
 	return false;
 }
 }
 
 

+ 32 - 131
include/ZeroTierOne.h

@@ -491,15 +491,15 @@ enum ZT_VirtualNetworkType
 /**
 /**
  * The type of a virtual network rules table entry
  * The type of a virtual network rules table entry
  *
  *
- * These must range from 0 to 127 (0x7f) because the most significant bit
- * is reserved as a NOT flag.
+ * These must be from 0 to 63 since the most significant two bits of each
+ * rule type are NOT (MSB) and AND/OR.
  *
  *
  * Each rule is composed of zero or more MATCHes followed by an ACTION.
  * Each rule is composed of zero or more MATCHes followed by an ACTION.
  * An ACTION with no MATCHes is always taken.
  * An ACTION with no MATCHes is always taken.
  */
  */
 enum ZT_VirtualNetworkRuleType
 enum ZT_VirtualNetworkRuleType
 {
 {
-	// 0 to 31 reserved for actions
+	// 0 to 15 reserved for actions
 
 
 	/**
 	/**
 	 * Drop frame
 	 * Drop frame
@@ -534,139 +534,40 @@ enum ZT_VirtualNetworkRuleType
 	/**
 	/**
 	 * Maximum ID for an ACTION, anything higher is a MATCH
 	 * Maximum ID for an ACTION, anything higher is a MATCH
 	 */
 	 */
-	ZT_NETWORK_RULE_ACTION__MAX_ID = 31,
-
-	// 32 to 127 reserved for match criteria
-
-	/**
-	 * Source ZeroTier address -- analogous to an Ethernet port ID on a switch
-	 */
-	ZT_NETWORK_RULE_MATCH_SOURCE_ZEROTIER_ADDRESS = 32,
-
-	/**
-	 * Destination ZeroTier address -- analogous to an Ethernet port ID on a switch
-	 */
-	ZT_NETWORK_RULE_MATCH_DEST_ZEROTIER_ADDRESS = 33,
-
-	/**
-	 * Ethernet VLAN ID
-	 */
-	ZT_NETWORK_RULE_MATCH_VLAN_ID = 34,
-
-	/** 
-	 * Ethernet VLAN PCP
-	 */
-	ZT_NETWORK_RULE_MATCH_VLAN_PCP = 35,
-
-	/**
-	 * Ethernet VLAN DEI
-	 */
-	ZT_NETWORK_RULE_MATCH_VLAN_DEI = 36,
-
-	/**
-	 * Ethernet frame type
-	 */
+	ZT_NETWORK_RULE_ACTION__MAX_ID = 15,
+
+	// 16 to 63 reserved for match criteria
+
+	ZT_NETWORK_RULE_MATCH_SOURCE_ZEROTIER_ADDRESS = 24,
+	ZT_NETWORK_RULE_MATCH_DEST_ZEROTIER_ADDRESS = 25,
+	ZT_NETWORK_RULE_MATCH_VLAN_ID = 26,
+	ZT_NETWORK_RULE_MATCH_VLAN_PCP = 27,
+	ZT_NETWORK_RULE_MATCH_VLAN_DEI = 28,
+	ZT_NETWORK_RULE_MATCH_MAC_SOURCE = 29,
+	ZT_NETWORK_RULE_MATCH_MAC_DEST = 30,
+	ZT_NETWORK_RULE_MATCH_IPV4_SOURCE = 31,
+	ZT_NETWORK_RULE_MATCH_IPV4_DEST = 32,
+	ZT_NETWORK_RULE_MATCH_IPV6_SOURCE = 33,
+	ZT_NETWORK_RULE_MATCH_IPV6_DEST = 34,
+	ZT_NETWORK_RULE_MATCH_IP_TOS = 35,
+	ZT_NETWORK_RULE_MATCH_IP_PROTOCOL = 36,
 	ZT_NETWORK_RULE_MATCH_ETHERTYPE = 37,
 	ZT_NETWORK_RULE_MATCH_ETHERTYPE = 37,
-
-	/**
-	 * Source Ethernet MAC address
-	 */
-	ZT_NETWORK_RULE_MATCH_MAC_SOURCE = 38,
-
-	/**
-	 * Destination Ethernet MAC address
-	 */
-	ZT_NETWORK_RULE_MATCH_MAC_DEST = 39,
-
-	/**
-	 * Source IPv4 address
-	 */
-	ZT_NETWORK_RULE_MATCH_IPV4_SOURCE = 40,
-
-	/**
-	 * Destination IPv4 address
-	 */
-	ZT_NETWORK_RULE_MATCH_IPV4_DEST = 41,
-
-	/**
-	 * Source IPv6 address
-	 */
-	ZT_NETWORK_RULE_MATCH_IPV6_SOURCE = 42,
-
-	/**
-	 * Destination IPv6 address
-	 */
-	ZT_NETWORK_RULE_MATCH_IPV6_DEST = 43,
-
-	/**
-	 * IP TOS (type of service)
-	 */
-	ZT_NETWORK_RULE_MATCH_IP_TOS = 44,
-
-	/**
-	 * IP protocol
-	 */
-	ZT_NETWORK_RULE_MATCH_IP_PROTOCOL = 45,
-
-	/**
-	 * ICMP type and possibly code (does not match if not ICMP)
-	 */
-	ZT_NETWORK_RULE_MATCH_ICMP = 46,
-
-	/**
-	 * IP source port range (start-end, inclusive)
-	 */
-	ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE = 47,
-
-	/**
-	 * IP destination port range (start-end, inclusive)
-	 */
-	ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE = 48,
-
-	/**
-	 * Packet characteristics (set of flags)
-	 */
-	ZT_NETWORK_RULE_MATCH_CHARACTERISTICS = 49,
-
-	/**
-	 * Frame size range (start-end, inclusive)
-	 */
-	ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE = 50,
-
-	/**
-	 * Random match with selectable probability
-	 */
-	ZT_NETWORK_RULE_MATCH_RANDOM = 51,
-
-	/**
-	 * Match if local and remote tags differ by no more than value, use 0 to check for equality
-	 */
-	ZT_NETWORK_RULE_MATCH_TAGS_DIFFERENCE = 52,
-
-	/**
-	 * Match if local and remote tags ANDed together equal value.
-	 */
-	ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND = 53,
-
-	/**
-	 * Match if local and remote tags ANDed together equal value.
-	 */
-	ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR = 54,
-
-	/**
-	 * Match if local and remote tags XORed together equal value.
-	 */
-	ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR = 55,
-
-	/**
-	 * Match if local and remote tags both equal a value
-	 */
-	ZT_NETWORK_RULE_MATCH_TAGS_EQUAL = 56,
+	ZT_NETWORK_RULE_MATCH_ICMP = 38,
+	ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE = 39,
+	ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE = 40,
+	ZT_NETWORK_RULE_MATCH_CHARACTERISTICS = 41,
+	ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE = 42,
+	ZT_NETWORK_RULE_MATCH_RANDOM = 43,
+	ZT_NETWORK_RULE_MATCH_TAGS_DIFFERENCE = 44,
+	ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND = 45,
+	ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR = 46,
+	ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR = 47,
+	ZT_NETWORK_RULE_MATCH_TAGS_EQUAL = 48,
 
 
 	/**
 	/**
 	 * Maximum ID allowed for a MATCH entry in the rules table
 	 * Maximum ID allowed for a MATCH entry in the rules table
 	 */
 	 */
-	ZT_NETWORK_RULE_MATCH__MAX_ID = 127
+	ZT_NETWORK_RULE_MATCH__MAX_ID = 63
 };
 };
 
 
 /**
 /**

+ 9 - 9
node/Capability.hpp

@@ -166,7 +166,7 @@ public:
 			// field followed by field data. The inclusion of the size will allow non-supported
 			// field followed by field data. The inclusion of the size will allow non-supported
 			// rules to be ignored but still parsed.
 			// rules to be ignored but still parsed.
 			b.append((uint8_t)rules[i].t);
 			b.append((uint8_t)rules[i].t);
-			switch((ZT_VirtualNetworkRuleType)(rules[i].t & 0x7f)) {
+			switch((ZT_VirtualNetworkRuleType)(rules[i].t & 0x3f)) {
 				//case ZT_NETWORK_RULE_ACTION_DROP:
 				//case ZT_NETWORK_RULE_ACTION_DROP:
 				//case ZT_NETWORK_RULE_ACTION_ACCEPT:
 				//case ZT_NETWORK_RULE_ACTION_ACCEPT:
 				//case ZT_NETWORK_RULE_ACTION_DEBUG_LOG:
 				//case ZT_NETWORK_RULE_ACTION_DEBUG_LOG:
@@ -198,10 +198,6 @@ public:
 					b.append((uint8_t)1);
 					b.append((uint8_t)1);
 					b.append((uint8_t)rules[i].v.vlanDei);
 					b.append((uint8_t)rules[i].v.vlanDei);
 					break;
 					break;
-				case ZT_NETWORK_RULE_MATCH_ETHERTYPE:
-					b.append((uint8_t)2);
-					b.append((uint16_t)rules[i].v.etherType);
-					break;
 				case ZT_NETWORK_RULE_MATCH_MAC_SOURCE:
 				case ZT_NETWORK_RULE_MATCH_MAC_SOURCE:
 				case ZT_NETWORK_RULE_MATCH_MAC_DEST:
 				case ZT_NETWORK_RULE_MATCH_MAC_DEST:
 					b.append((uint8_t)6);
 					b.append((uint8_t)6);
@@ -227,6 +223,10 @@ public:
 					b.append((uint8_t)1);
 					b.append((uint8_t)1);
 					b.append((uint8_t)rules[i].v.ipProtocol);
 					b.append((uint8_t)rules[i].v.ipProtocol);
 					break;
 					break;
+				case ZT_NETWORK_RULE_MATCH_ETHERTYPE:
+					b.append((uint8_t)2);
+					b.append((uint16_t)rules[i].v.etherType);
+					break;
 				case ZT_NETWORK_RULE_MATCH_ICMP:
 				case ZT_NETWORK_RULE_MATCH_ICMP:
 					b.append((uint8_t)3);
 					b.append((uint8_t)3);
 					b.append((uint8_t)rules[i].v.icmp.type);
 					b.append((uint8_t)rules[i].v.icmp.type);
@@ -270,7 +270,7 @@ public:
 		while ((ruleCount < maxRuleCount)&&(p < b.size())) {
 		while ((ruleCount < maxRuleCount)&&(p < b.size())) {
 			rules[ruleCount].t = (uint8_t)b[p++];
 			rules[ruleCount].t = (uint8_t)b[p++];
 			const unsigned int fieldLen = (unsigned int)b[p++];
 			const unsigned int fieldLen = (unsigned int)b[p++];
-			switch((ZT_VirtualNetworkRuleType)(rules[ruleCount].t & 0x7f)) {
+			switch((ZT_VirtualNetworkRuleType)(rules[ruleCount].t & 0x3f)) {
 				default:
 				default:
 					break;
 					break;
 				case ZT_NETWORK_RULE_ACTION_TEE:
 				case ZT_NETWORK_RULE_ACTION_TEE:
@@ -293,9 +293,6 @@ public:
 				case ZT_NETWORK_RULE_MATCH_VLAN_DEI:
 				case ZT_NETWORK_RULE_MATCH_VLAN_DEI:
 					rules[ruleCount].v.vlanDei = (uint8_t)b[p];
 					rules[ruleCount].v.vlanDei = (uint8_t)b[p];
 					break;
 					break;
-				case ZT_NETWORK_RULE_MATCH_ETHERTYPE:
-					rules[ruleCount].v.etherType = b.template at<uint16_t>(p);
-					break;
 				case ZT_NETWORK_RULE_MATCH_MAC_SOURCE:
 				case ZT_NETWORK_RULE_MATCH_MAC_SOURCE:
 				case ZT_NETWORK_RULE_MATCH_MAC_DEST:
 				case ZT_NETWORK_RULE_MATCH_MAC_DEST:
 					memcpy(rules[ruleCount].v.mac,b.field(p,6),6);
 					memcpy(rules[ruleCount].v.mac,b.field(p,6),6);
@@ -316,6 +313,9 @@ public:
 				case ZT_NETWORK_RULE_MATCH_IP_PROTOCOL:
 				case ZT_NETWORK_RULE_MATCH_IP_PROTOCOL:
 					rules[ruleCount].v.ipProtocol = (uint8_t)b[p];
 					rules[ruleCount].v.ipProtocol = (uint8_t)b[p];
 					break;
 					break;
+				case ZT_NETWORK_RULE_MATCH_ETHERTYPE:
+					rules[ruleCount].v.etherType = b.template at<uint16_t>(p);
+					break;
 				case ZT_NETWORK_RULE_MATCH_ICMP:
 				case ZT_NETWORK_RULE_MATCH_ICMP:
 					rules[ruleCount].v.icmp.type = (uint8_t)b[p];
 					rules[ruleCount].v.icmp.type = (uint8_t)b[p];
 					rules[ruleCount].v.icmp.code = (uint8_t)b[p+1];
 					rules[ruleCount].v.icmp.code = (uint8_t)b[p+1];

+ 12 - 10
node/Network.cpp

@@ -58,7 +58,6 @@ static const char *_rtn(const ZT_VirtualNetworkRuleType rt)
 		case ZT_NETWORK_RULE_MATCH_VLAN_ID: return "MATCH_VLAN_ID";
 		case ZT_NETWORK_RULE_MATCH_VLAN_ID: return "MATCH_VLAN_ID";
 		case ZT_NETWORK_RULE_MATCH_VLAN_PCP: return "MATCH_VLAN_PCP";
 		case ZT_NETWORK_RULE_MATCH_VLAN_PCP: return "MATCH_VLAN_PCP";
 		case ZT_NETWORK_RULE_MATCH_VLAN_DEI: return "MATCH_VLAN_DEI";
 		case ZT_NETWORK_RULE_MATCH_VLAN_DEI: return "MATCH_VLAN_DEI";
-		case ZT_NETWORK_RULE_MATCH_ETHERTYPE: return "MATCH_ETHERTYPE";
 		case ZT_NETWORK_RULE_MATCH_MAC_SOURCE: return "MATCH_MAC_SOURCE";
 		case ZT_NETWORK_RULE_MATCH_MAC_SOURCE: return "MATCH_MAC_SOURCE";
 		case ZT_NETWORK_RULE_MATCH_MAC_DEST: return "MATCH_MAC_DEST";
 		case ZT_NETWORK_RULE_MATCH_MAC_DEST: return "MATCH_MAC_DEST";
 		case ZT_NETWORK_RULE_MATCH_IPV4_SOURCE: return "MATCH_IPV4_SOURCE";
 		case ZT_NETWORK_RULE_MATCH_IPV4_SOURCE: return "MATCH_IPV4_SOURCE";
@@ -67,6 +66,7 @@ static const char *_rtn(const ZT_VirtualNetworkRuleType rt)
 		case ZT_NETWORK_RULE_MATCH_IPV6_DEST: return "MATCH_IPV6_DEST";
 		case ZT_NETWORK_RULE_MATCH_IPV6_DEST: return "MATCH_IPV6_DEST";
 		case ZT_NETWORK_RULE_MATCH_IP_TOS: return "MATCH_IP_TOS";
 		case ZT_NETWORK_RULE_MATCH_IP_TOS: return "MATCH_IP_TOS";
 		case ZT_NETWORK_RULE_MATCH_IP_PROTOCOL: return "MATCH_IP_PROTOCOL";
 		case ZT_NETWORK_RULE_MATCH_IP_PROTOCOL: return "MATCH_IP_PROTOCOL";
+		case ZT_NETWORK_RULE_MATCH_ETHERTYPE: return "MATCH_ETHERTYPE";
 		case ZT_NETWORK_RULE_MATCH_ICMP: return "MATCH_ICMP";
 		case ZT_NETWORK_RULE_MATCH_ICMP: return "MATCH_ICMP";
 		case ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE: return "MATCH_IP_SOURCE_PORT_RANGE";
 		case ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE: return "MATCH_IP_SOURCE_PORT_RANGE";
 		case ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE: return "MATCH_IP_DEST_PORT_RANGE";
 		case ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE: return "MATCH_IP_DEST_PORT_RANGE";
@@ -182,7 +182,7 @@ static _doZtFilterResult _doZtFilter(
 	uint8_t thisSetMatches = 1;
 	uint8_t thisSetMatches = 1;
 
 
 	for(unsigned int rn=0;rn<ruleCount;++rn) {
 	for(unsigned int rn=0;rn<ruleCount;++rn) {
-		const ZT_VirtualNetworkRuleType rt = (ZT_VirtualNetworkRuleType)(rules[rn].t & 0x7f);
+		const ZT_VirtualNetworkRuleType rt = (ZT_VirtualNetworkRuleType)(rules[rn].t & 0x3f);
 
 
 		// First check if this is an ACTION
 		// First check if this is an ACTION
 		if ((unsigned int)rt <= (unsigned int)ZT_NETWORK_RULE_ACTION__MAX_ID) {
 		if ((unsigned int)rt <= (unsigned int)ZT_NETWORK_RULE_ACTION__MAX_ID) {
@@ -272,8 +272,9 @@ static _doZtFilterResult _doZtFilter(
 			}
 			}
 		}
 		}
 
 
-		// Circuit breaker: skip further MATCH entries up to next ACTION if match state is false
-		if (!thisSetMatches)
+		// Circuit breaker: no need to evaluate an AND if the set's match state
+		// is currently false since anything AND false is false.
+		if ((!thisSetMatches)&&(!(rules[rn].t & 0x40)))
 			continue;
 			continue;
 
 
 		// If this was not an ACTION evaluate next MATCH and update thisSetMatches with (AND [result])
 		// If this was not an ACTION evaluate next MATCH and update thisSetMatches with (AND [result])
@@ -301,10 +302,6 @@ static _doZtFilterResult _doZtFilter(
 				thisRuleMatches = (uint8_t)(rules[rn].v.vlanDei == 0);
 				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);
 				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;
 				break;
-			case ZT_NETWORK_RULE_MATCH_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:
 			case ZT_NETWORK_RULE_MATCH_MAC_SOURCE:
 				thisRuleMatches = (uint8_t)(MAC(rules[rn].v.mac,6) == macSource);
 				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);
 				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);
@@ -380,6 +377,10 @@ static _doZtFilterResult _doZtFilter(
 					FILTER_TRACE("%u %s %c [frame not IP] -> 0",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='));
 					FILTER_TRACE("%u %s %c [frame not IP] -> 0",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='));
 				}
 				}
 				break;
 				break;
+			case ZT_NETWORK_RULE_MATCH_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_ICMP:
 			case ZT_NETWORK_RULE_MATCH_ICMP:
 				if ((etherType == ZT_ETHERTYPE_IPV4)&&(frameLen >= 20)) {
 				if ((etherType == ZT_ETHERTYPE_IPV4)&&(frameLen >= 20)) {
 					if (frameData[9] == 0x01) {
 					if (frameData[9] == 0x01) {
@@ -560,8 +561,9 @@ static _doZtFilterResult _doZtFilter(
 				break;
 				break;
 		}
 		}
 
 
-		// State of equals state AND result of last MATCH (possibly NOTed depending on bit 0x80)
-		thisSetMatches &= (thisRuleMatches ^ ((rules[rn].t >> 7) & 1));
+		if ((rules[rn].t & 0x40))
+			thisSetMatches |= (thisRuleMatches ^ ((rules[rn].t >> 7) & 1));
+		else thisSetMatches &= (thisRuleMatches ^ ((rules[rn].t >> 7) & 1));
 	}
 	}
 
 
 	return DOZTFILTER_NO_MATCH;
 	return DOZTFILTER_NO_MATCH;