Merge branch 'dev' into tl-add-homedir

This commit is contained in:
Grant Limberg 2024-03-01 12:37:47 -05:00 committed by GitHub
commit 7fb3711ed6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -107,11 +107,22 @@ static _doZtFilterResult _doZtFilter(
// The default match state for each set of entries starts as 'true' since an // The default match state for each set of entries starts as 'true' since an
// ACTION with no MATCH entries preceding it is always taken. // ACTION with no MATCH entries preceding it is always taken.
uint8_t thisSetMatches = 1; uint8_t thisSetMatches = 1;
uint8_t skipDrop = 0;
rrl.clear(); rrl.clear();
// uncomment for easier debugging fprintf
// if (!ztDest) { return DOZTFILTER_ACCEPT; }
#ifdef ZT_TRACE
char buf[40], buf2[40];
fprintf(stderr, "\nsrc %s dest %s inbound: %d ethertype %u", ztSource.toString(buf), ztDest.toString(buf2), inbound, etherType);
#endif
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 & 0x3f); const ZT_VirtualNetworkRuleType rt = (ZT_VirtualNetworkRuleType)(rules[rn].t & 0x3f);
#ifdef ZT_TRACE
fprintf(stderr, "\n%02u %02d", rn, rt);
#endif
// 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) {
@ -121,11 +132,25 @@ static _doZtFilterResult _doZtFilter(
qosBucket = (rules[rn].v.qosBucket <= 8) ? rules[rn].v.qosBucket : 4; // 4 = default bucket (no priority) qosBucket = (rules[rn].v.qosBucket <= 8) ? rules[rn].v.qosBucket : 4; // 4 = default bucket (no priority)
return DOZTFILTER_ACCEPT; return DOZTFILTER_ACCEPT;
case ZT_NETWORK_RULE_ACTION_DROP: case ZT_NETWORK_RULE_ACTION_DROP: {
if (!!skipDrop) {
#ifdef ZT_TRACE
fprintf(stderr, "\tskip Drop");
#endif
skipDrop = 0; continue;
}
#ifdef ZT_TRACE
fprintf(stderr, "\tDrop\n");
#endif
return DOZTFILTER_DROP; return DOZTFILTER_DROP;
}
case ZT_NETWORK_RULE_ACTION_ACCEPT: case ZT_NETWORK_RULE_ACTION_ACCEPT: {
#ifdef ZT_TRACE
fprintf(stderr, "\tAccept\n");
#endif
return (superAccept ? DOZTFILTER_SUPER_ACCEPT : DOZTFILTER_ACCEPT); // match, accept packet return (superAccept ? DOZTFILTER_SUPER_ACCEPT : DOZTFILTER_ACCEPT); // match, accept packet
}
// These are initially handled together since preliminary logic is common // These are initially handled together since preliminary logic is common
case ZT_NETWORK_RULE_ACTION_TEE: case ZT_NETWORK_RULE_ACTION_TEE:
@ -192,6 +217,9 @@ static _doZtFilterResult _doZtFilter(
// 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])
uint8_t thisRuleMatches = 0; uint8_t thisRuleMatches = 0;
uint64_t ownershipVerificationMask = 1; // this magic value means it hasn't been computed yet -- this is done lazily the first time it's needed uint64_t ownershipVerificationMask = 1; // this magic value means it hasn't been computed yet -- this is done lazily the first time it's needed
uint8_t hardYes = (rules[rn].t >> 7) ^ 1; // XOR with the NOT bit of the rule
uint8_t hardNo = (rules[rn].t >> 7) ^ 0;
switch(rt) { switch(rt) {
case ZT_NETWORK_RULE_MATCH_SOURCE_ZEROTIER_ADDRESS: case ZT_NETWORK_RULE_MATCH_SOURCE_ZEROTIER_ADDRESS:
thisRuleMatches = (uint8_t)(rules[rn].v.zt == ztSource.toInt()); thisRuleMatches = (uint8_t)(rules[rn].v.zt == ztSource.toInt());
@ -220,28 +248,28 @@ static _doZtFilterResult _doZtFilter(
if ((etherType == ZT_ETHERTYPE_IPV4)&&(frameLen >= 20)) { if ((etherType == ZT_ETHERTYPE_IPV4)&&(frameLen >= 20)) {
thisRuleMatches = (uint8_t)(InetAddress((const void *)&(rules[rn].v.ipv4.ip),4,rules[rn].v.ipv4.mask).containsAddress(InetAddress((const void *)(frameData + 12),4,0))); thisRuleMatches = (uint8_t)(InetAddress((const void *)&(rules[rn].v.ipv4.ip),4,rules[rn].v.ipv4.mask).containsAddress(InetAddress((const void *)(frameData + 12),4,0)));
} else { } else {
thisRuleMatches = 0; thisRuleMatches = hardNo;
} }
break; break;
case ZT_NETWORK_RULE_MATCH_IPV4_DEST: case ZT_NETWORK_RULE_MATCH_IPV4_DEST:
if ((etherType == ZT_ETHERTYPE_IPV4)&&(frameLen >= 20)) { if ((etherType == ZT_ETHERTYPE_IPV4)&&(frameLen >= 20)) {
thisRuleMatches = (uint8_t)(InetAddress((const void *)&(rules[rn].v.ipv4.ip),4,rules[rn].v.ipv4.mask).containsAddress(InetAddress((const void *)(frameData + 16),4,0))); thisRuleMatches = (uint8_t)(InetAddress((const void *)&(rules[rn].v.ipv4.ip),4,rules[rn].v.ipv4.mask).containsAddress(InetAddress((const void *)(frameData + 16),4,0)));
} else { } else {
thisRuleMatches = 0; thisRuleMatches = hardNo;
} }
break; break;
case ZT_NETWORK_RULE_MATCH_IPV6_SOURCE: case ZT_NETWORK_RULE_MATCH_IPV6_SOURCE:
if ((etherType == ZT_ETHERTYPE_IPV6)&&(frameLen >= 40)) { if ((etherType == ZT_ETHERTYPE_IPV6)&&(frameLen >= 40)) {
thisRuleMatches = (uint8_t)(InetAddress((const void *)rules[rn].v.ipv6.ip,16,rules[rn].v.ipv6.mask).containsAddress(InetAddress((const void *)(frameData + 8),16,0))); thisRuleMatches = (uint8_t)(InetAddress((const void *)rules[rn].v.ipv6.ip,16,rules[rn].v.ipv6.mask).containsAddress(InetAddress((const void *)(frameData + 8),16,0)));
} else { } else {
thisRuleMatches = 0; thisRuleMatches = hardNo;
} }
break; break;
case ZT_NETWORK_RULE_MATCH_IPV6_DEST: case ZT_NETWORK_RULE_MATCH_IPV6_DEST:
if ((etherType == ZT_ETHERTYPE_IPV6)&&(frameLen >= 40)) { if ((etherType == ZT_ETHERTYPE_IPV6)&&(frameLen >= 40)) {
thisRuleMatches = (uint8_t)(InetAddress((const void *)rules[rn].v.ipv6.ip,16,rules[rn].v.ipv6.mask).containsAddress(InetAddress((const void *)(frameData + 24),16,0))); thisRuleMatches = (uint8_t)(InetAddress((const void *)rules[rn].v.ipv6.ip,16,rules[rn].v.ipv6.mask).containsAddress(InetAddress((const void *)(frameData + 24),16,0)));
} else { } else {
thisRuleMatches = 0; thisRuleMatches = hardNo;
} }
break; break;
case ZT_NETWORK_RULE_MATCH_IP_TOS: case ZT_NETWORK_RULE_MATCH_IP_TOS:
@ -252,7 +280,7 @@ static _doZtFilterResult _doZtFilter(
const uint8_t tosMasked = (((frameData[0] << 4) & 0xf0) | ((frameData[1] >> 4) & 0x0f)) & rules[rn].v.ipTos.mask; const uint8_t tosMasked = (((frameData[0] << 4) & 0xf0) | ((frameData[1] >> 4) & 0x0f)) & rules[rn].v.ipTos.mask;
thisRuleMatches = (uint8_t)((tosMasked >= rules[rn].v.ipTos.value[0])&&(tosMasked <= rules[rn].v.ipTos.value[1])); thisRuleMatches = (uint8_t)((tosMasked >= rules[rn].v.ipTos.value[0])&&(tosMasked <= rules[rn].v.ipTos.value[1]));
} else { } else {
thisRuleMatches = 0; thisRuleMatches = hardNo;
} }
break; break;
case ZT_NETWORK_RULE_MATCH_IP_PROTOCOL: case ZT_NETWORK_RULE_MATCH_IP_PROTOCOL:
@ -263,10 +291,10 @@ static _doZtFilterResult _doZtFilter(
if (_ipv6GetPayload(frameData,frameLen,pos,proto)) { if (_ipv6GetPayload(frameData,frameLen,pos,proto)) {
thisRuleMatches = (uint8_t)(rules[rn].v.ipProtocol == (uint8_t)proto); thisRuleMatches = (uint8_t)(rules[rn].v.ipProtocol == (uint8_t)proto);
} else { } else {
thisRuleMatches = 0; thisRuleMatches = hardNo;
} }
} else { } else {
thisRuleMatches = 0; thisRuleMatches = hardNo;
} }
break; break;
case ZT_NETWORK_RULE_MATCH_ETHERTYPE: case ZT_NETWORK_RULE_MATCH_ETHERTYPE:
@ -281,16 +309,16 @@ static _doZtFilterResult _doZtFilter(
if ((rules[rn].v.icmp.flags & 0x01) != 0) { if ((rules[rn].v.icmp.flags & 0x01) != 0) {
thisRuleMatches = (uint8_t)(frameData[ihl+1] == rules[rn].v.icmp.code); thisRuleMatches = (uint8_t)(frameData[ihl+1] == rules[rn].v.icmp.code);
} else { } else {
thisRuleMatches = 1; thisRuleMatches = hardYes;
} }
} else { } else {
thisRuleMatches = 0; thisRuleMatches = hardNo;
} }
} else { } else {
thisRuleMatches = 0; thisRuleMatches = hardNo;
} }
} else { } else {
thisRuleMatches = 0; thisRuleMatches = hardNo;
} }
} else if (etherType == ZT_ETHERTYPE_IPV6) { } else if (etherType == ZT_ETHERTYPE_IPV6) {
unsigned int pos = 0,proto = 0; unsigned int pos = 0,proto = 0;
@ -300,19 +328,19 @@ static _doZtFilterResult _doZtFilter(
if ((rules[rn].v.icmp.flags & 0x01) != 0) { if ((rules[rn].v.icmp.flags & 0x01) != 0) {
thisRuleMatches = (uint8_t)(frameData[pos+1] == rules[rn].v.icmp.code); thisRuleMatches = (uint8_t)(frameData[pos+1] == rules[rn].v.icmp.code);
} else { } else {
thisRuleMatches = 1; thisRuleMatches = hardYes;
} }
} else { } else {
thisRuleMatches = 0; thisRuleMatches = hardNo;
} }
} else { } else {
thisRuleMatches = 0; thisRuleMatches = hardNo;
} }
} else { } else {
thisRuleMatches = 0; thisRuleMatches = hardNo;
} }
} else { } else {
thisRuleMatches = 0; thisRuleMatches = hardNo;
} }
break; break;
case ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE: case ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE:
@ -356,10 +384,10 @@ static _doZtFilterResult _doZtFilter(
} }
thisRuleMatches = (p > 0) ? (uint8_t)((p >= (int)rules[rn].v.port[0])&&(p <= (int)rules[rn].v.port[1])) : (uint8_t)0; thisRuleMatches = (p > 0) ? (uint8_t)((p >= (int)rules[rn].v.port[0])&&(p <= (int)rules[rn].v.port[1])) : (uint8_t)0;
} else { } else {
thisRuleMatches = 0; thisRuleMatches = hardNo;
} }
} else { } else {
thisRuleMatches = 0; thisRuleMatches = hardNo;
} }
break; break;
case ZT_NETWORK_RULE_MATCH_CHARACTERISTICS: { case ZT_NETWORK_RULE_MATCH_CHARACTERISTICS: {
@ -444,6 +472,14 @@ static _doZtFilterResult _doZtFilter(
const Tag *const localTag = std::lower_bound(&(nconf.tags[0]),&(nconf.tags[nconf.tagCount]),rules[rn].v.tag.id,Tag::IdComparePredicate()); 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)) { if ((localTag != &(nconf.tags[nconf.tagCount]))&&(localTag->id() == rules[rn].v.tag.id)) {
const Tag *const remoteTag = ((membership) ? membership->getTag(nconf,rules[rn].v.tag.id) : (const Tag *)0); const Tag *const remoteTag = ((membership) ? membership->getTag(nconf,rules[rn].v.tag.id) : (const Tag *)0);
#ifdef ZT_TRACE
fprintf(stderr, "\tlocal tag [%u: %u] remote tag [%u: %u] match [%u]",
!!localTag ? localTag->id() : 0,
!!localTag ? localTag->value() : 0,
!!remoteTag ? remoteTag->id() : 0,
!!remoteTag ? remoteTag->value() : 0,
thisRuleMatches);
#endif
if (remoteTag) { if (remoteTag) {
const uint32_t ltv = localTag->value(); const uint32_t ltv = localTag->value();
const uint32_t rtv = remoteTag->value(); const uint32_t rtv = remoteTag->value();
@ -459,28 +495,46 @@ static _doZtFilterResult _doZtFilter(
} else if (rt == ZT_NETWORK_RULE_MATCH_TAGS_EQUAL) { } else if (rt == ZT_NETWORK_RULE_MATCH_TAGS_EQUAL) {
thisRuleMatches = (uint8_t)((ltv == rules[rn].v.tag.value)&&(rtv == rules[rn].v.tag.value)); thisRuleMatches = (uint8_t)((ltv == rules[rn].v.tag.value)&&(rtv == rules[rn].v.tag.value));
} else { // sanity check, can't really happen } else { // sanity check, can't really happen
thisRuleMatches = 0; thisRuleMatches = hardNo;
} }
} else { } else {
if ((inbound)&&(!superAccept)) { if ((inbound)&&(!superAccept)) {
thisRuleMatches = 0; thisRuleMatches = hardNo;
#ifdef ZT_TRACE
fprintf(stderr, "\tinbound ");
#endif
} else { } else {
// Outbound side is not strict since if we have to match both tags and // 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 // 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 // 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 // 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. // not strict since we likely do not have these tags.
thisRuleMatches = 1; skipDrop = 1;
thisRuleMatches = hardYes;
#ifdef ZT_TRACE
fprintf(stderr, "\toutbound ");
#endif
} }
} }
} else { } else {
thisRuleMatches = 0; thisRuleMatches = hardNo;
} }
} break; } break;
case ZT_NETWORK_RULE_MATCH_TAG_SENDER: case ZT_NETWORK_RULE_MATCH_TAG_SENDER:
case ZT_NETWORK_RULE_MATCH_TAG_RECEIVER: { case ZT_NETWORK_RULE_MATCH_TAG_RECEIVER: {
const Tag *const localTag = std::lower_bound(&(nconf.tags[0]),&(nconf.tags[nconf.tagCount]),rules[rn].v.tag.id,Tag::IdComparePredicate());
#ifdef ZT_TRACE
const Tag *const remoteTag = ((membership) ? membership->getTag(nconf,rules[rn].v.tag.id) : (const Tag *)0);
fprintf(stderr, "\tlocal tag [%u: %u] remote tag [%u: %u] match [%u]",
!!localTag ? localTag->id() : 0,
!!localTag ? localTag->value() : 0,
!!remoteTag ? remoteTag->id() : 0,
!!remoteTag ? remoteTag->value() : 0,
thisRuleMatches);
#endif
if (superAccept) { if (superAccept) {
thisRuleMatches = 1; skipDrop = 1;
thisRuleMatches = hardYes;
} else if ( ((rt == ZT_NETWORK_RULE_MATCH_TAG_SENDER)&&(inbound)) || ((rt == ZT_NETWORK_RULE_MATCH_TAG_RECEIVER)&&(!inbound)) ) { } 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); const Tag *const remoteTag = ((membership) ? membership->getTag(nconf,rules[rn].v.tag.id) : (const Tag *)0);
if (remoteTag) { if (remoteTag) {
@ -489,17 +543,17 @@ static _doZtFilterResult _doZtFilter(
if (rt == ZT_NETWORK_RULE_MATCH_TAG_RECEIVER) { if (rt == ZT_NETWORK_RULE_MATCH_TAG_RECEIVER) {
// If we are checking the receiver and this is an outbound packet, we // 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. // can't be strict since we may not yet know the receiver's tag.
thisRuleMatches = 1; skipDrop = 1;
thisRuleMatches = hardYes;
} else { } else {
thisRuleMatches = 0; thisRuleMatches = hardNo;
} }
} }
} else { // sender and outbound or receiver and inbound } 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)) { if ((localTag != &(nconf.tags[nconf.tagCount]))&&(localTag->id() == rules[rn].v.tag.id)) {
thisRuleMatches = (uint8_t)(localTag->value() == rules[rn].v.tag.value); thisRuleMatches = (uint8_t)(localTag->value() == rules[rn].v.tag.value);
} else { } else {
thisRuleMatches = 0; thisRuleMatches = hardNo;
} }
} }
} break; } break;