mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-04-25 21:40:10 +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["id"] = rule.v.tag.id;
|
||||||
r["value"] = rule.v.tag.value;
|
r["value"] = rule.v.tag.value;
|
||||||
break;
|
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:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -245,6 +255,7 @@ static bool _parseRule(json &r,ZT_VirtualNetworkRule &rule)
|
|||||||
if (OSUtils::jsonBool(r["or"],false))
|
if (OSUtils::jsonBool(r["or"],false))
|
||||||
rule.t |= 0x40;
|
rule.t |= 0x40;
|
||||||
|
|
||||||
|
bool tag = false;
|
||||||
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;
|
||||||
@ -388,26 +399,27 @@ static bool _parseRule(json &r,ZT_VirtualNetworkRule &rule)
|
|||||||
return true;
|
return true;
|
||||||
} else if (t == "MATCH_TAGS_DIFFERENCE") {
|
} else if (t == "MATCH_TAGS_DIFFERENCE") {
|
||||||
rule.t |= ZT_NETWORK_RULE_MATCH_TAGS_DIFFERENCE;
|
rule.t |= ZT_NETWORK_RULE_MATCH_TAGS_DIFFERENCE;
|
||||||
rule.v.tag.id = (uint32_t)(OSUtils::jsonInt(r["id"],0ULL) & 0xffffffffULL);
|
tag = true;
|
||||||
rule.v.tag.value = (uint32_t)(OSUtils::jsonInt(r["value"],0ULL) & 0xffffffffULL);
|
|
||||||
return true;
|
|
||||||
} else if (t == "MATCH_TAGS_BITWISE_AND") {
|
} else if (t == "MATCH_TAGS_BITWISE_AND") {
|
||||||
rule.t |= ZT_NETWORK_RULE_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);
|
tag = true;
|
||||||
rule.v.tag.value = (uint32_t)(OSUtils::jsonInt(r["value"],0ULL) & 0xffffffffULL);
|
|
||||||
return true;
|
|
||||||
} else if (t == "MATCH_TAGS_BITWISE_OR") {
|
} else if (t == "MATCH_TAGS_BITWISE_OR") {
|
||||||
rule.t |= ZT_NETWORK_RULE_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);
|
tag = true;
|
||||||
rule.v.tag.value = (uint32_t)(OSUtils::jsonInt(r["value"],0ULL) & 0xffffffffULL);
|
|
||||||
return true;
|
|
||||||
} else if (t == "MATCH_TAGS_BITWISE_XOR") {
|
} else if (t == "MATCH_TAGS_BITWISE_XOR") {
|
||||||
rule.t |= ZT_NETWORK_RULE_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);
|
tag = true;
|
||||||
rule.v.tag.value = (uint32_t)(OSUtils::jsonInt(r["value"],0ULL) & 0xffffffffULL);
|
|
||||||
return true;
|
|
||||||
} else if (t == "MATCH_TAGS_EQUAL") {
|
} else if (t == "MATCH_TAGS_EQUAL") {
|
||||||
rule.t |= ZT_NETWORK_RULE_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.id = (uint32_t)(OSUtils::jsonInt(r["id"],0ULL) & 0xffffffffULL);
|
||||||
rule.v.tag.value = (uint32_t)(OSUtils::jsonInt(r["value"],0ULL) & 0xffffffffULL);
|
rule.v.tag.value = (uint32_t)(OSUtils::jsonInt(r["value"],0ULL) & 0xffffffffULL);
|
||||||
return true;
|
return true;
|
||||||
|
@ -604,6 +604,8 @@ enum ZT_VirtualNetworkRuleType
|
|||||||
ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR = 46,
|
ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR = 46,
|
||||||
ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR = 47,
|
ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR = 47,
|
||||||
ZT_NETWORK_RULE_MATCH_TAGS_EQUAL = 48,
|
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
|
* Maximum ID allowed for a MATCH entry in the rules table
|
||||||
|
@ -167,9 +167,6 @@ public:
|
|||||||
// 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 & 0x3f)) {
|
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:
|
default:
|
||||||
b.append((uint8_t)0);
|
b.append((uint8_t)0);
|
||||||
break;
|
break;
|
||||||
@ -258,6 +255,9 @@ public:
|
|||||||
case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND:
|
case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND:
|
||||||
case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR:
|
case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR:
|
||||||
case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR:
|
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((uint8_t)8);
|
||||||
b.append((uint32_t)rules[i].v.tag.id);
|
b.append((uint32_t)rules[i].v.tag.id);
|
||||||
b.append((uint32_t)rules[i].v.tag.value);
|
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_OR:
|
||||||
case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR:
|
case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR:
|
||||||
case ZT_NETWORK_RULE_MATCH_TAGS_EQUAL:
|
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.id = b.template at<uint32_t>(p);
|
||||||
rules[ruleCount].v.tag.value = b.template at<uint32_t>(p + 4);
|
rules[ruleCount].v.tag.value = b.template at<uint32_t>(p + 4);
|
||||||
break;
|
break;
|
||||||
|
@ -515,7 +515,6 @@ static _doZtFilterResult _doZtFilter(
|
|||||||
src.set((const void *)(frameData + 12),4,0);
|
src.set((const void *)(frameData + 12),4,0);
|
||||||
} else if ((etherType == ZT_ETHERTYPE_IPV6)&&(frameLen >= 40)) {
|
} 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.
|
// 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 ( (frameLen >= (40 + 8 + 16)) && (frameData[6] == 0x3a) && ((frameData[40] == 0x87)||(frameData[40] == 0x88)) ) {
|
||||||
if (frameData[40] == 0x87) {
|
if (frameData[40] == 0x87) {
|
||||||
// Neighbor solicitations contain no reliable source address, so we implement a small
|
// Neighbor solicitations contain no reliable source address, so we implement a small
|
||||||
@ -609,6 +608,11 @@ static _doZtFilterResult _doZtFilter(
|
|||||||
thisRuleMatches = 0;
|
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);
|
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 {
|
} 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;
|
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);
|
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);
|
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;
|
} 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
|
// The result of an unsupported MATCH is configurable at the network
|
||||||
// level via a flag.
|
// level via a flag.
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "zerotier-rule-compiler",
|
"name": "zerotier-rule-compiler",
|
||||||
"version": "1.1.17-2",
|
"version": "1.1.17-3",
|
||||||
"description": "ZeroTier Rule Script Compiler",
|
"description": "ZeroTier Rule Script Compiler",
|
||||||
"main": "cli.js",
|
"main": "cli.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -105,6 +105,8 @@ const RESERVED_WORDS = {
|
|||||||
'txor': true,
|
'txor': true,
|
||||||
'tdiff': true,
|
'tdiff': true,
|
||||||
'teq': true,
|
'teq': true,
|
||||||
|
'tseq': true,
|
||||||
|
'treq': true,
|
||||||
|
|
||||||
'type': true,
|
'type': true,
|
||||||
'enum': true,
|
'enum': true,
|
||||||
@ -152,7 +154,9 @@ const KEYWORD_TO_API_MAP = {
|
|||||||
'tor': 'MATCH_TAGS_BITWISE_OR',
|
'tor': 'MATCH_TAGS_BITWISE_OR',
|
||||||
'txor': 'MATCH_TAGS_BITWISE_XOR',
|
'txor': 'MATCH_TAGS_BITWISE_XOR',
|
||||||
'tdiff': 'MATCH_TAGS_DIFFERENCE',
|
'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
|
// Number of args for each match
|
||||||
@ -179,7 +183,9 @@ const MATCH_ARG_COUNTS = {
|
|||||||
'tor': 2,
|
'tor': 2,
|
||||||
'txor': 2,
|
'txor': 2,
|
||||||
'tdiff': 2,
|
'tdiff': 2,
|
||||||
'teq': 2
|
'teq': 2,
|
||||||
|
'tseq': 2,
|
||||||
|
'treq': 2
|
||||||
};
|
};
|
||||||
|
|
||||||
// Regex of all alphanumeric characters in Unicode
|
// Regex of all alphanumeric characters in Unicode
|
||||||
@ -477,7 +483,9 @@ function _renderMatches(mtree,rules,macros,caps,tags,params)
|
|||||||
case 'tor':
|
case 'tor':
|
||||||
case 'txor':
|
case 'txor':
|
||||||
case 'tdiff':
|
case 'tdiff':
|
||||||
case 'teq': {
|
case 'teq':
|
||||||
|
case 'tseq':
|
||||||
|
case 'treq': {
|
||||||
let tag = tags[args[0][0]];
|
let tag = tags[args[0][0]];
|
||||||
let tagId = -1;
|
let tagId = -1;
|
||||||
let tagValue = -1;
|
let tagValue = -1;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user