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

This commit is contained in:
Adam Ierymenko 2016-10-11 12:00:16 -07:00
parent e59ed3e68f
commit e53f63ca87
4 changed files with 192 additions and 291 deletions

View File

@ -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: default:
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;
break; 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; 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;
} }

View File

@ -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 * These must be from 0 to 63 since the most significant two bits of each
* is reserved as a NOT flag. * 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, ZT_NETWORK_RULE_ACTION__MAX_ID = 15,
// 32 to 127 reserved for match criteria // 16 to 63 reserved for match criteria
/** ZT_NETWORK_RULE_MATCH_SOURCE_ZEROTIER_ADDRESS = 24,
* Source ZeroTier address -- analogous to an Ethernet port ID on a switch ZT_NETWORK_RULE_MATCH_DEST_ZEROTIER_ADDRESS = 25,
*/ ZT_NETWORK_RULE_MATCH_VLAN_ID = 26,
ZT_NETWORK_RULE_MATCH_SOURCE_ZEROTIER_ADDRESS = 32, ZT_NETWORK_RULE_MATCH_VLAN_PCP = 27,
ZT_NETWORK_RULE_MATCH_VLAN_DEI = 28,
/** ZT_NETWORK_RULE_MATCH_MAC_SOURCE = 29,
* Destination ZeroTier address -- analogous to an Ethernet port ID on a switch ZT_NETWORK_RULE_MATCH_MAC_DEST = 30,
*/ ZT_NETWORK_RULE_MATCH_IPV4_SOURCE = 31,
ZT_NETWORK_RULE_MATCH_DEST_ZEROTIER_ADDRESS = 33, ZT_NETWORK_RULE_MATCH_IPV4_DEST = 32,
ZT_NETWORK_RULE_MATCH_IPV6_SOURCE = 33,
/** ZT_NETWORK_RULE_MATCH_IPV6_DEST = 34,
* Ethernet VLAN ID ZT_NETWORK_RULE_MATCH_IP_TOS = 35,
*/ ZT_NETWORK_RULE_MATCH_IP_PROTOCOL = 36,
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_ETHERTYPE = 37, ZT_NETWORK_RULE_MATCH_ETHERTYPE = 37,
ZT_NETWORK_RULE_MATCH_ICMP = 38,
/** ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE = 39,
* Source Ethernet MAC address ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE = 40,
*/ ZT_NETWORK_RULE_MATCH_CHARACTERISTICS = 41,
ZT_NETWORK_RULE_MATCH_MAC_SOURCE = 38, ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE = 42,
ZT_NETWORK_RULE_MATCH_RANDOM = 43,
/** ZT_NETWORK_RULE_MATCH_TAGS_DIFFERENCE = 44,
* Destination Ethernet MAC address ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND = 45,
*/ ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR = 46,
ZT_NETWORK_RULE_MATCH_MAC_DEST = 39, ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR = 47,
ZT_NETWORK_RULE_MATCH_TAGS_EQUAL = 48,
/**
* 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,
/** /**
* 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
}; };
/** /**

View File

@ -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];

View File

@ -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 // Circuit breaker: no need to evaluate an AND if the set's match state
if (!thisSetMatches) // 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) if ((rules[rn].t & 0x40))
thisSetMatches &= (thisRuleMatches ^ ((rules[rn].t >> 7) & 1)); thisSetMatches |= (thisRuleMatches ^ ((rules[rn].t >> 7) & 1));
else thisSetMatches &= (thisRuleMatches ^ ((rules[rn].t >> 7) & 1));
} }
return DOZTFILTER_NO_MATCH; return DOZTFILTER_NO_MATCH;