summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Ierymenko <adam.ierymenko@gmail.com>2013-08-28 16:01:27 -0400
committerAdam Ierymenko <adam.ierymenko@gmail.com>2013-08-28 16:01:27 -0400
commit55616388eaa5c43b4316882a5c4ab2e0c132b62e (patch)
tree6e02779f8864c636e6d35609a984d884ae7741b3
parent8e1b897f0ae8a228799058153e9dda0a18aeb4c1 (diff)
downloadinfinitytier-55616388eaa5c43b4316882a5c4ab2e0c132b62e.tar.gz
infinitytier-55616388eaa5c43b4316882a5c4ab2e0c132b62e.zip
Check network ethernet type whitelist instead of hard-coded ethernet types.
-rw-r--r--node/Network.cpp9
-rw-r--r--node/Network.hpp47
-rw-r--r--node/PacketDecoder.cpp15
-rw-r--r--node/Switch.cpp7
-rw-r--r--node/Utils.hpp33
5 files changed, 83 insertions, 28 deletions
diff --git a/node/Network.cpp b/node/Network.cpp
index 1e436a27..fc52e6d7 100644
--- a/node/Network.cpp
+++ b/node/Network.cpp
@@ -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());
diff --git a/node/Network.hpp b/node/Network.hpp
index f692c168..47e6430c 100644
--- a/node/Network.hpp
+++ b/node/Network.hpp
@@ -268,6 +268,24 @@ public:
}
/**
+ * @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
*/
inline std::set<InetAddress> staticAddresses() const
@@ -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;
diff --git a/node/PacketDecoder.cpp b/node/PacketDecoder.cpp
index 345c7914..fd817410 100644
--- a/node/PacketDecoder.cpp
+++ b/node/PacketDecoder.cpp
@@ -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];
diff --git a/node/Switch.cpp b/node/Switch.cpp
index 9370522e..157ecec8 100644
--- a/node/Switch.cpp
+++ b/node/Switch.cpp
@@ -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;
}
diff --git a/node/Utils.hpp b/node/Utils.hpp
index 79a2b04f..8bced8ad 100644
--- a/node/Utils.hpp
+++ b/node/Utils.hpp
@@ -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
*