diff options
author | Adam Ierymenko <adam.ierymenko@gmail.com> | 2016-08-04 09:51:15 -0700 |
---|---|---|
committer | Adam Ierymenko <adam.ierymenko@gmail.com> | 2016-08-04 09:51:15 -0700 |
commit | 404a0bbddd90ef2fbd624a0089076aac7e9184b4 (patch) | |
tree | 1b4dc5fa1331bb34a74bfd44a55f7557baa1303a /node | |
parent | f057bb63cdc4bebc4608f4f2ed6da4656ddbc8a9 (diff) | |
download | infinitytier-404a0bbddd90ef2fbd624a0089076aac7e9184b4.tar.gz infinitytier-404a0bbddd90ef2fbd624a0089076aac7e9184b4.zip |
...
Diffstat (limited to 'node')
-rw-r--r-- | node/Constants.hpp | 11 | ||||
-rw-r--r-- | node/IncomingPacket.cpp | 7 | ||||
-rw-r--r-- | node/Membership.cpp | 133 | ||||
-rw-r--r-- | node/Membership.hpp | 62 | ||||
-rw-r--r-- | node/NetworkConfig.hpp | 18 | ||||
-rw-r--r-- | node/Packet.hpp | 9 |
6 files changed, 176 insertions, 64 deletions
diff --git a/node/Constants.hpp b/node/Constants.hpp index dc36b3a1..489203fe 100644 --- a/node/Constants.hpp +++ b/node/Constants.hpp @@ -310,13 +310,6 @@ #define ZT_NAT_T_TACTICAL_ESCALATION_DELAY 1000 /** - * How long (max) to remember network certificates of membership? - * - * This only applies to networks we don't belong to. - */ -#define ZT_PEER_NETWORK_COM_EXPIRATION 3600000 - -/** * Sanity limit on maximum bridge routes * * If the number of bridge routes exceeds this, we cull routes from the @@ -330,7 +323,7 @@ /** * If there is no known route, spam to up to this many active bridges */ -#define ZT_MAX_BRIDGE_SPAM 16 +#define ZT_MAX_BRIDGE_SPAM 32 /** * Interval between direct path pushes in milliseconds @@ -357,7 +350,7 @@ #define ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY 4 /** - * Enable support for old Dictionary based network configs + * Enable support for older network configurations from older (pre-1.1.6) controllers */ #define ZT_SUPPORT_OLD_STYLE_NETCONF 1 diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index 6548bda6..c7e6e439 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -709,7 +709,7 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const S p += com.deserialize(*this,p); LockingPtr<Membership> m = peer->membership(com.networkId(),true); if (!m) return true; // sanity check - m->addCredential(RR,now,com); + if (m->addCredential(RR,now,com) == 1) return false; // wait for WHOIS } ++p; // skip trailing 0 after COMs if present @@ -719,14 +719,15 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const S p += cap.deserialize(*this,p); LockingPtr<Membership> m = peer->membership(cap.networkId(),true); if (!m) return true; // sanity check - m->addCredential(RR,now,cap); + if (m->addCredential(RR,now,cap) == 1) return false; // wait for WHOIS } + 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); if (!m) return true; // sanity check - m->addCredential(RR,now,tag); + if (m->addCredential(RR,now,tag) == 1) return false; // wait for WHOIS } } diff --git a/node/Membership.cpp b/node/Membership.cpp new file mode 100644 index 00000000..91cf693a --- /dev/null +++ b/node/Membership.cpp @@ -0,0 +1,133 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "Membership.hpp" +#include "RuntimeEnvironment.hpp" +#include "Peer.hpp" +#include "Topology.hpp" +#include "Switch.hpp" +#include "Packet.hpp" +#include "Node.hpp" + +#define ZT_CREDENTIAL_PUSH_EVERY (ZT_NETWORK_AUTOCONF_DELAY / 2) + +namespace ZeroTier { + +bool Membership::sendCredentialsIfNeeded(const RuntimeEnvironment *RR,const uint64_t now,const Peer &peer,const NetworkConfig &nconf,const uint32_t *capIds,const unsigned int capCount,const uint32_t *tagIds,const unsigned int tagCount) +{ + try { + Buffer<ZT_PROTO_MAX_PACKET_LENGTH> capsAndTags; + + capsAndTags.addSize(2); + unsigned int appendedCaps = 0; + for(unsigned int i=0;i<capCount;++i) { + CState *cs = _caps.get(capIds[i]); + if ((now - cs->lastPushed) >= ZT_CREDENTIAL_PUSH_EVERY) { + if ((capsAndTags.size() + sizeof(Capability)) > (ZT_PROTO_MAX_PACKET_LENGTH - sizeof(CertificateOfMembership))) + break; + const Capability *c = nconf.capability(capIds[i]); + if (c) { + c->serialize(capsAndTags); + ++appendedCaps; + cs->lastPushed = now; + } + } + } + capsAndTags.setAt<uint16_t>(0,(uint16_t)appendedCaps); + + const unsigned int tagCountPos = capsAndTags.size(); + capsAndTags.addSize(2); + unsigned int appendedTags = 0; + for(unsigned int i=0;i<tagCount;++i) { + TState *ts = _tags.get(tagIds[i]); + if ((now - ts->lastPushed) >= ZT_CREDENTIAL_PUSH_EVERY) { + if ((capsAndTags.size() + sizeof(Tag)) > (ZT_PROTO_MAX_PACKET_LENGTH - sizeof(CertificateOfMembership))) + break; + const Tag *t = nconf.tag(tagIds[i]); + if (t) { + t->serialize(capsAndTags); + ++appendedTags; + ts->lastPushed = now; + } + } + } + capsAndTags.setAt<uint16_t>(tagCountPos,(uint16_t)appendedTags); + + if (((now - _lastPushedCom) >= ZT_CREDENTIAL_PUSH_EVERY)||(appendedCaps)||(appendedTags)) { + Packet outp(peer.address(),RR->identity.address(),Packet::VERB_NETWORK_CREDENTIALS); + nconf.com.serialize(outp); + outp.append((uint8_t)0x00); + outp.append(capsAndTags.data(),capsAndTags.size()); + outp.compress(); + RR->sw->send(outp,true,0); + _lastPushedCom = now; + return true; + } + } catch ( ... ) { + TRACE("unable to send credentials due to unexpected exception"); + return false; + } +} + +int Membership::addCredential(const RuntimeEnvironment *RR,const uint64_t now,const CertificateOfMembership &com) +{ + if (com.issuedTo() != RR->identity.address()) + return -1; + if (_com == com) + return 0; + const int vr = com.verify(RR); + if (vr == 0) + _com = com; + return vr; +} + +int Membership::addCredential(const RuntimeEnvironment *RR,const uint64_t now,const Tag &tag) +{ + if (tag.issuedTo() != RR->identity.address()) + return -1; + TState *t = _tags.get(tag.networkId()); + if ((t)&&(t->lastReceived != 0)&&(t->tag == tag)) + return 0; + const int vr = tag.verify(RR); + if (vr == 0) { + if (!t) + t = &(_tags[tag.networkId()]); + t->lastReceived = now; + t->tag = tag; + } + return vr; +} + +int Membership::addCredential(const RuntimeEnvironment *RR,const uint64_t now,const Capability &cap) +{ + if (!cap.wasIssuedTo(RR->identity.address())) + return -1; + CState *c = _caps.get(cap.networkId()); + if ((c)&&(c->lastReceived != 0)&&(c->cap == cap)) + return 0; + const int vr = cap.verify(RR); + if (vr == 0) { + if (!c) + c = &(_caps[cap.networkId()]); + c->lastReceived = now; + c->cap = cap; + } + return vr; +} + +} // namespace ZeroTier diff --git a/node/Membership.hpp b/node/Membership.hpp index 642d46c6..abfff9e3 100644 --- a/node/Membership.hpp +++ b/node/Membership.hpp @@ -98,7 +98,21 @@ public: * @param tagCount Number of tag IDs * @return True if we pushed something */ - bool sendCredentialsIfNeeded(const RuntimeEnvironment *RR,const uint64_t now,const Peer &peer,const NetworkConfig &nconf,const uint32_t *capIds,const unsigned int capCount,const uint32_t *tagIds,const unsigned int tagCount) const; + bool sendCredentialsIfNeeded(const RuntimeEnvironment *RR,const uint64_t now,const Peer &peer,const NetworkConfig &nconf,const uint32_t *capIds,const unsigned int capCount,const uint32_t *tagIds,const unsigned int tagCount); + + /** + * Send COM if needed + * + * @param RR Runtime environment + * @param now Current time + * @param peer Peer that "owns" this membership + * @param nconf Network configuration + * @return True if we pushed something + */ + inline bool sendCredentialsIfNeeded(const RuntimeEnvironment *RR,const uint64_t now,const Peer &peer,const NetworkConfig &nconf) + { + return sendCredentialsIfNeeded(RR,now,peer,nconf,(const uint32_t *)0,0,(const uint32_t *)0,0); + } /** * @param nconf Network configuration @@ -127,61 +141,21 @@ public: * * @return 0 == OK, 1 == waiting for WHOIS, -1 == BAD signature or credential */ - inline int addCredential(const RuntimeEnvironment *RR,const uint64_t now,const CertificateOfMembership &com) - { - if (com.issuedTo() != RR->identity.address()) - return -1; - if (_com == com) - return 0; - const int vr = com.verify(RR); - if (vr == 0) - _com = com; - return vr; - } + int addCredential(const RuntimeEnvironment *RR,const uint64_t now,const CertificateOfMembership &com); /** * Validate and add a credential if signature is okay and it's otherwise good * * @return 0 == OK, 1 == waiting for WHOIS, -1 == BAD signature or credential */ - inline int addCredential(const RuntimeEnvironment *RR,const uint64_t now,const Tag &tag) - { - if (tag.issuedTo() != RR->identity.address()) - return -1; - TState *t = _tags.get(tag.networkId()); - if ((t)&&(t->lastReceived != 0)&&(t->tag == tag)) - return 0; - const int vr = tag.verify(RR); - if (vr == 0) { - if (!t) - t = &(_tags[tag.networkId()]); - t->lastReceived = now; - t->tag = tag; - } - return vr; - } + int addCredential(const RuntimeEnvironment *RR,const uint64_t now,const Tag &tag); /** * Validate and add a credential if signature is okay and it's otherwise good * * @return 0 == OK, 1 == waiting for WHOIS, -1 == BAD signature or credential */ - inline int addCredential(const RuntimeEnvironment *RR,const uint64_t now,const Capability &cap) - { - if (!cap.wasIssuedTo(RR->identity.address())) - return -1; - CState *c = _caps.get(cap.networkId()); - if ((c)&&(c->lastReceived != 0)&&(c->cap == cap)) - return 0; - const int vr = cap.verify(RR); - if (vr == 0) { - if (!c) - c = &(_caps[cap.networkId()]); - c->lastReceived = now; - c->cap = cap; - } - return vr; - } + int addCredential(const RuntimeEnvironment *RR,const uint64_t now,const Capability &cap); /** * Clean up old or stale entries diff --git a/node/NetworkConfig.hpp b/node/NetworkConfig.hpp index 6158c566..7bbedf20 100644 --- a/node/NetworkConfig.hpp +++ b/node/NetworkConfig.hpp @@ -318,6 +318,24 @@ public: return false; } + const Capability *capability(const uint32_t id) const + { + for(unsigned int i=0;i<capabilityCount;++i) { + if (capabilities[i].id() == id) + return &(capabilities[i]); + } + return (Capability *)0; + } + + const Tag *tag(const uint32_t id) const + { + for(unsigned int i=0;i<tagCount;++i) { + if (tags[i].id() == id) + return &(tags[i]); + } + return (Tag *)0; + } + /* inline void dump() const { diff --git a/node/Packet.hpp b/node/Packet.hpp index e2dc4e8b..977dc1bc 100644 --- a/node/Packet.hpp +++ b/node/Packet.hpp @@ -704,7 +704,7 @@ public: * Network membership credential push: * <[...] serialized certificate of membership> * [<[...] additional certificates of membership>] - * <[1] null byte for backward compatibility (see below)> + * <[1] 0x00, null byte marking end of COM array> * <[2] 16-bit number of capabilities> * <[...] one or more serialized Capability> * <[2] 16-bit number of tags> @@ -713,13 +713,6 @@ public: * This is sent in response to ERROR_NEED_MEMBERSHIP_CERTIFICATE and may * be pushed at any other time to keep exchanged certificates up to date. * - * Protocol versions prior to 8 do not support capabilities or tags and - * just expect an array of COMs. Adding a single NULL byte after the COM - * array causes these older versions to harmlessly abort parsing and - * ignore the newer fields. The new version checks for this null byte to - * indicate the end of the COM array, since all serialized COMs begin with - * non-zero bytes (see CertificateOfMembership). - * * OK/ERROR are not generated. */ VERB_NETWORK_CREDENTIALS = 0x0a, |