summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Ierymenko <adam.ierymenko@gmail.com>2016-05-06 13:29:10 -0700
committerAdam Ierymenko <adam.ierymenko@gmail.com>2016-05-06 13:29:10 -0700
commit529515d1d173e6850c86230106cbfc36e1b9bf97 (patch)
tree53f0eca20d9ce1ff4e02287813677e0401346387
parent69d0562e2c2ff4e5ddbc6f33ba43ddba913a25a9 (diff)
downloadinfinitytier-529515d1d173e6850c86230106cbfc36e1b9bf97.tar.gz
infinitytier-529515d1d173e6850c86230106cbfc36e1b9bf97.zip
Changes to how new-style binary network configs are detected, and a new-style binary serialized meta-data representation.
-rw-r--r--node/Buffer.hpp17
-rw-r--r--node/Network.cpp30
-rw-r--r--node/NetworkConfig.hpp40
-rw-r--r--node/NetworkConfigRequestMetaData.hpp128
-rw-r--r--version.h3
5 files changed, 176 insertions, 42 deletions
diff --git a/node/Buffer.hpp b/node/Buffer.hpp
index c5d625de..0b171592 100644
--- a/node/Buffer.hpp
+++ b/node/Buffer.hpp
@@ -301,6 +301,23 @@ public:
}
/**
+ * Append a C string including null termination byte
+ *
+ * @param s C string
+ * @throws std::out_of_range Attempt to append beyond capacity
+ */
+ inline void appendCString(const char *s)
+ throw(std::out_of_range)
+ {
+ for(;;) {
+ if (_l >= C)
+ throw std::out_of_range("Buffer: append beyond capacity");
+ if (!(_b[_l++] = *(s++)))
+ break;
+ }
+ }
+
+ /**
* Append a buffer
*
* @param b Buffer to append
diff --git a/node/Network.cpp b/node/Network.cpp
index e7b99661..00ae795a 100644
--- a/node/Network.cpp
+++ b/node/Network.cpp
@@ -181,12 +181,23 @@ bool Network::applyConfiguration(const NetworkConfig &conf)
int Network::setConfiguration(const void *confBytes,unsigned int confLen,bool saveToDisk)
{
try {
- if (!confLen)
+ if (confLen <= 1)
return 0;
NetworkConfig newConfig;
- if (reinterpret_cast<const uint8_t *>(confBytes)[0] == ZT_NETWORKCONFIG_V2_MARKER_BYTE) {
- Buffer<8194> tmp(confBytes,confLen);
+
+ // Find the length of any string-serialized old-style Dictionary,
+ // including its terminating NULL (if any). If this is before
+ // the end of the config, that tells us there is a new-style
+ // binary config which is preferred.
+ unsigned int dictLen = 0;
+ while (dictLen < confLen) {
+ if (!(reinterpret_cast<const uint8_t *>(confBytes)[dictLen++]))
+ break;
+ }
+
+ if (dictLen < (confLen - 2)) {
+ Buffer<8194> tmp(reinterpret_cast<const uint8_t *>(confBytes) + dictLen,confLen - dictLen);
newConfig.deserialize(tmp,0);
} else {
#ifdef ZT_SUPPORT_OLD_STYLE_NETCONF
@@ -422,15 +433,15 @@ public:
_now(renv->node->now()),
_controller(nw->controller()),
_network(nw),
+ _anchors(nw->config().anchors()),
_rootAddresses(renv->topology->rootAddresses())
{}
inline void operator()(Topology &t,const SharedPtr<Peer> &p)
{
- if (
- (_network->_isAllowed(p)) ||
- (p->address() == _controller) ||
- (std::find(_rootAddresses.begin(),_rootAddresses.end(),p->address()) != _rootAddresses.end())
- ) {
+ if ( (_network->_isAllowed(p)) || // FIXME: this causes multicast LIKEs for public networks to get spammed
+ (p->address() == _controller) ||
+ (std::find(_rootAddresses.begin(),_rootAddresses.end(),p->address()) != _rootAddresses.end()) ||
+ (std::find(_anchors.begin(),_anchors.end(),p->address()) != _anchors.end()) ) {
peers.push_back(p);
}
}
@@ -439,14 +450,15 @@ private:
const uint64_t _now;
const Address _controller;
Network *const _network;
+ const std::vector<Address> _anchors;
const std::vector<Address> _rootAddresses;
};
void Network::_announceMulticastGroups()
{
// Assumes _lock is locked
+ std::vector<MulticastGroup> allMulticastGroups(_allMulticastGroups());
_MulticastAnnounceAll gpfunc(RR,this);
RR->topology->eachPeer<_MulticastAnnounceAll &>(gpfunc);
- std::vector<MulticastGroup> allMulticastGroups(_allMulticastGroups());
for(std::vector< SharedPtr<Peer> >::const_iterator i(gpfunc.peers.begin());i!=gpfunc.peers.end();++i)
_announceMulticastGroupsTo(*i,allMulticastGroups);
}
diff --git a/node/NetworkConfig.hpp b/node/NetworkConfig.hpp
index 15778aed..a03c1faf 100644
--- a/node/NetworkConfig.hpp
+++ b/node/NetworkConfig.hpp
@@ -25,6 +25,7 @@
#include <vector>
#include <stdexcept>
+#include <algorithm>
#include "../include/ZeroTierOne.h"
@@ -41,13 +42,6 @@
#endif
/**
- * First byte of V2 binary-serialized network configs
- *
- * This will never begin a Dictionary, so it serves to distinguish.
- */
-#define ZT_NETWORKCONFIG_V2_MARKER_BYTE 0x00
-
-/**
* Flag: allow passive bridging (experimental)
*/
#define ZT_NETWORKCONFIG_FLAG_ALLOW_PASSIVE_BRIDGING 0x0001
@@ -68,9 +62,9 @@
#define ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE 0x0000020000000000ULL
/**
- * This device is allowed to send packets from any Ethernet MAC, including ZeroTier-reserved ones
+ * An anchor is a device that is willing to be one and has been online/stable for a long time on this network
*/
-#define ZT_NETWORKCONFIG_SPECIALIST_TYPE_IMPOSTOR 0x0000040000000000ULL
+#define ZT_NETWORKCONFIG_SPECIALIST_TYPE_ANCHOR 0x0000040000000000ULL
namespace ZeroTier {
@@ -303,6 +297,19 @@ public:
}
/**
+ * @return ZeroTier addresses of "anchor" devices on this network
+ */
+ inline std::vector<Address> anchors() const
+ {
+ std::vector<Address> r;
+ for(unsigned int i=0;i<_specialistCount;++i) {
+ if ((_specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_ANCHOR) != 0)
+ r.push_back(Address(_specialists[i]));
+ }
+ return r;
+ }
+
+ /**
* Look up a static physical address for a given ZeroTier address
*
* @param zt ZeroTier address
@@ -321,6 +328,8 @@ public:
}
/**
+ * This gets network preferred relays with their static physical address if one is defined
+ *
* @return Network-preferred relays for this network (if none, only roots will be used)
*/
inline std::vector<Relay> relays() const
@@ -393,9 +402,7 @@ public:
template<unsigned int C>
inline void serialize(Buffer<C> &b) const
{
- b.append((uint8_t)ZT_NETWORKCONFIG_V2_MARKER_BYTE);
-
- b.append((uint16_t)0); // version
+ b.append((uint16_t)1); // version
b.append((uint64_t)_nwid);
b.append((uint64_t)_timestamp);
@@ -517,9 +524,7 @@ public:
unsigned int p = startAt;
- if (b[p++] != ZT_NETWORKCONFIG_V2_MARKER_BYTE)
- throw std::invalid_argument("unrecognized format");
- if (b.template at<uint16_t>(p) != 0)
+ if (b.template at<uint16_t>(p) != 1)
throw std::invalid_argument("unrecognized version");
p += 2;
@@ -532,9 +537,8 @@ public:
_type = (ZT_VirtualNetworkType)b[p++];
unsigned int nl = (unsigned int)b[p++];
- if (nl > ZT_MAX_NETWORK_SHORT_NAME_LENGTH)
- nl = ZT_MAX_NETWORK_SHORT_NAME_LENGTH;
- memcpy(_name,b.field(p,nl),nl);
+ memcpy(_name,b.field(p,nl),std::max(nl,(unsigned int)ZT_MAX_NETWORK_SHORT_NAME_LENGTH));
+ p += nl;
// _name will always be null terminated since field size is ZT_MAX_NETWORK_SHORT_NAME_LENGTH + 1
_specialistCount = (unsigned int)b.template at<uint16_t>(p); p += 2;
diff --git a/node/NetworkConfigRequestMetaData.hpp b/node/NetworkConfigRequestMetaData.hpp
index 5bf8bac4..3756d0d8 100644
--- a/node/NetworkConfigRequestMetaData.hpp
+++ b/node/NetworkConfigRequestMetaData.hpp
@@ -25,6 +25,9 @@
#include "Constants.hpp"
#include "NetworkConfig.hpp"
+#include "Buffer.hpp"
+
+#include "../version.h"
#ifdef ZT_SUPPORT_OLD_STYLE_NETCONF
#include <string>
@@ -33,27 +36,122 @@
namespace ZeroTier {
+/**
+ * Network configuration request meta data
+ */
class NetworkConfigRequestMetaData
{
public:
- NetworkConfigRequestMetaData() :
- _vendor(0),
- _majorVersion(0),
- _minorVersion(0),
- _revision(0),
- _buildNo(0),
- _flags(0)
+ NetworkConfigRequestMetaData()
{
+ memset(this,0,sizeof(NetworkConfigRequestMetaData));
+ }
+
+ template<unsigned int C>
+ inline void serialize(Buffer<C> &b) const
+ {
+ // Unlike network config we always send the old fields. Newer network
+ // controllers will detect the presence of the new serialized data by
+ // detecting extra data after the terminating NULL. But always sending
+ // these maintains backward compatibility with old controllers.
+ b.appendCString("majv="ZEROTIER_ONE_VERSION_MAJOR_S"\nminv="ZEROTIER_ONE_VERSION_MINOR_S"\nrevv="ZEROTIER_ONE_VERSION_REVISION_S"\n");
+
+ b.append((uint16_t)1); // version
+
+ b.append((uint64_t)buildId);
+ b.append((uint64_t)flags);
+ b.append((uint16_t)vendor);
+ b.append((uint16_t)platform);
+ b.append((uint16_t)architecture);
+ b.append((uint16_t)majorVersion);
+ b.append((uint16_t)minorVersion);
+ b.append((uint16_t)revision);
+
+ unsigned int tl = (unsigned int)strlen(_auth);
+ if (tl > 255) tl = 255; // sanity check
+ b.append((uint8_t)tl);
+ b.append((const void *)auth,tl);
+
+ b.append((uint16_t)0); // extended bytes, currently 0 since unused
}
-protected:
- unsigned int _vendor;
- unsigned int _majorVersion;
- unsigned int _minorVersion;
- unsigned int _revision;
- unsigned int _buildNo;
- unsigned int _flags;
- char _passcode[ZT_MAX_NETWORK_SHORT_NAME_LENGTH + 1];
+ template<unsigned int C>
+ inline unsigned int deserialize(const Buffer<C> &b,unsigned int startAt = 0)
+ {
+ memset(this,0,sizeof(NetworkConfigRequestMetaData));
+
+ unsigned int p = startAt;
+
+ // Seek past old style meta-data
+ while (b[p]) ++p;
+
+ if (b.template at<uint16_t>(p) != 1)
+ throw std::invalid_argument("unrecognized version");
+ p += 2;
+
+ buildId = b.template at<uint64_t>(p); p += 8;
+ flags = b.template at<uint64_t>(p); p += 8;
+ vendor = (ZT_Vendor)b.template at<uint16_t>(p); p += 2;
+ platform = (ZT_Platform)b.template at<uint16_t>(p); p += 2;
+ architecture = (ZT_Architecture)b.template at<uint16_t>(p); p += 2;
+ majorVersion = b.template at<uint16_t>(p); p += 2;
+ minorVersion = b.template at<uint16_t>(p); p += 2;
+ revision = b.template at<uint16_t>(p); p += 2;
+
+ unsigned int tl = (unsigned int)b[p++];
+ memcpy(auth,b.field(p,tl),std::max(tl,(unsigned int)ZT_MAX_NETWORK_SHORT_NAME_LENGTH));
+ // auth[] is ZT_MAX_NETWORK_SHORT_NAME_LENGTH + 1 and so will always end up null-terminated since we zeroed the structure
+ p += tl;
+
+ p += b.template at<uint16_t>(p) + 2;
+
+ return (p - startAt);
+ }
+
+ /**
+ * Build ID (currently unused, must be 0)
+ */
+ uint64_t buildId;
+
+ /**
+ * Flags (currently unused, must be 0)
+ */
+ uint64_t flags;
+
+ /**
+ * ZeroTier vendor or 0 for unspecified
+ */
+ ZT_Vendor vendor;
+
+ /**
+ * ZeroTier platform or 0 for unspecified
+ */
+ ZT_Platform platform;
+
+ /**
+ * ZeroTier architecture or 0 for unspecified
+ */
+ ZT_Architecture architecture;
+
+ /**
+ * ZeroTier software major version
+ */
+ unsigned int majorVersion;
+
+ /**
+ * ZeroTier software minor version
+ */
+ unsigned int minorVersion;
+
+ /**
+ * ZeroTier software revision
+ */
+ unsigned int revision;
+
+ /**
+ * Authentication data (e.g. bearer=<token>)
+ */
+ char auth[ZT_MAX_NETWORK_SHORT_NAME_LENGTH + 1];
};
} // namespace ZeroTier
diff --git a/version.h b/version.h
index 62045ed8..70815daf 100644
--- a/version.h
+++ b/version.h
@@ -23,15 +23,18 @@
* Major version
*/
#define ZEROTIER_ONE_VERSION_MAJOR 1
+#define ZEROTIER_ONE_VERSION_MAJOR_S "1"
/**
* Minor version
*/
#define ZEROTIER_ONE_VERSION_MINOR 1
+#define ZEROTIER_ONE_VERSION_MINOR_S "1"
/**
* Revision
*/
#define ZEROTIER_ONE_VERSION_REVISION 5
+#define ZEROTIER_ONE_VERSION_REVISION_S "5"
#endif