Add overlooked MATCH_ICMP to rule set.

This commit is contained in:
Adam Ierymenko 2016-08-31 14:01:15 -07:00
parent 2ff2a8fd9a
commit 8e3004591b
4 changed files with 105 additions and 8 deletions

View File

@ -221,6 +221,14 @@ static json _renderRule(ZT_VirtualNetworkRule &rule)
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);
@ -375,6 +383,18 @@ 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_ICMP") {
rule.t |= ZT_NETWORK_RULE_MATCH_ICMP;
rule.v.icmp.type = (uint8_t)(_jI(r["type"],0ULL) & 0xffULL);
json &code = r["code"];
if (code.is_null()) {
rule.v.icmp.code = 0;
rule.v.icmp.flags = 0x00;
} else {
rule.v.icmp.code = (uint8_t)(_jI(code,0ULL) & 0xffULL);
rule.v.icmp.flags = 0x01;
}
return true;
} else if (t == "MATCH_IP_SOURCE_PORT_RANGE") {
rule.t |= ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE;
rule.v.port[0] = (uint16_t)(_jI(r["start"],0ULL) & 0xffffULL);

View File

@ -597,45 +597,50 @@ enum ZT_VirtualNetworkRuleType
*/
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 = 46,
ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE = 47,
/**
* IP destination port range (start-end, inclusive)
*/
ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE = 47,
ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE = 48,
/**
* Packet characteristics (set of flags)
*/
ZT_NETWORK_RULE_MATCH_CHARACTERISTICS = 48,
ZT_NETWORK_RULE_MATCH_CHARACTERISTICS = 49,
/**
* Frame size range (start-end, inclusive)
*/
ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE = 49,
ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE = 50,
/**
* Match if local and remote tags differ by no more than value, use 0 to check for equality
*/
ZT_NETWORK_RULE_MATCH_TAGS_SAMENESS = 50,
ZT_NETWORK_RULE_MATCH_TAGS_SAMENESS = 51,
/**
* Match if local and remote tags ANDed together equal value.
*/
ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND = 51,
ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND = 52,
/**
* Match if local and remote tags ANDed together equal value.
*/
ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR = 52,
ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR = 53,
/**
* Match if local and remote tags XORed together equal value.
*/
ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR = 53
ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR = 54
};
/**
@ -739,6 +744,15 @@ typedef struct
*/
uint16_t frameSize[2];
/**
* ICMP type and code
*/
struct {
uint8_t type; // ICMP type, always matched
uint8_t code; // ICMP code if matched
uint8_t flags; // flag 0x01 means also match code, otherwise only match type
} icmp;
/**
* For tag-related rules
*/

View File

@ -233,6 +233,12 @@ public:
b.append((uint8_t)1);
b.append((uint8_t)rules[i].v.ipProtocol);
break;
case ZT_NETWORK_RULE_MATCH_ICMP:
b.append((uint8_t)3);
b.append((uint8_t)rules[i].v.icmp.type);
b.append((uint8_t)rules[i].v.icmp.code);
b.append((uint8_t)rules[i].v.icmp.flags);
break;
case ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE:
case ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE:
b.append((uint8_t)4);
@ -312,6 +318,11 @@ public:
case ZT_NETWORK_RULE_MATCH_IP_PROTOCOL:
rules[ruleCount].v.ipProtocol = (uint8_t)b[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];
rules[ruleCount].v.icmp.flags = (uint8_t)b[p+2];
break;
case ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE:
case ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE:
rules[ruleCount].v.port[0] = b.template at<uint16_t>(p);

View File

@ -64,6 +64,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_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";
case ZT_NETWORK_RULE_MATCH_CHARACTERISTICS: return "MATCH_CHARACTERISTICS";
@ -362,6 +363,57 @@ static int _doZtFilter(
FILTER_TRACE("%u %s %c [frame not IP] -> 0",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='));
}
break;
case ZT_NETWORK_RULE_MATCH_ICMP:
if ((etherType == ZT_ETHERTYPE_IPV4)&&(frameLen >= 20)) {
if (frameData[9] == 0x01) {
const unsigned int ihl = (frameData[0] & 0xf) * 32;
if (frameLen >= (ihl + 2)) {
if (rules[rn].v.icmp.type == frameData[ihl]) {
if ((rules[rn].v.icmp.flags & 0x01) != 0) {
thisRuleMatches = (uint8_t)(frameData[ihl+1] == rules[rn].v.icmp.code);
} else {
thisRuleMatches = 1;
}
} else {
thisRuleMatches = 0;
}
FILTER_TRACE("%u %s %c (IPv4) icmp-type:%d==%d icmp-code:%d==%d -> %u",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),(int)frameData[ihl],(int)rules[rn].v.icmp.type,(int)frameData[ihl+1],(((rules[rn].v.icmp.flags & 0x01) != 0) ? (int)rules[rn].v.icmp.code : -1),(unsigned int)thisRuleMatches);
} else {
thisRuleMatches = 0;
FILTER_TRACE("%u %s %c [IPv4 frame invalid] -> 0",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='));
}
} else {
thisRuleMatches = 0;
FILTER_TRACE("%u %s %c [frame not ICMP] -> 0",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='));
}
} else if (etherType == ZT_ETHERTYPE_IPV6) {
unsigned int pos = 0,proto = 0;
if (_ipv6GetPayload(frameData,frameLen,pos,proto)) {
if ((proto == 0x3a)&&(frameLen >= (pos+2))) {
if (rules[rn].v.icmp.type == frameData[pos]) {
if ((rules[rn].v.icmp.flags & 0x01) != 0) {
thisRuleMatches = (uint8_t)(frameData[pos+1] == rules[rn].v.icmp.code);
} else {
thisRuleMatches = 1;
}
} else {
thisRuleMatches = 0;
}
FILTER_TRACE("%u %s %c (IPv4) icmp-type:%d==%d icmp-code:%d==%d -> %u",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),(int)frameData[pos],(int)rules[rn].v.icmp.type,(int)frameData[pos+1],(((rules[rn].v.icmp.flags & 0x01) != 0) ? (int)rules[rn].v.icmp.code : -1),(unsigned int)thisRuleMatches);
} else {
thisRuleMatches = 0;
FILTER_TRACE("%u %s %c [frame not ICMPv6] -> 0",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='));
}
} else {
thisRuleMatches = 0;
FILTER_TRACE("%u %s %c [invalid IPv6] -> 0",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='));
}
} else {
thisRuleMatches = 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_IP_SOURCE_PORT_RANGE:
case ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE:
if ((etherType == ZT_ETHERTYPE_IPV4)&&(frameLen >= 20)) {