summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--node/Network.cpp35
-rw-r--r--node/Network.hpp62
-rw-r--r--node/Packet.cpp3
-rw-r--r--node/Packet.hpp5
-rw-r--r--node/Switch.cpp2
-rw-r--r--node/Topology.cpp6
6 files changed, 95 insertions, 18 deletions
diff --git a/node/Network.cpp b/node/Network.cpp
index 696426e4..5878a281 100644
--- a/node/Network.cpp
+++ b/node/Network.cpp
@@ -103,8 +103,7 @@ Network::Network(const RuntimeEnvironment *renv,uint64_t id)
throw(std::runtime_error) :
_r(renv),
_tap(renv,renv->identity.address().toMAC(),ZT_IF_MTU,&_CBhandleTapData,this),
- _id(id),
- _isOpen(false)
+ _id(id)
{
}
@@ -114,12 +113,44 @@ Network::~Network()
void Network::setConfiguration(const Network::Config &conf)
{
+ Mutex::Lock _l(_lock);
+ _configuration = conf;
+ _myCertificate = conf.certificateOfMembership();
}
void Network::requestConfiguration()
{
}
+bool Network::isAllowed(const Address &peer) const
+{
+ try {
+ Mutex::Lock _l(_lock);
+ if (_configuration.isOpen())
+ return true;
+ std::map<Address,Certificate>::const_iterator pc(_membershipCertificates.find(peer));
+ if (pc == _membershipCertificates.end())
+ return false;
+ return _myCertificate.qualifyMembership(pc->second);
+ } catch (std::exception &exc) {
+ TRACE("isAllowed() check failed for peer %s: unexpected exception: %s",peer.toString().c_str(),exc.what());
+ return false;
+ } catch ( ... ) {
+ TRACE("isAllowed() check failed for peer %s: unexpected exception: unknown exception",peer.toString().c_str());
+ return false;
+ }
+}
+
+void Network::clean()
+{
+ Mutex::Lock _l(_lock);
+ for(std::map<Address,Certificate>::iterator i=(_membershipCertificates.begin());i!=_membershipCertificates.end();) {
+ if (_myCertificate.qualifyMembership(i->second))
+ ++i;
+ else _membershipCertificates.erase(i++);
+ }
+}
+
void Network::_CBhandleTapData(void *arg,const MAC &from,const MAC &to,unsigned int etherType,const Buffer<4096> &data)
{
const RuntimeEnvironment *_r = ((Network *)arg)->_r;
diff --git a/node/Network.hpp b/node/Network.hpp
index c13f00a4..e553cd3a 100644
--- a/node/Network.hpp
+++ b/node/Network.hpp
@@ -208,6 +208,30 @@ public:
{
}
+ inline void setNetworkId(uint64_t id)
+ {
+ char buf[32];
+ sprintf(buf,"%llu",id);
+ (*this)["nwid"] = buf;
+ }
+
+ inline uint64_t networkId() const
+ throw(std::invalid_argument)
+ {
+ return strtoull(get("nwid").c_str(),(char **)0,10);
+ }
+
+ inline void setPeerAddress(Address &a)
+ {
+ (*this)["peer"] = a.toString();
+ }
+
+ inline Address peerAddress() const
+ throw(std::invalid_argument)
+ {
+ return Address(get("peer"));
+ }
+
/**
* @return Certificate of membership for this network, or empty cert if none
*/
@@ -221,7 +245,7 @@ public:
*/
inline bool isOpen() const
{
- return (get("isOpen","0") == "1");
+ return (get("isOpen") == "1");
}
/**
@@ -304,8 +328,12 @@ public:
inline bool isOpen() const
throw()
{
- Mutex::Lock _l(_lock);
- return _isOpen;
+ try {
+ Mutex::Lock _l(_lock);
+ return _configuration.isOpen();
+ } catch ( ... ) {
+ return false;
+ }
}
/**
@@ -343,6 +371,27 @@ public:
*/
void requestConfiguration();
+ /**
+ * Add or update a peer's membership certificate
+ *
+ * The certificate must already have been validated via signature checking.
+ *
+ * @param peer Peer that owns certificate
+ * @param cert Certificate itself
+ */
+ inline void addMembershipCertificate(const Address &peer,const Certificate &cert)
+ {
+ Mutex::Lock _l(_lock);
+ _membershipCertificates[peer] = cert;
+ }
+
+ bool isAllowed(const Address &peer) const;
+
+ /**
+ * Perform periodic database cleaning such as removing expired membership certificates
+ */
+ void clean();
+
private:
static void _CBhandleTapData(void *arg,const MAC &from,const MAC &to,unsigned int etherType,const Buffer<4096> &data);
@@ -350,10 +399,11 @@ private:
EthernetTap _tap;
std::set<MulticastGroup> _multicastGroups;
-
+ std::map<Address,Certificate> _membershipCertificates;
+ Config _configuration;
+ Certificate _myCertificate;
+ uint64_t _lastCertificateUpdate;
uint64_t _id;
- bool _isOpen;
-
Mutex _lock;
AtomicCounter __refCount;
diff --git a/node/Packet.cpp b/node/Packet.cpp
index 0aae1e2d..94d9164b 100644
--- a/node/Packet.cpp
+++ b/node/Packet.cpp
@@ -60,8 +60,7 @@ const char *Packet::errorString(ErrorCode e)
case ERROR_IDENTITY_COLLISION: return "IDENTITY_COLLISION";
case ERROR_IDENTITY_INVALID: return "IDENTITY_INVALID";
case ERROR_UNSUPPORTED_OPERATION: return "UNSUPPORTED_OPERATION";
- case ERROR_NO_MEMBER_CERTIFICATE_ON_FILE: return "NO_MEMBER_CERTIFICATE_ON_FILE";
- case ERROR_MEMBER_CERTIFICATE_UNQUALIFIED: return "MEMBER_CERTIFICATE_UNQUALIFIED";
+ case ERROR_NO_MEMBER_CERTIFICATE: return "NO_MEMBER_CERTIFICATE";
}
return "(unknown)";
}
diff --git a/node/Packet.hpp b/node/Packet.hpp
index 85ccb466..41acf512 100644
--- a/node/Packet.hpp
+++ b/node/Packet.hpp
@@ -537,10 +537,7 @@ public:
ERROR_UNSUPPORTED_OPERATION = 6,
/* Message to private network rejected -- no unexpired certificate on file */
- ERROR_NO_MEMBER_CERTIFICATE_ON_FILE = 7,
-
- /* Membership certificate no longer qualified for membership in network */
- ERROR_MEMBER_CERTIFICATE_UNQUALIFIED = 8
+ ERROR_NO_MEMBER_CERTIFICATE = 7
};
/**
diff --git a/node/Switch.cpp b/node/Switch.cpp
index 1af5e41e..bb10b412 100644
--- a/node/Switch.cpp
+++ b/node/Switch.cpp
@@ -386,7 +386,7 @@ void Switch::announceMulticastGroups(const std::map< SharedPtr<Network>,std::set
Packet outp((*p)->address(),_r->identity.address(),Packet::VERB_MULTICAST_LIKE);
for(std::map< SharedPtr<Network>,std::set<MulticastGroup> >::const_iterator nwmgs(allMemberships.begin());nwmgs!=allMemberships.end();++nwmgs) {
- if ((nwmgs->first->open())||(_r->topology->isSupernode((*p)->address()))||(nwmgs->first->isMember((*p)->address()))) {
+ if ((_r->topology->isSupernode((*p)->address()))||(nwmgs->first->isAllowed((*p)->address()))) {
for(std::set<MulticastGroup>::iterator mg(nwmgs->second.begin());mg!=nwmgs->second.end();++mg) {
if ((outp.size() + 18) > ZT_UDP_DEFAULT_PAYLOAD_MTU) {
send(outp,true);
diff --git a/node/Topology.cpp b/node/Topology.cpp
index 7d770930..8487684e 100644
--- a/node/Topology.cpp
+++ b/node/Topology.cpp
@@ -133,7 +133,7 @@ SharedPtr<Peer> Topology::getPeer(const Address &zta)
}
unsigned char ztatmp[ZT_ADDRESS_LENGTH];
- zta.copyTo(ztatmp);
+ zta.copyTo(ztatmp,ZT_ADDRESS_LENGTH);
Buffer<ZT_KISSDB_VALUE_SIZE> b(ZT_KISSDB_VALUE_SIZE);
_dbm_m.lock();
@@ -309,7 +309,7 @@ void Topology::main()
if (p->second->getAndResetDirty()) {
try {
uint64_t atmp[ZT_ADDRESS_LENGTH];
- p->second->identity().address().copyTo(atmp);
+ p->second->identity().address().copyTo(atmp,ZT_ADDRESS_LENGTH);
Buffer<ZT_PEER_MAX_SERIALIZED_LENGTH> b;
p->second->serialize(b);
b.zeroUnused();
@@ -340,7 +340,7 @@ void Topology::_reallyAddPeer(const SharedPtr<Peer> &p)
}
try {
uint64_t atmp[ZT_ADDRESS_LENGTH];
- p->address().copyTo(atmp);
+ p->address().copyTo(atmp,ZT_ADDRESS_LENGTH);
Buffer<ZT_PEER_MAX_SERIALIZED_LENGTH> b;
p->serialize(b);
b.zeroUnused();