diff options
Diffstat (limited to 'node')
-rw-r--r-- | node/CertificateOfMembership.cpp | 3 | ||||
-rw-r--r-- | node/IncomingPacket.cpp | 12 | ||||
-rw-r--r-- | node/Membership.hpp | 5 | ||||
-rw-r--r-- | node/Network.cpp | 69 | ||||
-rw-r--r-- | node/Topology.hpp | 8 |
5 files changed, 58 insertions, 39 deletions
diff --git a/node/CertificateOfMembership.cpp b/node/CertificateOfMembership.cpp index 7b99f2c7..0c36aa45 100644 --- a/node/CertificateOfMembership.cpp +++ b/node/CertificateOfMembership.cpp @@ -155,6 +155,9 @@ bool CertificateOfMembership::agreesWith(const CertificateOfMembership &other) c unsigned int myidx = 0; unsigned int otheridx = 0; + if ((_qualifierCount == 0)||(other._qualifierCount == 0)) + return false; + while (myidx < _qualifierCount) { // Fail if we're at the end of other, since this means the field is // missing. diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index c7e6e439..029570f1 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -446,7 +446,7 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &p if ((flags & 0x01) != 0) { // deprecated but still used by older peers CertificateOfMembership com; offset += com.deserialize(*this,ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_COM_AND_GATHER_RESULTS); - LockingPtr<Membership> m = peer->membership(com.networkId(),true); + LockingPtr<Membership> m(peer->membership(com.networkId(),true)); if (m) m->addCredential(RR,RR->node->now(),com); } @@ -586,7 +586,7 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,const SharedPtr<P if ((flags & 0x01) != 0) { // deprecated but still used by old peers CertificateOfMembership com; comLen = com.deserialize(*this,ZT_PROTO_VERB_EXT_FRAME_IDX_COM); - LockingPtr<Membership> m = peer->membership(com.networkId(),true); + LockingPtr<Membership> m(peer->membership(com.networkId(),true)); if (m) m->addCredential(RR,RR->node->now(),com); } @@ -707,7 +707,7 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const S unsigned int p = ZT_PACKET_IDX_PAYLOAD; while ((p < size())&&((*this)[p])) { p += com.deserialize(*this,p); - LockingPtr<Membership> m = peer->membership(com.networkId(),true); + LockingPtr<Membership> m(peer->membership(com.networkId(),true)); if (!m) return true; // sanity check if (m->addCredential(RR,now,com) == 1) return false; // wait for WHOIS } @@ -717,7 +717,7 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const S const unsigned int numCapabilities = at<uint16_t>(p); p += 2; for(unsigned int i=0;i<numCapabilities;++i) { p += cap.deserialize(*this,p); - LockingPtr<Membership> m = peer->membership(cap.networkId(),true); + LockingPtr<Membership> m(peer->membership(cap.networkId(),true)); if (!m) return true; // sanity check if (m->addCredential(RR,now,cap) == 1) return false; // wait for WHOIS } @@ -725,7 +725,7 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const S const unsigned int numTags = at<uint16_t>(p); p += 2; for(unsigned int i=0;i<numTags;++i) { p += tag.deserialize(*this,p); - LockingPtr<Membership> m = peer->membership(tag.networkId(),true); + LockingPtr<Membership> m(peer->membership(tag.networkId(),true)); if (!m) return true; // sanity check if (m->addCredential(RR,now,tag) == 1) return false; // wait for WHOIS } @@ -868,7 +868,7 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,const Share if ((flags & 0x01) != 0) { // deprecated but still used by older peers CertificateOfMembership com; offset += com.deserialize(*this,ZT_PROTO_VERB_MULTICAST_FRAME_IDX_COM); - LockingPtr<Membership> m = peer->membership(com.networkId(),true); + LockingPtr<Membership> m(peer->membership(com.networkId(),true)); if (m) m->addCredential(RR,RR->node->now(),com); } diff --git a/node/Membership.hpp b/node/Membership.hpp index abfff9e3..0e72b7b1 100644 --- a/node/Membership.hpp +++ b/node/Membership.hpp @@ -115,6 +115,11 @@ public: } /** + * @return This peer's COM if they have sent one + */ + inline const CertificateOfMembership &com() const { return _com; } + + /** * @param nconf Network configuration * @param id Tag ID * @return Pointer to tag or NULL if not found diff --git a/node/Network.cpp b/node/Network.cpp index 061cca07..d9ad7838 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -29,6 +29,7 @@ #include "Buffer.hpp" #include "NetworkController.hpp" #include "Node.hpp" +#include "Peer.hpp" #include "../version.h" @@ -384,17 +385,20 @@ bool Network::_isAllowed(const SharedPtr<Peer> &peer) const { // Assumes _lock is locked try { - if (!_config) - return false; - if (_config.isPublic()) - return true; - return ((_config.com)&&(peer->networkMembershipCertificatesAgree(_id,_config.com))); - } catch (std::exception &exc) { - TRACE("isAllowed() check failed for peer %s: unexpected exception: %s",peer->address().toString().c_str(),exc.what()); + if (_config) { + if (_config.isPublic()) { + return true; + } else { + LockingPtr<Membership> m(peer->membership(_id,false)); + if (m) { + return _config.com.agreesWith(m->com()); + } + } + } } catch ( ... ) { - TRACE("isAllowed() check failed for peer %s: unexpected exception: unknown exception",peer->address().toString().c_str()); + TRACE("isAllowed() check failed for peer %s: unexpected exception: unexpected exception",peer->address().toString().c_str()); } - return false; // default position on any failure + return false; } class _MulticastAnnounceAll @@ -405,13 +409,13 @@ public: _controller(nw->controller()), _network(nw), _anchors(nw->config().anchors()), - _rootAddresses(renv->topology->rootAddresses()) + _upstreamAddresses(renv->topology->upstreamAddresses()) {} inline void operator()(Topology &t,const SharedPtr<Peer> &p) { - if ( (_network->_isAllowed(p)) || // FIXME: this causes multicast LIKEs for public networks to get spammed + if ( (_network->_isAllowed(p)) || // FIXME: this causes multicast LIKEs for public networks to get spammed, which isn't terrible but is a bit stupid (p->address() == _controller) || - (std::find(_rootAddresses.begin(),_rootAddresses.end(),p->address()) != _rootAddresses.end()) || + (std::find(_upstreamAddresses.begin(),_upstreamAddresses.end(),p->address()) != _upstreamAddresses.end()) || (std::find(_anchors.begin(),_anchors.end(),p->address()) != _anchors.end()) ) { peers.push_back(p); } @@ -422,7 +426,7 @@ private: const Address _controller; Network *const _network; const std::vector<Address> _anchors; - const std::vector<Address> _rootAddresses; + const std::vector<Address> _upstreamAddresses; }; void Network::_announceMulticastGroups() { @@ -438,31 +442,30 @@ void Network::_announceMulticastGroupsTo(const SharedPtr<Peer> &peer,const std:: { // 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())&&(peer->needsOurNetworkMembershipCertificate(_id,RR->node->now(),true))) { - Packet outp(peer->address(),RR->identity.address(),Packet::VERB_NETWORK_MEMBERSHIP_CERTIFICATE); - _config.com.serialize(outp); - RR->sw->send(outp,true,0); - } - + // Anyone we announce multicast groups to will need our COM to authenticate GATHER requests. { - Packet outp(peer->address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE); + LockingPtr<Membership> m(peer->membership(_id,false)); + if (m) m->sendCredentialsIfNeeded(RR,RR->node->now(),*peer,_config); + } - 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(peer->address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE); - } + Packet outp(peer->address(),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()); + for(std::vector<MulticastGroup>::const_iterator mg(allMulticastGroups.begin());mg!=allMulticastGroups.end();++mg) { + if ((outp.size() + 24) >= ZT_PROTO_MAX_PACKET_LENGTH) { + outp.compress(); + RR->sw->send(outp,true,0); + outp.reset(peer->address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE); } - if (outp.size() > ZT_PROTO_MIN_PACKET_LENGTH) - RR->sw->send(outp,true,0); + // 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) { + outp.compress(); + RR->sw->send(outp,true,0); } } diff --git a/node/Topology.hpp b/node/Topology.hpp index 03c491e5..b8213cf8 100644 --- a/node/Topology.hpp +++ b/node/Topology.hpp @@ -154,6 +154,14 @@ public: } /** + * @return Vector of active upstream addresses (including roots) + */ + inline std::vector<Address> upstreamAddresses() const + { + return rootAddresses(); + } + + /** * @return Current World (copy) */ inline World world() const |