diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp index aa95ac647..7559cf830 100644 --- a/controller/EmbeddedNetworkController.cpp +++ b/controller/EmbeddedNetworkController.cpp @@ -127,7 +127,9 @@ static json _renderRule(ZT_VirtualNetworkRule &rule) { char tmp[128]; 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: r["type"] = "ACTION_DROP"; break; @@ -154,146 +156,136 @@ static json _renderRule(ZT_VirtualNetworkRule &rule) case ZT_NETWORK_RULE_ACTION_DEBUG_LOG: r["type"] = "ACTION_DEBUG_LOG"; 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(); - 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"; - r["not"] = ((rule.t & 0x80) != 0); - r["id"] = rule.v.tag.id; - r["value"] = rule.v.tag.value; + default: break; } + + 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["or"] = ((rule.t & 0x40) != 0); + } + } + return r; } @@ -301,11 +293,16 @@ static bool _parseRule(json &r,ZT_VirtualNetworkRule &rule) { if (!r.is_object()) return false; + const std::string t(_jS(r["type"],"")); memset(&rule,0,sizeof(ZT_VirtualNetworkRule)); + if (_jB(r["not"],false)) rule.t = 0x80; else rule.t = 0x00; + if (_jB(r["or"],false)) + rule.t |= 0x40; + if (t == "ACTION_DROP") { rule.t |= ZT_NETWORK_RULE_ACTION_DROP; return true; @@ -352,10 +349,6 @@ static bool _parseRule(json &r,ZT_VirtualNetworkRule &rule) rule.t |= ZT_NETWORK_RULE_MATCH_VLAN_DEI; rule.v.vlanDei = (uint8_t)(_jI(r["vlanDei"],0ULL) & 0xffULL); 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") { rule.t |= ZT_NETWORK_RULE_MATCH_MAC_SOURCE; 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.v.ipProtocol = (uint8_t)(_jI(r["ipProtocol"],0ULL) & 0xffULL); 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") { rule.t |= ZT_NETWORK_RULE_MATCH_ICMP; 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); return true; } + return false; } diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index 8d7b0cd40..17112e905 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -491,15 +491,15 @@ enum ZT_VirtualNetworkType /** * 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. * An ACTION with no MATCHes is always taken. */ enum ZT_VirtualNetworkRuleType { - // 0 to 31 reserved for actions + // 0 to 15 reserved for actions /** * Drop frame @@ -534,139 +534,40 @@ enum ZT_VirtualNetworkRuleType /** * Maximum ID for an ACTION, anything higher is a MATCH */ - ZT_NETWORK_RULE_ACTION__MAX_ID = 31, + ZT_NETWORK_RULE_ACTION__MAX_ID = 15, - // 32 to 127 reserved for match criteria + // 16 to 63 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_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, - - /** - * 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 */ - ZT_NETWORK_RULE_MATCH__MAX_ID = 127 + ZT_NETWORK_RULE_MATCH__MAX_ID = 63 }; /** diff --git a/node/Capability.hpp b/node/Capability.hpp index 99980ce72..2c829ee5d 100644 --- a/node/Capability.hpp +++ b/node/Capability.hpp @@ -166,7 +166,7 @@ public: // 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)) { + switch((ZT_VirtualNetworkRuleType)(rules[i].t & 0x3f)) { //case ZT_NETWORK_RULE_ACTION_DROP: //case ZT_NETWORK_RULE_ACTION_ACCEPT: //case ZT_NETWORK_RULE_ACTION_DEBUG_LOG: @@ -198,10 +198,6 @@ public: b.append((uint8_t)1); 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); - break; case ZT_NETWORK_RULE_MATCH_MAC_SOURCE: case ZT_NETWORK_RULE_MATCH_MAC_DEST: b.append((uint8_t)6); @@ -227,6 +223,10 @@ public: b.append((uint8_t)1); b.append((uint8_t)rules[i].v.ipProtocol); 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: b.append((uint8_t)3); b.append((uint8_t)rules[i].v.icmp.type); @@ -270,7 +270,7 @@ public: while ((ruleCount < maxRuleCount)&&(p < b.size())) { rules[ruleCount].t = (uint8_t)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: break; case ZT_NETWORK_RULE_ACTION_TEE: @@ -293,9 +293,6 @@ public: case ZT_NETWORK_RULE_MATCH_VLAN_DEI: rules[ruleCount].v.vlanDei = (uint8_t)b[p]; break; - case ZT_NETWORK_RULE_MATCH_ETHERTYPE: - rules[ruleCount].v.etherType = b.template at(p); - break; case ZT_NETWORK_RULE_MATCH_MAC_SOURCE: case ZT_NETWORK_RULE_MATCH_MAC_DEST: memcpy(rules[ruleCount].v.mac,b.field(p,6),6); @@ -316,6 +313,9 @@ public: case ZT_NETWORK_RULE_MATCH_IP_PROTOCOL: rules[ruleCount].v.ipProtocol = (uint8_t)b[p]; break; + case ZT_NETWORK_RULE_MATCH_ETHERTYPE: + rules[ruleCount].v.etherType = b.template at(p); + break; case ZT_NETWORK_RULE_MATCH_ICMP: rules[ruleCount].v.icmp.type = (uint8_t)b[p]; rules[ruleCount].v.icmp.code = (uint8_t)b[p+1]; diff --git a/node/Network.cpp b/node/Network.cpp index 00c201ba0..177f1a6da 100644 --- a/node/Network.cpp +++ b/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_PCP: return "MATCH_VLAN_PCP"; 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_DEST: return "MATCH_MAC_DEST"; 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_IP_TOS: return "MATCH_IP_TOS"; 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_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"; @@ -182,7 +182,7 @@ static _doZtFilterResult _doZtFilter( uint8_t thisSetMatches = 1; for(unsigned int rn=0;rn %u",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),(unsigned int)rules[rn].v.vlanDei,0,(unsigned int)thisRuleMatches); 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: 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); @@ -380,6 +377,10 @@ static _doZtFilterResult _doZtFilter( FILTER_TRACE("%u %s %c [frame not IP] -> 0",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '=')); } 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: if ((etherType == ZT_ETHERTYPE_IPV4)&&(frameLen >= 20)) { if (frameData[9] == 0x01) { @@ -560,8 +561,9 @@ static _doZtFilterResult _doZtFilter( 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;