summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Ierymenko <adam.ierymenko@gmail.com>2017-02-28 09:22:10 -0800
committerAdam Ierymenko <adam.ierymenko@gmail.com>2017-02-28 09:22:10 -0800
commit2b10a982e9c9aad4a6ed9b10f5d7bda93a55ffcf (patch)
tree95645d1d1868f40986c648fe6d3c910b03622d65
parent31bece7fa076cf1c5f21743a9a936ade54c0fe1a (diff)
downloadinfinitytier-2b10a982e9c9aad4a6ed9b10f5d7bda93a55ffcf.tar.gz
infinitytier-2b10a982e9c9aad4a6ed9b10f5d7bda93a55ffcf.zip
Match on tag sender equals or tag recipient equals.
-rw-r--r--controller/EmbeddedNetworkController.cpp36
-rw-r--r--include/ZeroTierOne.h2
-rw-r--r--node/Capability.hpp8
-rw-r--r--node/Network.cpp38
-rw-r--r--rule-compiler/package.json2
-rw-r--r--rule-compiler/rule-compiler.js14
6 files changed, 80 insertions, 20 deletions
diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp
index 78a9b7c7..0e57fc14 100644
--- a/controller/EmbeddedNetworkController.cpp
+++ b/controller/EmbeddedNetworkController.cpp
@@ -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;
diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h
index 8a13c117..2c141f47 100644
--- a/include/ZeroTierOne.h
+++ b/include/ZeroTierOne.h
@@ -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
diff --git a/node/Capability.hpp b/node/Capability.hpp
index d884625e..1ad6ea42 100644
--- a/node/Capability.hpp
+++ b/node/Capability.hpp
@@ -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;
diff --git a/node/Network.cpp b/node/Network.cpp
index aad6e716..dc976f03 100644
--- a/node/Network.cpp
+++ b/node/Network.cpp
@@ -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.
diff --git a/rule-compiler/package.json b/rule-compiler/package.json
index f0e747a2..451295a4 100644
--- a/rule-compiler/package.json
+++ b/rule-compiler/package.json
@@ -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": {
diff --git a/rule-compiler/rule-compiler.js b/rule-compiler/rule-compiler.js
index 7445d39f..feb30f90 100644
--- a/rule-compiler/rule-compiler.js
+++ b/rule-compiler/rule-compiler.js
@@ -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;