From a53cfc909638ea9eeb2bd477cee20d106f79bf6d Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 29 Jul 2013 13:56:20 -0400 Subject: Network membership certificate work in progress... does not build yet. --- node/Network.cpp | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 83 insertions(+), 4 deletions(-) (limited to 'node/Network.cpp') diff --git a/node/Network.cpp b/node/Network.cpp index f34e07e0..34a9a85b 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -25,19 +25,90 @@ * LLC. Start here: http://www.zerotier.com/ */ +#include +#include + +#include + +#include "RuntimeEnvironment.hpp" +#include "NodeConfig.hpp" #include "Network.hpp" #include "Switch.hpp" namespace ZeroTier { +void Network::Certificate::sign(const Identity &with) +{ + unsigned char dig[32]; + SHA256_CTX sha; + SHA256_Init(&sha); + unsigned char zero = 0; + for(const_iterator i(begin());i!=end();++i) { + if (i->first != "sig") { + SHA256_Update(&sha,&zero,1); + SHA256_Update(&sha,(const unsigned char *)i->first.data(),i->first.length()); + SHA256_Update(&sha,&zero,1); + SHA256_Update(&sha,(const unsigned char *)i->second.data(),i->second.length()); + SHA256_Update(&sha,&zero,1); + } + } + SHA256_Final(dig,&sha); + (*this)["sig"] = with.sign(dig); +} + +static const std::string _DELTA_PREFIX("~"); +bool Network::Certificate::qualifyMembership(const Network::Certificate &mc) const +{ + // Note: optimization probably needed here, probably via some kind of + // memoization / dynamic programming. + + for(const_iterator myField(begin());myField!=end();++myField) { + if (!((myField->first.length() > 1)&&(myField->first[0] == '~'))) { // ~fields are max delta range specs + // If they lack the same field, comparison fails. + const_iterator theirField(mc.find(myField->first)); + if (theirField == mc.end()) + return false; + + const_iterator deltaField(find(_DELTA_PREFIX + myField->first)); + if (deltaField == end()) { + // If there is no delta, compare for equality (e.g. node, nwid) + if (myField->second != theirField->second) + return false; + } else { + // Otherwise compare range with max delta. Presence of a dot in delta + // indicates a floating point comparison. Otherwise an integer + // comparison occurs. + if (deltaField->second.find('.') != std::string::npos) { + double my = strtod(myField->second.c_str(),(char **)0); + double their = strtod(theirField->second.c_str(),(char **)0); + double delta = strtod(deltaField->second.c_str(),(char **)0); + if (fabs(my - their) > delta) + return false; + } else { + int64_t my = strtoll(myField->second.c_str(),(char **)0,10); + int64_t their = strtoll(theirField->second.c_str(),(char **)0,10); + int64_t delta = strtoll(deltaField->second.c_str(),(char **)0,10); + if (my > their) { + if ((my - their) > delta) + return false; + } else { + if ((their - my) > delta) + return false; + } + } + } + } + } + + return true; +} + Network::Network(const RuntimeEnvironment *renv,uint64_t id) throw(std::runtime_error) : _r(renv), - _id(id), _tap(renv,renv->identity.address().toMAC(),ZT_IF_MTU,&_CBhandleTapData,this), - _members(), - _open(false), - _lock() + _id(id), + _isOpen(false) { } @@ -45,6 +116,14 @@ Network::~Network() { } +void Network::setConfiguration(const Network::Config &conf) +{ +} + +void Network::requestConfiguration() +{ +} + void Network::_CBhandleTapData(void *arg,const MAC &from,const MAC &to,unsigned int etherType,const Buffer<4096> &data) { const RuntimeEnvironment *_r = ((Network *)arg)->_r; -- cgit v1.2.3 From 439e602d5a5712d1b33fb19d558d0e9fdf784703 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 29 Jul 2013 16:18:29 -0400 Subject: Fix a bunch of errors due to minor method signature changes, still a work in progress. --- node/Identity.hpp | 2 +- node/Network.cpp | 18 +++++++----------- node/Network.hpp | 32 +++++++++++++++++++++++++++----- node/Packet.cpp | 5 +++-- node/Packet.hpp | 22 +++++++++++----------- node/PacketDecoder.cpp | 16 ++++++++-------- node/PacketDecoder.hpp | 2 +- 7 files changed, 58 insertions(+), 39 deletions(-) (limited to 'node/Network.cpp') diff --git a/node/Identity.hpp b/node/Identity.hpp index e5a11d6a..a9f78c8a 100644 --- a/node/Identity.hpp +++ b/node/Identity.hpp @@ -340,7 +340,7 @@ public: unsigned int p = startAt; - _address = b.field(p,ZT_ADDRESS_LENGTH); + _address.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); p += ZT_ADDRESS_LENGTH; if (b[p++] != IDENTITY_TYPE_NIST_P_521) diff --git a/node/Network.cpp b/node/Network.cpp index 34a9a85b..696426e4 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -37,23 +37,19 @@ namespace ZeroTier { -void Network::Certificate::sign(const Identity &with) +void Network::Certificate::_shaForSignature(unsigned char *dig) const { - unsigned char dig[32]; SHA256_CTX sha; SHA256_Init(&sha); unsigned char zero = 0; for(const_iterator i(begin());i!=end();++i) { - if (i->first != "sig") { - SHA256_Update(&sha,&zero,1); - SHA256_Update(&sha,(const unsigned char *)i->first.data(),i->first.length()); - SHA256_Update(&sha,&zero,1); - SHA256_Update(&sha,(const unsigned char *)i->second.data(),i->second.length()); - SHA256_Update(&sha,&zero,1); - } + SHA256_Update(&sha,&zero,1); + SHA256_Update(&sha,(const unsigned char *)i->first.data(),i->first.length()); + SHA256_Update(&sha,&zero,1); + SHA256_Update(&sha,(const unsigned char *)i->second.data(),i->second.length()); + SHA256_Update(&sha,&zero,1); } SHA256_Final(dig,&sha); - (*this)["sig"] = with.sign(dig); } static const std::string _DELTA_PREFIX("~"); @@ -71,7 +67,7 @@ bool Network::Certificate::qualifyMembership(const Network::Certificate &mc) con const_iterator deltaField(find(_DELTA_PREFIX + myField->first)); if (deltaField == end()) { - // If there is no delta, compare for equality (e.g. node, nwid) + // If there is no delta, compare on simple equality if (myField->second != theirField->second) return false; } else { diff --git a/node/Network.hpp b/node/Network.hpp index 359e2ce5..c13f00a4 100644 --- a/node/Network.hpp +++ b/node/Network.hpp @@ -129,7 +129,7 @@ public: } /** - * Set the timestamp and max-delta + * Set the timestamp and timestamp max-delta * * @param ts Timestamp in ms since epoch * @param maxDelta Maximum difference between two peers on the same network @@ -144,11 +144,31 @@ public: } /** - * Set or update the sig field to contain a signature + * Sign this certificate * * @param with Signing identity -- the identity of this network's controller + * @return Signature or empty string on failure */ - void sign(const Identity &with); + inline std::string sign(const Identity &with) const + { + unsigned char dig[32]; + _shaForSignature(dig); + return with.sign(dig); + } + + /** + * Verify this certificate's signature + * + * @param with Signing identity -- the identity of this network's controller + * @param sig Signature + * @param siglen Length of signature in bytes + */ + inline bool verify(const Identity &with,const void *sig,unsigned int siglen) const + { + unsigned char dig[32]; + _shaForSignature(dig); + return with.verifySignature(dig,sig,siglen); + } /** * Check if another peer is indeed a current member of this network @@ -157,13 +177,15 @@ public: * delta in this certificate. Fields without ~fields are compared for * equality. * - * This does not verify the certificate's signature! The signature - * must be verified first. + * This does not verify the certificate's signature! * * @param mc Peer membership certificate * @return True if mc's membership in this network is current */ bool qualifyMembership(const Certificate &mc) const; + + private: + void _shaForSignature(unsigned char *dig) const; }; /** diff --git a/node/Packet.cpp b/node/Packet.cpp index d3c0a3af..0aae1e2d 100644 --- a/node/Packet.cpp +++ b/node/Packet.cpp @@ -42,7 +42,7 @@ const char *Packet::verbString(Verb v) case VERB_FRAME: return "FRAME"; case VERB_MULTICAST_FRAME: return "MULTICAST_FRAME"; case VERB_MULTICAST_LIKE: return "MULTICAST_LIKE"; - case VERB_NETWORK_PERMISSION_CERTIFICATE: return "NETWORK_PERMISSION_CERTIFICATE"; + case VERB_NETWORK_MEMBERSHIP_CERTIFICATE: return "NETWORK_MEMBERSHIP_CERTIFICATE"; case VERB_NETWORK_CONFIG_REQUEST: return "NETWORK_CONFIG_REQUEST"; case VERB_NETWORK_CONFIG_REFRESH: return "NETWORK_CONFIG_REFRESH"; } @@ -60,7 +60,8 @@ 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_NETWORK_CERTIFICATE_ON_FILE: return "NO_NETWORK_CERTIFICATE_ON_FILE"; + case ERROR_NO_MEMBER_CERTIFICATE_ON_FILE: return "NO_MEMBER_CERTIFICATE_ON_FILE"; + case ERROR_MEMBER_CERTIFICATE_UNQUALIFIED: return "MEMBER_CERTIFICATE_UNQUALIFIED"; } return "(unknown)"; } diff --git a/node/Packet.hpp b/node/Packet.hpp index 2f88ac37..85ccb466 100644 --- a/node/Packet.hpp +++ b/node/Packet.hpp @@ -465,21 +465,17 @@ public: */ VERB_MULTICAST_FRAME = 9, - /* Network permission certificate: + /* Network member certificate for sending peer: * <[8] 64-bit network ID> - * <[1] flags (currently unused, must be 0)> - * <[2] 16-bit length of qualifying fields> - * <[...] string-serialized dictionary of qualifying fields> + * <[2] 16-bit length of certificate> + * <[...] string-serialized certificate dictionary> * <[2] 16-bit length of signature> - * <[...] ECDSA signature of my binary serialized identity and timestamp> - * - * This message is used to send ahead of time a certificate proving - * this node has permission to communicate on a private network. + * <[...] ECDSA signature of certificate> * * OK is generated on acceptance. ERROR is returned on failure. In both * cases the payload is the network ID. */ - VERB_NETWORK_PERMISSION_CERTIFICATE = 10, + VERB_NETWORK_MEMBERSHIP_CERTIFICATE = 10, /* Network configuration request: * <[8] 64-bit network ID> @@ -506,7 +502,8 @@ public: * <[8] 64-bit network ID> * * This message can be sent by the network configuration master node - * to request that nodes refresh their network configuration. + * to request that nodes refresh their network configuration. It can + * thus be used to "push" updates. * * It is only a hint and does not presently elicit a response. */ @@ -540,7 +537,10 @@ public: ERROR_UNSUPPORTED_OPERATION = 6, /* Message to private network rejected -- no unexpired certificate on file */ - ERROR_NO_NETWORK_CERTIFICATE_ON_FILE = 7 + ERROR_NO_MEMBER_CERTIFICATE_ON_FILE = 7, + + /* Membership certificate no longer qualified for membership in network */ + ERROR_MEMBER_CERTIFICATE_UNQUALIFIED = 8 }; /** diff --git a/node/PacketDecoder.cpp b/node/PacketDecoder.cpp index cd9985c3..0353625c 100644 --- a/node/PacketDecoder.cpp +++ b/node/PacketDecoder.cpp @@ -102,8 +102,8 @@ bool PacketDecoder::tryDecode(const RuntimeEnvironment *_r) return _doMULTICAST_LIKE(_r,peer); case Packet::VERB_MULTICAST_FRAME: return _doMULTICAST_FRAME(_r,peer); - case Packet::VERB_NETWORK_PERMISSION_CERTIFICATE: - return _doNETWORK_PERMISSION_CERTIFICATE(_r,peer); + case Packet::VERB_NETWORK_MEMBERSHIP_CERTIFICATE: + return _doNETWORK_MEMBERSHIP_CERTIFICATE(_r,peer); case Packet::VERB_NETWORK_CONFIG_REQUEST: return _doNETWORK_CONFIG_REQUEST(_r,peer); case Packet::VERB_NETWORK_CONFIG_REFRESH: @@ -311,7 +311,7 @@ bool PacketDecoder::_doOK(const RuntimeEnvironment *_r,const SharedPtr &pe bool PacketDecoder::_doWHOIS(const RuntimeEnvironment *_r,const SharedPtr &peer) { if (payloadLength() == ZT_ADDRESS_LENGTH) { - SharedPtr p(_r->topology->getPeer(Address(payload()))); + SharedPtr p(_r->topology->getPeer(Address(payload(),ZT_ADDRESS_LENGTH))); if (p) { Packet outp(source(),_r->identity.address(),Packet::VERB_OK); outp.append((unsigned char)Packet::VERB_WHOIS); @@ -320,7 +320,7 @@ bool PacketDecoder::_doWHOIS(const RuntimeEnvironment *_r,const SharedPtr outp.encrypt(peer->cryptKey()); outp.hmacSet(peer->macKey()); _r->demarc->send(_localPort,_remoteAddress,outp.data(),outp.size(),-1); - TRACE("sent WHOIS response to %s for %s",source().toString().c_str(),Address(payload()).toString().c_str()); + TRACE("sent WHOIS response to %s for %s",source().toString().c_str(),Address(payload(),ZT_ADDRESS_LENGTH).toString().c_str()); } else { Packet outp(source(),_r->identity.address(),Packet::VERB_ERROR); outp.append((unsigned char)Packet::VERB_WHOIS); @@ -330,7 +330,7 @@ bool PacketDecoder::_doWHOIS(const RuntimeEnvironment *_r,const SharedPtr outp.encrypt(peer->cryptKey()); outp.hmacSet(peer->macKey()); _r->demarc->send(_localPort,_remoteAddress,outp.data(),outp.size(),-1); - TRACE("sent WHOIS ERROR to %s for %s (not found)",source().toString().c_str(),Address(payload()).toString().c_str()); + TRACE("sent WHOIS ERROR to %s for %s (not found)",source().toString().c_str(),Address(payload(),ZT_ADDRESS_LENGTH).toString().c_str()); } } else { TRACE("dropped WHOIS from %s(%s): missing or invalid address",source().toString().c_str(),_remoteAddress.toString().c_str()); @@ -341,7 +341,7 @@ bool PacketDecoder::_doWHOIS(const RuntimeEnvironment *_r,const SharedPtr bool PacketDecoder::_doRENDEZVOUS(const RuntimeEnvironment *_r,const SharedPtr &peer) { try { - Address with(field(ZT_PROTO_VERB_RENDEZVOUS_IDX_ZTADDRESS,ZT_ADDRESS_LENGTH)); + Address with(field(ZT_PROTO_VERB_RENDEZVOUS_IDX_ZTADDRESS,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); SharedPtr withPeer(_r->topology->getPeer(with)); if (withPeer) { unsigned int port = at(ZT_PROTO_VERB_RENDEZVOUS_IDX_PORT); @@ -439,7 +439,7 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared if (network->isAllowed(source())) { if (size() > ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PAYLOAD) { - Address originalSubmitterAddress(field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SUBMITTER_ADDRESS,ZT_ADDRESS_LENGTH)); + Address originalSubmitterAddress(field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SUBMITTER_ADDRESS,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); MAC fromMac(field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SOURCE_MAC,6)); MulticastGroup mg(MAC(field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DESTINATION_MAC,6)),at(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ADI)); unsigned int hops = (*this)[ZT_PROTO_VERB_MULTICAST_FRAME_IDX_HOP_COUNT]; @@ -544,7 +544,7 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared return true; } -bool PacketDecoder::_doNETWORK_PERMISSION_CERTIFICATE(const RuntimeEnvironment *_r,const SharedPtr &peer) +bool PacketDecoder::_doNETWORK_MEMBERSHIP_CERTIFICATE(const RuntimeEnvironment *_r,const SharedPtr &peer) { } diff --git a/node/PacketDecoder.hpp b/node/PacketDecoder.hpp index 1cd1dca7..51408ba5 100644 --- a/node/PacketDecoder.hpp +++ b/node/PacketDecoder.hpp @@ -122,7 +122,7 @@ private: bool _doFRAME(const RuntimeEnvironment *_r,const SharedPtr &peer); bool _doMULTICAST_LIKE(const RuntimeEnvironment *_r,const SharedPtr &peer); bool _doMULTICAST_FRAME(const RuntimeEnvironment *_r,const SharedPtr &peer); - bool _doNETWORK_PERMISSION_CERTIFICATE(const RuntimeEnvironment *_r,const SharedPtr &peer); + bool _doNETWORK_MEMBERSHIP_CERTIFICATE(const RuntimeEnvironment *_r,const SharedPtr &peer); bool _doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *_r,const SharedPtr &peer); bool _doNETWORK_CONFIG_REFRESH(const RuntimeEnvironment *_r,const SharedPtr &peer); -- cgit v1.2.3 From e4c5ad9f43f37f3c5cd9feb1035d3b3091820e43 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 29 Jul 2013 17:11:00 -0400 Subject: More work on network membership certs, and it builds now. Still in heavy development. --- node/Network.cpp | 35 +++++++++++++++++++++++++++++-- node/Network.hpp | 62 +++++++++++++++++++++++++++++++++++++++++++++++++------ node/Packet.cpp | 3 +-- node/Packet.hpp | 5 +---- node/Switch.cpp | 2 +- node/Topology.cpp | 6 +++--- 6 files changed, 95 insertions(+), 18 deletions(-) (limited to 'node/Network.cpp') 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::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::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 _multicastGroups; - + std::map _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,std::set Packet outp((*p)->address(),_r->identity.address(),Packet::VERB_MULTICAST_LIKE); for(std::map< SharedPtr,std::set >::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::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 Topology::getPeer(const Address &zta) } unsigned char ztatmp[ZT_ADDRESS_LENGTH]; - zta.copyTo(ztatmp); + zta.copyTo(ztatmp,ZT_ADDRESS_LENGTH); Buffer 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 b; p->second->serialize(b); b.zeroUnused(); @@ -340,7 +340,7 @@ void Topology::_reallyAddPeer(const SharedPtr &p) } try { uint64_t atmp[ZT_ADDRESS_LENGTH]; - p->address().copyTo(atmp); + p->address().copyTo(atmp,ZT_ADDRESS_LENGTH); Buffer b; p->serialize(b); b.zeroUnused(); -- cgit v1.2.3 From 7e156b262283985cbfe560317ec3d69d1bf19511 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 30 Jul 2013 11:14:53 -0400 Subject: Call clean on all networks periodically, generalize Topology clean cycle to an overall clean cycle. --- node/Constants.hpp | 4 ++-- node/Network.cpp | 13 +++++++++++-- node/Network.hpp | 11 ++++++++++- node/Node.cpp | 9 +++++---- node/NodeConfig.cpp | 7 +++++++ node/NodeConfig.hpp | 5 +++++ 6 files changed, 40 insertions(+), 9 deletions(-) (limited to 'node/Network.cpp') diff --git a/node/Constants.hpp b/node/Constants.hpp index b8dc9ebf..36973b38 100644 --- a/node/Constants.hpp +++ b/node/Constants.hpp @@ -183,9 +183,9 @@ error_no_ZT_ARCH_defined; #define ZT_MAC_FIRST_OCTET 0x32 /** - * How often Topology::clean() is called in ms + * How often Topology::clean() and Network::clean() are called in ms */ -#define ZT_TOPOLOGY_CLEAN_PERIOD 300000 +#define ZT_DB_CLEAN_PERIOD 300000 /** * Delay between WHOIS retries in ms diff --git a/node/Network.cpp b/node/Network.cpp index 5878a281..a50d56dc 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -34,6 +34,7 @@ #include "NodeConfig.hpp" #include "Network.hpp" #include "Switch.hpp" +#include "Packet.hpp" namespace ZeroTier { @@ -103,6 +104,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), + _lastConfigUpdate(0), _id(id) { } @@ -114,16 +116,23 @@ Network::~Network() void Network::setConfiguration(const Network::Config &conf) { Mutex::Lock _l(_lock); - _configuration = conf; - _myCertificate = conf.certificateOfMembership(); + if ((conf.networkId() == _id)&&(conf.peerAddress() == _r->identity.address())) { // sanity check + _configuration = conf; + _myCertificate = conf.certificateOfMembership(); + _lastConfigUpdate = Utils::now(); + } } void Network::requestConfiguration() { + Packet outp(controller(),_r->identity.address(),Packet::VERB_NETWORK_CONFIG_REQUEST); + outp.append((uint64_t)_id); + _r->sw->send(outp,true); } bool Network::isAllowed(const Address &peer) const { + // Exceptions can occur if we do not yet have *our* configuration. try { Mutex::Lock _l(_lock); if (_configuration.isOpen()) diff --git a/node/Network.hpp b/node/Network.hpp index e553cd3a..62c0e978 100644 --- a/node/Network.hpp +++ b/node/Network.hpp @@ -392,6 +392,15 @@ public: */ void clean(); + /** + * @return Time of last updated configuration or 0 if none + */ + inline uint64_t lastConfigUpdate() const + throw() + { + return _lastConfigUpdate; + } + private: static void _CBhandleTapData(void *arg,const MAC &from,const MAC &to,unsigned int etherType,const Buffer<4096> &data); @@ -402,7 +411,7 @@ private: std::map _membershipCertificates; Config _configuration; Certificate _myCertificate; - uint64_t _lastCertificateUpdate; + uint64_t _lastConfigUpdate; uint64_t _id; Mutex _lock; diff --git a/node/Node.cpp b/node/Node.cpp index 827af23b..9c748b4a 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -339,7 +339,7 @@ Node::ReasonForTermination Node::run() try { uint64_t lastPingCheck = 0; - uint64_t lastTopologyClean = Utils::now(); // don't need to do this immediately + uint64_t lastClean = Utils::now(); // don't need to do this immediately uint64_t lastNetworkFingerprintCheck = 0; uint64_t lastAutoconfigureCheck = 0; uint64_t networkConfigurationFingerprint = _r->sysEnv->getNetworkConfigurationFingerprint(); @@ -459,9 +459,10 @@ Node::ReasonForTermination Node::run() } } - if ((now - lastTopologyClean) >= ZT_TOPOLOGY_CLEAN_PERIOD) { - lastTopologyClean = now; - _r->topology->clean(); // happens in background + if ((now - lastClean) >= ZT_DB_CLEAN_PERIOD) { + lastClean = now; + _r->topology->clean(); + _r->nc->cleanAllNetworks(); } try { diff --git a/node/NodeConfig.cpp b/node/NodeConfig.cpp index 214c06b7..4a174535 100644 --- a/node/NodeConfig.cpp +++ b/node/NodeConfig.cpp @@ -72,6 +72,13 @@ void NodeConfig::whackAllTaps() n->second->tap().whack(); } +void NodeConfig::cleanAllNetworks() +{ + Mutex::Lock _l(_networks_m); + for(std::map< uint64_t,SharedPtr >::const_iterator n(_networks.begin());n!=_networks.end();++n) + n->second->clean(); +} + // Macro used in execute() #undef _P #define _P(f,...) { r.push_back(std::string()); Utils::stdsprintf(r.back(),(f),##__VA_ARGS__); } diff --git a/node/NodeConfig.hpp b/node/NodeConfig.hpp index 98678944..62b23609 100644 --- a/node/NodeConfig.hpp +++ b/node/NodeConfig.hpp @@ -107,6 +107,11 @@ public: */ void whackAllTaps(); + /** + * Call clean() on all networks + */ + void cleanAllNetworks(); + /** * @param nwid Network ID * @return True if this network exists -- cgit v1.2.3