mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-04-08 03:34:14 +00:00
.
This commit is contained in:
parent
4d9b74b171
commit
e2f783ebbd
@ -165,9 +165,69 @@ extern "C" {
|
||||
#define ZT_CLUSTER_MAX_MESSAGE_LENGTH (1500 - 48)
|
||||
|
||||
/**
|
||||
* Packet characteristics flag: packet direction, 1 for incoming 0 for outgoing
|
||||
* Packet characteristics flag: packet direction, 1 if inbound 0 if outbound
|
||||
*/
|
||||
#define ZT_RULE_PACKET_CHARACTERISTICS_0_INBOUND 0x0000000000000001ULL
|
||||
#define ZT_RULE_PACKET_CHARACTERISTICS_INBOUND 0x8000000000000000ULL
|
||||
|
||||
/**
|
||||
* Packet characteristics flag: TCP left-most reserved bit
|
||||
*/
|
||||
#define ZT_RULE_PACKET_CHARACTERISTICS_TCP_RESERVED_0 0x0000000000000800ULL
|
||||
|
||||
/**
|
||||
* Packet characteristics flag: TCP middle reserved bit
|
||||
*/
|
||||
#define ZT_RULE_PACKET_CHARACTERISTICS_TCP_RESERVED_1 0x0000000000000400ULL
|
||||
|
||||
/**
|
||||
* Packet characteristics flag: TCP right-most reserved bit
|
||||
*/
|
||||
#define ZT_RULE_PACKET_CHARACTERISTICS_TCP_RESERVED_2 0x0000000000000200ULL
|
||||
|
||||
/**
|
||||
* Packet characteristics flag: TCP NS flag
|
||||
*/
|
||||
#define ZT_RULE_PACKET_CHARACTERISTICS_TCP_NS 0x0000000000000100ULL
|
||||
|
||||
/**
|
||||
* Packet characteristics flag: TCP CWR flag
|
||||
*/
|
||||
#define ZT_RULE_PACKET_CHARACTERISTICS_TCP_CWR 0x0000000000000080ULL
|
||||
|
||||
/**
|
||||
* Packet characteristics flag: TCP ECE flag
|
||||
*/
|
||||
#define ZT_RULE_PACKET_CHARACTERISTICS_TCP_ECE 0x0000000000000040ULL
|
||||
|
||||
/**
|
||||
* Packet characteristics flag: TCP URG flag
|
||||
*/
|
||||
#define ZT_RULE_PACKET_CHARACTERISTICS_TCP_URG 0x0000000000000020ULL
|
||||
|
||||
/**
|
||||
* Packet characteristics flag: TCP ACK flag
|
||||
*/
|
||||
#define ZT_RULE_PACKET_CHARACTERISTICS_TCP_ACK 0x0000000000000010ULL
|
||||
|
||||
/**
|
||||
* Packet characteristics flag: TCP PSH flag
|
||||
*/
|
||||
#define ZT_RULE_PACKET_CHARACTERISTICS_TCP_PSH 0x0000000000000008ULL
|
||||
|
||||
/**
|
||||
* Packet characteristics flag: TCP RST flag
|
||||
*/
|
||||
#define ZT_RULE_PACKET_CHARACTERISTICS_TCP_RST 0x0000000000000004ULL
|
||||
|
||||
/**
|
||||
* Packet characteristics flag: TCP SYN flag
|
||||
*/
|
||||
#define ZT_RULE_PACKET_CHARACTERISTICS_TCP_SYN 0x0000000000000002ULL
|
||||
|
||||
/**
|
||||
* Packet characteristics flag: TCP FIN flag
|
||||
*/
|
||||
#define ZT_RULE_PACKET_CHARACTERISTICS_TCP_FIN 0x0000000000000001ULL
|
||||
|
||||
/**
|
||||
* A null/empty sockaddr (all zero) to signify an unspecified socket address
|
||||
@ -533,19 +593,24 @@ enum ZT_VirtualNetworkRuleType
|
||||
ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE = 49,
|
||||
|
||||
/**
|
||||
* Match a range of tag values (equality match if start==end)
|
||||
* Match if local and remote tags differ by no more than value, use 0 to check for equality
|
||||
*/
|
||||
ZT_NETWORK_RULE_MATCH_TAG_VALUE_RANGE = 50,
|
||||
ZT_NETWORK_RULE_MATCH_TAGS_SAMENESS = 50,
|
||||
|
||||
/**
|
||||
* Match if all bits are set in a tag value
|
||||
* Match if local and remote tags ANDed together equal value.
|
||||
*/
|
||||
ZT_NETWORK_RULE_MATCH_TAG_VALUE_BITS_ALL = 51,
|
||||
ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND = 51,
|
||||
|
||||
/**
|
||||
* Match if any bit from a mask is set in a tag value
|
||||
* Match if local and remote tags ANDed together equal value.
|
||||
*/
|
||||
ZT_NETWORK_RULE_MATCH_TAG_VALUE_BITS_ANY = 52
|
||||
ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR = 52,
|
||||
|
||||
/**
|
||||
* Match if local and remote tags XORed together equal value.
|
||||
*/
|
||||
ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR = 53
|
||||
};
|
||||
|
||||
/**
|
||||
@ -650,11 +715,11 @@ typedef struct
|
||||
uint16_t frameSize[2];
|
||||
|
||||
/**
|
||||
* For matching tag values
|
||||
* For tag-related rules
|
||||
*/
|
||||
struct {
|
||||
uint32_t id;
|
||||
uint32_t value[2]; // only [0] is used for BITS_ALL or BITS_ANY, [0]-[1] for range
|
||||
uint32_t value;
|
||||
} tag;
|
||||
} v;
|
||||
} ZT_VirtualNetworkRule;
|
||||
|
@ -52,13 +52,13 @@ class RuntimeEnvironment;
|
||||
* On the receiving side the receiver does the following for each packet:
|
||||
*
|
||||
* (1) Evaluates the capabilities of the sender (that the sender has
|
||||
* presented) to determine if the sender was allowed to send this.
|
||||
* presented) to determine if it should received this packet.
|
||||
* (2) Evaluates its own capabilities to determine if it should receive
|
||||
* and process this packet.
|
||||
* this packet.
|
||||
* (3) If both check out, it receives the packet.
|
||||
*
|
||||
* Note that rules in capabilities can do other things as well such as TEE
|
||||
* or REDIRECT packets. See Filter and ZT_VirtualNetworkRule.
|
||||
* or REDIRECT packets. See filter code and ZT_VirtualNetworkRule.
|
||||
*/
|
||||
class Capability
|
||||
{
|
||||
@ -248,17 +248,13 @@ public:
|
||||
b.append((uint16_t)rules[i].v.frameSize[0]);
|
||||
b.append((uint16_t)rules[i].v.frameSize[1]);
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_TAG_VALUE_RANGE:
|
||||
b.append((uint8_t)12);
|
||||
b.append((uint32_t)rules[i].v.tag.id);
|
||||
b.append((uint32_t)rules[i].v.tag.value[0]);
|
||||
b.append((uint32_t)rules[i].v.tag.value[1]);
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_TAG_VALUE_BITS_ALL:
|
||||
case ZT_NETWORK_RULE_MATCH_TAG_VALUE_BITS_ANY:
|
||||
case ZT_NETWORK_RULE_MATCH_TAGS_SAMENESS:
|
||||
case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND:
|
||||
case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR:
|
||||
case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR:
|
||||
b.append((uint8_t)8);
|
||||
b.append((uint32_t)rules[i].v.tag.id);
|
||||
b.append((uint32_t)rules[i].v.tag.value[0]);
|
||||
b.append((uint32_t)rules[i].v.tag.value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -360,15 +356,12 @@ public:
|
||||
rules[i].v.frameSize[0] = b.template at<uint16_t>(p);
|
||||
rules[i].v.frameSize[0] = b.template at<uint16_t>(p + 2);
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_TAG_VALUE_RANGE:
|
||||
case ZT_NETWORK_RULE_MATCH_TAGS_SAMENESS:
|
||||
case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND:
|
||||
case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR:
|
||||
case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR:
|
||||
rules[i].v.tag.id = b.template at<uint32_t>(p);
|
||||
rules[i].v.tag.value[0] = b.template at<uint32_t>(p + 4);
|
||||
rules[i].v.tag.value[1] = b.template at<uint32_t>(p + 8);
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_TAG_VALUE_BITS_ALL:
|
||||
case ZT_NETWORK_RULE_MATCH_TAG_VALUE_BITS_ANY:
|
||||
rules[i].v.tag.id = b.template at<uint32_t>(p);
|
||||
rules[i].v.tag.value[0] = b.template at<uint32_t>(p + 4);
|
||||
rules[i].v.tag.value = b.template at<uint32_t>(p + 4);
|
||||
break;
|
||||
}
|
||||
p += fieldLen;
|
||||
|
@ -103,9 +103,9 @@ public:
|
||||
friend class Hashtable::Iterator;
|
||||
|
||||
/**
|
||||
* @param bc Initial capacity in buckets (default: 128, must be nonzero)
|
||||
* @param bc Initial capacity in buckets (default: 64, must be nonzero)
|
||||
*/
|
||||
Hashtable(unsigned long bc = 128) :
|
||||
Hashtable(unsigned long bc = 64) :
|
||||
_t(reinterpret_cast<_Bucket **>(::malloc(sizeof(_Bucket *) * bc))),
|
||||
_bc(bc),
|
||||
_s(0)
|
||||
|
@ -28,49 +28,44 @@
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
bool Membership::sendCredentialsIfNeeded(const RuntimeEnvironment *RR,const uint64_t now,const Peer &peer,const NetworkConfig &nconf,const uint32_t *capIds,const unsigned int capCount,const uint32_t *tagIds,const unsigned int tagCount)
|
||||
bool Membership::sendCredentialsIfNeeded(const RuntimeEnvironment *RR,const uint64_t now,const Address &peerAddress,const CertificateOfMembership &com,const Capability *cap,const Tag **tags,const unsigned int tagCount)
|
||||
{
|
||||
try {
|
||||
Buffer<ZT_PROTO_MAX_PACKET_LENGTH> capsAndTags;
|
||||
|
||||
capsAndTags.addSize(2);
|
||||
unsigned int appendedCaps = 0;
|
||||
for(unsigned int i=0;i<capCount;++i) {
|
||||
CState *cs = _caps.get(capIds[i]);
|
||||
if (cap) {
|
||||
capsAndTags.addSize(2);
|
||||
CState *const cs = _caps.get(cap->id());
|
||||
if ((now - cs->lastPushed) >= ZT_CREDENTIAL_PUSH_EVERY) {
|
||||
if ((capsAndTags.size() + sizeof(Capability)) > (ZT_PROTO_MAX_PACKET_LENGTH - sizeof(CertificateOfMembership)))
|
||||
break;
|
||||
const Capability *c = nconf.capability(capIds[i]);
|
||||
if (c) {
|
||||
c->serialize(capsAndTags);
|
||||
++appendedCaps;
|
||||
cs->lastPushed = now;
|
||||
}
|
||||
cap->serialize(capsAndTags);
|
||||
cs->lastPushed = now;
|
||||
++appendedCaps;
|
||||
}
|
||||
capsAndTags.setAt<uint16_t>(0,(uint16_t)appendedCaps);
|
||||
} else {
|
||||
capsAndTags.append((uint16_t)0);
|
||||
}
|
||||
capsAndTags.setAt<uint16_t>(0,(uint16_t)appendedCaps);
|
||||
|
||||
unsigned int appendedTags = 0;
|
||||
const unsigned int tagCountPos = capsAndTags.size();
|
||||
capsAndTags.addSize(2);
|
||||
unsigned int appendedTags = 0;
|
||||
for(unsigned int i=0;i<tagCount;++i) {
|
||||
TState *ts = _tags.get(tagIds[i]);
|
||||
TState *const ts = _tags.get(tags[i]->id());
|
||||
if ((now - ts->lastPushed) >= ZT_CREDENTIAL_PUSH_EVERY) {
|
||||
if ((capsAndTags.size() + sizeof(Tag)) > (ZT_PROTO_MAX_PACKET_LENGTH - sizeof(CertificateOfMembership)))
|
||||
break;
|
||||
const Tag *t = nconf.tag(tagIds[i]);
|
||||
if (t) {
|
||||
t->serialize(capsAndTags);
|
||||
++appendedTags;
|
||||
ts->lastPushed = now;
|
||||
}
|
||||
tags[i]->serialize(capsAndTags);
|
||||
ts->lastPushed = now;
|
||||
++appendedTags;
|
||||
}
|
||||
}
|
||||
capsAndTags.setAt<uint16_t>(tagCountPos,(uint16_t)appendedTags);
|
||||
|
||||
if (((now - _lastPushedCom) >= ZT_CREDENTIAL_PUSH_EVERY)||(appendedCaps)||(appendedTags)) {
|
||||
Packet outp(peer.address(),RR->identity.address(),Packet::VERB_NETWORK_CREDENTIALS);
|
||||
nconf.com.serialize(outp);
|
||||
if ( ((com)&&((now - _lastPushedCom) >= ZT_CREDENTIAL_PUSH_EVERY)) || (appendedCaps) || (appendedTags) ) {
|
||||
Packet outp(peerAddress,RR->identity.address(),Packet::VERB_NETWORK_CREDENTIALS);
|
||||
if (com)
|
||||
com.serialize(outp);
|
||||
outp.append((uint8_t)0x00);
|
||||
outp.append(capsAndTags.data(),capsAndTags.size());
|
||||
outp.compress();
|
||||
|
@ -40,7 +40,6 @@
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
class Peer;
|
||||
class RuntimeEnvironment;
|
||||
|
||||
/**
|
||||
@ -54,18 +53,18 @@ private:
|
||||
struct TState
|
||||
{
|
||||
TState() : lastPushed(0),lastReceived(0) {}
|
||||
// Last time we pushed this tag to this peer
|
||||
// Last time we pushed our tag to this peer (our tag with the same ID)
|
||||
uint64_t lastPushed;
|
||||
// Last time we received this tag from this peer
|
||||
uint64_t lastReceived;
|
||||
// Tag from peer
|
||||
// Tag from peer (remote tag)
|
||||
Tag tag;
|
||||
};
|
||||
|
||||
struct CState
|
||||
{
|
||||
CState() : lastPushed(0),lastReceived(0) {}
|
||||
// Last time we pushed this capability to this peer
|
||||
// Last time we pushed our capability to this peer (our capability with this ID)
|
||||
uint64_t lastPushed;
|
||||
// Last time we received this capability from this peer
|
||||
uint64_t lastReceived;
|
||||
@ -90,29 +89,14 @@ public:
|
||||
*
|
||||
* @param RR Runtime environment
|
||||
* @param now Current time
|
||||
* @param peer Peer that "owns" this membership
|
||||
* @param nconf Network configuration
|
||||
* @param capIds Capability IDs that this peer might need
|
||||
* @param capCount Number of capability IDs
|
||||
* @param tagIds Tag IDs that this peer might need
|
||||
* @param peerAddress Address of member peer
|
||||
* @param com Network certificate of membership (if any)
|
||||
* @param cap Capability to send or 0 if none
|
||||
* @param tags Tags that this peer might need
|
||||
* @param tagCount Number of tag IDs
|
||||
* @return True if we pushed something
|
||||
*/
|
||||
bool sendCredentialsIfNeeded(const RuntimeEnvironment *RR,const uint64_t now,const Peer &peer,const NetworkConfig &nconf,const uint32_t *capIds,const unsigned int capCount,const uint32_t *tagIds,const unsigned int tagCount);
|
||||
|
||||
/**
|
||||
* Send COM if needed
|
||||
*
|
||||
* @param RR Runtime environment
|
||||
* @param now Current time
|
||||
* @param peer Peer that "owns" this membership
|
||||
* @param nconf Network configuration
|
||||
* @return True if we pushed something
|
||||
*/
|
||||
inline bool sendCredentialsIfNeeded(const RuntimeEnvironment *RR,const uint64_t now,const Peer &peer,const NetworkConfig &nconf)
|
||||
{
|
||||
return sendCredentialsIfNeeded(RR,now,peer,nconf,(const uint32_t *)0,0,(const uint32_t *)0,0);
|
||||
}
|
||||
bool sendCredentialsIfNeeded(const RuntimeEnvironment *RR,const uint64_t now,const Address &peerAddress,const CertificateOfMembership &com,const Capability *cap,const Tag **tags,const unsigned int tagCount);
|
||||
|
||||
/**
|
||||
* @return This peer's COM if they have sent one
|
||||
@ -130,6 +114,30 @@ public:
|
||||
return ((t) ? (((t->lastReceived != 0)&&(t->tag.expiration() < nconf.timestamp)) ? &(t->tag) : (const Tag *)0) : (const Tag *)0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nconf Network configuration
|
||||
* @param ids Array to store IDs into
|
||||
* @param values Array to store values into
|
||||
* @param maxTags Capacity of ids[] and values[]
|
||||
* @return Number of tags added to arrays
|
||||
*/
|
||||
inline unsigned int getAllTags(const NetworkConfig &nconf,uint32_t *ids,uint32_t *values,unsigned int maxTags) const
|
||||
{
|
||||
unsigned int n = 0;
|
||||
uint32_t *id = (uint32_t *)0;
|
||||
TState *ts = (TState *)0;
|
||||
Hashtable<uint32_t,TState>::Iterator i(const_cast<Membership *>(this)->_tags);
|
||||
while (i.next(id,ts)) {
|
||||
if ((ts->lastReceived)&&(ts->tag.expiration() < nconf.timestamp)) {
|
||||
if (n >= maxTags)
|
||||
return n;
|
||||
ids[n] = *id;
|
||||
values[n] = ts->tag.value();
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nconf Network configuration
|
||||
* @param id Capablity ID
|
||||
|
400
node/Network.cpp
400
node/Network.cpp
@ -22,19 +22,313 @@
|
||||
#include <math.h>
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "../version.h"
|
||||
#include "Network.hpp"
|
||||
#include "RuntimeEnvironment.hpp"
|
||||
#include "MAC.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "Switch.hpp"
|
||||
#include "Packet.hpp"
|
||||
#include "Buffer.hpp"
|
||||
#include "Packet.hpp"
|
||||
#include "NetworkController.hpp"
|
||||
#include "Node.hpp"
|
||||
#include "Peer.hpp"
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
// Returns true if packet appears valid; pos and proto will be set
|
||||
static bool _ipv6GetPayload(const uint8_t *frameData,unsigned int frameLen,unsigned int &pos,unsigned int &proto)
|
||||
{
|
||||
if (frameLen < 40)
|
||||
return false;
|
||||
pos = 40;
|
||||
proto = frameData[6];
|
||||
while (pos <= frameLen) {
|
||||
switch(proto) {
|
||||
case 0: // hop-by-hop options
|
||||
case 43: // routing
|
||||
case 60: // destination options
|
||||
case 135: // mobility options
|
||||
if ((pos + 8) > frameLen)
|
||||
return false; // invalid!
|
||||
proto = frameData[pos];
|
||||
pos += ((unsigned int)frameData[pos + 1] * 8) + 8;
|
||||
break;
|
||||
|
||||
//case 44: // fragment -- we currently can't parse these and they are deprecated in IPv6 anyway
|
||||
//case 50:
|
||||
//case 51: // IPSec ESP and AH -- we have to stop here since this is encrypted stuff
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false; // overflow == invalid
|
||||
}
|
||||
|
||||
static bool _doZtFilter(
|
||||
const RuntimeEnvironment *RR,
|
||||
const uint64_t nwid,
|
||||
const bool inbound,
|
||||
const Address &ztSource,
|
||||
const Address &ztDest,
|
||||
const MAC &macSource,
|
||||
const MAC &macDest,
|
||||
const uint8_t *frameData,
|
||||
const unsigned int frameLen,
|
||||
const unsigned int etherType,
|
||||
const unsigned int vlanId,
|
||||
const ZT_VirtualNetworkRule *rules,
|
||||
const unsigned int ruleCount,
|
||||
const Tag *localTags,
|
||||
const unsigned int localTagCount,
|
||||
const uint32_t *remoteTagIds,
|
||||
const uint32_t *remoteTagValues,
|
||||
const unsigned int remoteTagCount,
|
||||
const Tag **relevantLocalTags, // pointer array must be at least [localTagCount] in size
|
||||
unsigned int &relevantLocalTagCount)
|
||||
{
|
||||
// For each set of rules we start by assuming that they match (since no constraints
|
||||
// yields a 'match all' rule).
|
||||
uint8_t thisSetMatches = 1;
|
||||
|
||||
for(unsigned int rn=0;rn<ruleCount;++rn) {
|
||||
const ZT_VirtualNetworkRuleType rt = (ZT_VirtualNetworkRuleType)(rules[rn].t & 0x7f);
|
||||
uint8_t thisRuleMatches = 0;
|
||||
|
||||
switch(rt) {
|
||||
// Actions -------------------------------------------------------------
|
||||
|
||||
case ZT_NETWORK_RULE_ACTION_DROP:
|
||||
if (thisSetMatches) {
|
||||
return false;
|
||||
} else {
|
||||
thisSetMatches = 1; // continue parsing next set of rules
|
||||
}
|
||||
break;
|
||||
case ZT_NETWORK_RULE_ACTION_ACCEPT:
|
||||
if (thisSetMatches) {
|
||||
return true;
|
||||
} else {
|
||||
thisSetMatches = 1; // continue parsing next set of rules
|
||||
}
|
||||
break;
|
||||
case ZT_NETWORK_RULE_ACTION_TEE:
|
||||
case ZT_NETWORK_RULE_ACTION_REDIRECT: {
|
||||
Packet outp(Address(rules[rn].v.zt),RR->identity.address(),Packet::VERB_EXT_FRAME);
|
||||
outp.append(nwid);
|
||||
outp.append((uint8_t)((rt == ZT_NETWORK_RULE_ACTION_REDIRECT) ? 0x04 : 0x02));
|
||||
macDest.appendTo(outp);
|
||||
macSource.appendTo(outp);
|
||||
outp.append((uint16_t)etherType);
|
||||
outp.append(frameData,frameLen);
|
||||
outp.compress();
|
||||
RR->sw->send(outp,true,nwid);
|
||||
|
||||
if (rt == ZT_NETWORK_RULE_ACTION_REDIRECT) {
|
||||
return false;
|
||||
} else {
|
||||
thisSetMatches = 1; // TEE does not terminate parsing
|
||||
}
|
||||
} break;
|
||||
|
||||
// Rules ---------------------------------------------------------------
|
||||
|
||||
case ZT_NETWORK_RULE_MATCH_SOURCE_ZEROTIER_ADDRESS:
|
||||
thisRuleMatches = (uint8_t)(rules[rn].v.zt == ztSource.toInt());
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_DEST_ZEROTIER_ADDRESS:
|
||||
thisRuleMatches = (uint8_t)(rules[rn].v.zt == ztDest.toInt());
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_VLAN_ID:
|
||||
thisRuleMatches = (uint8_t)(rules[rn].v.vlanId == (uint16_t)vlanId);
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_VLAN_PCP:
|
||||
// NOT SUPPORTED YET
|
||||
thisRuleMatches = (uint8_t)(rules[rn].v.vlanPcp == 0);
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_VLAN_DEI:
|
||||
// NOT SUPPORTED YET
|
||||
thisRuleMatches = (uint8_t)(rules[rn].v.vlanDei == 0);
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_ETHERTYPE:
|
||||
thisRuleMatches = (uint8_t)(rules[rn].v.etherType == (uint16_t)etherType);
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_MAC_SOURCE:
|
||||
thisRuleMatches = (uint8_t)(MAC(rules[rn].v.mac,6) == macSource);
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_MAC_DEST:
|
||||
thisRuleMatches = (uint8_t)(MAC(rules[rn].v.mac,6) == macDest);
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_IPV4_SOURCE:
|
||||
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)));
|
||||
} else {
|
||||
thisRuleMatches = 0;
|
||||
}
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_IPV4_DEST:
|
||||
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)));
|
||||
} else {
|
||||
thisRuleMatches = 0;
|
||||
}
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_IPV6_SOURCE:
|
||||
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)));
|
||||
} else {
|
||||
thisRuleMatches = 0;
|
||||
}
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_IPV6_DEST:
|
||||
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)));
|
||||
} else {
|
||||
thisRuleMatches = 0;
|
||||
}
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_IP_TOS:
|
||||
if ((etherType == ZT_ETHERTYPE_IPV4)&&(frameLen >= 20)) {
|
||||
thisRuleMatches = (uint8_t)(rules[rn].v.ipTos == ((frameData[1] & 0xfc) >> 2));
|
||||
} else if ((etherType == ZT_ETHERTYPE_IPV6)&&(frameLen >= 40)) {
|
||||
const uint8_t trafficClass = ((frameData[0] << 4) & 0xf0) | ((frameData[1] >> 4) & 0x0f);
|
||||
thisRuleMatches = (uint8_t)(rules[rn].v.ipTos == ((trafficClass & 0xfc) >> 2));
|
||||
} else {
|
||||
thisRuleMatches = 0;
|
||||
}
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_IP_PROTOCOL:
|
||||
if ((etherType == ZT_ETHERTYPE_IPV4)&&(frameLen >= 20)) {
|
||||
thisRuleMatches = (uint8_t)(rules[rn].v.ipProtocol == frameData[9]);
|
||||
} else if (etherType == ZT_ETHERTYPE_IPV6) {
|
||||
unsigned int pos = 0,proto = 0;
|
||||
if (_ipv6GetPayload(frameData,frameLen,pos,proto)) {
|
||||
thisRuleMatches = (uint8_t)(rules[rn].v.ipProtocol == (uint8_t)proto);
|
||||
} else {
|
||||
thisRuleMatches = 0;
|
||||
}
|
||||
} else {
|
||||
thisRuleMatches = 0;
|
||||
}
|
||||
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)) {
|
||||
const unsigned int headerLen = 4 * (frameData[0] & 0xf);
|
||||
int p = -1;
|
||||
switch(frameData[9]) { // IP protocol number
|
||||
// All these start with 16-bit source and destination port in that order
|
||||
case 0x06: // TCP
|
||||
case 0x11: // UDP
|
||||
case 0x84: // SCTP
|
||||
case 0x88: // UDPLite
|
||||
if (frameLen > (headerLen + 4)) {
|
||||
unsigned int pos = headerLen + ((rt == ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE) ? 2 : 0);
|
||||
p = (int)frameData[pos++] << 8;
|
||||
p |= (int)frameData[pos];
|
||||
}
|
||||
break;
|
||||
}
|
||||
thisRuleMatches = (p > 0) ? (uint8_t)((p >= (int)rules[rn].v.port[0])&&(p <= (int)rules[rn].v.port[1])) : (uint8_t)0;
|
||||
} else if (etherType == ZT_ETHERTYPE_IPV6) {
|
||||
unsigned int pos = 0,proto = 0;
|
||||
if (_ipv6GetPayload(frameData,frameLen,pos,proto)) {
|
||||
int p = -1;
|
||||
switch(proto) { // IP protocol number
|
||||
// All these start with 16-bit source and destination port in that order
|
||||
case 0x06: // TCP
|
||||
case 0x11: // UDP
|
||||
case 0x84: // SCTP
|
||||
case 0x88: // UDPLite
|
||||
if (frameLen > (pos + 4)) {
|
||||
if (rt == ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE) pos += 2;
|
||||
p = (int)frameData[pos++] << 8;
|
||||
p |= (int)frameData[pos];
|
||||
}
|
||||
break;
|
||||
}
|
||||
thisRuleMatches = (p > 0) ? (uint8_t)((p >= (int)rules[rn].v.port[0])&&(p <= (int)rules[rn].v.port[1])) : (uint8_t)0;
|
||||
} else {
|
||||
thisRuleMatches = 0;
|
||||
}
|
||||
} else {
|
||||
thisRuleMatches = 0;
|
||||
}
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_CHARACTERISTICS: {
|
||||
uint64_t cf = (inbound) ? ZT_RULE_PACKET_CHARACTERISTICS_INBOUND : 0ULL;
|
||||
if ((etherType == ZT_ETHERTYPE_IPV4)&&(frameLen >= 20)&&(frameData[9] == 0x06)) {
|
||||
const unsigned int headerLen = 4 * (frameData[0] & 0xf);
|
||||
cf |= (uint64_t)frameData[headerLen + 13];
|
||||
cf |= (((uint64_t)(frameData[headerLen + 12] & 0x0f)) << 8);
|
||||
} else if (etherType == ZT_ETHERTYPE_IPV6) {
|
||||
unsigned int pos = 0,proto = 0;
|
||||
if (_ipv6GetPayload(frameData,frameLen,pos,proto)) {
|
||||
if ((proto == 0x06)&&(frameLen > (pos + 14))) {
|
||||
cf |= (uint64_t)frameData[pos + 13];
|
||||
cf |= (((uint64_t)(frameData[pos + 12] & 0x0f)) << 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
thisRuleMatches = (uint8_t)((cf & rules[rn].v.characteristics[0]) == rules[rn].v.characteristics[1]);
|
||||
} break;
|
||||
case ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE:
|
||||
thisRuleMatches = (uint8_t)((frameLen >= (unsigned int)rules[rn].v.frameSize[0])&&(frameLen <= (unsigned int)rules[rn].v.frameSize[1]));
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_TAGS_SAMENESS:
|
||||
case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND:
|
||||
case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR:
|
||||
case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR: {
|
||||
const Tag *lt = (const Tag *)0;
|
||||
for(unsigned int i=0;i<localTagCount;++i) {
|
||||
if (rules[rn].v.tag.id == localTags[i].id()) {
|
||||
lt = &(localTags[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!lt) {
|
||||
thisRuleMatches = 0;
|
||||
} else {
|
||||
const uint32_t *rtv = (const uint32_t *)0;
|
||||
for(unsigned int i=0;i<remoteTagCount;++i) {
|
||||
if (rules[rn].v.tag.id == remoteTagIds[i]) {
|
||||
rtv = &(remoteTagValues[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!rtv) {
|
||||
thisRuleMatches = 0;
|
||||
} else {
|
||||
if (rt == ZT_NETWORK_RULE_MATCH_TAGS_SAMENESS) {
|
||||
const uint32_t sameness = (lt->value() > *rtv) ? (lt->value() - *rtv) : (*rtv - lt->value());
|
||||
thisRuleMatches = (uint8_t)(sameness <= rules[rn].v.tag.value);
|
||||
} else if (rt == ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND) {
|
||||
thisRuleMatches = (uint8_t)((lt->value() & *rtv) <= rules[rn].v.tag.value);
|
||||
} else if (rt == ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR) {
|
||||
thisRuleMatches = (uint8_t)((lt->value() | *rtv) <= rules[rn].v.tag.value);
|
||||
} else if (rt == ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR) {
|
||||
thisRuleMatches = (uint8_t)((lt->value() ^ *rtv) <= rules[rn].v.tag.value);
|
||||
} else { // sanity check, can't really happen
|
||||
thisRuleMatches = 0;
|
||||
}
|
||||
if (thisRuleMatches) {
|
||||
relevantLocalTags[relevantLocalTagCount++] = lt;
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
// thisSetMatches remains true if the current rule matched... or does NOT match if not bit (0x80) is 1
|
||||
thisSetMatches &= (thisRuleMatches ^ ((rules[rn].t & 0x80) >> 7));
|
||||
|
||||
//TRACE("[%u] %u result==%u set==%u",rn,(unsigned int)rt,(unsigned int)thisRuleMatches,(unsigned int)thisSetMatches);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const ZeroTier::MulticastGroup Network::BROADCAST(ZeroTier::MAC(0xffffffffffffULL),0);
|
||||
|
||||
Network::Network(const RuntimeEnvironment *renv,uint64_t nwid,void *uptr) :
|
||||
@ -100,6 +394,96 @@ Network::~Network()
|
||||
}
|
||||
}
|
||||
|
||||
bool Network::filterOutgoingPacket(
|
||||
const Address &ztSource,
|
||||
const Address &ztDest,
|
||||
const MAC &macSource,
|
||||
const MAC &macDest,
|
||||
const uint8_t *frameData,
|
||||
const unsigned int frameLen,
|
||||
const unsigned int etherType,
|
||||
const unsigned int vlanId)
|
||||
{
|
||||
uint32_t remoteTagIds[ZT_MAX_NETWORK_TAGS];
|
||||
uint32_t remoteTagValues[ZT_MAX_NETWORK_TAGS];
|
||||
const Tag *relevantLocalTags[ZT_MAX_NETWORK_TAGS];
|
||||
unsigned int relevantLocalTagCount = 0;
|
||||
|
||||
Mutex::Lock _l(_lock);
|
||||
|
||||
Membership &m = _memberships[ztDest];
|
||||
const unsigned int remoteTagCount = m.getAllTags(_config,remoteTagIds,remoteTagValues,ZT_MAX_NETWORK_TAGS);
|
||||
|
||||
if (_doZtFilter(
|
||||
RR,
|
||||
_id,
|
||||
false,
|
||||
ztSource,
|
||||
ztDest,
|
||||
macSource,
|
||||
macDest,
|
||||
frameData,
|
||||
frameLen,
|
||||
etherType,
|
||||
vlanId,
|
||||
_config.rules,
|
||||
_config.ruleCount,
|
||||
_config.tags,
|
||||
_config.tagCount,
|
||||
remoteTagIds,
|
||||
remoteTagValues,
|
||||
remoteTagCount,
|
||||
relevantLocalTags,
|
||||
relevantLocalTagCount
|
||||
)) {
|
||||
m.sendCredentialsIfNeeded(RR,RR->node->now(),ztDest,_config.com,(const Capability *)0,relevantLocalTags,relevantLocalTagCount);
|
||||
return true;
|
||||
}
|
||||
|
||||
for(unsigned int c=0;c<_config.capabilityCount;++c) {
|
||||
relevantLocalTagCount = 0;
|
||||
if (_doZtFilter(
|
||||
RR,
|
||||
_id,
|
||||
false,
|
||||
ztSource,
|
||||
ztDest,
|
||||
macSource,
|
||||
macDest,
|
||||
frameData,
|
||||
frameLen,
|
||||
etherType,
|
||||
vlanId,
|
||||
_config.capabilities[c].rules(),
|
||||
_config.capabilities[c].ruleCount(),
|
||||
_config.tags,
|
||||
_config.tagCount,
|
||||
remoteTagIds,
|
||||
remoteTagValues,
|
||||
remoteTagCount,
|
||||
relevantLocalTags,
|
||||
relevantLocalTagCount
|
||||
)) {
|
||||
m.sendCredentialsIfNeeded(RR,RR->node->now(),ztDest,_config.com,&(_config.capabilities[c]),relevantLocalTags,relevantLocalTagCount);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Network::filterIncomingPacket(
|
||||
const SharedPtr<Peer> &sourcePeer,
|
||||
const Address &ztDest,
|
||||
const MAC &macSource,
|
||||
const MAC &macDest,
|
||||
const uint8_t *frameData,
|
||||
const unsigned int frameLen,
|
||||
const unsigned int etherType,
|
||||
const unsigned int vlanId)
|
||||
{
|
||||
}
|
||||
|
||||
bool Network::subscribedToMulticastGroup(const MulticastGroup &mg,bool includeBridgedGroups) const
|
||||
{
|
||||
Mutex::Lock _l(_lock);
|
||||
@ -267,6 +651,16 @@ void Network::clean()
|
||||
_multicastGroupsBehindMe.erase(*mg);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
Address *a = (Address *)0;
|
||||
Membership *m = (Membership *)0;
|
||||
Hashtable<Address,Membership>::Iterator i(_memberships);
|
||||
while (i.next(a,m)) {
|
||||
if ((now - m->clean(now)) > ZT_MEMBERSHIP_EXPIRATION_TIME)
|
||||
_memberships.erase(*a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Network::learnBridgeRoute(const MAC &mac,const Address &addr)
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "MAC.hpp"
|
||||
#include "Dictionary.hpp"
|
||||
#include "Multicaster.hpp"
|
||||
#include "Membership.hpp"
|
||||
#include "NetworkConfig.hpp"
|
||||
#include "CertificateOfMembership.hpp"
|
||||
|
||||
@ -113,7 +114,7 @@ public:
|
||||
* a match certain actions may be taken such as sending a copy of the packet
|
||||
* to a TEE or REDIRECT target.
|
||||
*
|
||||
* @param ztSource Source Peer (to save an extra lookup)
|
||||
* @param sourcePeer Source Peer
|
||||
* @param ztDest Destination ZeroTier address
|
||||
* @param macSource Ethernet layer source address
|
||||
* @param macDest Ethernet layer destination address
|
||||
@ -124,7 +125,7 @@ public:
|
||||
* @return True if packet should be accepted locally
|
||||
*/
|
||||
bool filterIncomingPacket(
|
||||
const SharedPtr<Peer> &ztSource,
|
||||
const SharedPtr<Peer> &sourcePeer,
|
||||
const Address &ztDest,
|
||||
const MAC &macSource,
|
||||
const MAC &macDest,
|
||||
@ -387,6 +388,8 @@ private:
|
||||
} _netconfFailure;
|
||||
volatile int _portError; // return value from port config callback
|
||||
|
||||
Hashtable<Address,Membership> _memberships;
|
||||
|
||||
Mutex _lock;
|
||||
|
||||
AtomicCounter __refCount;
|
||||
|
@ -39,19 +39,22 @@ void OutboundMulticast::init(
|
||||
const void *payload,
|
||||
unsigned int len)
|
||||
{
|
||||
uint8_t flags = 0;
|
||||
|
||||
_timestamp = timestamp;
|
||||
_nwid = nwid;
|
||||
if (src)
|
||||
if (src) {
|
||||
_macSrc = src;
|
||||
else _macSrc.fromAddress(RR->identity.address(),nwid);
|
||||
flags |= 0x04;
|
||||
} else {
|
||||
_macSrc.fromAddress(RR->identity.address(),nwid);
|
||||
}
|
||||
_macDest = dest.mac();
|
||||
_limit = limit;
|
||||
_frameLen = (len < ZT_MAX_MTU) ? len : ZT_MAX_MTU;
|
||||
_etherType = etherType;
|
||||
|
||||
uint8_t flags = 0;
|
||||
if (gatherLimit) flags |= 0x02;
|
||||
if (src) flags |= 0x04;
|
||||
|
||||
/*
|
||||
TRACE(">>MC %.16llx INIT %.16llx/%s limit %u gatherLimit %u from %s to %s length %u",
|
||||
|
@ -660,6 +660,8 @@ public:
|
||||
*
|
||||
* Flags:
|
||||
* 0x01 - Certificate of network membership attached (DEPRECATED)
|
||||
* 0x02 - Packet is a TEE'd packet
|
||||
* 0x04 - Packet is a REDIRECT'ed packet
|
||||
*
|
||||
* An extended frame carries full MAC addressing, making them a
|
||||
* superset of VERB_FRAME. They're used for bridging or when we
|
||||
|
@ -373,28 +373,15 @@ void Peer::getBestActiveAddresses(uint64_t now,InetAddress &v4,InetAddress &v6)
|
||||
|
||||
void Peer::clean(uint64_t now)
|
||||
{
|
||||
{
|
||||
unsigned int np = _numPaths;
|
||||
unsigned int x = 0;
|
||||
unsigned int y = 0;
|
||||
while (x < np) {
|
||||
if (_paths[x].active(now))
|
||||
_paths[y++] = _paths[x];
|
||||
++x;
|
||||
}
|
||||
_numPaths = y;
|
||||
}
|
||||
|
||||
{
|
||||
Mutex::Lock _l(_memberships_m);
|
||||
uint64_t *nwid = (uint64_t *)0;
|
||||
Membership *m = (Membership *)0;
|
||||
Hashtable<uint64_t,Membership>::Iterator i(_memberships);
|
||||
while (i.next(nwid,m)) {
|
||||
if ((now - m->clean(now)) > ZT_MEMBERSHIP_EXPIRATION_TIME)
|
||||
_memberships.erase(*nwid);
|
||||
}
|
||||
unsigned int np = _numPaths;
|
||||
unsigned int x = 0;
|
||||
unsigned int y = 0;
|
||||
while (x < np) {
|
||||
if (_paths[x].active(now))
|
||||
_paths[y++] = _paths[x];
|
||||
++x;
|
||||
}
|
||||
_numPaths = y;
|
||||
}
|
||||
|
||||
void Peer::_doDeadPathDetection(Path &p,const uint64_t now)
|
||||
|
@ -40,10 +40,8 @@
|
||||
#include "SharedPtr.hpp"
|
||||
#include "AtomicCounter.hpp"
|
||||
#include "Hashtable.hpp"
|
||||
#include "Membership.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "NonCopyable.hpp"
|
||||
#include "LockingPtr.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
@ -386,34 +384,6 @@ public:
|
||||
return (_directPathPushCutoffCount < ZT_PUSH_DIRECT_PATHS_CUTOFF_LIMIT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the membership record for this network, possibly creating if missing
|
||||
*
|
||||
* @param networkId Network ID
|
||||
* @param createIfMissing If true, create a Membership record if there isn't one
|
||||
* @return Single-scope locking pointer (see LockingPtr.hpp) to Membership or NULL if not found and createIfMissing is false
|
||||
*/
|
||||
inline LockingPtr<Membership> membership(const uint64_t networkId,bool createIfMissing)
|
||||
{
|
||||
_memberships_m.lock();
|
||||
try {
|
||||
if (createIfMissing) {
|
||||
return LockingPtr<Membership>(&(_memberships[networkId]),&_memberships_m);
|
||||
} else {
|
||||
Membership *m = _memberships.get(networkId);
|
||||
if (m) {
|
||||
return LockingPtr<Membership>(m,&_memberships_m);
|
||||
} else {
|
||||
_memberships_m.unlock();
|
||||
return LockingPtr<Membership>();
|
||||
}
|
||||
}
|
||||
} catch ( ... ) {
|
||||
_memberships_m.unlock();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a common set of addresses by which two peers can link, if any
|
||||
*
|
||||
@ -460,9 +430,6 @@ private:
|
||||
unsigned int _latency;
|
||||
unsigned int _directPathPushCutoffCount;
|
||||
|
||||
Hashtable<uint64_t,Membership> _memberships;
|
||||
Mutex _memberships_m;
|
||||
|
||||
AtomicCounter __refCount;
|
||||
};
|
||||
|
||||
|
@ -79,7 +79,7 @@ public:
|
||||
inline uint64_t networkId() const { return _nwid; }
|
||||
inline uint64_t expiration() const { return _expiration; }
|
||||
inline uint32_t id() const { return _id; }
|
||||
inline uint32_t value() const { return _value; }
|
||||
inline const uint32_t &value() const { return _value; }
|
||||
inline const Address &issuedTo() const { return _issuedTo; }
|
||||
inline const Address &signedBy() const { return _signedBy; }
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user