Changes to how new-style binary network configs are detected, and a new-style binary serialized meta-data representation.

This commit is contained in:
Adam Ierymenko 2016-05-06 13:29:10 -07:00
parent 69d0562e2c
commit 529515d1d1
5 changed files with 176 additions and 42 deletions

View File

@ -300,6 +300,23 @@ public:
append(s.data(),(unsigned int)s.length());
}
/**
* 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
*

View File

@ -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);
}

View File

@ -25,6 +25,7 @@
#include <vector>
#include <stdexcept>
#include <algorithm>
#include "../include/ZeroTierOne.h"
@ -40,13 +41,6 @@
#include <string>
#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)
*/
@ -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 {
@ -302,6 +296,19 @@ public:
return r;
}
/**
* @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
*
@ -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;

View File

@ -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));
}
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 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
}
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

View File

@ -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