Eliminate some poorly thought out optimizations from the netconf/controller interaction,

and go ahead and bump version to 1.0.4.

For a while in 1.0.3 -dev I was trying to optimize out repeated network controller
requests by using a ratcheting mechanism. If the client received a network config
that was indeed different from the one it had, it would respond by instantlly
requesting it again.

Not sure what I was thinking. It's fundamentally unsafe to respond to a message
with another message of the same type -- it risks a race condition. In this case
that's exactly what could happen.

It just isn't worth the added complexity to avoid a tiny, tiny amount of network
overhead, so I've taken this whole path out.

A few extra bytes every two minutes isn't worth fretting about, but as I recall
the reason for this optimization was to save CPU on the controller. This can be
achieved by just caching responses in memory *there* and serving those same
responses back out if they haven't changed.

I think I developed that 'ratcheting' stuff before I went full time on this. It's
hard to develop stuff like this without hours of sustained focus.
This commit is contained in:
Adam Ierymenko 2015-07-23 09:50:10 -07:00
parent e2a2993b18
commit 3ba54c7e35
7 changed files with 55 additions and 80 deletions

View file

@ -296,6 +296,12 @@ SqliteNetworkController::~SqliteNetworkController()
NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(const InetAddress &fromAddr,const Identity &signingId,const Identity &identity,uint64_t nwid,const Dictionary &metaData,uint64_t haveRevision,Dictionary &netconf) NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(const InetAddress &fromAddr,const Identity &signingId,const Identity &identity,uint64_t nwid,const Dictionary &metaData,uint64_t haveRevision,Dictionary &netconf)
{ {
// Decode some stuff from metaData
const unsigned int clientMajorVersion = (unsigned int)metaData.getHexUInt(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MAJOR_VERSION,0);
const unsigned int clientMinorVersion = (unsigned int)metaData.getHexUInt(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MINOR_VERSION,0);
const unsigned int clientRevision = (unsigned int)metaData.getHexUInt(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_REVISION,0);
const bool clientIs104 = (Utils::compareVersion(clientMajorVersion,clientMinorVersion,clientRevision,1,0,4) >= 0);
Mutex::Lock _l(_lock); Mutex::Lock _l(_lock);
// Note: we can't reuse prepared statements that return const char * pointers without // Note: we can't reuse prepared statements that return const char * pointers without
@ -418,13 +424,6 @@ NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(co
if (!member.authorized) if (!member.authorized)
return NetworkController::NETCONF_QUERY_ACCESS_DENIED; return NetworkController::NETCONF_QUERY_ACCESS_DENIED;
// If netconf is unchanged from client reported revision, just tell client they're up to date
// Temporarily disabled -- old version didn't do this, and we'll go ahead and
// test more thoroughly before enabling this optimization.
//if ((haveRevision > 0)&&(haveRevision == network.revision))
// return NetworkController::NETCONF_QUERY_OK_BUT_NOT_NEWER;
// Create and sign netconf // Create and sign netconf
netconf.clear(); netconf.clear();
@ -581,7 +580,8 @@ NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(co
if ((ipNetmaskBits <= 0)||(ipNetmaskBits > 32)) if ((ipNetmaskBits <= 0)||(ipNetmaskBits > 32))
continue; continue;
switch((IpAssignmentType)sqlite3_column_int(_sGetIpAssignmentsForNode,0)) { const IpAssignmentType ipt = (IpAssignmentType)sqlite3_column_int(_sGetIpAssignmentsForNode,0);
switch(ipt) {
case ZT_IP_ASSIGNMENT_TYPE_ADDRESS: case ZT_IP_ASSIGNMENT_TYPE_ADDRESS:
haveStaticIpAssignment = true; haveStaticIpAssignment = true;
break; break;
@ -592,13 +592,15 @@ NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(co
continue; continue;
} }
// We send both routes and IP assignments -- client knows which is // 1.0.4 or newer clients support network routes in addition to IPs.
// which by whether address ends in all zeroes after netmask. // Older clients only support IP address / netmask entries.
char tmp[32]; if ((clientIs104)||(ipt == ZT_IP_ASSIGNMENT_TYPE_ADDRESS)) {
Utils::snprintf(tmp,sizeof(tmp),"%d.%d.%d.%d/%d",(int)ip[12],(int)ip[13],(int)ip[14],(int)ip[15],ipNetmaskBits); char tmp[32];
if (v4s.length()) Utils::snprintf(tmp,sizeof(tmp),"%d.%d.%d.%d/%d",(int)ip[12],(int)ip[13],(int)ip[14],(int)ip[15],ipNetmaskBits);
v4s.push_back(','); if (v4s.length())
v4s.append(tmp); v4s.push_back(',');
v4s.append(tmp);
}
} }
if (!haveStaticIpAssignment) { if (!haveStaticIpAssignment) {
@ -1388,7 +1390,6 @@ unsigned int SqliteNetworkController::_doCPGet(
const char *result = ""; const char *result = "";
switch(this->doNetworkConfigRequest(InetAddress(),sigid,memid,nwid,Dictionary(),hr,netconf)) { switch(this->doNetworkConfigRequest(InetAddress(),sigid,memid,nwid,Dictionary(),hr,netconf)) {
case NetworkController::NETCONF_QUERY_OK: result = "OK"; break; case NetworkController::NETCONF_QUERY_OK: result = "OK"; break;
case NetworkController::NETCONF_QUERY_OK_BUT_NOT_NEWER: result = "OK_BUT_NOT_NEWER"; break;
case NetworkController::NETCONF_QUERY_OBJECT_NOT_FOUND: result = "OBJECT_NOT_FOUND"; break; case NetworkController::NETCONF_QUERY_OBJECT_NOT_FOUND: result = "OBJECT_NOT_FOUND"; break;
case NetworkController::NETCONF_QUERY_ACCESS_DENIED: result = "ACCESS_DENIED"; break; case NetworkController::NETCONF_QUERY_ACCESS_DENIED: result = "ACCESS_DENIED"; break;
case NetworkController::NETCONF_QUERY_INTERNAL_SERVER_ERROR: result = "INTERNAL_SERVER_ERROR"; break; case NetworkController::NETCONF_QUERY_INTERNAL_SERVER_ERROR: result = "INTERNAL_SERVER_ERROR"; break;

View file

@ -392,28 +392,7 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &p
const unsigned int dictlen = at<uint16_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_DICT_LEN); const unsigned int dictlen = at<uint16_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_DICT_LEN);
const std::string dict((const char *)field(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_DICT,dictlen),dictlen); const std::string dict((const char *)field(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_DICT,dictlen),dictlen);
if (dict.length()) { if (dict.length()) {
if (nw->setConfiguration(Dictionary(dict)) == 2) { // 2 == accepted and actually new nw->setConfiguration(Dictionary(dict));
/* If this configuration was indeed new, we do another
* controller request with its revision. We do this in
* order to (a) tell the network controller we got it (it
* won't send a duplicate if ts == current), and (b)
* get another one if the controller is changing rapidly
* until we finally have the final version.
*
* Note that we don't do this for network controllers with
* versions <= 1.0.3, since those regenerate a new controller
* with a new revision every time. In that case this double
* confirmation would create a race condition. */
const SharedPtr<NetworkConfig> nc(nw->config2());
if ((peer->atLeastVersion(1,0,3))&&(nc)&&(nc->revision() > 0)) {
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_NETWORK_CONFIG_REQUEST);
outp.append((uint64_t)nw->id());
outp.append((uint16_t)0); // no meta-data
outp.append((uint64_t)nc->revision());
outp.armor(peer->key(),true);
RR->node->putPacket(_remoteAddress,outp.data(),outp.size());
}
}
TRACE("got network configuration for network %.16llx from %s",(unsigned long long)nw->id(),source().toString().c_str()); TRACE("got network configuration for network %.16llx from %s",(unsigned long long)nw->id(),source().toString().c_str());
} }
} }
@ -692,6 +671,7 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons
if (RR->localNetworkController) { if (RR->localNetworkController) {
Dictionary netconf; Dictionary netconf;
switch(RR->localNetworkController->doNetworkConfigRequest((h > 0) ? InetAddress() : _remoteAddress,RR->identity,peer->identity(),nwid,metaData,haveRevision,netconf)) { switch(RR->localNetworkController->doNetworkConfigRequest((h > 0) ? InetAddress() : _remoteAddress,RR->identity,peer->identity(),nwid,metaData,haveRevision,netconf)) {
case NetworkController::NETCONF_QUERY_OK: { case NetworkController::NETCONF_QUERY_OK: {
const std::string netconfStr(netconf.toString()); const std::string netconfStr(netconf.toString());
if (netconfStr.length() > 0xffff) { // sanity check since field ix 16-bit if (netconfStr.length() > 0xffff) { // sanity check since field ix 16-bit
@ -712,8 +692,7 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons
} }
} }
} break; } break;
case NetworkController::NETCONF_QUERY_OK_BUT_NOT_NEWER: // nothing to do -- netconf has not changed
break;
case NetworkController::NETCONF_QUERY_OBJECT_NOT_FOUND: { case NetworkController::NETCONF_QUERY_OBJECT_NOT_FOUND: {
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_ERROR); Packet outp(peer->address(),RR->identity.address(),Packet::VERB_ERROR);
outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST); outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
@ -723,6 +702,7 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons
outp.armor(peer->key(),true); outp.armor(peer->key(),true);
RR->node->putPacket(_remoteAddress,outp.data(),outp.size()); RR->node->putPacket(_remoteAddress,outp.data(),outp.size());
} break; } break;
case NetworkController::NETCONF_QUERY_ACCESS_DENIED: { case NetworkController::NETCONF_QUERY_ACCESS_DENIED: {
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_ERROR); Packet outp(peer->address(),RR->identity.address(),Packet::VERB_ERROR);
outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST); outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
@ -732,12 +712,15 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons
outp.armor(peer->key(),true); outp.armor(peer->key(),true);
RR->node->putPacket(_remoteAddress,outp.data(),outp.size()); RR->node->putPacket(_remoteAddress,outp.data(),outp.size());
} break; } break;
case NetworkController::NETCONF_QUERY_INTERNAL_SERVER_ERROR: case NetworkController::NETCONF_QUERY_INTERNAL_SERVER_ERROR:
TRACE("NETWORK_CONFIG_REQUEST failed: internal error: %s",netconf.get("error","(unknown)").c_str()); TRACE("NETWORK_CONFIG_REQUEST failed: internal error: %s",netconf.get("error","(unknown)").c_str());
break; break;
default: default:
TRACE("NETWORK_CONFIG_REQUEST failed: invalid return value from NetworkController::doNetworkConfigRequest()"); TRACE("NETWORK_CONFIG_REQUEST failed: invalid return value from NetworkController::doNetworkConfigRequest()");
break; break;
} }
} else { } else {
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_ERROR); Packet outp(peer->address(),RR->identity.address(),Packet::VERB_ERROR);

