mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2024-12-18 20:47:53 +00:00
Match on tag sender equals or tag recipient equals.
This commit is contained in:
parent
31bece7fa0
commit
2b10a982e9
@ -218,6 +218,16 @@ static json _renderRule(ZT_VirtualNetworkRule &rule)
|
||||
r["id"] = rule.v.tag.id;
|
||||
r["value"] = rule.v.tag.value;
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_TAG_SENDER:
|
||||
r["type"] = "MATCH_TAG_SENDER";
|
||||
r["id"] = rule.v.tag.id;
|
||||
r["value"] = rule.v.tag.value;
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_TAG_RECEIVER:
|
||||
r["type"] = "MATCH_TAG_RECEIVER";
|
||||
r["id"] = rule.v.tag.id;
|
||||
r["value"] = rule.v.tag.value;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -245,6 +255,7 @@ static bool _parseRule(json &r,ZT_VirtualNetworkRule &rule)
|
||||
if (OSUtils::jsonBool(r["or"],false))
|
||||
rule.t |= 0x40;
|
||||
|
||||
bool tag = false;
|
||||
if (t == "ACTION_DROP") {
|
||||
rule.t |= ZT_NETWORK_RULE_ACTION_DROP;
|
||||
return true;
|
||||
@ -388,26 +399,27 @@ static bool _parseRule(json &r,ZT_VirtualNetworkRule &rule)
|
||||
return true;
|
||||
} else if (t == "MATCH_TAGS_DIFFERENCE") {
|
||||
rule.t |= ZT_NETWORK_RULE_MATCH_TAGS_DIFFERENCE;
|
||||
rule.v.tag.id = (uint32_t)(OSUtils::jsonInt(r["id"],0ULL) & 0xffffffffULL);
|
||||
rule.v.tag.value = (uint32_t)(OSUtils::jsonInt(r["value"],0ULL) & 0xffffffffULL);
|
||||
return true;
|
||||
tag = true;
|
||||
} else if (t == "MATCH_TAGS_BITWISE_AND") {
|
||||
rule.t |= ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND;
|
||||
rule.v.tag.id = (uint32_t)(OSUtils::jsonInt(r["id"],0ULL) & 0xffffffffULL);
|
||||
rule.v.tag.value = (uint32_t)(OSUtils::jsonInt(r["value"],0ULL) & 0xffffffffULL);
|
||||
return true;
|
||||
tag = true;
|
||||
} else if (t == "MATCH_TAGS_BITWISE_OR") {
|
||||
rule.t |= ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR;
|
||||
rule.v.tag.id = (uint32_t)(OSUtils::jsonInt(r["id"],0ULL) & 0xffffffffULL);
|
||||
rule.v.tag.value = (uint32_t)(OSUtils::jsonInt(r["value"],0ULL) & 0xffffffffULL);
|
||||
return true;
|
||||
tag = true;
|
||||
} else if (t == "MATCH_TAGS_BITWISE_XOR") {
|
||||
rule.t |= ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR;
|
||||
rule.v.tag.id = (uint32_t)(OSUtils::jsonInt(r["id"],0ULL) & 0xffffffffULL);
|
||||
rule.v.tag.value = (uint32_t)(OSUtils::jsonInt(r["value"],0ULL) & 0xffffffffULL);
|
||||
return true;
|
||||
tag = true;
|
||||
} else if (t == "MATCH_TAGS_EQUAL") {
|
||||
rule.t |= ZT_NETWORK_RULE_MATCH_TAGS_EQUAL;
|
||||
tag = true;
|
||||
} else if (t == "MATCH_TAG_SENDER") {
|
||||
rule.t |= ZT_NETWORK_RULE_MATCH_TAG_SENDER;
|
||||
tag = true;
|
||||
} else if (t == "MATCH_TAG_RECEIVER") {
|
||||
rule.t |= ZT_NETWORK_RULE_MATCH_TAG_RECEIVER;
|
||||
tag = true;
|
||||
}
|
||||
if (tag) {
|
||||
rule.v.tag.id = (uint32_t)(OSUtils::jsonInt(r["id"],0ULL) & 0xffffffffULL);
|
||||
rule.v.tag.value = (uint32_t)(OSUtils::jsonInt(r["value"],0ULL) & 0xffffffffULL);
|
||||
return true;
|
||||
|
@ -604,6 +604,8 @@ enum ZT_VirtualNetworkRuleType
|
||||
ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR = 46,
|
||||
ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR = 47,
|
||||
ZT_NETWORK_RULE_MATCH_TAGS_EQUAL = 48,
|
||||
ZT_NETWORK_RULE_MATCH_TAG_SENDER = 49,
|
||||
ZT_NETWORK_RULE_MATCH_TAG_RECEIVER = 50,
|
||||
|
||||
/**
|
||||
* Maximum ID allowed for a MATCH entry in the rules table
|
||||
|
@ -167,9 +167,6 @@ public:
|
||||
// rules to be ignored but still parsed.
|
||||
b.append((uint8_t)rules[i].t);
|
||||
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:
|
||||
default:
|
||||
b.append((uint8_t)0);
|
||||
break;
|
||||
@ -258,6 +255,9 @@ public:
|
||||
case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND:
|
||||
case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR:
|
||||
case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR:
|
||||
case ZT_NETWORK_RULE_MATCH_TAGS_EQUAL:
|
||||
case ZT_NETWORK_RULE_MATCH_TAG_SENDER:
|
||||
case ZT_NETWORK_RULE_MATCH_TAG_RECEIVER:
|
||||
b.append((uint8_t)8);
|
||||
b.append((uint32_t)rules[i].v.tag.id);
|
||||
b.append((uint32_t)rules[i].v.tag.value);
|
||||
@ -345,6 +345,8 @@ public:
|
||||
case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR:
|
||||
case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR:
|
||||
case ZT_NETWORK_RULE_MATCH_TAGS_EQUAL:
|
||||
case ZT_NETWORK_RULE_MATCH_TAG_SENDER:
|
||||
case ZT_NETWORK_RULE_MATCH_TAG_RECEIVER:
|
||||
rules[ruleCount].v.tag.id = b.template at<uint32_t>(p);
|
||||
rules[ruleCount].v.tag.value = b.template at<uint32_t>(p + 4);
|
||||
break;
|
||||
|
@ -515,7 +515,6 @@ static _doZtFilterResult _doZtFilter(
|
||||
src.set((const void *)(frameData + 12),4,0);
|
||||
} else if ((etherType == ZT_ETHERTYPE_IPV6)&&(frameLen >= 40)) {
|
||||
// IPv6 NDP requires special handling, since the src and dest IPs in the packet are empty or link-local.
|
||||
unsigned int pos = 0,proto = 0;
|
||||
if ( (frameLen >= (40 + 8 + 16)) && (frameData[6] == 0x3a) && ((frameData[40] == 0x87)||(frameData[40] == 0x88)) ) {
|
||||
if (frameData[40] == 0x87) {
|
||||
// Neighbor solicitations contain no reliable source address, so we implement a small
|
||||
@ -609,6 +608,11 @@ static _doZtFilterResult _doZtFilter(
|
||||
thisRuleMatches = 0;
|
||||
FILTER_TRACE("%u %s %c remote tag %u not found -> 0 (inbound side is strict)",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),(unsigned int)rules[rn].v.tag.id);
|
||||
} else {
|
||||
// Outbound side is not strict since if we have to match both tags and
|
||||
// we are sending a first packet to a recipient, we probably do not know
|
||||
// about their tags yet. They will filter on inbound and we will filter
|
||||
// once we get their tag. If we are a tee/redirect target we are also
|
||||
// not strict since we likely do not have these tags.
|
||||
thisRuleMatches = 1;
|
||||
FILTER_TRACE("%u %s %c remote tag %u not found -> 1 (outbound side and TEE/REDIRECT targets are not strict)",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),(unsigned int)rules[rn].v.tag.id);
|
||||
}
|
||||
@ -618,6 +622,38 @@ static _doZtFilterResult _doZtFilter(
|
||||
FILTER_TRACE("%u %s %c local tag %u not found -> 0",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),(unsigned int)rules[rn].v.tag.id);
|
||||
}
|
||||
} break;
|
||||
case ZT_NETWORK_RULE_MATCH_TAG_SENDER:
|
||||
case ZT_NETWORK_RULE_MATCH_TAG_RECEIVER: {
|
||||
if (superAccept) {
|
||||
thisRuleMatches = 1;
|
||||
FILTER_TRACE("%u %s %c we are a TEE/REDIRECT target -> 1",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='));
|
||||
} else if ( ((rt == ZT_NETWORK_RULE_MATCH_TAG_SENDER)&&(inbound)) || ((rt == ZT_NETWORK_RULE_MATCH_TAG_RECEIVER)&&(!inbound)) ) {
|
||||
const Tag *const remoteTag = ((membership) ? membership->getTag(nconf,rules[rn].v.tag.id) : (const Tag *)0);
|
||||
if (remoteTag) {
|
||||
thisRuleMatches = (uint8_t)(remoteTag->value() == rules[rn].v.tag.value);
|
||||
FILTER_TRACE("%u %s %c TAG %u %.8x == %.8x -> %u",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),(unsigned int)rules[rn].v.tag.id,remoteTag->value(),(unsigned int)rules[rn].v.tag.value,(unsigned int)thisRuleMatches);
|
||||
} else {
|
||||
if (rt == ZT_NETWORK_RULE_MATCH_TAG_RECEIVER) {
|
||||
// If we are checking the receiver and this is an outbound packet, we
|
||||
// can't be strict since we may not yet know the receiver's tag.
|
||||
thisRuleMatches = 1;
|
||||
FILTER_TRACE("%u %s %c (inbound) remote tag %u not found -> 1 (outbound receiver match is not strict)",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),(unsigned int)rules[rn].v.tag.id);
|
||||
} else {
|
||||
thisRuleMatches = 0;
|
||||
FILTER_TRACE("%u %s %c (inbound) remote tag %u not found -> 0",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),(unsigned int)rules[rn].v.tag.id);
|
||||
}
|
||||
}
|
||||
} else { // sender and outbound or receiver and inbound
|
||||
const Tag *const localTag = std::lower_bound(&(nconf.tags[0]),&(nconf.tags[nconf.tagCount]),rules[rn].v.tag.id,Tag::IdComparePredicate());
|
||||
if ((localTag != &(nconf.tags[nconf.tagCount]))&&(localTag->id() == rules[rn].v.tag.id)) {
|
||||
thisRuleMatches = (uint8_t)(localTag->value() == rules[rn].v.tag.value);
|
||||
FILTER_TRACE("%u %s %c TAG %u %.8x == %.8x -> %u",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),(unsigned int)rules[rn].v.tag.id,remoteTag->value(),(unsigned int)rules[rn].v.tag.value,(unsigned int)thisRuleMatches);
|
||||
} else {
|
||||
thisRuleMatches = 0;
|
||||
FILTER_TRACE("%u %s %c local tag %u not found -> 0",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),(unsigned int)rules[rn].v.tag.id);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
// The result of an unsupported MATCH is configurable at the network
|
||||
// level via a flag.
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "zerotier-rule-compiler",
|
||||
"version": "1.1.17-2",
|
||||
"version": "1.1.17-3",
|
||||
"description": "ZeroTier Rule Script Compiler",
|
||||
"main": "cli.js",
|
||||
"scripts": {
|
||||
|
@ -105,6 +105,8 @@ const RESERVED_WORDS = {
|
||||
'txor': true,
|
||||
'tdiff': true,
|
||||
'teq': true,
|
||||
'tseq': true,
|
||||
'treq': true,
|
||||
|
||||
'type': true,
|
||||
'enum': true,
|
||||
@ -152,7 +154,9 @@ const KEYWORD_TO_API_MAP = {
|
||||
'tor': 'MATCH_TAGS_BITWISE_OR',
|
||||
'txor': 'MATCH_TAGS_BITWISE_XOR',
|
||||
'tdiff': 'MATCH_TAGS_DIFFERENCE',
|
||||
'teq': 'MATCH_TAGS_EQUAL'
|
||||
'teq': 'MATCH_TAGS_EQUAL',
|
||||
'tseq': 'MATCH_TAG_SENDER',
|
||||
'treq': 'MATCH_TAG_RECEIVER'
|
||||
};
|
||||
|
||||
// Number of args for each match
|
||||
@ -179,7 +183,9 @@ const MATCH_ARG_COUNTS = {
|
||||
'tor': 2,
|
||||
'txor': 2,
|
||||
'tdiff': 2,
|
||||
'teq': 2
|
||||
'teq': 2,
|
||||
'tseq': 2,
|
||||
'treq': 2
|
||||
};
|
||||
|
||||
// Regex of all alphanumeric characters in Unicode
|
||||
@ -477,7 +483,9 @@ function _renderMatches(mtree,rules,macros,caps,tags,params)
|
||||
case 'tor':
|
||||
case 'txor':
|
||||
case 'tdiff':
|
||||
case 'teq': {
|
||||
case 'teq':
|
||||
case 'tseq':
|
||||
case 'treq': {
|
||||
let tag = tags[args[0][0]];
|
||||
let tagId = -1;
|
||||
let tagValue = -1;
|
||||
|
Loading…
Reference in New Issue
Block a user