diff options
| author | Grant Limberg <glimberg@gmail.com> | 2015-11-02 18:32:21 -0800 |
|---|---|---|
| committer | Grant Limberg <glimberg@gmail.com> | 2015-11-02 18:32:21 -0800 |
| commit | 179b064b05460b706526a3249a25cd07232a42f5 (patch) | |
| tree | d26dfeb2c02ce59c4a531142684695e45bb515ad /node/Network.cpp | |
| parent | 75a191a8564030f4d5e99aca76b980e2d69abd20 (diff) | |
| parent | 4e9d4304761f93a1764d3ec2d2b0c38140decad8 (diff) | |
| download | infinitytier-179b064b05460b706526a3249a25cd07232a42f5.tar.gz infinitytier-179b064b05460b706526a3249a25cd07232a42f5.zip | |
Merge branch 'edge' into android-jni-dev
Diffstat (limited to 'node/Network.cpp')
| -rw-r--r-- | node/Network.cpp | 263 |
1 files changed, 89 insertions, 174 deletions
diff --git a/node/Network.cpp b/node/Network.cpp index 2b24d5f9..afbe1074 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -37,6 +37,7 @@ #include "Packet.hpp" #include "Buffer.hpp" #include "NetworkController.hpp" +#include "Node.hpp" #include "../version.h" @@ -59,6 +60,9 @@ Network::Network(const RuntimeEnvironment *renv,uint64_t nwid) : Utils::snprintf(confn,sizeof(confn),"networks.d/%.16llx.conf",_id); Utils::snprintf(mcdbn,sizeof(mcdbn),"networks.d/%.16llx.mcerts",_id); + // These files are no longer used, so clean them. + RR->node->dataStoreDelete(mcdbn); + if (_id == ZT_TEST_NETWORK_ID) { applyConfiguration(NetworkConfig::createTestNetworkConfig(RR->identity.address())); @@ -79,24 +83,6 @@ Network::Network(const RuntimeEnvironment *renv,uint64_t nwid) : // Save a one-byte CR to persist membership while we request a real netconf RR->node->dataStorePut(confn,"\n",1,false); } - - try { - std::string mcdb(RR->node->dataStoreGet(mcdbn)); - if (mcdb.length() > 6) { - const char *p = mcdb.data(); - const char *e = p + mcdb.length(); - if (!memcmp("ZTMCD0",p,6)) { - p += 6; - while (p != e) { - CertificateOfMembership com; - com.deserialize2(p,e); - if (!com) - break; - _certInfo[com.issuedTo()].com = com; - } - } - } - } catch ( ... ) {} // ignore invalid MCDB, we'll re-learn from peers } if (!_portInitialized) { @@ -115,32 +101,10 @@ Network::~Network() char n[128]; if (_destroyed) { RR->node->configureVirtualNetworkPort(_id,ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY,&ctmp); - Utils::snprintf(n,sizeof(n),"networks.d/%.16llx.conf",_id); RR->node->dataStoreDelete(n); - Utils::snprintf(n,sizeof(n),"networks.d/%.16llx.mcerts",_id); - RR->node->dataStoreDelete(n); } else { RR->node->configureVirtualNetworkPort(_id,ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DOWN,&ctmp); - - clean(); - - Utils::snprintf(n,sizeof(n),"networks.d/%.16llx.mcerts",_id); - - Mutex::Lock _l(_lock); - if ((!_config)||(_config->isPublic())||(_certInfo.empty())) { - RR->node->dataStoreDelete(n); - } else { - std::string buf("ZTMCD0"); - Hashtable< Address,_RemoteMemberCertificateInfo >::Iterator i(_certInfo); - Address *a = (Address *)0; - _RemoteMemberCertificateInfo *ci = (_RemoteMemberCertificateInfo *)0; - while (i.next(a,ci)) { - if (ci->com) - ci->com.serialize2(buf); - } - RR->node->dataStorePut(n,buf,true); - } } } @@ -178,6 +142,20 @@ void Network::multicastUnsubscribe(const MulticastGroup &mg) _myMulticastGroups.swap(nmg); } +bool Network::tryAnnounceMulticastGroupsTo(const SharedPtr<Peer> &peer) +{ + Mutex::Lock _l(_lock); + if ( + (_isAllowed(peer)) || + (peer->address() == this->controller()) || + (RR->topology->isRoot(peer->identity())) + ) { + _announceMulticastGroupsTo(peer->address(),_allMulticastGroups()); + return true; + } + return false; +} + bool Network::applyConfiguration(const SharedPtr<NetworkConfig> &conf) { if (_destroyed) // sanity check @@ -281,70 +259,6 @@ void Network::requestConfiguration() RR->sw->send(outp,true,0); } -bool Network::validateAndAddMembershipCertificate(const CertificateOfMembership &cert) -{ - if (!cert) // sanity check - return false; - - Mutex::Lock _l(_lock); - - { - const _RemoteMemberCertificateInfo *ci = _certInfo.get(cert.issuedTo()); - if ((ci)&&(ci->com == cert)) - return true; // we already have it - } - - // Check signature, log and return if cert is invalid - if (cert.signedBy() != controller()) { - TRACE("rejected network membership certificate for %.16llx signed by %s: signer not a controller of this network",(unsigned long long)_id,cert.signedBy().toString().c_str()); - return false; // invalid signer - } - - if (cert.signedBy() == RR->identity.address()) { - - // We are the controller: RR->identity.address() == controller() == cert.signedBy() - // So, verify that we signed th cert ourself - if (!cert.verify(RR->identity)) { - TRACE("rejected network membership certificate for %.16llx self signed by %s: signature check failed",(unsigned long long)_id,cert.signedBy().toString().c_str()); - return false; // invalid signature - } - - } else { - - SharedPtr<Peer> signer(RR->topology->getPeer(cert.signedBy())); - - if (!signer) { - // This would be rather odd, since this is our controller... could happen - // if we get packets before we've gotten config. - RR->sw->requestWhois(cert.signedBy()); - return false; // signer unknown - } - - if (!cert.verify(signer->identity())) { - TRACE("rejected network membership certificate for %.16llx signed by %s: signature check failed",(unsigned long long)_id,cert.signedBy().toString().c_str()); - return false; // invalid signature - } - } - - // If we made it past authentication, add or update cert in our cert info store - _certInfo[cert.issuedTo()].com = cert; - - return true; -} - -bool Network::peerNeedsOurMembershipCertificate(const Address &to,uint64_t now) -{ - Mutex::Lock _l(_lock); - if ((_config)&&(!_config->isPublic())&&(_config->com())) { - _RemoteMemberCertificateInfo &ci = _certInfo[to]; - if ((now - ci.lastPushed) > (ZT_NETWORK_AUTOCONF_DELAY / 2)) { - ci.lastPushed = now; - return true; - } - } - return false; -} - void Network::clean() { const uint64_t now = RR->node->now(); @@ -353,22 +267,6 @@ void Network::clean() if (_destroyed) return; - if ((_config)&&(_config->isPublic())) { - // Open (public) networks do not track certs or cert pushes at all. - _certInfo.clear(); - } else if (_config) { - // Clean obsolete entries from private network cert info table - Hashtable< Address,_RemoteMemberCertificateInfo >::Iterator i(_certInfo); - Address *a = (Address *)0; - _RemoteMemberCertificateInfo *ci = (_RemoteMemberCertificateInfo *)0; - const uint64_t forgetIfBefore = now - (ZT_PEER_ACTIVITY_TIMEOUT * 16); // arbitrary reasonable cutoff - while (i.next(a,ci)) { - if ((ci->lastPushed < forgetIfBefore)&&(!ci->com.agreesWith(_config->com()))) - _certInfo.erase(*a); - } - } - - // Clean learned multicast groups if we haven't heard from them in a while { Hashtable< MulticastGroup,uint64_t >::Iterator i(_multicastGroupsBehindMe); MulticastGroup *mg = (MulticastGroup *)0; @@ -494,7 +392,7 @@ void Network::_externalConfig(ZT_VirtualNetworkConfig *ec) const } else ec->assignedAddressCount = 0; } -bool Network::_isAllowed(const Address &peer) const +bool Network::_isAllowed(const SharedPtr<Peer> &peer) const { // Assumes _lock is locked try { @@ -502,82 +400,99 @@ bool Network::_isAllowed(const Address &peer) const return false; if (_config->isPublic()) return true; - const _RemoteMemberCertificateInfo *ci = _certInfo.get(peer); - if (!ci) - return false; - return _config->com().agreesWith(ci->com); + return ((_config->com())&&(peer->networkMembershipCertificatesAgree(_id,_config->com()))); } catch (std::exception &exc) { - TRACE("isAllowed() check failed for peer %s: unexpected exception: %s",peer.toString().c_str(),exc.what()); + TRACE("isAllowed() check failed for peer %s: unexpected exception: %s",peer->address().toString().c_str(),exc.what()); } catch ( ... ) { - TRACE("isAllowed() check failed for peer %s: unexpected exception: unknown exception",peer.toString().c_str()); + TRACE("isAllowed() check failed for peer %s: unexpected exception: unknown exception",peer->address().toString().c_str()); } return false; // default position on any failure } -std::vector<MulticastGroup> Network::_allMulticastGroups() const -{ - // Assumes _lock is locked - std::vector<MulticastGroup> mgs; - mgs.reserve(_myMulticastGroups.size() + _multicastGroupsBehindMe.size() + 1); - mgs.insert(mgs.end(),_myMulticastGroups.begin(),_myMulticastGroups.end()); - _multicastGroupsBehindMe.appendKeys(mgs); - if ((_config)&&(_config->enableBroadcast())) - mgs.push_back(Network::BROADCAST); - std::sort(mgs.begin(),mgs.end()); - mgs.erase(std::unique(mgs.begin(),mgs.end()),mgs.end()); - return mgs; -} - -// Used in Network::_announceMulticastGroups() -class _AnnounceMulticastGroupsToPeersWithActiveDirectPaths +class _GetPeersThatNeedMulticastAnnouncement { public: - _AnnounceMulticastGroupsToPeersWithActiveDirectPaths(const RuntimeEnvironment *renv,Network *nw) : - RR(renv), + _GetPeersThatNeedMulticastAnnouncement(const RuntimeEnvironment *renv,Network *nw) : _now(renv->node->now()), + _controller(nw->controller()), _network(nw), - _rootAddresses(renv->topology->rootAddresses()), - _allMulticastGroups(nw->_allMulticastGroups()) + _rootAddresses(renv->topology->rootAddresses()) {} - inline void operator()(Topology &t,const SharedPtr<Peer> &p) { - if ( ( (p->hasActiveDirectPath(_now)) && ( (_network->_isAllowed(p->address())) || (p->address() == _network->controller()) ) ) || (std::find(_rootAddresses.begin(),_rootAddresses.end(),p->address()) != _rootAddresses.end()) ) { - Packet outp(p->address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE); - - for(std::vector<MulticastGroup>::iterator mg(_allMulticastGroups.begin());mg!=_allMulticastGroups.end();++mg) { - if ((outp.size() + 18) >= ZT_UDP_DEFAULT_PAYLOAD_MTU) { - outp.armor(p->key(),true); - p->send(RR,outp.data(),outp.size(),_now); - outp.reset(p->address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE); - } - - // network ID, MAC, ADI - outp.append((uint64_t)_network->id()); - mg->mac().appendTo(outp); - outp.append((uint32_t)mg->adi()); - } - - if (outp.size() > ZT_PROTO_MIN_PACKET_LENGTH) { - outp.armor(p->key(),true); - p->send(RR,outp.data(),outp.size(),_now); - } + if ( + (_network->_isAllowed(p)) || + (p->address() == _controller) || + (std::find(_rootAddresses.begin(),_rootAddresses.end(),p->address()) != _rootAddresses.end()) + ) { + peers.push_back(p->address()); } } - + std::vector<Address> peers; private: - const RuntimeEnvironment *RR; uint64_t _now; + Address _controller; Network *_network; std::vector<Address> _rootAddresses; - std::vector<MulticastGroup> _allMulticastGroups; }; - void Network::_announceMulticastGroups() { // Assumes _lock is locked - _AnnounceMulticastGroupsToPeersWithActiveDirectPaths afunc(RR,this); - RR->topology->eachPeer<_AnnounceMulticastGroupsToPeersWithActiveDirectPaths &>(afunc); + + _GetPeersThatNeedMulticastAnnouncement gpfunc(RR,this); + RR->topology->eachPeer<_GetPeersThatNeedMulticastAnnouncement &>(gpfunc); + + std::vector<MulticastGroup> allMulticastGroups(_allMulticastGroups()); + for(std::vector<Address>::const_iterator pa(gpfunc.peers.begin());pa!=gpfunc.peers.end();++pa) + _announceMulticastGroupsTo(*pa,allMulticastGroups); +} + +void Network::_announceMulticastGroupsTo(const Address &peerAddress,const std::vector<MulticastGroup> &allMulticastGroups) const +{ + // Assumes _lock is locked + + // We push COMs ahead of MULTICAST_LIKE since they're used for access control -- a COM is a public + // credential so "over-sharing" isn't really an issue (and we only do so with roots). + if ((_config)&&(_config->com())&&(!_config->isPublic())) { + Packet outp(peerAddress,RR->identity.address(),Packet::VERB_NETWORK_MEMBERSHIP_CERTIFICATE); + _config->com().serialize(outp); + RR->sw->send(outp,true,0); + } + + { + Packet outp(peerAddress,RR->identity.address(),Packet::VERB_MULTICAST_LIKE); + + for(std::vector<MulticastGroup>::const_iterator mg(allMulticastGroups.begin());mg!=allMulticastGroups.end();++mg) { + if ((outp.size() + 18) >= ZT_UDP_DEFAULT_PAYLOAD_MTU) { + RR->sw->send(outp,true,0); + outp.reset(peerAddress,RR->identity.address(),Packet::VERB_MULTICAST_LIKE); + } + + // network ID, MAC, ADI + outp.append((uint64_t)_id); + mg->mac().appendTo(outp); + outp.append((uint32_t)mg->adi()); + } + + if (outp.size() > ZT_PROTO_MIN_PACKET_LENGTH) + RR->sw->send(outp,true,0); + } +} + +std::vector<MulticastGroup> Network::_allMulticastGroups() const +{ + // Assumes _lock is locked + + std::vector<MulticastGroup> mgs; + mgs.reserve(_myMulticastGroups.size() + _multicastGroupsBehindMe.size() + 1); + mgs.insert(mgs.end(),_myMulticastGroups.begin(),_myMulticastGroups.end()); + _multicastGroupsBehindMe.appendKeys(mgs); + if ((_config)&&(_config->enableBroadcast())) + mgs.push_back(Network::BROADCAST); + std::sort(mgs.begin(),mgs.end()); + mgs.erase(std::unique(mgs.begin(),mgs.end()),mgs.end()); + + return mgs; } } // namespace ZeroTier |