View file

@ -38,6 +38,8 @@
#include "Buffer.hpp" #include "Buffer.hpp"
#include "NetworkController.hpp" #include "NetworkController.hpp"
#include "../version.h"
namespace ZeroTier { namespace ZeroTier {
const ZeroTier::MulticastGroup Network::BROADCAST(ZeroTier::MAC(0xffffffffffffULL),0); const ZeroTier::MulticastGroup Network::BROADCAST(ZeroTier::MAC(0xffffffffffffULL),0);
@ -255,9 +257,18 @@ void Network::requestConfiguration()
} }
TRACE("requesting netconf for network %.16llx from controller %s",(unsigned long long)_id,controller().toString().c_str()); TRACE("requesting netconf for network %.16llx from controller %s",(unsigned long long)_id,controller().toString().c_str());
// TODO: in the future we will include things like join tokens here, etc.
Dictionary metaData;
metaData.setHex(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MAJOR_VERSION,ZEROTIER_ONE_VERSION_MAJOR);
metaData.setHex(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MINOR_VERSION,ZEROTIER_ONE_VERSION_MINOR);
metaData.setHex(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_REVISION,ZEROTIER_ONE_VERSION_REVISION);
std::string mds(metaData.toString());
Packet outp(controller(),RR->identity.address(),Packet::VERB_NETWORK_CONFIG_REQUEST); Packet outp(controller(),RR->identity.address(),Packet::VERB_NETWORK_CONFIG_REQUEST);
outp.append((uint64_t)_id); outp.append((uint64_t)_id);
outp.append((uint16_t)0); // no meta-data outp.append((uint16_t)mds.length());
outp.append((const void *)mds.data(),(unsigned int)mds.length());
{ {
Mutex::Lock _l(_lock); Mutex::Lock _l(_lock);
if (_config) if (_config)

View file

@ -47,7 +47,6 @@ SharedPtr<NetworkConfig> NetworkConfig::createTestNetworkConfig(const Address &s
nc->_private = false; nc->_private = false;
nc->_enableBroadcast = true; nc->_enableBroadcast = true;
nc->_name = "ZT_TEST_NETWORK"; nc->_name = "ZT_TEST_NETWORK";
nc->_description = "Built-in dummy test network";
// Make up a V4 IP from 'self' in the 10.0.0.0/8 range -- no // Make up a V4 IP from 'self' in the 10.0.0.0/8 range -- no
// guarantee of uniqueness but collisions are unlikely. // guarantee of uniqueness but collisions are unlikely.
@ -111,7 +110,6 @@ void NetworkConfig::_fromDictionary(const Dictionary &d)
_name = d.get(ZT_NETWORKCONFIG_DICT_KEY_NAME); _name = d.get(ZT_NETWORKCONFIG_DICT_KEY_NAME);
if (_name.length() > ZT1_MAX_NETWORK_SHORT_NAME_LENGTH) if (_name.length() > ZT1_MAX_NETWORK_SHORT_NAME_LENGTH)
throw std::invalid_argument("network short name too long (max: 255 characters)"); throw std::invalid_argument("network short name too long (max: 255 characters)");
_description = d.get(ZT_NETWORKCONFIG_DICT_KEY_DESC,std::string());
// In dictionary IPs are split into V4 and V6 addresses, but we don't really // In dictionary IPs are split into V4 and V6 addresses, but we don't really
// need that so merge them here. // need that so merge them here.
@ -132,26 +130,22 @@ void NetworkConfig::_fromDictionary(const Dictionary &d)
case AF_INET: case AF_INET:
if ((!addr.netmaskBits())||(addr.netmaskBits() > 32)) if ((!addr.netmaskBits())||(addr.netmaskBits() > 32))
continue; continue;
else if (addr.isNetwork()) {
// TODO: add route to network -- this is a route without an IP assignment
continue;
}
break; break;
case AF_INET6: case AF_INET6:
if ((!addr.netmaskBits())||(addr.netmaskBits() > 128)) if ((!addr.netmaskBits())||(addr.netmaskBits() > 128))
continue; continue;
else if (addr.isNetwork()) {
// TODO: add route to network -- this is a route without an IP assignment
continue;
}
break; break;
default: // ignore unrecognized address types or junk/empty fields default: // ignore unrecognized address types or junk/empty fields
continue; continue;
} }
_staticIps.push_back(addr); if (addr.isNetwork())
_localRoutes.push_back(addr);
else _staticIps.push_back(addr);
} }
if (_staticIps.size() > ZT1_MAX_ZT_ASSIGNED_ADDRESSES) if (_localRoutes.size() > ZT1_MAX_ZT_ASSIGNED_ADDRESSES) throw std::invalid_argument("too many ZT-assigned routes");
throw std::invalid_argument("too many ZT-assigned IP addresses or routes"); if (_staticIps.size() > ZT1_MAX_ZT_ASSIGNED_ADDRESSES) throw std::invalid_argument("too many ZT-assigned IP addresses");
std::sort(_localRoutes.begin(),_localRoutes.end());
_localRoutes.erase(std::unique(_localRoutes.begin(),_localRoutes.end()),_localRoutes.end());
std::sort(_staticIps.begin(),_staticIps.end()); std::sort(_staticIps.begin(),_staticIps.end());
_staticIps.erase(std::unique(_staticIps.begin(),_staticIps.end()),_staticIps.end()); _staticIps.erase(std::unique(_staticIps.begin(),_staticIps.end()),_staticIps.end());
@ -201,7 +195,7 @@ bool NetworkConfig::operator==(const NetworkConfig &nc) const
if (_private != nc._private) return false; if (_private != nc._private) return false;
if (_enableBroadcast != nc._enableBroadcast) return false; if (_enableBroadcast != nc._enableBroadcast) return false;
if (_name != nc._name) return false; if (_name != nc._name) return false;
if (_description != nc._description) return false; if (_localRoutes != nc._localRoutes) return false;
if (_staticIps != nc._staticIps) return false; if (_staticIps != nc._staticIps) return false;
if (_gateways != nc._gateways) return false; if (_gateways != nc._gateways) return false;
if (_activeBridges != nc._activeBridges) return false; if (_activeBridges != nc._activeBridges) return false;
@ -211,4 +205,3 @@ bool NetworkConfig::operator==(const NetworkConfig &nc) const
} }
} // namespace ZeroTier } // namespace ZeroTier

