mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-01-18 18:56:24 +00:00
.
This commit is contained in:
parent
a4bc40542b
commit
23fe8975e7
@ -1,794 +0,0 @@
|
||||
/*
|
||||
* 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';
|
||||
|
||||
/**
|
||||
* @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;
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
let r = [];
|
||||
if ((rules)&&(Array.isArray(rules))) {
|
||||
for(let a=0;a<rules.length;++a) {
|
||||
let rule = rules[a];
|
||||
if (rule.type) {
|
||||
let nr = null;
|
||||
switch(rule.type) {
|
||||
case 'ACTION_DROP':
|
||||
case 'ACTION_ACCEPT':
|
||||
case 'ACTION_BREAK':
|
||||
break;
|
||||
case 'ACTION_TEE':
|
||||
case 'ACTION_WATCH':
|
||||
nr = { 'type': rule['type'],'not': !!rule['not'],'or': !!rule['or'] };
|
||||
nr.address = formatZeroTierIdentifier(rule.address,10);
|
||||
nr.flags = parseInt(rule.flags)||0;
|
||||
nr['length'] = parseInt(rule['length'])||0;
|
||||
break;
|
||||
case 'ACTION_REDIRECT':
|
||||
nr = { 'type': rule['type'],'not': !!rule['not'],'or': !!rule['or'] };
|
||||
nr.address = formatZeroTierIdentifier(rule.address,10);
|
||||
nr.flags = parseInt(rule.flags)||0;
|
||||
break;
|
||||
case 'MATCH_SOURCE_ZEROTIER_ADDRESS':
|
||||
case 'MATCH_DEST_ZEROTIER_ADDRESS':
|
||||
nr = { 'type': rule['type'],'not': !!rule['not'],'or': !!rule['or'] };
|
||||
nr.zt = formatZeroTierIdentifier(rule.zt,10);
|
||||
break;
|
||||
case 'MATCH_VLAN_ID':
|
||||
nr = { 'type': rule['type'],'not': !!rule['not'],'or': !!rule['or'] };
|
||||
nr.vlanId = parseInt(rule.vlanId)||0;
|
||||
break;
|
||||
case 'MATCH_VLAN_PCP':
|
||||
nr = { 'type': rule['type'],'not': !!rule['not'],'or': !!rule['or'] };
|
||||
nr.vlanPcp = parseInt(rule.vlanPcp)||0;
|
||||
break;
|
||||
case 'MATCH_VLAN_DEI':
|
||||
nr = { 'type': rule['type'],'not': !!rule['not'],'or': !!rule['or'] };
|
||||
nr.vlanDei = parseInt(rule.vlanDei)||0;
|
||||
break;
|
||||
case 'MATCH_MAC_SOURCE':
|
||||
case 'MATCH_MAC_DEST':
|
||||
nr = { 'type': rule['type'],'not': !!rule['not'],'or': !!rule['or'] };
|
||||
nr.mac = formatZeroTierIdentifier(rule.mac,12);
|
||||
nr.mac = (nr.mac.substr(0,2)+':'+nr.mac.substr(2,2)+':'+nr.mac.substr(4,2)+':'+nr.mac.substr(6,2)+':'+nr.mac.substr(8,2)+':'+nr.mac.substr(10,2));
|
||||
break;
|
||||
case 'MATCH_IPV4_SOURCE':
|
||||
case 'MATCH_IPV4_DEST':
|
||||
if (ipClassify(rule.ip) !== 4)
|
||||
continue;
|
||||
nr = { 'type': rule['type'],'not': !!rule['not'],'or': !!rule['or'] };
|
||||
nr.ip = rule.ip;
|
||||
break;
|
||||
case 'MATCH_IPV6_SOURCE':
|
||||
case 'MATCH_IPV6_DEST':
|
||||
if (ipClassify(rule.ip) !== 6)
|
||||
continue;
|
||||
nr = { 'type': rule['type'],'not': !!rule['not'],'or': !!rule['or'] };
|
||||
nr.ip = rule.ip;
|
||||
break;
|
||||
case 'MATCH_IP_TOS':
|
||||
nr = { 'type': rule['type'],'not': !!rule['not'],'or': !!rule['or'] };
|
||||
nr.mask = parseInt(rule.mask)||0;
|
||||
nr.start = parseInt(rule.start)||0;
|
||||
nr.end = parseInt(rule.end)||0;
|
||||
break;
|
||||
case 'MATCH_IP_PROTOCOL':
|
||||
nr = { 'type': rule['type'],'not': !!rule['not'],'or': !!rule['or'] };
|
||||
nr.ipProtocol = parseInt(rule.ipProtocol)||0;
|
||||
break;
|
||||
case 'MATCH_ETHERTYPE':
|
||||
nr = { 'type': rule['type'],'not': !!rule['not'],'or': !!rule['or'] };
|
||||
nr.etherType = parseInt(rule.etherType)||0;
|
||||
break;
|
||||
case 'MATCH_ICMP':
|
||||
nr = { 'type': rule['type'],'not': !!rule['not'],'or': !!rule['or'] };
|
||||
nr.icmpType = parseInt(rule.icmpType)||0;
|
||||
nr.icmpCode = ('icmpCode' in rule) ? ((rule.icmpCode === null) ? null : (parseInt(rule.icmpCode)||0)) : null;
|
||||
break;
|
||||
case 'MATCH_IP_SOURCE_PORT_RANGE':
|
||||
case 'MATCH_IP_DEST_PORT_RANGE':
|
||||
nr = { 'type': rule['type'],'not': !!rule['not'],'or': !!rule['or'] };
|
||||
nr.start = parseInt(rule.start)||0;
|
||||
nr.end = parseInt(rule.end)||0;
|
||||
break;
|
||||
case 'MATCH_CHARACTERISTICS':
|
||||
nr = { 'type': rule['type'],'not': !!rule['not'],'or': !!rule['or'] };
|
||||
nr.mask = formatZeroTierIdentifier(rule.mask,16); // hex number, so this will work
|
||||
break;
|
||||
case 'MATCH_FRAME_SIZE_RANGE':
|
||||
nr = { 'type': rule['type'],'not': !!rule['not'],'or': !!rule['or'] };
|
||||
nr.start = parseInt(rule.start)||0;
|
||||
nr.end = parseInt(rule.end)||0;
|
||||
break;
|
||||
case 'MATCH_RANDOM':
|
||||
nr = { 'type': rule['type'],'not': !!rule['not'],'or': !!rule['or'] };
|
||||
nr.probability = parseInt(rule.probability)||0;
|
||||
break;
|
||||
case 'MATCH_TAGS_DIFFERENCE':
|
||||
case 'MATCH_TAGS_BITWISE_AND':
|
||||
case 'MATCH_TAGS_BITWISE_OR':
|
||||
case 'MATCH_TAGS_BITWISE_XOR':
|
||||
case 'MATCH_TAGS_EQUAL':
|
||||
case 'MATCH_TAG_SENDER':
|
||||
case 'MATCH_TAG_RECEIVER':
|
||||
nr = { 'type': rule['type'],'not': !!rule['not'],'or': !!rule['or'] };
|
||||
nr.id = parseInt(rule.id)||0;
|
||||
nr.value = parseInt(rule.value)||0;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
r.push(nr);
|
||||
}
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
exports.formatRuleSetArray = formatRuleSetArray;
|
||||
|
||||
// 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)
|
||||
{
|
||||
let caps = {};
|
||||
let ca = [];
|
||||
if ((c)&&(Array.isArray(c))) {
|
||||
for(let a=0;a<c.length;++a) {
|
||||
let capId = parseInt(c[a])||0;
|
||||
if ((capId >= 0)&&(capId <= 0xffffffff)&&(!caps[capId])) {
|
||||
caps[capId] = true;
|
||||
ca.push(capId);
|
||||
}
|
||||
}
|
||||
}
|
||||
ca.sort();
|
||||
this._capabilities = ca;
|
||||
return ca;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
let ips = {};
|
||||
if ((ipa)&&(Array.isArray(ipa))) {
|
||||
for(let a=0;a<ipa.length;++a) {
|
||||
let ip = ipa[a];
|
||||
if (ipClassify(ip) > 0)
|
||||
ips[ip] = true;
|
||||
}
|
||||
}
|
||||
this._ipAssignments = Object.keys(ips);
|
||||
this._ipAssignments.sort();
|
||||
return this._ipAssignments;
|
||||
}
|
||||
|
||||
get noAutoAssignIps() { return this._noAutoAssignIps; }
|
||||
set noAutoAssignIps(b) { this._noAutoAssignIps = !!b; }
|
||||
|
||||
get tags() { return this._tags; }
|
||||
set tags(t)
|
||||
{
|
||||
let ta = [];
|
||||
let pairs = {};
|
||||
if ((t)&&(Array.isArray(t))) {
|
||||
for(let a=0;a<t.length;++a) {
|
||||
let tag = a[t];
|
||||
if ((tag)&&(Array.isArray(tag))&&(tag.length === 2)) {
|
||||
let tagId = parseInt(tag[0])||0;
|
||||
let tagValue = parseInt(tag[1])||0;
|
||||
let pk = tagId.toString()+'_'+tagValue.toString();
|
||||
if ((tagId >= 0)&&(tagId <= 0xffffffff)&&(tagValue >= 0)&&(tagValue <= 0xffffffff)&&(!pairs[pk])) {
|
||||
pairs[pk] = true;
|
||||
ta.push([ tagId,tagValue ]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ta.sort(function(a,b) {
|
||||
return ((a[0] < b[0]) ? -1 : ((a[0] > b[0]) ? 1 : 0));
|
||||
});
|
||||
this._tags = ta;
|
||||
return ta;
|
||||
}
|
||||
|
||||
get creationTime() { return this.__creationTime; }
|
||||
get lastAuthorizedTime() { return this.__lastAuthorizedTime; }
|
||||
get lastAuthorizedCredentialType() { return this.__lastAuthorizedCredentialType; }
|
||||
get lastAuthorizedCredential() { return this.__lastAuthorizedCredential; }
|
||||
get lastDeauthorizedTime() { return this.__lastDeauthorizedTime; }
|
||||
get physicalAddr() { return this.__physicalAddr; }
|
||||
get revision() { return this.__revision; }
|
||||
get vMajor() { return this.__vMajor; }
|
||||
get vMinor() { return this.__vMinor; }
|
||||
get vRev() { return this.__vRev; }
|
||||
get vProto() { return this.__vProto; }
|
||||
|
||||
toJSONExcludeControllerGenerated()
|
||||
{
|
||||
return {
|
||||
id: this.id,
|
||||
nwid: this.nwid,
|
||||
objtype: 'member',
|
||||
address: this.id,
|
||||
authorized: this.authorized,
|
||||
activeBridge: this.activeBridge,
|
||||
capabilities: this.capabilities,
|
||||
identity: this.identity,
|
||||
ipAssignments: this.ipAssignments,
|
||||
noAutoAssignIps: this.noAutoAssignIps,
|
||||
tags: this.tags
|
||||
};
|
||||
}
|
||||
|
||||
toJSON()
|
||||
{
|
||||
let j = this.toJSONExcludeControllerGenerated();
|
||||
j.creationTime = this.creationTime;
|
||||
j.lastAuthorizedTime = this.lastAuthorizedTime;
|
||||
j.lastAuthorizedCredentialType = this.lastAuthorizedCredentialType;
|
||||
j.lastAuthorizedCredential = this.lastAuthorizedCredential;
|
||||
j.lastDeauthorizedTime = this.lastDeauthorizedTime;
|
||||
j.physicalAddr = this.physicalAddr;
|
||||
j.revision = this.revision;
|
||||
j.vMajor = this.vMajor;
|
||||
j.vMinor = this.vMinor;
|
||||
j.vRev = this.vRev;
|
||||
j.vProto = this.vProto;
|
||||
return j;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
patch(obj)
|
||||
{
|
||||
if (obj instanceof Member)
|
||||
obj = obj.toJSON();
|
||||
if ((obj)&&(typeof obj === 'object')&&(!Array.isArray(obj))) {
|
||||
for(var k in obj) {
|
||||
try {
|
||||
switch(k) {
|
||||
case 'id':
|
||||
case 'nwid':
|
||||
case 'authorized':
|
||||
case 'activeBridge':
|
||||
case 'capabilities':
|
||||
case 'identity':
|
||||
case 'ipAssignments':
|
||||
case 'noAutoAssignIps':
|
||||
case 'tags':
|
||||
this[k] = obj[k];
|
||||
break;
|
||||
|
||||
case 'creationTime':
|
||||
case 'lastAuthorizedTime':
|
||||
case 'lastAuthorizedCredentialType':
|
||||
case 'lastAuthorizedCredential':
|
||||
case 'lastDeauthorizedTime':
|
||||
case 'physicalAddr':
|
||||
case 'revision':
|
||||
case 'vMajor':
|
||||
case 'vMinor':
|
||||
case 'vRev':
|
||||
case 'vProto':
|
||||
this['__'+k] = parseInt(obj[k])||0;
|
||||
break;
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
exports.Member = Member;
|
Loading…
Reference in New Issue
Block a user