summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ZeroTierUI/mainwindow.cpp15
-rw-r--r--ZeroTierUI/mainwindow.h1
-rw-r--r--ZeroTierUI/stylesheet.css3
-rw-r--r--node/EthernetTap.cpp35
-rw-r--r--node/EthernetTap.hpp6
-rw-r--r--node/Network.cpp82
-rw-r--r--node/Network.hpp163
-rw-r--r--node/Node.cpp1
-rw-r--r--node/NodeConfig.cpp13
-rw-r--r--node/NodeConfig.hpp12
-rw-r--r--node/PacketDecoder.cpp8
-rw-r--r--node/Switch.cpp7
12 files changed, 240 insertions, 106 deletions
diff --git a/ZeroTierUI/mainwindow.cpp b/ZeroTierUI/mainwindow.cpp
index 1b3f57cd..ffb27af1 100644
--- a/ZeroTierUI/mainwindow.cpp
+++ b/ZeroTierUI/mainwindow.cpp
@@ -121,7 +121,8 @@ MainWindow::MainWindow(QWidget *parent) :
ui->bottomContainerWidget->setVisible(false);
ui->networkListWidget->setVisible(false);
- this->pollServiceTimerId = this->startTimer(1000);
+ this->firstTimerTick = true;
+ this->pollServiceTimerId = this->startTimer(200);
this->cyclesSinceResponseFromService = 0;
}
@@ -133,15 +134,19 @@ MainWindow::~MainWindow()
mainWindow = (MainWindow *)0;
}
-void MainWindow::timerEvent(QTimerEvent *event)
+void MainWindow::timerEvent(QTimerEvent *event) // event can be null since code also calls this directly
{
- event->accept();
-
if (this->isHidden())
return;
- if (pollServiceTimerId < 0)
+ if (this->pollServiceTimerId < 0)
return;
+ if (this->firstTimerTick) {
+ this->firstTimerTick = false;
+ this->killTimer(this->pollServiceTimerId);
+ this->pollServiceTimerId = this->startTimer(1500);
+ }
+
if (!zeroTierClient) {
std::string authToken;
if (!ZeroTier::Utils::readFile(ZeroTier::Node::LocalClient::authTokenDefaultUserPath().c_str(),authToken)) {
diff --git a/ZeroTierUI/mainwindow.h b/ZeroTierUI/mainwindow.h
index 92cfabf1..c4bb72ae 100644
--- a/ZeroTierUI/mainwindow.h
+++ b/ZeroTierUI/mainwindow.h
@@ -86,6 +86,7 @@ private:
QString myAddress;
QString myStatus;
QString myVersion;
+ bool firstTimerTick;
int pollServiceTimerId;
unsigned int numPeers;
unsigned int cyclesSinceResponseFromService;
diff --git a/ZeroTierUI/stylesheet.css b/ZeroTierUI/stylesheet.css
index 9639f2b5..31904df5 100644
--- a/ZeroTierUI/stylesheet.css
+++ b/ZeroTierUI/stylesheet.css
@@ -64,6 +64,9 @@ QListWidget.ipAddressList::item {
}
QListWidget.ipAddressList::item:selected {
background: transparent;
+ border-top: 0;
+ border-left: 0;
+ border-right: 0;
border-bottom: 1px solid transparent;
}
QListWidget.ipAddressList::item:hover {
diff --git a/node/EthernetTap.cpp b/node/EthernetTap.cpp
index c6decba8..b669c489 100644
--- a/node/EthernetTap.cpp
+++ b/node/EthernetTap.cpp
@@ -336,8 +336,6 @@ EthernetTap::EthernetTap(
}
}
- whack(); // turns on IPv6 on OSX
-
::pipe(_shutdownSignalPipe);
_thread = Thread::start(this);
@@ -378,7 +376,7 @@ EthernetTap::~EthernetTap()
#endif // __APPLE__
}
-#ifdef __APPLE__
+/*
void EthernetTap::whack()
{
const char *ipconfig = UNIX_COMMANDS[ZT_MAC_IPCONFIG_COMMAND];
@@ -393,9 +391,7 @@ void EthernetTap::whack()
}
}
}
-#else
-void EthernetTap::whack() {}
-#endif // __APPLE__ / !__APPLE__
+*/
void EthernetTap::setDisplayName(const char *dn)
{
@@ -979,7 +975,8 @@ EthernetTap::EthernetTap(
_arg(arg),
_tap(INVALID_HANDLE_VALUE),
_injectSemaphore(INVALID_HANDLE_VALUE),
- _run(true)
+ _run(true),
+ _initialized(false)
{
char subkeyName[4096];
char subkeyClass[4096];
@@ -1203,11 +1200,15 @@ EthernetTap::EthernetTap(
// Start background thread that actually performs I/O
_injectSemaphore = CreateSemaphore(NULL,0,1,NULL);
_thread = Thread::start(this);
+
+ // Certain functions can now work (e.g. ips())
+ _initialized = true;
}
EthernetTap::~EthernetTap()
{
_run = false;
+
ReleaseSemaphore(_injectSemaphore,1,NULL);
Thread::join(_thread);
CloseHandle(_tap);
@@ -1237,12 +1238,10 @@ EthernetTap::~EthernetTap()
}
}
-void EthernetTap::whack()
-{
-}
-
void EthernetTap::setDisplayName(const char *dn)
{
+ if (!_initialized)
+ return;
HKEY ifp;
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,(std::string("SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\") + _myDeviceInstanceId).c_str(),0,KEY_READ|KEY_WRITE,&ifp) == ERROR_SUCCESS) {
RegSetKeyValueA(ifp,"Connection","Name",REG_SZ,(LPCVOID)dn,(DWORD)(strlen(dn)+1));
@@ -1252,6 +1251,8 @@ void EthernetTap::setDisplayName(const char *dn)
bool EthernetTap::addIP(const InetAddress &ip)
{
+ if (!_initialized)
+ return false;
if (!ip.netmaskBits()) // sanity check... netmask of 0.0.0.0 is WUT?
return false;
@@ -1299,6 +1300,8 @@ bool EthernetTap::addIP(const InetAddress &ip)
bool EthernetTap::removeIP(const InetAddress &ip)
{
+ if (!_initialized)
+ return false;
try {
MIB_UNICASTIPADDRESS_TABLE *ipt = (MIB_UNICASTIPADDRESS_TABLE *)0;
std::pair<NET_LUID,NET_IFINDEX> ifidx = _findAdapterByGuid(_deviceGuid);
@@ -1339,6 +1342,9 @@ std::set<InetAddress> EthernetTap::ips() const
static const InetAddress linkLocalLoopback("fe80::1",64); // what is this and why does Windows assign it?
std::set<InetAddress> addrs;
+ if (!_initialized)
+ return addrs;
+
try {
MIB_UNICASTIPADDRESS_TABLE *ipt = (MIB_UNICASTIPADDRESS_TABLE *)0;
std::pair<NET_LUID,NET_IFINDEX> ifidx = _findAdapterByGuid(_deviceGuid);
@@ -1369,6 +1375,8 @@ std::set<InetAddress> EthernetTap::ips() const
void EthernetTap::put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len)
{
+ if (!_initialized)
+ return;
if (len > (ZT_IF_MTU))
return;
@@ -1398,6 +1406,9 @@ std::string EthernetTap::persistentId() const
bool EthernetTap::updateMulticastGroups(std::set<MulticastGroup> &groups)
{
+ if (!_initialized)
+ return false;
+
std::set<MulticastGroup> newGroups;
// Ensure that groups are added for each IP... this handles the MAC:ADI
@@ -1456,7 +1467,7 @@ void EthernetTap::threadMain()
HANDLE wait4[3];
wait4[0] = _injectSemaphore;
wait4[1] = _tapOvlRead.hEvent;
- wait4[2] = _tapOvlWrite.hEvent;
+ wait4[2] = _tapOvlWrite.hEvent; // only included if writeInProgress is true
ReadFile(_tap,_tapReadBuf,sizeof(_tapReadBuf),NULL,&_tapOvlRead);
bool writeInProgress = false;
diff --git a/node/EthernetTap.hpp b/node/EthernetTap.hpp
index 15e7aede..799885db 100644
--- a/node/EthernetTap.hpp
+++ b/node/EthernetTap.hpp
@@ -95,11 +95,6 @@ public:
~EthernetTap();
/**
- * Perform OS dependent actions on network configuration change detection
- */
- void whack();
-
- /**
* Set the user display name for this connection
*
* This does nothing on platforms that don't have this concept.
@@ -245,6 +240,7 @@ private:
std::queue< std::pair< Array<char,ZT_IF_MTU + 32>,unsigned int > > _injectPending;
Mutex _injectPending_m;
volatile bool _run;
+ volatile bool _initialized;
#endif
};
diff --git a/node/Network.cpp b/node/Network.cpp
index 37d93b99..8ba597ba 100644
--- a/node/Network.cpp
+++ b/node/Network.cpp
@@ -46,6 +46,7 @@ const char *Network::statusString(const Status s)
throw()
{
switch(s) {
+ case NETWORK_INITIALIZING: return "INITIALIZING";
case NETWORK_WAITING_FOR_FIRST_AUTOCONF: return "WAITING_FOR_FIRST_AUTOCONF";
case NETWORK_OK: return "OK";
case NETWORK_ACCESS_DENIED: return "ACCESS_DENIED";
@@ -56,6 +57,8 @@ const char *Network::statusString(const Status s)
Network::~Network()
{
+ Thread::join(_setupThread);
+
std::string devPersistentId(_tap->persistentId());
delete _tap;
@@ -73,46 +76,50 @@ Network::~Network()
SharedPtr<Network> Network::newInstance(const RuntimeEnvironment *renv,uint64_t id)
{
- // Tag to identify tap device -- used on some OSes like Windows
- char tag[32];
- Utils::snprintf(tag,sizeof(tag),"%.16llx",(unsigned long long)id);
-
- // We construct Network via a static method to ensure that it is immediately
- // wrapped in a SharedPtr<>. Otherwise if there is traffic on the Ethernet
- // tap device, a SharedPtr<> wrap can occur in the Ethernet frame handler
- // that then causes the Network instance to be deleted before it is finished
- // being constructed. C++ edge cases, how I love thee.
+ /* We construct Network via a static method to ensure that it is immediately
+ * wrapped in a SharedPtr<>. Otherwise if there is traffic on the Ethernet
+ * tap device, a SharedPtr<> wrap can occur in the Ethernet frame handler
+ * that then causes the Network instance to be deleted before it is finished
+ * being constructed. C++ edge cases, how I love thee. */
+
SharedPtr<Network> nw(new Network());
nw->_id = id;
- nw->_ready = false; // disable handling of Ethernet frames during construct
+ nw->_mac = renv->identity.address().toMAC();
nw->_r = renv;
- nw->_tap = new EthernetTap(renv,tag,renv->identity.address().toMAC(),ZT_IF_MTU,&_CBhandleTapData,nw.ptr());
+ nw->_tap = (EthernetTap *)0;
nw->_lastConfigUpdate = 0;
- nw->_status = NETWORK_WAITING_FOR_FIRST_AUTOCONF;
nw->_destroyOnDelete = false;
+ nw->_netconfFailure = NETCONF_FAILURE_NONE;
+
if (nw->controller() == renv->identity.address()) // netconf masters can't really join networks
throw std::runtime_error("cannot join a network for which I am the netconf master");
- nw->_restoreState();
- nw->_ready = true; // enable handling of Ethernet frames
- nw->requestConfiguration();
+
+ nw->_setupThread = Thread::start<Network>(nw.ptr());
return nw;
}
-void Network::setConfiguration(const Dictionary &conf,bool saveToDisk)
+bool Network::setConfiguration(const Dictionary &conf,bool saveToDisk)
{
+ Mutex::Lock _l(_lock);
+
+ EthernetTap *t = _tap;
+ if (!t) {
+ TRACE("BUG: setConfiguration() called while tap is null!");
+ return false; // can't accept config in initialization state
+ }
+
try {
SharedPtr<NetworkConfig> newConfig(new NetworkConfig(conf));
if ((newConfig->networkId() == _id)&&(newConfig->issuedTo() == _r->identity.address())) {
- Mutex::Lock _l(_lock);
_config = newConfig;
if (newConfig->staticIps().size())
- _tap->setIps(newConfig->staticIps());
- _tap->setDisplayName((std::string("ZeroTier One [") + newConfig->name() + "]").c_str());
+ t->setIps(newConfig->staticIps());
+ t->setDisplayName((std::string("ZeroTier One [") + newConfig->name() + "]").c_str());
_lastConfigUpdate = Utils::now();
- _status = NETWORK_OK;
+ _netconfFailure = NETCONF_FAILURE_NONE;
if (saveToDisk) {
std::string confPath(_r->homePath + ZT_PATH_SEPARATOR_S + "networks.d" + ZT_PATH_SEPARATOR_S + idString() + ".conf");
@@ -122,6 +129,8 @@ void Network::setConfiguration(const Dictionary &conf,bool saveToDisk)
Utils::lockDownFile(confPath.c_str(),false);
}
}
+
+ return true;
} else {
LOG("ignored invalid configuration for network %.16llx (configuration contains mismatched network ID or issued-to address)",(unsigned long long)_id);
}
@@ -130,10 +139,15 @@ void Network::setConfiguration(const Dictionary &conf,bool saveToDisk)
} catch ( ... ) {
LOG("ignored invalid configuration for network %.16llx (unknown exception)",(unsigned long long)_id);
}
+
+ return false;
}
void Network::requestConfiguration()
{
+ if (!_tap)
+ return; // don't bother requesting until we are initialized
+
if (controller() == _r->identity.address()) {
// netconf master cannot be a member of its own nets
LOG("unable to request network configuration for network %.16llx: I am the network master, cannot query self",(unsigned long long)_id);
@@ -190,6 +204,7 @@ bool Network::isAllowed(const Address &peer) const
void Network::clean()
{
Mutex::Lock _l(_lock);
+
if ((_config)&&(_config->isOpen())) {
// Open (public) networks do not track certs or cert pushes at all.
_membershipCertificates.clear();
@@ -215,7 +230,7 @@ void Network::clean()
void Network::_CBhandleTapData(void *arg,const MAC &from,const MAC &to,unsigned int etherType,const Buffer<4096> &data)
{
- if (!((Network *)arg)->isUp())
+ if (((Network *)arg)->status() != NETWORK_OK)
return;
const RuntimeEnvironment *_r = ((Network *)arg)->_r;
@@ -250,6 +265,31 @@ void Network::_pushMembershipCertificate(const Address &peer,bool force,uint64_t
}
}
+void Network::threadMain()
+{
+ try {
+ // Setup thread -- this exits when tap is constructed. It's here
+ // because opening the tap can take some time on some platforms.
+ char tag[32];
+ Utils::snprintf(tag,sizeof(tag),"%.16llx",(unsigned long long)_id);
+ _tap = new EthernetTap(_r,tag,_mac,ZT_IF_MTU,&_CBhandleTapData,this);
+ } catch (std::exception &exc) {
+ LOG("network %.16llx failed to initialize: %s",_id,exc.what());
+ _netconfFailure = NETCONF_FAILURE_INIT_FAILED;
+ } catch ( ... ) {
+ LOG("network %.16llx failed to initialize: unknown error",_id);
+ _netconfFailure = NETCONF_FAILURE_INIT_FAILED;
+ }
+
+ try {
+ _restoreState();
+ requestConfiguration();
+ } catch ( ... ) {
+ TRACE("BUG: exception in network setup thread in _restoreState() or requestConfiguration()!");
+ _lastConfigUpdate = 0; // call requestConfiguration() again
+ }
+}
+
void Network::_restoreState()
{
if (!_id)
diff --git a/node/Network.hpp b/node/Network.hpp
index f41e7502..af51e368 100644
--- a/node/Network.hpp
+++ b/node/Network.hpp
@@ -53,6 +53,7 @@
#include "BandwidthAccount.hpp"
#include "NetworkConfig.hpp"
#include "CertificateOfMembership.hpp"
+#include "Thread.hpp"
namespace ZeroTier {
@@ -91,6 +92,9 @@ private:
* If there is no saved state, a dummy .conf is created on disk to remember
* this network across restarts.
*
+ * This can be a time consuming operation on some platforms (cough Windows
+ * cough).
+ *
* @param renv Runtime environment
* @param id Network ID
* @return Reference counted pointer to new network
@@ -109,10 +113,12 @@ public:
*/
enum Status
{
+ NETWORK_INITIALIZING,
NETWORK_WAITING_FOR_FIRST_AUTOCONF,
NETWORK_OK,
NETWORK_ACCESS_DENIED,
- NETWORK_NOT_FOUND
+ NETWORK_NOT_FOUND,
+ NETWORK_INITIALIZATION_FAILED
};
/**
@@ -128,11 +134,6 @@ public:
inline uint64_t id() const throw() { return _id; }
/**
- * @return Ethernet tap
- */
- inline EthernetTap &tap() throw() { return *_tap; }
-
- /**
* @return Address of network's controlling node
*/
inline Address controller() throw() { return Address(_id >> 24); }
@@ -155,7 +156,10 @@ public:
inline bool updateMulticastGroups()
{
Mutex::Lock _l(_lock);
- return _tap->updateMulticastGroups(_multicastGroups);
+ EthernetTap *t = _tap;
+ if (t)
+ return _tap->updateMulticastGroups(_multicastGroups);
+ return false;
}
/**
@@ -173,10 +177,34 @@ public:
* This is called by PacketDecoder when an update comes over the wire, or
* internally when an old config is reloaded from disk.
*
+ * This also cancels any netconf failure flags.
+ *
+ * The network can't accept configuration when in INITIALIZATION state,
+ * and so in that state this will just return false.
+ *
* @param conf Configuration in key/value dictionary form
* @param saveToDisk IF true (default), write config to disk
+ * @return True if configuration was accepted
+ */
+ bool setConfiguration(const Dictionary &conf,bool saveToDisk = true);
+
+ /**
+ * Set netconf failure to 'access denied'.
*/
- void setConfiguration(const Dictionary &conf,bool saveToDisk = true);
+ inline void setAccessDenied()
+ {
+ Mutex::Lock _l(_lock);
+ _netconfFailure = NETCONF_FAILURE_ACCESS_DENIED;
+ }
+
+ /**
+ * Set netconf failure to 'not found'.
+ */
+ inline void setNotFound()
+ {
+ Mutex::Lock _l(_lock);
+ _netconfFailure = NETCONF_FAILURE_NOT_FOUND;
+ }
/**
* Causes this network to request an updated configuration from its master node now
@@ -223,16 +251,6 @@ public:
*/
inline uint64_t lastConfigUpdate() const throw() { return _lastConfigUpdate; }
- /**
- * Force this network's status to a particular state based on config reply
- */
- inline void forceStatusTo(const Status s)
- throw()
- {
- Mutex::Lock _l(_lock);
- _status = s;
- }
-
/**
* @return Status of this network
*/
@@ -240,17 +258,20 @@ public:
throw()
{
Mutex::Lock _l(_lock);
- return _status;
- }
-
- /**
- * @return True if this network is in "OK" status and can accept traffic from us
- */
- inline bool isUp() const
- throw()
- {
- Mutex::Lock _l(_lock);
- return ((_config)&&(_status == NETWORK_OK)&&(_ready));
+ if (_tap) {
+ switch(_netconfFailure) {
+ case NETCONF_FAILURE_ACCESS_DENIED:
+ return NETWORK_ACCESS_DENIED;
+ case NETCONF_FAILURE_NOT_FOUND:
+ return NETWORK_NOT_FOUND;
+ case NETCONF_FAILURE_NONE:
+ if (_lastConfigUpdate > 0)
+ return NETWORK_OK;
+ else return NETWORK_WAITING_FOR_FIRST_AUTOCONF;
+ }
+ } else if (_netconfFailure == NETCONF_FAILURE_INIT_FAILED)
+ return NETWORK_INITIALIZATION_FAILED;
+ else return NETWORK_INITIALIZING;
}
/**
@@ -307,6 +328,73 @@ public:
return _config;
}
+ /**
+ * Thread main method; do not call elsewhere
+ */
+ void threadMain()
+ throw();
+
+ /**
+ * Inject a frame into tap (if it's created)
+ *
+ * @param from Origin MAC
+ * @param to Destination MC
+ * @param etherType Ethernet frame type
+ * @param data Frame data
+ * @param len Frame length
+ */
+ inline void tapPut(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len)
+ {
+ EthernetTap *t = _tap;
+ if (t)
+ t->put(from,to,etherType,data,len);
+ }
+
+ /**
+ * Inject a frame into tap with local MAC as destination MAC (if it's created)
+ *
+ * @param from Origin MAC
+ * @param etherType Ethernet frame type
+ * @param data Frame data
+ * @param len Frame length
+ */
+ inline void tapPut(const MAC &from,unsigned int etherType,const void *data,unsigned int len)
+ {
+ EthernetTap *t = _tap;
+ if (t)
+ t->put(from,t->mac(),etherType,data,len);
+ }
+
+ /**
+ * @return Tap device name or empty string if still initializing
+ */
+ inline std::string tapDeviceName() const
+ {
+ EthernetTap *t = _tap;
+ if (t)
+ return t->deviceName();
+ else return std::string();
+ }
+
+ /**
+ * @return Ethernet MAC address for this network's local interface
+ */
+ inline const MAC &mac() const
+ {
+ return _mac;
+ }
+
+ /**
+ * @return Set of currently assigned IP addresses
+ */
+ inline std::set<InetAddress> ips() const
+ {
+ EthernetTap *t = _tap;
+ if (t)
+ return t->ips();
+ return std::set<InetAddress>();
+ }
+
private:
static void _CBhandleTapData(void *arg,const MAC &from,const MAC &to,unsigned int etherType,const Buffer<4096> &data);
@@ -315,22 +403,23 @@ private:
void _dumpMulticastCerts();
uint64_t _id;
-
+ MAC _mac;
const RuntimeEnvironment *_r;
-
- EthernetTap *_tap;
+ EthernetTap *volatile _tap;
std::set<MulticastGroup> _multicastGroups;
-
std::map< std::pair<Address,MulticastGroup>,BandwidthAccount > _multicastRateAccounts;
std::map<Address,CertificateOfMembership> _membershipCertificates;
std::map<Address,uint64_t> _lastPushedMembershipCertificate;
SharedPtr<NetworkConfig> _config;
-
volatile uint64_t _lastConfigUpdate;
- volatile Status _status;
volatile bool _destroyOnDelete;
- volatile bool _ready;
-
+ volatile enum {
+ NETCONF_FAILURE_NONE,
+ NETCONF_FAILURE_ACCESS_DENIED,
+ NETCONF_FAILURE_NOT_FOUND,
+ NETCONF_FAILURE_INIT_FAILED
+ } _netconfFailure;
+ Thread _setupThread;
Mutex _lock;
AtomicCounter __refCount;
diff --git a/node/Node.cpp b/node/Node.cpp
index 71f3e087..b1c7e820 100644
--- a/node/Node.cpp
+++ b/node/Node.cpp
@@ -545,7 +545,6 @@ Node::ReasonForTermination Node::run()
LOG("netconf fingerprint change: %.16llx != %.16llx, resyncing with network",networkConfigurationFingerprint,fp);
networkConfigurationFingerprint = fp;
resynchronize = true;
- _r->nc->whackAllTaps(); // call whack() on all tap devices -- hack, might go away
}
}
diff --git a/node/NodeConfig.cpp b/node/NodeConfig.cpp
index eb0802a4..acdcd49d 100644
--- a/node/NodeConfig.cpp
+++ b/node/NodeConfig.cpp
@@ -115,14 +115,6 @@ NodeConfig::~NodeConfig()
{
}
-void NodeConfig::whackAllTaps()
-{
- std::vector< SharedPtr<Network> > nwlist;
- Mutex::Lock _l(_networks_m);
- for(std::map< uint64_t,SharedPtr<Network> >::const_iterator n(_networks.begin());n!=_networks.end();++n)
- n->second->tap().whack();
-}
-
void NodeConfig::clean()
{
Mutex::Lock _l(_networks_m);
@@ -205,7 +197,7 @@ std::vector<std::string> NodeConfig::execute(const char *command)
_P("200 listnetworks <nwid> <name> <status> <config age> <type> <dev> <ips>");
for(std::map< uint64_t,SharedPtr<Network> >::const_iterator nw(_networks.begin());nw!=_networks.end();++nw) {
std::string tmp;
- std::set<InetAddress> ips(nw->second->tap().ips());
+ std::set<InetAddress> ips(nw->second->ips());
for(std::set<InetAddress>::iterator i(ips.begin());i!=ips.end();++i) {
if (tmp.length())
tmp.push_back(',');
@@ -219,13 +211,14 @@ std::vector<std::string> NodeConfig::execute(const char *command)
age = 0;
age /= 1000;
+ std::string dn(nw->second->tapDeviceName());
_P("200 listnetworks %.16llx %s %s %lld %s %s %s",
(unsigned long long)nw->first,
((nconf) ? nconf->name().c_str() : "?"),
Network::statusString(nw->second->status()),
age,
((nconf) ? (nconf->isOpen() ? "public" : "private") : "?"),
- nw->second->tap().deviceName().c_str(),
+ (dn.length() > 0) ? dn.c_str() : "?",
((tmp.length() > 0) ? tmp.c_str() : "-"));
}
} else if (cmd[0] == "join") {
diff --git a/node/NodeConfig.hpp b/node/NodeConfig.hpp
index 2612cf6a..b26d180b 100644
--- a/node/NodeConfig.hpp
+++ b/node/NodeConfig.hpp
@@ -91,11 +91,6 @@ public:
}
/**
- * Call whack() on all networks' tap devices
- */
- void whackAllTaps();
-
- /**
* Perform cleanup and possibly update saved state
*/
void clean();
@@ -117,8 +112,11 @@ public:
{
std::set<std::string> tapDevs;
Mutex::Lock _l(_networks_m);
- for(std::map< uint64_t,SharedPtr<Network> >::const_iterator n(_networks.begin());n!=_networks.end();++n)
- tapDevs.insert(n->second->tap().deviceName());
+ for(std::map< uint64_t,SharedPtr<Network> >::const_iterator n(_networks.begin());n!=_networks.end();++n) {
+ std::string dn(n->second->tapDeviceName());
+ if (dn.length())
+ tapDevs.insert(dn);
+ }
return tapDevs;
}
diff --git a/node/PacketDecoder.cpp b/node/PacketDecoder.cpp
index 4869bca5..410e273e 100644
--- a/node/PacketDecoder.cpp
+++ b/node/PacketDecoder.cpp
@@ -139,7 +139,7 @@ bool PacketDecoder::_doERROR(const RuntimeEnvironment *_r,const SharedPtr<Peer>
} else if (inReVerb == Packet::VERB_NETWORK_CONFIG_REQUEST) {
SharedPtr<Network> network(_r->nc->network(at<uint64_t>(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD)));
if ((network)&&(network->controller() == source()))
- network->forceStatusTo(Network::NETWORK_NOT_FOUND);
+ network->setNotFound();
}
break;
case Packet::ERROR_IDENTITY_COLLISION:
@@ -154,7 +154,7 @@ bool PacketDecoder::_doERROR(const RuntimeEnvironment *_r,const SharedPtr<Peer>
case Packet::ERROR_NETWORK_ACCESS_DENIED_: {
SharedPtr<Network> network(_r->nc->network(at<uint64_t>(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD)));
if ((network)&&(network->controller() == source()))
- network->forceStatusTo(Network::NETWORK_ACCESS_DENIED);
+ network->setAccessDenied();
} break;
default:
break;
@@ -416,7 +416,7 @@ bool PacketDecoder::_doFRAME(const RuntimeEnvironment *_r,const SharedPtr<Peer>
unsigned int etherType = at<uint16_t>(ZT_PROTO_VERB_FRAME_IDX_ETHERTYPE);
if (size() > ZT_PROTO_VERB_FRAME_IDX_PAYLOAD) {
if (network->config()->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);
+ network->tapPut(source().toMAC(),etherType,data() + ZT_PROTO_VERB_FRAME_IDX_PAYLOAD,size() - ZT_PROTO_VERB_FRAME_IDX_PAYLOAD);
} else {
TRACE("dropped FRAME from %s: ethernet type %u not allowed on network %.16llx",source().toString().c_str(),etherType,(unsigned long long)network->id());
return true;
@@ -677,7 +677,7 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared
TRACE("dropped MULTICAST_FRAME from %s(%s): rate limits exceeded for sender %s",source().toString().c_str(),_remoteAddress.toString().c_str(),origin.toString().c_str());
return true;
} else {
- network->tap().put(sourceMac,dest.mac(),etherType,frame,frameLen);
+ network->tapPut(sourceMac,dest.mac(),etherType,frame,frameLen);
}
}
}
diff --git a/node/Switch.cpp b/node/Switch.cpp
index 5473402d..cf3580df 100644
--- a/node/Switch.cpp
+++ b/node/Switch.cpp
@@ -86,12 +86,11 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
if (!nconf)
return;
- if (to == network->tap().mac()) {
- LOG("%s: frame received from self, ignoring (bridge loop? OS bug?)",network->tap().deviceName().c_str());
+ if (to == network->mac()) {
+ LOG("%s: frame received from self, ignoring (bridge loop? OS bug?)",network->tapDeviceName().c_str());
return;
}
-
- if (from != network->tap().mac()) {
+ if (from != network->mac()) {
LOG("ignored tap: %s -> %s %s (bridging not supported)",from.toString().c_str(),to.toString().c_str(),etherTypeName(etherType));
return;
}