View file

@ -47,59 +47,48 @@
namespace ZeroTier { namespace ZeroTier {
// Fields for meta-data sent with network config requests
#define ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MAJOR_VERSION "majv"
#define ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MINOR_VERSION "minv"
#define ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_REVISION "revv"
// These dictionary keys are short so they don't take up much room in // These dictionary keys are short so they don't take up much room in
// netconf response packets. // netconf response packets.
// integer(hex)[,integer(hex),...] // integer(hex)[,integer(hex),...]
#define ZT_NETWORKCONFIG_DICT_KEY_ALLOWED_ETHERNET_TYPES "et" #define ZT_NETWORKCONFIG_DICT_KEY_ALLOWED_ETHERNET_TYPES "et"
// network ID // network ID
#define ZT_NETWORKCONFIG_DICT_KEY_NETWORK_ID "nwid" #define ZT_NETWORKCONFIG_DICT_KEY_NETWORK_ID "nwid"
// integer(hex) // integer(hex)
#define ZT_NETWORKCONFIG_DICT_KEY_TIMESTAMP "ts" #define ZT_NETWORKCONFIG_DICT_KEY_TIMESTAMP "ts"
// integer(hex) // integer(hex)
#define ZT_NETWORKCONFIG_DICT_KEY_REVISION "r" #define ZT_NETWORKCONFIG_DICT_KEY_REVISION "r"
// address of member // address of member
#define ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO "id" #define ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO "id"
// integer(hex) // integer(hex)
#define ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT "ml" #define ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT "ml"
// 0/1 // 0/1
#define ZT_NETWORKCONFIG_DICT_KEY_PRIVATE "p" #define ZT_NETWORKCONFIG_DICT_KEY_PRIVATE "p"
// text // text
#define ZT_NETWORKCONFIG_DICT_KEY_NAME "n" #define ZT_NETWORKCONFIG_DICT_KEY_NAME "n"
// text // text
#define ZT_NETWORKCONFIG_DICT_KEY_DESC "d" #define ZT_NETWORKCONFIG_DICT_KEY_DESC "d"
// IP/bits[,IP/bits,...] // IP/bits[,IP/bits,...]
// Note that IPs that end in all zeroes are routes with no assignment in them. // Note that IPs that end in all zeroes are routes with no assignment in them.
#define ZT_NETWORKCONFIG_DICT_KEY_IPV4_STATIC "v4s" #define ZT_NETWORKCONFIG_DICT_KEY_IPV4_STATIC "v4s"
// IP/bits[,IP/bits,...] // IP/bits[,IP/bits,...]
// Note that IPs that end in all zeroes are routes with no assignment in them. // Note that IPs that end in all zeroes are routes with no assignment in them.
#define ZT_NETWORKCONFIG_DICT_KEY_IPV6_STATIC "v6s" #define ZT_NETWORKCONFIG_DICT_KEY_IPV6_STATIC "v6s"
// serialized CertificateOfMembership // serialized CertificateOfMembership
#define ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATE_OF_MEMBERSHIP "com" #define ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATE_OF_MEMBERSHIP "com"
// 0/1 // 0/1
#define ZT_NETWORKCONFIG_DICT_KEY_ENABLE_BROADCAST "eb" #define ZT_NETWORKCONFIG_DICT_KEY_ENABLE_BROADCAST "eb"
// 0/1 // 0/1
#define ZT_NETWORKCONFIG_DICT_KEY_ALLOW_PASSIVE_BRIDGING "pb" #define ZT_NETWORKCONFIG_DICT_KEY_ALLOW_PASSIVE_BRIDGING "pb"
// node[,node,...] // node[,node,...]
#define ZT_NETWORKCONFIG_DICT_KEY_ACTIVE_BRIDGES "ab" #define ZT_NETWORKCONFIG_DICT_KEY_ACTIVE_BRIDGES "ab"
// node;IP/port[,node;IP/port] // node;IP/port[,node;IP/port]
#define ZT_NETWORKCONFIG_DICT_KEY_RELAYS "rl" #define ZT_NETWORKCONFIG_DICT_KEY_RELAYS "rl"
// IP/metric[,IP/metric,...] // IP/metric[,IP/metric,...]
#define ZT_NETWORKCONFIG_DICT_KEY_GATEWAYS "gw" #define ZT_NETWORKCONFIG_DICT_KEY_GATEWAYS "gw"
@ -158,7 +147,7 @@ public:
inline bool isPublic() const throw() { return (!_private); } inline bool isPublic() const throw() { return (!_private); }
inline bool isPrivate() const throw() { return _private; } inline bool isPrivate() const throw() { return _private; }
inline const std::string &name() const throw() { return _name; } inline const std::string &name() const throw() { return _name; }
inline const std::string &description() const throw() { return _description; } inline const std::vector<InetAddress> &localRoutes() const throw() { return _localRoutes; }
inline const std::vector<InetAddress> &staticIps() const throw() { return _staticIps; } inline const std::vector<InetAddress> &staticIps() const throw() { return _staticIps; }
inline const std::vector<InetAddress> &gateways() const throw() { return _gateways; } inline const std::vector<InetAddress> &gateways() const throw() { return _gateways; }
inline const std::vector<Address> &activeBridges() const throw() { return _activeBridges; } inline const std::vector<Address> &activeBridges() const throw() { return _activeBridges; }
@ -194,7 +183,7 @@ private:
bool _private; bool _private;
bool _enableBroadcast; bool _enableBroadcast;
std::string _name; std::string _name;
std::string _description; std::vector<InetAddress> _localRoutes;
std::vector<InetAddress> _staticIps; std::vector<InetAddress> _staticIps;
std::vector<InetAddress> _gateways; std::vector<InetAddress> _gateways;
std::vector<Address> _activeBridges; std::vector<Address> _activeBridges;
@ -207,4 +196,3 @@ private:
} // namespace ZeroTier } // namespace ZeroTier
#endif #endif

View file

@ -52,10 +52,9 @@ public:
enum ResultCode enum ResultCode
{ {
NETCONF_QUERY_OK = 0, NETCONF_QUERY_OK = 0,
NETCONF_QUERY_OK_BUT_NOT_NEWER = 1, NETCONF_QUERY_OBJECT_NOT_FOUND = 1,
NETCONF_QUERY_OBJECT_NOT_FOUND = 2, NETCONF_QUERY_ACCESS_DENIED = 2,
NETCONF_QUERY_ACCESS_DENIED = 3, NETCONF_QUERY_INTERNAL_SERVER_ERROR = 3
NETCONF_QUERY_INTERNAL_SERVER_ERROR = 4
}; };
NetworkController() {} NetworkController() {}

View file

@ -41,6 +41,6 @@
/** /**
* Revision * Revision
*/ */
#define ZEROTIER_ONE_VERSION_REVISION 3 #define ZEROTIER_ONE_VERSION_REVISION 4
#endif #endif