mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-05 20:13:44 +02:00
Small controller revisions, first run of controller API model JavaScript.
This commit is contained in:
parent
ff5e22031a
commit
2c682b4d1c
3 changed files with 577 additions and 75 deletions
|
@ -638,14 +638,10 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST(
|
||||||
if (newAuth != OSUtils::jsonBool(member["authorized"],false)) {
|
if (newAuth != OSUtils::jsonBool(member["authorized"],false)) {
|
||||||
member["authorized"] = newAuth;
|
member["authorized"] = newAuth;
|
||||||
member[((newAuth) ? "lastAuthorizedTime" : "lastDeauthorizedTime")] = now;
|
member[((newAuth) ? "lastAuthorizedTime" : "lastDeauthorizedTime")] = now;
|
||||||
|
if (newAuth) {
|
||||||
json ah;
|
member["lastAuthorizedCredentialType"] = "api";
|
||||||
ah["a"] = newAuth;
|
member["lastAuthorizedCredential"] = json();
|
||||||
ah["by"] = "api";
|
}
|
||||||
ah["ts"] = now;
|
|
||||||
ah["ct"] = json();
|
|
||||||
ah["c"] = json();
|
|
||||||
member["authHistory"].push_back(ah);
|
|
||||||
|
|
||||||
// Member is being de-authorized, so spray Revocation objects to all online members
|
// Member is being de-authorized, so spray Revocation objects to all online members
|
||||||
if (!newAuth) {
|
if (!newAuth) {
|
||||||
|
@ -896,22 +892,15 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST(
|
||||||
|
|
||||||
if (b.count("authTokens")) {
|
if (b.count("authTokens")) {
|
||||||
json &authTokens = b["authTokens"];
|
json &authTokens = b["authTokens"];
|
||||||
if (authTokens.is_array()) {
|
if (authTokens.is_object()) {
|
||||||
json nat = json::array();
|
json nat;
|
||||||
for(unsigned long i=0;i<authTokens.size();++i) {
|
for(json::iterator t(authTokens.begin());t!=authTokens.end();++t) {
|
||||||
json &token = authTokens[i];
|
if ((t.value().is_number())&&(t.value() >= 0))
|
||||||
if (token.is_object()) {
|
nat[t.key()] = t.value();
|
||||||
std::string tstr = token["token"];
|
|
||||||
if (tstr.length() > 0) {
|
|
||||||
json t = json::object();
|
|
||||||
t["token"] = tstr;
|
|
||||||
t["expires"] = OSUtils::jsonInt(token["expires"],0ULL);
|
|
||||||
t["maxUsesPerMember"] = OSUtils::jsonInt(token["maxUsesPerMember"],0ULL);
|
|
||||||
nat.push_back(t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
network["authTokens"] = nat;
|
network["authTokens"] = nat;
|
||||||
|
} else {
|
||||||
|
network["authTokens"] = {{}};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1268,56 +1257,29 @@ void EmbeddedNetworkController::_request(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine whether and how member is authorized
|
// Determine whether and how member is authorized
|
||||||
const char *authorizedBy = (const char *)0;
|
bool authorized = false;
|
||||||
bool autoAuthorized = false;
|
bool autoAuthorized = false;
|
||||||
json autoAuthCredentialType,autoAuthCredential;
|
json autoAuthCredentialType,autoAuthCredential;
|
||||||
if (OSUtils::jsonBool(member["authorized"],false)) {
|
if (OSUtils::jsonBool(member["authorized"],false)) {
|
||||||
authorizedBy = "memberIsAuthorized";
|
authorized = true;
|
||||||
} else if (!OSUtils::jsonBool(network["private"],true)) {
|
} else if (!OSUtils::jsonBool(network["private"],true)) {
|
||||||
authorizedBy = "networkIsPublic";
|
authorized = true;
|
||||||
json &ahist = member["authHistory"];
|
autoAuthorized = true;
|
||||||
if ((!ahist.is_array())||(ahist.size() == 0))
|
autoAuthCredentialType = "public";
|
||||||
autoAuthorized = true;
|
|
||||||
} else {
|
} else {
|
||||||
char presentedAuth[512];
|
char presentedAuth[512];
|
||||||
if (metaData.get(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_AUTH,presentedAuth,sizeof(presentedAuth)) > 0) {
|
if (metaData.get(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_AUTH,presentedAuth,sizeof(presentedAuth)) > 0) {
|
||||||
presentedAuth[511] = (char)0; // sanity check
|
presentedAuth[511] = (char)0; // sanity check
|
||||||
|
|
||||||
// Check for bearer token presented by member
|
|
||||||
if ((strlen(presentedAuth) > 6)&&(!strncmp(presentedAuth,"token:",6))) {
|
if ((strlen(presentedAuth) > 6)&&(!strncmp(presentedAuth,"token:",6))) {
|
||||||
const char *const presentedToken = presentedAuth + 6;
|
const char *const presentedToken = presentedAuth + 6;
|
||||||
|
json authTokens(network["authTokens"]);
|
||||||
json &authTokens = network["authTokens"];
|
json &tokenExpires = authTokens[presentedToken];
|
||||||
if (authTokens.is_array()) {
|
if (tokenExpires.is_number()) {
|
||||||
for(unsigned long i=0;i<authTokens.size();++i) {
|
if ((tokenExpires == 0)||(tokenExpires > now)) {
|
||||||
json &token = authTokens[i];
|
authorized = true;
|
||||||
if (token.is_object()) {
|
autoAuthorized = true;
|
||||||
const uint64_t expires = OSUtils::jsonInt(token["expires"],0ULL);
|
autoAuthCredentialType = "token";
|
||||||
const uint64_t maxUses = OSUtils::jsonInt(token["maxUsesPerMember"],0ULL);
|
autoAuthCredential = presentedToken;
|
||||||
std::string tstr = OSUtils::jsonString(token["token"],"");
|
|
||||||
|
|
||||||
if (((expires == 0ULL)||(expires > now))&&(tstr == presentedToken)) {
|
|
||||||
bool usable = (maxUses == 0);
|
|
||||||
if (!usable) {
|
|
||||||
uint64_t useCount = 0;
|
|
||||||
json &ahist = member["authHistory"];
|
|
||||||
if (ahist.is_array()) {
|
|
||||||
for(unsigned long j=0;j<ahist.size();++j) {
|
|
||||||
json &ah = ahist[j];
|
|
||||||
if ((OSUtils::jsonString(ah["ct"],"") == "token")&&(OSUtils::jsonString(ah["c"],"") == tstr)&&(OSUtils::jsonBool(ah["a"],false)))
|
|
||||||
++useCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
usable = (useCount < maxUses);
|
|
||||||
}
|
|
||||||
if (usable) {
|
|
||||||
authorizedBy = "token";
|
|
||||||
autoAuthorized = true;
|
|
||||||
autoAuthCredentialType = "token";
|
|
||||||
autoAuthCredential = tstr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1325,23 +1287,16 @@ void EmbeddedNetworkController::_request(
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we auto-authorized, update member record
|
// If we auto-authorized, update member record
|
||||||
if ((autoAuthorized)&&(authorizedBy)) {
|
if ((autoAuthorized)&&(authorized)) {
|
||||||
member["authorized"] = true;
|
member["authorized"] = true;
|
||||||
member["lastAuthorizedTime"] = now;
|
member["lastAuthorizedTime"] = now;
|
||||||
|
member["lastAuthorizedCredentialType"] = autoAuthCredentialType;
|
||||||
json ah;
|
member["lastAuthorizedCredential"] = autoAuthCredential;
|
||||||
ah["a"] = true;
|
|
||||||
ah["by"] = authorizedBy;
|
|
||||||
ah["ts"] = now;
|
|
||||||
ah["ct"] = autoAuthCredentialType;
|
|
||||||
ah["c"] = autoAuthCredential;
|
|
||||||
member["authHistory"].push_back(ah);
|
|
||||||
|
|
||||||
json &revj = member["revision"];
|
json &revj = member["revision"];
|
||||||
member["revision"] = (revj.is_number() ? ((uint64_t)revj + 1ULL) : 1ULL);
|
member["revision"] = (revj.is_number() ? ((uint64_t)revj + 1ULL) : 1ULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (authorizedBy) {
|
if (authorized) {
|
||||||
// Update version info and meta-data if authorized and if this is a genuine request
|
// Update version info and meta-data if authorized and if this is a genuine request
|
||||||
if (requestPacketId) {
|
if (requestPacketId) {
|
||||||
const uint64_t vMajor = metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MAJOR_VERSION,0);
|
const uint64_t vMajor = metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MAJOR_VERSION,0);
|
||||||
|
|
|
@ -129,7 +129,6 @@ private:
|
||||||
inline void _initMember(nlohmann::json &member)
|
inline void _initMember(nlohmann::json &member)
|
||||||
{
|
{
|
||||||
if (!member.count("authorized")) member["authorized"] = false;
|
if (!member.count("authorized")) member["authorized"] = false;
|
||||||
if (!member.count("authHistory")) member["authHistory"] = nlohmann::json::array();
|
|
||||||
if (!member.count("ipAssignments")) member["ipAssignments"] = nlohmann::json::array();
|
if (!member.count("ipAssignments")) member["ipAssignments"] = nlohmann::json::array();
|
||||||
if (!member.count("activeBridge")) member["activeBridge"] = false;
|
if (!member.count("activeBridge")) member["activeBridge"] = false;
|
||||||
if (!member.count("tags")) member["tags"] = nlohmann::json::array();
|
if (!member.count("tags")) member["tags"] = nlohmann::json::array();
|
||||||
|
@ -139,6 +138,8 @@ private:
|
||||||
if (!member.count("revision")) member["revision"] = 0ULL;
|
if (!member.count("revision")) member["revision"] = 0ULL;
|
||||||
if (!member.count("lastDeauthorizedTime")) member["lastDeauthorizedTime"] = 0ULL;
|
if (!member.count("lastDeauthorizedTime")) member["lastDeauthorizedTime"] = 0ULL;
|
||||||
if (!member.count("lastAuthorizedTime")) member["lastAuthorizedTime"] = 0ULL;
|
if (!member.count("lastAuthorizedTime")) member["lastAuthorizedTime"] = 0ULL;
|
||||||
|
if (!member.count("lastAuthorizedCredentialType")) member["lastAuthorizedCredentialType"] = nlohmann::json();
|
||||||
|
if (!member.count("lastAuthorizedCredential")) member["lastAuthorizedCredential"] = nlohmann::json();
|
||||||
if (!member.count("vMajor")) member["vMajor"] = -1;
|
if (!member.count("vMajor")) member["vMajor"] = -1;
|
||||||
if (!member.count("vMinor")) member["vMinor"] = -1;
|
if (!member.count("vMinor")) member["vMinor"] = -1;
|
||||||
if (!member.count("vRev")) member["vRev"] = -1;
|
if (!member.count("vRev")) member["vRev"] = -1;
|
||||||
|
@ -156,7 +157,7 @@ private:
|
||||||
if (!network.count("enableBroadcast")) network["enableBroadcast"] = true;
|
if (!network.count("enableBroadcast")) network["enableBroadcast"] = true;
|
||||||
if (!network.count("v4AssignMode")) network["v4AssignMode"] = {{"zt",false}};
|
if (!network.count("v4AssignMode")) network["v4AssignMode"] = {{"zt",false}};
|
||||||
if (!network.count("v6AssignMode")) network["v6AssignMode"] = {{"rfc4193",false},{"zt",false},{"6plane",false}};
|
if (!network.count("v6AssignMode")) network["v6AssignMode"] = {{"rfc4193",false},{"zt",false},{"6plane",false}};
|
||||||
if (!network.count("authTokens")) network["authTokens"] = nlohmann::json::array();
|
if (!network.count("authTokens")) network["authTokens"] = {{}};
|
||||||
if (!network.count("capabilities")) network["capabilities"] = nlohmann::json::array();
|
if (!network.count("capabilities")) network["capabilities"] = nlohmann::json::array();
|
||||||
if (!network.count("tags")) network["tags"] = nlohmann::json::array();
|
if (!network.count("tags")) network["tags"] = nlohmann::json::array();
|
||||||
if (!network.count("routes")) network["routes"] = nlohmann::json::array();
|
if (!network.count("routes")) network["routes"] = nlohmann::json::array();
|
||||||
|
|
546
controller/controller-api-model.js
Normal file
546
controller/controller-api-model.js
Normal file
|
@ -0,0 +1,546 @@
|
||||||
|
/*
|
||||||
|
* A JavaScript class based model for the ZeroTier controller microservice API
|
||||||
|
* Copyright (C) 2011-2017 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/>.
|
||||||
|
*
|
||||||
|
* --
|
||||||
|
*
|
||||||
|
* You can be released from the requirements of the license by purchasing
|
||||||
|
* a commercial license. Buying such a license is mandatory as soon as you
|
||||||
|
* develop commercial closed-source software that incorporates or links
|
||||||
|
* directly against ZeroTier software without disclosing the source code
|
||||||
|
* of your own application.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Goes through a rule set array and makes sure it's valid, returning a canonicalized version
|
||||||
|
*
|
||||||
|
* @param {array[object]} rules Array of ZeroTier rules
|
||||||
|
* @return New array of canonicalized rules
|
||||||
|
* @throws {Error} Rule set is invalid
|
||||||
|
*/
|
||||||
|
function formatRuleSetArray(rules)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
exports.formatRuleSetArray = formatRuleSetArray;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} IP with optional /netmask|port section
|
||||||
|
* @return 4, 6, or 0 if invalid
|
||||||
|
*/
|
||||||
|
function ipClassify(ip)
|
||||||
|
{
|
||||||
|
if ((!ip)||(typeof ip !== 'string'))
|
||||||
|
return 0;
|
||||||
|
let ips = ip.split('/');
|
||||||
|
if (ips.length > 0) {
|
||||||
|
if (ips.length > 1) {
|
||||||
|
if (ips[1].length === 0)
|
||||||
|
return 0;
|
||||||
|
for(let i=0;i<ips[1].length;++i) {
|
||||||
|
if ('0123456789'.indexOf(ips[1].charAt(i)) < 0)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ips[0].indexOf(':') > 0) {
|
||||||
|
for(let i=0;i<ips[0].length;++i) {
|
||||||
|
if ('0123456789abcdefABCDEF:'.indexOf(ips[0].charAt(i)) < 0)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 6;
|
||||||
|
} else if (ips[0].indexOf('.') > 0) {
|
||||||
|
for(let i=0;i<ips[0].length;++i) {
|
||||||
|
if ('0123456789.'.indexOf(ips[0].charAt(i)) < 0)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
exports.ipClassify = ipClassify;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make sure a string is lower case hex and optionally left pad
|
||||||
|
*
|
||||||
|
* @param x {string} String to format/canonicalize
|
||||||
|
* @param l {number} Length of desired string or 0/null to not left pad
|
||||||
|
* @return Padded string
|
||||||
|
*/
|
||||||
|
function formatZeroTierIdentifier(x,l)
|
||||||
|
{
|
||||||
|
x = (x) ? x.toString().toLowerCase() : '';
|
||||||
|
l = ((typeof l !== 'number')||(l < 0)) ? 0 : l;
|
||||||
|
|
||||||
|
let r = '';
|
||||||
|
for(let i=0;i<x.length;++i) {
|
||||||
|
let c = x.charAt(i);
|
||||||
|
if ('0123456789abcdef'.indexOf(c) >= 0) {
|
||||||
|
r += c;
|
||||||
|
if (r.length === l)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (r.length < l)
|
||||||
|
r = '0' + r;
|
||||||
|
|
||||||
|
return r;
|
||||||
|
};
|
||||||
|
exports.formatZeroTierIdentifier = formatZeroTierIdentifier;
|
||||||
|
|
||||||
|
// Internal container classes
|
||||||
|
class _V4AssignMode
|
||||||
|
{
|
||||||
|
get zt() { return (this._zt)||false; }
|
||||||
|
set zt(b) { this._zt = !!b; }
|
||||||
|
toJSON()
|
||||||
|
{
|
||||||
|
return { zt: this.zt };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
class _v6AssignMode
|
||||||
|
{
|
||||||
|
get ['6plane'] { return (this._6plane)||false; }
|
||||||
|
set ['6plane'](b) { this._6plane = !!b; }
|
||||||
|
get zt() { return (this._zt)||false; }
|
||||||
|
set zt(b) { this._zt = !!b; }
|
||||||
|
get rfc4193() { return (this._rfc4193)||false; }
|
||||||
|
set rfc4193(b) { this._rfc4193 = !!b; }
|
||||||
|
toJSON()
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
zt: this.zt,
|
||||||
|
rfc4193: this.rfc4193,
|
||||||
|
'6plane': this['6plane']
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Network
|
||||||
|
{
|
||||||
|
constructor(obj)
|
||||||
|
{
|
||||||
|
this.clear();
|
||||||
|
this.patch(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
get objtype() { return 'network'; }
|
||||||
|
|
||||||
|
get id() { return this._id; }
|
||||||
|
set id(x) { return (this._id = formatZeroTierIdentifier(x,16)); }
|
||||||
|
|
||||||
|
get nwid() { return this._id; } // legacy
|
||||||
|
|
||||||
|
get authTokens() { return this._authTokens; }
|
||||||
|
set authTokens(at)
|
||||||
|
{
|
||||||
|
this._authTokens = {};
|
||||||
|
if ((at)&&(typeof at === 'object')&&(!Array.isArray(at))) {
|
||||||
|
for(let k in at) {
|
||||||
|
let exp = parseInt(at[k])||0;
|
||||||
|
if (exp >= 0)
|
||||||
|
this._authTokens[k] = exp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this._authTokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
get capabilities() { return this._capabilities; }
|
||||||
|
set capabilities(c)
|
||||||
|
{
|
||||||
|
let ca = [];
|
||||||
|
let ids = {};
|
||||||
|
if ((c)&&(Array.isArray(c))) {
|
||||||
|
for(let a=0;a<c.length;++a) {
|
||||||
|
let cap = c[a];
|
||||||
|
if ((cap)&&(typeof cap === 'object')&&(!Array.isArray(cap))) {
|
||||||
|
let capId = parseInt(cap.id)||-1;
|
||||||
|
if ((capId >= 0)&&(capId <= 0xffffffff)&&(!ids[capId])) {
|
||||||
|
ids[capId] = true;
|
||||||
|
let capDefault = !!cap['default'];
|
||||||
|
let capRules = formatRuleSetArray(cap.rules);
|
||||||
|
ca.push({
|
||||||
|
id: capId,
|
||||||
|
'default': capDefault,
|
||||||
|
rules: capRules
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ca.sort(function(a,b) {
|
||||||
|
a = a.id;
|
||||||
|
b = b.id;
|
||||||
|
return ((a > b) ? 1 : ((a < b) ? -1 : 0));
|
||||||
|
});
|
||||||
|
this._capabilities = ca;
|
||||||
|
return ca;
|
||||||
|
}
|
||||||
|
|
||||||
|
get ipAssignmentPools() return { this._ipAssignmentPools; }
|
||||||
|
set ipAssignmentPools(ipp)
|
||||||
|
{
|
||||||
|
let pa = [];
|
||||||
|
let ranges = {};
|
||||||
|
if ((ipp)&&(Array.isArray(ipp))) {
|
||||||
|
for(let a=0;a<ipp.length;++a) {
|
||||||
|
let range = ipp[a];
|
||||||
|
if ((range)&&(typeof range === 'object')&&(!Array.isArray(range))) {
|
||||||
|
let start = range.ipRangeStart;
|
||||||
|
let end = range.ipRangeEnd;
|
||||||
|
if ((start)&&(end)) {
|
||||||
|
let stype = ipClassify(start);
|
||||||
|
if ((stype > 0)&&(stype === ipClassify(end))&&(!ranges[start+'_'+end])) {
|
||||||
|
ranges[start+'_'+end] = true;
|
||||||
|
pa.push({ ipRangeStart: start, ipRangeEnd: end });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pa.sort(function(a,b) { return a.ipRangeStart.localeCompare(b.ipRangeStart); });
|
||||||
|
this._ipAssignmentPools = pa;
|
||||||
|
return pa;
|
||||||
|
}
|
||||||
|
|
||||||
|
get multicastLimit() return { this._multicastLimit; }
|
||||||
|
set multicastLimit(n)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
let nn = parseInt(n)||0;
|
||||||
|
this._multicastLimit = (nn >= 0) ? nn : 0;
|
||||||
|
} catch (e) {
|
||||||
|
this._multicastLimit = 0;
|
||||||
|
}
|
||||||
|
return this._multicastLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
get routes() return { this._routes; }
|
||||||
|
set routes(r)
|
||||||
|
{
|
||||||
|
let ra = [];
|
||||||
|
let targets = {};
|
||||||
|
if ((r)&&(Array.isArray(r))) {
|
||||||
|
for(let a=0;a<r.length;++a) {
|
||||||
|
let route = r[a];
|
||||||
|
if ((route)&&(typeof route === 'object')&&(!Array.isArray(route))) {
|
||||||
|
let routeTarget = route.target;
|
||||||
|
let routeVia = route.via||null;
|
||||||
|
let rtt = ipClassify(routeTarget);
|
||||||
|
if ((rtt > 0)&&((routeVia === null)||(ipClassify(routeVia) === rtt))&&(!targets[routeTarget])) {
|
||||||
|
targets[routeTarget] = true;
|
||||||
|
ra.push({ target: routeTarget, via: routeVia });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ra.sort(function(a,b) { return a.routeTarget.localeCompare(b.routeTarget); });
|
||||||
|
this._routes = ra;
|
||||||
|
return ra;
|
||||||
|
}
|
||||||
|
|
||||||
|
get tags() return { this._tags; }
|
||||||
|
set tags(t)
|
||||||
|
{
|
||||||
|
let ta = [];
|
||||||
|
if ((t)&&(Array.isArray(t))) {
|
||||||
|
for(let a=0;a<t.length;++a) {
|
||||||
|
let tag = t[a];
|
||||||
|
if ((tag)&&(typeof tag === 'object')&&(!Array.isArray(tag))) {
|
||||||
|
let tagId = parseInt(tag.id)||-1;
|
||||||
|
if ((tagId >= 0)||(tagId <= 0xffffffff)) {
|
||||||
|
let tagDefault = tag.default;
|
||||||
|
if (typeof tagDefault !== 'number')
|
||||||
|
tagDefault = parseInt(tagDefault)||null;
|
||||||
|
if ((tagDefault < 0)||(tagDefault > 0xffffffff))
|
||||||
|
tagDefault = null;
|
||||||
|
ta.push({ 'id': tagId, 'default': tagDefault });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ta.sort(function(a,b) {
|
||||||
|
a = a.id;
|
||||||
|
b = b.id;
|
||||||
|
return ((a > b) ? 1 : ((a < b) ? -1 : 0));
|
||||||
|
});
|
||||||
|
this._tags = ta;
|
||||||
|
return ta;
|
||||||
|
}
|
||||||
|
|
||||||
|
get v4AssignMode() return { this._v4AssignMode; }
|
||||||
|
set v4AssignMode(m)
|
||||||
|
{
|
||||||
|
if ((m)&&(typeof m === 'object')&&(!Array.isArray(m))) {
|
||||||
|
this._v4AssignMode.zt = m.zt;
|
||||||
|
} else if (m === 'zt') { // legacy
|
||||||
|
this._v4AssignMode.zt = true;
|
||||||
|
} else {
|
||||||
|
this._v4AssignMode.zt = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get v6AssignMode() return { this._v6AssignMode; }
|
||||||
|
set v6AssignMode(m)
|
||||||
|
{
|
||||||
|
if ((m)&&(typeof m === 'object')&&(!Array.isArray(m))) {
|
||||||
|
this._v6AssignMode.zt = m.zt;
|
||||||
|
this._v6AssignMode.rfc4193 = m.rfc4193;
|
||||||
|
this._v6AssignMode['6plane'] = m['6plane'];
|
||||||
|
} else if (typeof m === 'string') { // legacy
|
||||||
|
let ms = m.split(',');
|
||||||
|
this._v6AssignMode.zt = false;
|
||||||
|
this._v6AssignMode.rfc4193 = false;
|
||||||
|
this._v6AssignMode['6plane'] = false;
|
||||||
|
for(let i=0;i<ms.length;++i) {
|
||||||
|
switch(ms[i]) {
|
||||||
|
case 'zt':
|
||||||
|
this._v6AssignMode.zt = true;
|
||||||
|
break;
|
||||||
|
case 'rfc4193':
|
||||||
|
this._v6AssignMode.rfc4193 = true;
|
||||||
|
break;
|
||||||
|
case '6plane':
|
||||||
|
this._v6AssignMode['6plane'] = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this._v6AssignMode.zt = false;
|
||||||
|
this._v6AssignMode.rfc4193 = false;
|
||||||
|
this._v6AssignMode['6plane'] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get rules() { return this._rules; }
|
||||||
|
set rules(r) { this._rules = formatRuleSetArray(r); }
|
||||||
|
|
||||||
|
get enableBroadcast() { return this._enableBroadcast; }
|
||||||
|
set enableBroadcast(b) { this._enableBroadcast = !!b; }
|
||||||
|
|
||||||
|
get mtu() { return this._mtu; }
|
||||||
|
set mtu(n)
|
||||||
|
{
|
||||||
|
let mtu = parseInt(n)||0;
|
||||||
|
if (mtu <= 1280) mtu = 1280; // minimum as per IPv6 spec
|
||||||
|
if (mtu >= 10000) mtu = 10000; // maximum as per ZT spec
|
||||||
|
this._mtu = mtu;
|
||||||
|
}
|
||||||
|
|
||||||
|
get name() { return this._name; }
|
||||||
|
set name(n)
|
||||||
|
{
|
||||||
|
if (typeof n === 'string')
|
||||||
|
this._name = n;
|
||||||
|
else if (typeof n === 'number')
|
||||||
|
this._name = n.toString();
|
||||||
|
else this._name = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
get private() { return this._private; }
|
||||||
|
set private(b)
|
||||||
|
{
|
||||||
|
// This is really meaningful for security, so make true unless explicitly set to false.
|
||||||
|
this._private = (b !== false);
|
||||||
|
}
|
||||||
|
|
||||||
|
get activeMemberCount() { return this.__activeMemberCount; }
|
||||||
|
get authorizedMemberCount() { return this.__authorizedMemberCount; }
|
||||||
|
get totalMemberCount() { return this.__totalMemberCount; }
|
||||||
|
get clock() { return this.__clock; }
|
||||||
|
get creationTime() { return this.__creationTime; }
|
||||||
|
get revision() { return this.__revision; }
|
||||||
|
|
||||||
|
toJSONExcludeControllerGenerated()
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
id: this.id,
|
||||||
|
objtype: 'network',
|
||||||
|
nwid: this.nwid,
|
||||||
|
authTokens: this.authTokens,
|
||||||
|
capabilities: this.capabilities,
|
||||||
|
ipAssignmentPools: this.ipAssignmentPools,
|
||||||
|
multicastLimit: this.multicastLimit,
|
||||||
|
routes: this.routes,
|
||||||
|
tags: this.tags,
|
||||||
|
v4AssignMode: this._v4AssignMode.toJSON(),
|
||||||
|
v6AssignMode: this._v6AssignMode.toJSON(),
|
||||||
|
rules: this.rules,
|
||||||
|
enableBroadcast: this.enableBroadcast,
|
||||||
|
mtu: this.mtu,
|
||||||
|
name: this.name,
|
||||||
|
'private': this['private']
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
toJSON()
|
||||||
|
{
|
||||||
|
var j = this.toJSONExcludeControllerGenerated();
|
||||||
|
j.activeMemberCount = this.activeMemberCount;
|
||||||
|
j.authorizedMemberCount = this.authorizedMemberCount;
|
||||||
|
j.totalMemberCount = this.totalMemberCount;
|
||||||
|
j.clock = this.clock;
|
||||||
|
j.creationTime = this.creationTime;
|
||||||
|
j.revision = this.revision;
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
|
||||||
|
clear()
|
||||||
|
{
|
||||||
|
this._id = '';
|
||||||
|
this._authTokens = {};
|
||||||
|
this._capabilities = [];
|
||||||
|
this._ipAssignmentPools = [];
|
||||||
|
this._multicastLimit = 32;
|
||||||
|
this._routes = [];
|
||||||
|
this._tags = [];
|
||||||
|
this._v4AssignMode = new _V4AssignMode();
|
||||||
|
this._v6AssignMode = new _v6AssignMode();
|
||||||
|
this._rules = [];
|
||||||
|
this._enableBroadcast = true;
|
||||||
|
this._mtu = 2800;
|
||||||
|
this._name = '';
|
||||||
|
this._private = true;
|
||||||
|
|
||||||
|
this.__activeMemberCount = 0;
|
||||||
|
this.__authorizedMemberCount = 0;
|
||||||
|
this.__totalMemberCount = 0;
|
||||||
|
this.__clock = 0;
|
||||||
|
this.__creationTime = 0;
|
||||||
|
this.__revision = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
patch(obj)
|
||||||
|
{
|
||||||
|
if (obj instanceof Network)
|
||||||
|
obj = obj.toJSON();
|
||||||
|
if ((obj)&&(typeof obj === 'object')&&(!Array.isArray(obj))) {
|
||||||
|
for(var k in obj) {
|
||||||
|
try {
|
||||||
|
switch(k) {
|
||||||
|
case 'id':
|
||||||
|
case 'authTokens':
|
||||||
|
case 'capabilities':
|
||||||
|
case 'ipAssignmentPools':
|
||||||
|
case 'multicastLimit':
|
||||||
|
case 'routes':
|
||||||
|
case 'tags':
|
||||||
|
case 'rules':
|
||||||
|
case 'enableBroadcast':
|
||||||
|
case 'mtu':
|
||||||
|
case 'name':
|
||||||
|
case 'private':
|
||||||
|
case 'v4AssignMode':
|
||||||
|
case 'v6AssignMode':
|
||||||
|
this[k] = obj[k];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'activeMemberCount':
|
||||||
|
case 'authorizedMemberCount':
|
||||||
|
case 'totalMemberCount':
|
||||||
|
case 'clock':
|
||||||
|
case 'creationTime':
|
||||||
|
case 'revision':
|
||||||
|
this['__'+k] = parseInt(obj[k])||0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (e) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
exports.Network = Network;
|
||||||
|
|
||||||
|
class Member
|
||||||
|
{
|
||||||
|
constructor(obj)
|
||||||
|
{
|
||||||
|
this.clear();
|
||||||
|
this.patch(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
get objtype() { return 'member'; }
|
||||||
|
|
||||||
|
get id() { return this._id; }
|
||||||
|
set id(x) { this._id = formatZeroTierIdentifier((typeof x === 'number') ? x.toString(16) : x,10); }
|
||||||
|
|
||||||
|
get address() { return this._id; } // legacy
|
||||||
|
|
||||||
|
get nwid() { return this._nwid; }
|
||||||
|
set nwid(x) { this._nwid = formatZeroTierIdentifier(x,16); }
|
||||||
|
|
||||||
|
get controllerId() { return this.nwid.substr(0,10); }
|
||||||
|
|
||||||
|
get authorized() { return this._authorized; }
|
||||||
|
set authorized(b) { this._authorized = (b === true); } // security critical so require explicit set to true
|
||||||
|
|
||||||
|
get activeBridge() { return this._activeBridge; }
|
||||||
|
set activeBridge(b) { this._activeBridge = !!b; }
|
||||||
|
|
||||||
|
get capabilities() { return this._capabilities; }
|
||||||
|
set capabilities(c)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
get identity() { return this._identity; }
|
||||||
|
set identity(istr)
|
||||||
|
{
|
||||||
|
if ((istr)&&(typeof istr === 'string'))
|
||||||
|
this._identity = istr;
|
||||||
|
else this._identity = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
get ipAssignments() { return this._ipAssignments; }
|
||||||
|
set ipAssignments(ipa)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
get noAutoAssignIps() { return this._noAutoAssignIps; }
|
||||||
|
set noAutoAssignIps(b) { this._noAutoAssignIps = !!b; }
|
||||||
|
|
||||||
|
get tags() { return this._tags; }
|
||||||
|
set tags(t)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
clear()
|
||||||
|
{
|
||||||
|
this._id = '';
|
||||||
|
this._nwid = '';
|
||||||
|
this._authorized = false;
|
||||||
|
this._activeBridge = false;
|
||||||
|
this._capabilities = [];
|
||||||
|
this._identity = '';
|
||||||
|
this._ipAssignments = [];
|
||||||
|
this._noAutoAssignIps = false;
|
||||||
|
this._tags = [];
|
||||||
|
|
||||||
|
this.__creationTime = 0;
|
||||||
|
this.__lastAuthorizedTime = 0;
|
||||||
|
this.__lastAuthorizedCredentialType = null;
|
||||||
|
this.__lastAuthorizedCredential = null;
|
||||||
|
this.__lastDeauthorizedTime = 0;
|
||||||
|
this.__physicalAddr = '';
|
||||||
|
this.__revision = 0;
|
||||||
|
this.__vMajor = 0;
|
||||||
|
this.__vMinor = 0;
|
||||||
|
this.__vRev = 0;
|
||||||
|
this.__vProto = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
exports.Member = Member;
|
Loading…
Add table
Reference in a new issue