summaryrefslogtreecommitdiff
path: root/node
diff options
context:
space:
mode:
Diffstat (limited to 'node')
-rw-r--r--node/CertificateOfMembership.cpp3
-rw-r--r--node/IncomingPacket.cpp12
-rw-r--r--node/Membership.hpp5
-rw-r--r--node/Network.cpp69
-rw-r--r--node/Topology.hpp8
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