diff options
Diffstat (limited to 'node/Network.cpp')
-rw-r--r-- | node/Network.cpp | 126 |
1 files changed, 53 insertions, 73 deletions
diff --git a/node/Network.cpp b/node/Network.cpp index f45d6c2f..43565e9f 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -37,12 +37,8 @@ #include "Switch.hpp" #include "Packet.hpp" #include "Buffer.hpp" - -#ifdef __WINDOWS__ -#include "WindowsEthernetTap.hpp" -#else -#include "UnixEthernetTap.hpp" -#endif +#include "EthernetTap.hpp" +#include "EthernetTapFactory.hpp" #define ZT_NETWORK_CERT_WRITE_BUF_SIZE 131072 @@ -69,26 +65,13 @@ Network::~Network() { Thread::join(_setupThread); -#ifdef __WINDOWS__ - std::string devPersistentId; - if (_tap) { - devPersistentId = _tap->persistentId(); - delete _tap; - } -#else if (_tap) - delete _tap; -#endif + _r->tapFactory->close(_tap,_destroyOnDelete); if (_destroyOnDelete) { Utils::rm(std::string(_r->homePath + ZT_PATH_SEPARATOR_S + "networks.d" + ZT_PATH_SEPARATOR_S + idString() + ".conf")); Utils::rm(std::string(_r->homePath + ZT_PATH_SEPARATOR_S + "networks.d" + ZT_PATH_SEPARATOR_S + idString() + ".mcerts")); -#ifdef __WINDOWS__ - if (devPersistentId.length()) - WindowsEthernetTap::deletePersistentTapDevice(_r,devPersistentId.c_str()); -#endif } else { - // Causes flush of membership certs to disk clean(); _dumpMulticastCerts(); } @@ -113,10 +96,16 @@ SharedPtr<Network> Network::newInstance(const RuntimeEnvironment *renv,NodeConfi nw->_destroyOnDelete = false; nw->_netconfFailure = NETCONF_FAILURE_NONE; - if (nw->controller() == renv->identity.address()) // netconf masters can't really join networks + if (nw->controller() == renv->identity.address()) // TODO: fix Switch to allow packets to self throw std::runtime_error("cannot join a network for which I am the netconf master"); - nw->_setupThread = Thread::start<Network>(nw.ptr()); + try { + nw->_restoreState(); + nw->requestConfiguration(); + } catch ( ... ) { + TRACE("exception in network setup thread in _restoreState() or requestConfiguration()!"); + nw->_lastConfigUpdate = 0; // call requestConfiguration() again + } return nw; } @@ -127,7 +116,7 @@ bool Network::updateMulticastGroups() EthernetTap *t = _tap; if (t) { // Grab current groups from the local tap - bool updated = _tap->updateMulticastGroups(_multicastGroups); + bool updated = t->updateMulticastGroups(_multicastGroups); // Merge in learned groups from any hosts bridged in behind us for(std::map<MulticastGroup,uint64_t>::const_iterator mg(_bridgedMulticastGroups.begin());mg!=_bridgedMulticastGroups.end();++mg) @@ -154,21 +143,11 @@ 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)); + SharedPtr<NetworkConfig> newConfig(new NetworkConfig(conf)); // throws if invalid if ((newConfig->networkId() == _id)&&(newConfig->issuedTo() == _r->identity.address())) { _config = newConfig; - if (newConfig->staticIps().size()) - t->setIps(newConfig->staticIps()); - t->setDisplayName((std::string("ZeroTier One [") + newConfig->name() + "]").c_str()); - _lastConfigUpdate = Utils::now(); _netconfFailure = NETCONF_FAILURE_NONE; @@ -181,6 +160,17 @@ bool Network::setConfiguration(const Dictionary &conf,bool saveToDisk) } } + EthernetTap *t = _tap; + if (t) { + char fname[1024]; + _mkNetworkFriendlyName(fname,sizeof(fname)); + t->setIps(newConfig->staticIps()); + t->setFriendlyName(fname); + } else { + if (!_setupThread) + _setupThread = Thread::start<Network>(this); + } + return true; } else { LOG("ignored invalid configuration for network %.16llx (configuration contains mismatched network ID or issued-to address)",(unsigned long long)_id); @@ -196,9 +186,6 @@ bool Network::setConfiguration(const Dictionary &conf,bool saveToDisk) 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); @@ -346,51 +333,46 @@ void Network::_pushMembershipCertificate(const Address &peer,bool force,uint64_t } } +// Ethernet tap creation thread -- required on some platforms where tap +// creation may be time consuming (e.g. Windows). void Network::threadMain() throw() { - // Setup thread -- this exits when tap is constructed. It's here - // because opening the tap can take some time on some platforms. + char fname[1024],lcentry[128]; + Utils::snprintf(lcentry,sizeof(lcentry),"_dev_for_%.16llx",(unsigned long long)_id); + EthernetTap *t; try { -#ifdef __WINDOWS__ - // Windows tags interfaces by their network IDs, which are shoved into the - // registry to mark persistent instance of the tap device. - char tag[24]; - Utils::snprintf(tag,sizeof(tag),"%.16llx",(unsigned long long)_id); - _tap = new WindowsEthernetTap(_r,tag,_mac,ZT_IF_MTU,&_CBhandleTapData,this); -#else - // Unix tries to get the same device name next time, if possible. - std::string tagstr; - char lcentry[128]; - Utils::snprintf(lcentry,sizeof(lcentry),"_dev_for_%.16llx",(unsigned long long)_id); - tagstr = _nc->getLocalConfig(lcentry); - - const char *tag = (tagstr.length() > 0) ? tagstr.c_str() : (const char *)0; - _tap = new UnixEthernetTap(_r,tag,_mac,ZT_IF_MTU,&_CBhandleTapData,this); - - std::string dn(_tap->deviceName()); - if ((!tag)||(dn != tag)) + std::string desiredDevice(_nc->getLocalConfig(lcentry)); + _mkNetworkFriendlyName(fname,sizeof(fname)); + + t = _r->tapFactory->open(_mac,ZT_IF_MTU,ZT_DEFAULT_IF_METRIC,_id,(desiredDevice.length() > 0) ? desiredDevice.c_str() : (const char *)0,fname,_CBhandleTapData,this); + + std::string dn(t->deviceName()); + if ((dn.length())&&(dn != desiredDevice)) _nc->putLocalConfig(lcentry,dn); -#endif } catch (std::exception &exc) { - delete _tap; - _tap = (EthernetTap *)0; + delete t; + t = (EthernetTap *)0; LOG("network %.16llx failed to initialize: %s",_id,exc.what()); _netconfFailure = NETCONF_FAILURE_INIT_FAILED; } catch ( ... ) { - delete _tap; - _tap = (EthernetTap *)0; + delete t; + t = (EthernetTap *)0; 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 + { + Mutex::Lock _l(_lock); + if (_tap) // the tap creation thread can technically be re-launched, though this isn't done right now + _r->tapFactory->close(_tap,_destroyOnDelete); + _tap = t; + if (t) { + if (_config) + t->setIps(_config->staticIps()); + t->setEnabled(_enabled); + } } } @@ -423,14 +405,12 @@ void Network::setEnabled(bool enabled) { Mutex::Lock _l(_lock); _enabled = enabled; - // TODO: bring OS network device to "down" state if enabled == false + if (_tap) + _tap->setEnabled(enabled); } void Network::_restoreState() { - if (!_id) - return; // sanity check - Buffer<ZT_NETWORK_CERT_WRITE_BUF_SIZE> buf; std::string idstr(idString()); @@ -448,7 +428,7 @@ void Network::_restoreState() } else { // If the conf file isn't present, "touch" it so we'll remember // the existence of this network. - FILE *tmp = fopen(confPath.c_str(),"wb"); + FILE *tmp = fopen(confPath.c_str(),"w"); if (tmp) fclose(tmp); } |