mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2024-12-19 04:57:53 +00:00
Check network ethernet type whitelist instead of hard-coded ethernet types.
This commit is contained in:
parent
8e1b897f0a
commit
55616388ea
@ -150,10 +150,8 @@ SharedPtr<Network> Network::newInstance(const RuntimeEnvironment *renv,uint64_t
|
||||
SharedPtr<Network> nw(new Network());
|
||||
nw->_ready = false; // disable handling of Ethernet frames during construct
|
||||
nw->_r = renv;
|
||||
nw->_rlLimit.bytesPerSecond = ZT_MULTICAST_DEFAULT_BYTES_PER_SECOND;
|
||||
nw->_rlLimit.maxBalance = ZT_MULTICAST_DEFAULT_RATE_MAX_BALANCE;
|
||||
nw->_rlLimit.minBalance = ZT_MULTICAST_DEFAULT_RATE_MIN_BALANCE;
|
||||
nw->_tap = new EthernetTap(renv,tag,renv->identity.address().toMAC(),ZT_IF_MTU,&_CBhandleTapData,nw.ptr());
|
||||
memset(nw->_etWhitelist,0,sizeof(nw->_etWhitelist));
|
||||
nw->_id = id;
|
||||
nw->_lastConfigUpdate = 0;
|
||||
nw->_destroyOnDelete = false;
|
||||
@ -177,6 +175,11 @@ void Network::setConfiguration(const Network::Config &conf)
|
||||
_tap->setIps(conf.staticAddresses());
|
||||
_tap->setDisplayName((std::string("ZeroTier One [") + conf.name() + "]").c_str());
|
||||
|
||||
memset(_etWhitelist,0,sizeof(_etWhitelist));
|
||||
std::set<unsigned int> wl(conf.etherTypes());
|
||||
for(std::set<unsigned int>::const_iterator t(wl.begin());t!=wl.end();++t)
|
||||
_etWhitelist[*t / 8] |= (unsigned char)(1 << (*t % 8));
|
||||
|
||||
std::string confPath(_r->homePath + ZT_PATH_SEPARATOR_S + "networks.d" + ZT_PATH_SEPARATOR_S + toString() + ".conf");
|
||||
if (!Utils::writeFile(confPath.c_str(),conf.toString())) {
|
||||
LOG("error: unable to write network configuration file at: %s",confPath.c_str());
|
||||
|
@ -267,6 +267,24 @@ public:
|
||||
return (get("isOpen","0") == "1");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Network ethertype whitelist
|
||||
*/
|
||||
inline std::set<unsigned int> etherTypes() const
|
||||
{
|
||||
char tmp[16384];
|
||||
char *saveptr = (char *)0;
|
||||
std::set<unsigned int> et;
|
||||
if (!Utils::scopy(tmp,sizeof(tmp),get("etherTypes","").c_str()))
|
||||
return et; // sanity check
|
||||
for(char *f=Utils::stok(tmp,",",&saveptr);(f);f=Utils::stok((char *)0,",",&saveptr)) {
|
||||
unsigned int t = Utils::stoui(f);
|
||||
if (t)
|
||||
et.insert(t);
|
||||
}
|
||||
return et;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return All static addresses / netmasks, IPv4 or IPv6
|
||||
*/
|
||||
@ -445,22 +463,17 @@ public:
|
||||
Status status() const;
|
||||
|
||||
/**
|
||||
* Invoke multicast rate limiter gate for a given address
|
||||
*
|
||||
* @param addr Address to check
|
||||
* @param bytes Bytes address wishes to send us / propagate
|
||||
* @return True if allowed, false if overshot rate limit
|
||||
* @param etherType Ethernet frame type
|
||||
* @return True if network permits this type
|
||||
*/
|
||||
inline bool multicastRateGate(const Address &addr,unsigned int bytes)
|
||||
inline bool permitsEtherType(unsigned int etherType) const
|
||||
throw()
|
||||
{
|
||||
Mutex::Lock _l(_lock);
|
||||
std::map<Address,RateLimiter>::iterator rl(_multicastRateLimiters.find(addr));
|
||||
if (rl == _multicastRateLimiters.end()) {
|
||||
RateLimiter &newrl = _multicastRateLimiters[addr];
|
||||
newrl.init(ZT_MULTICAST_DEFAULT_RATE_PRELOAD);
|
||||
return newrl.gate(_rlLimit,(double)bytes);
|
||||
}
|
||||
return rl->second.gate(_rlLimit,(double)bytes);
|
||||
if (!etherType)
|
||||
return false;
|
||||
else if (etherType > 65535)
|
||||
return false;
|
||||
else return ((_etWhitelist[etherType / 8] & (unsigned char)(1 << (etherType % 8))) != 0);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -469,9 +482,6 @@ private:
|
||||
|
||||
const RuntimeEnvironment *_r;
|
||||
|
||||
// Rate limits for this network
|
||||
RateLimiter::Limit _rlLimit;
|
||||
|
||||
// Tap and tap multicast memberships
|
||||
EthernetTap *_tap;
|
||||
std::set<MulticastGroup> _multicastGroups;
|
||||
@ -486,6 +496,9 @@ private:
|
||||
Config _configuration;
|
||||
Certificate _myCertificate;
|
||||
|
||||
// Ethertype whitelist bit field, set from config, for really fast lookup
|
||||
unsigned char _etWhitelist[65536 / 8];
|
||||
|
||||
uint64_t _id;
|
||||
volatile uint64_t _lastConfigUpdate;
|
||||
volatile bool _destroyOnDelete;
|
||||
|
@ -418,10 +418,10 @@ bool PacketDecoder::_doFRAME(const RuntimeEnvironment *_r,const SharedPtr<Peer>
|
||||
if (network) {
|
||||
if (network->isAllowed(source())) {
|
||||
unsigned int etherType = at<uint16_t>(ZT_PROTO_VERB_FRAME_IDX_ETHERTYPE);
|
||||
if ((etherType != ZT_ETHERTYPE_ARP)&&(etherType != ZT_ETHERTYPE_IPV4)&&(etherType != ZT_ETHERTYPE_IPV6)) {
|
||||
TRACE("dropped FRAME from %s: unsupported ethertype",source().toString().c_str());
|
||||
} else if (size() > ZT_PROTO_VERB_FRAME_IDX_PAYLOAD) {
|
||||
if (network->permitsEtherType(etherType)) {
|
||||
network->tap().put(source().toMAC(),network->tap().mac(),etherType,data() + ZT_PROTO_VERB_FRAME_IDX_PAYLOAD,size() - ZT_PROTO_VERB_FRAME_IDX_PAYLOAD);
|
||||
} else if (size() > ZT_PROTO_VERB_FRAME_IDX_PAYLOAD) {
|
||||
TRACE("dropped FRAME from %s: ethernet type %u not allowed on network %.16llx",source().toString().c_str(),etherType,(unsigned long long)network->id());
|
||||
}
|
||||
} else {
|
||||
TRACE("dropped FRAME from %s(%s): not a member of closed network %llu",source().toString().c_str(),_remoteAddress.toString().c_str(),network->id());
|
||||
@ -509,8 +509,8 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared
|
||||
return true;
|
||||
}
|
||||
|
||||
if (++hops >= ZT_MULTICAST_PROPAGATION_DEPTH) {
|
||||
TRACE("dropped MULTICAST_FRAME from original submitter %s, received from %s(%s): max depth reached",originalSubmitterAddress.toString().c_str(),source().toString().c_str(),_remoteAddress.toString().c_str());
|
||||
if (!network->permitsEtherType(etherType)) {
|
||||
LOG("dropped MULTICAST_FRAME from original submitter %s, received from %s(%s): ethernet type %s not allowed on network %.16llx",originalSubmitterAddress.toString().c_str(),source().toString().c_str(),_remoteAddress.toString().c_str(),Filter::etherTypeName(etherType),(unsigned long long)network->id());
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -533,6 +533,11 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared
|
||||
_r->multicaster->addToDedupHistory(mccrc,now);
|
||||
}
|
||||
|
||||
if (++hops >= ZT_MULTICAST_PROPAGATION_DEPTH) {
|
||||
TRACE("not propagating MULTICAST_FRAME from original submitter %s, received from %s(%s): max depth reached",originalSubmitterAddress.toString().c_str(),source().toString().c_str(),_remoteAddress.toString().c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
Address upstream(source()); // save this since we might mangle it below
|
||||
Multicaster::MulticastBloomFilter bloom(field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_BLOOM_FILTER,ZT_PROTO_VERB_MULTICAST_FRAME_BLOOM_FILTER_SIZE_BYTES));
|
||||
SharedPtr<Peer> propPeers[ZT_MULTICAST_PROPAGATION_BREADTH];
|
||||
|
@ -85,13 +85,14 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
|
||||
LOG("ignored tap: %s -> %s %s (bridging is not (yet?) supported)",from.toString().c_str(),to.toString().c_str(),Filter::etherTypeName(etherType));
|
||||
return;
|
||||
}
|
||||
|
||||
if (to == network->tap().mac()) {
|
||||
LOG("%s: frame received from self, ignoring (bridge loop?)",network->tap().deviceName().c_str());
|
||||
LOG("%s: frame received from self, ignoring (bridge loop? OS bug?)",network->tap().deviceName().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if ((etherType != ZT_ETHERTYPE_ARP)&&(etherType != ZT_ETHERTYPE_IPV4)&&(etherType != ZT_ETHERTYPE_IPV6)) {
|
||||
LOG("ignored tap: %s -> %s %s (not a supported etherType)",from.toString().c_str(),to.toString().c_str(),Filter::etherTypeName(etherType));
|
||||
if (!network->permitsEtherType(etherType)) {
|
||||
LOG("ignored tap: %s -> %s: ethernet type %s not allowed on network %.16llx",from.toString().c_str(),to.toString().c_str(),Filter::etherTypeName(etherType),(unsigned long long)network->id());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <string>
|
||||
@ -460,6 +461,38 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
// String to int converters (and hex string to int)
|
||||
static inline unsigned int stoui(const char *s)
|
||||
throw()
|
||||
{
|
||||
return (unsigned int)strtoul(s,(char **)0,10);
|
||||
}
|
||||
static inline unsigned long stoul(const char *s)
|
||||
throw()
|
||||
{
|
||||
return strtoul(s,(char **)0,10);
|
||||
}
|
||||
static inline unsigned long long stoull(const char *s)
|
||||
throw()
|
||||
{
|
||||
return strtoull(s,(char **)0,10);
|
||||
}
|
||||
static inline unsigned int hstoui(const char *s)
|
||||
throw()
|
||||
{
|
||||
return (unsigned int)strtoul(s,(char **)0,16);
|
||||
}
|
||||
static inline unsigned long hstoul(const char *s)
|
||||
throw()
|
||||
{
|
||||
return strtoul(s,(char **)0,16);
|
||||
}
|
||||
static inline unsigned long long hstoull(const char *s)
|
||||
throw()
|
||||
{
|
||||
return strtoull(s,(char **)0,16);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a safe C string copy
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user