diff options
-rw-r--r-- | node/Network.cpp | 35 | ||||
-rw-r--r-- | node/Network.hpp | 62 | ||||
-rw-r--r-- | node/Packet.cpp | 3 | ||||
-rw-r--r-- | node/Packet.hpp | 5 | ||||
-rw-r--r-- | node/Switch.cpp | 2 | ||||
-rw-r--r-- | node/Topology.cpp | 6 |
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(); |