mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-04-16 03:56:54 +02:00
Merge branch 'dev' into edge
This commit is contained in:
commit
0945d6ec0d
13 changed files with 362 additions and 407 deletions
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* ZeroTier One - Network Virtualization Everywhere
|
||||
* Copyright (C) 2011-2015 ZeroTier, Inc.
|
||||
* Copyright (C) 2011-2018 ZeroTier, Inc.
|
||||
*
|
||||
* 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
|
||||
|
@ -41,7 +41,6 @@ void DB::initNetwork(nlohmann::json &network)
|
|||
if (!network.count("tags")) network["tags"] = nlohmann::json::array();
|
||||
if (!network.count("routes")) network["routes"] = nlohmann::json::array();
|
||||
if (!network.count("ipAssignmentPools")) network["ipAssignmentPools"] = nlohmann::json::array();
|
||||
//if (!network.count("anchors")) network["anchors"] = nlohmann::json::array();
|
||||
if (!network.count("mtu")) network["mtu"] = ZT_DEFAULT_MTU;
|
||||
if (!network.count("remoteTraceTarget")) network["remoteTraceTarget"] = nlohmann::json();
|
||||
if (!network.count("removeTraceLevel")) network["remoteTraceLevel"] = 0;
|
||||
|
@ -222,7 +221,7 @@ void DB::networks(std::vector<uint64_t> &networks)
|
|||
networks.push_back(n->first);
|
||||
}
|
||||
|
||||
void DB::_memberChanged(nlohmann::json &old,nlohmann::json &member,bool push)
|
||||
void DB::_memberChanged(nlohmann::json &old,nlohmann::json &memberConfig,bool push)
|
||||
{
|
||||
uint64_t memberId = 0;
|
||||
uint64_t networkId = 0;
|
||||
|
@ -230,6 +229,102 @@ void DB::_memberChanged(nlohmann::json &old,nlohmann::json &member,bool push)
|
|||
bool wasAuth = false;
|
||||
std::shared_ptr<_Network> nw;
|
||||
|
||||
if (old.is_object()) {
|
||||
memberId = OSUtils::jsonIntHex(old["id"],0ULL);
|
||||
networkId = OSUtils::jsonIntHex(old["nwid"],0ULL);
|
||||
if ((memberId)&&(networkId)) {
|
||||
{
|
||||
std::lock_guard<std::mutex> l(_networks_l);
|
||||
auto nw2 = _networks.find(networkId);
|
||||
if (nw2 != _networks.end())
|
||||
nw = nw2->second;
|
||||
}
|
||||
if (nw) {
|
||||
std::lock_guard<std::mutex> l(nw->lock);
|
||||
if (OSUtils::jsonBool(old["activeBridge"],false))
|
||||
nw->activeBridgeMembers.erase(memberId);
|
||||
wasAuth = OSUtils::jsonBool(old["authorized"],false);
|
||||
if (wasAuth)
|
||||
nw->authorizedMembers.erase(memberId);
|
||||
json &ips = old["ipAssignments"];
|
||||
if (ips.is_array()) {
|
||||
for(unsigned long i=0;i<ips.size();++i) {
|
||||
json &ipj = ips[i];
|
||||
if (ipj.is_string()) {
|
||||
const std::string ips = ipj;
|
||||
InetAddress ipa(ips.c_str());
|
||||
ipa.setPort(0);
|
||||
nw->allocatedIps.erase(ipa);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (memberConfig.is_object()) {
|
||||
if (!nw) {
|
||||
memberId = OSUtils::jsonIntHex(memberConfig["id"],0ULL);
|
||||
networkId = OSUtils::jsonIntHex(memberConfig["nwid"],0ULL);
|
||||
if ((!memberId)||(!networkId))
|
||||
return;
|
||||
std::lock_guard<std::mutex> l(_networks_l);
|
||||
std::shared_ptr<_Network> &nw2 = _networks[networkId];
|
||||
if (!nw2)
|
||||
nw2.reset(new _Network);
|
||||
nw = nw2;
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> l(nw->lock);
|
||||
|
||||
nw->members[memberId] = memberConfig;
|
||||
|
||||
if (OSUtils::jsonBool(memberConfig["activeBridge"],false))
|
||||
nw->activeBridgeMembers.insert(memberId);
|
||||
isAuth = OSUtils::jsonBool(memberConfig["authorized"],false);
|
||||
if (isAuth)
|
||||
nw->authorizedMembers.insert(memberId);
|
||||
json &ips = memberConfig["ipAssignments"];
|
||||
if (ips.is_array()) {
|
||||
for(unsigned long i=0;i<ips.size();++i) {
|
||||
json &ipj = ips[i];
|
||||
if (ipj.is_string()) {
|
||||
const std::string ips = ipj;
|
||||
InetAddress ipa(ips.c_str());
|
||||
ipa.setPort(0);
|
||||
nw->allocatedIps.insert(ipa);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isAuth) {
|
||||
const int64_t ldt = (int64_t)OSUtils::jsonInt(memberConfig["lastDeauthorizedTime"],0ULL);
|
||||
if (ldt > nw->mostRecentDeauthTime)
|
||||
nw->mostRecentDeauthTime = ldt;
|
||||
}
|
||||
}
|
||||
|
||||
if (push)
|
||||
_controller->onNetworkMemberUpdate(networkId,memberId);
|
||||
} else if (memberId) {
|
||||
if (nw) {
|
||||
std::lock_guard<std::mutex> l(nw->lock);
|
||||
nw->members.erase(memberId);
|
||||
}
|
||||
if (networkId) {
|
||||
std::lock_guard<std::mutex> l(_networks_l);
|
||||
auto er = _networkByMember.equal_range(memberId);
|
||||
for(auto i=er.first;i!=er.second;++i) {
|
||||
if (i->second == networkId) {
|
||||
_networkByMember.erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if (old.is_object()) {
|
||||
json &config = old["config"];
|
||||
if (config.is_object()) {
|
||||
|
@ -330,16 +425,46 @@ void DB::_memberChanged(nlohmann::json &old,nlohmann::json &member,bool push)
|
|||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if ((push)&&((wasAuth)&&(!isAuth)&&(networkId)&&(memberId)))
|
||||
_controller->onNetworkMemberDeauthorize(networkId,memberId);
|
||||
}
|
||||
|
||||
void DB::_networkChanged(nlohmann::json &old,nlohmann::json &network,bool push)
|
||||
void DB::_networkChanged(nlohmann::json &old,nlohmann::json &networkConfig,bool push)
|
||||
{
|
||||
if (networkConfig.is_object()) {
|
||||
const std::string ids = networkConfig["id"];
|
||||
const uint64_t id = Utils::hexStrToU64(ids.c_str());
|
||||
if (id) {
|
||||
std::shared_ptr<_Network> nw;
|
||||
{
|
||||
std::lock_guard<std::mutex> l(_networks_l);
|
||||
std::shared_ptr<_Network> &nw2 = _networks[id];
|
||||
if (!nw2)
|
||||
nw2.reset(new _Network);
|
||||
nw = nw2;
|
||||
}
|
||||
{
|
||||
std::lock_guard<std::mutex> l2(nw->lock);
|
||||
nw->config = networkConfig;
|
||||
}
|
||||
if (push)
|
||||
_controller->onNetworkUpdate(id);
|
||||
}
|
||||
} else if (old.is_object()) {
|
||||
const std::string ids = old["id"];
|
||||
const uint64_t id = Utils::hexStrToU64(ids.c_str());
|
||||
if (id) {
|
||||
std::lock_guard<std::mutex> l(_networks_l);
|
||||
_networks.erase(id);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if (network.is_object()) {
|
||||
json &config = network["config"];
|
||||
if (config.is_object()) {
|
||||
if (networkConfig.is_object()) {
|
||||
const std::string ids = config["id"];
|
||||
const uint64_t id = Utils::hexStrToU64(ids.c_str());
|
||||
if (id) {
|
||||
|
@ -367,6 +492,7 @@ void DB::_networkChanged(nlohmann::json &old,nlohmann::json &network,bool push)
|
|||
_networks.erase(id);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void DB::_fillSummaryInfo(const std::shared_ptr<_Network> &nw,NetworkSummaryInfo &info)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* ZeroTier One - Network Virtualization Everywhere
|
||||
* Copyright (C) 2011-2015 ZeroTier, Inc.
|
||||
* Copyright (C) 2011-2018 ZeroTier, Inc.
|
||||
*
|
||||
* 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
|
||||
|
@ -119,8 +119,8 @@ protected:
|
|||
std::mutex lock;
|
||||
};
|
||||
|
||||
void _memberChanged(nlohmann::json &old,nlohmann::json &member,bool push);
|
||||
void _networkChanged(nlohmann::json &old,nlohmann::json &network,bool push);
|
||||
void _memberChanged(nlohmann::json &old,nlohmann::json &memberConfig,bool push);
|
||||
void _networkChanged(nlohmann::json &old,nlohmann::json &networkConfig,bool push);
|
||||
void _fillSummaryInfo(const std::shared_ptr<_Network> &nw,NetworkSummaryInfo &info);
|
||||
|
||||
EmbeddedNetworkController *const _controller;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* ZeroTier One - Network Virtualization Everywhere
|
||||
* Copyright (C) 2011-2015 ZeroTier, Inc->
|
||||
* Copyright (C) 2011-2018 ZeroTier, Inc
|
||||
*
|
||||
* 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
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* ZeroTier One - Network Virtualization Everywhere
|
||||
* Copyright (C) 2011-2015 ZeroTier, Inc.
|
||||
* Copyright (C) 2011-2018 ZeroTier, Inc.
|
||||
*
|
||||
* 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
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* ZeroTier One - Network Virtualization Everywhere
|
||||
* Copyright (C) 2011-2015 ZeroTier, Inc.
|
||||
* Copyright (C) 2011-2018 ZeroTier, Inc.
|
||||
*
|
||||
* 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
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* ZeroTier One - Network Virtualization Everywhere
|
||||
* Copyright (C) 2011-2015 ZeroTier, Inc.
|
||||
* Copyright (C) 2011-2018 ZeroTier, Inc.
|
||||
*
|
||||
* 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
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* ZeroTier One - Network Virtualization Everywhere
|
||||
* Copyright (C) 2011-2015 ZeroTier, Inc.
|
||||
* Copyright (C) 2011-2018 ZeroTier, Inc.
|
||||
*
|
||||
* 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
|
||||
|
@ -97,10 +97,11 @@ RethinkDB::RethinkDB(EmbeddedNetworkController *const nc,const Identity &myId,co
|
|||
try {
|
||||
json &ov = tmp["old_val"];
|
||||
json &nv = tmp["new_val"];
|
||||
if (ov.is_object()||nv.is_object()) {
|
||||
//if (nv.is_object()) printf("MEMBER: %s" ZT_EOL_S,nv.dump().c_str());
|
||||
this->_memberChanged(ov,nv,(this->_ready <= 0));
|
||||
}
|
||||
json oldConfig,newConfig;
|
||||
if (ov.is_object()) oldConfig = ov["config"];
|
||||
if (nv.is_object()) newConfig = nv["config"];
|
||||
if (oldConfig.is_object()||newConfig.is_object())
|
||||
this->_memberChanged(oldConfig,newConfig,(this->_ready <= 0));
|
||||
} catch ( ... ) {} // ignore bad records
|
||||
}
|
||||
}
|
||||
|
@ -138,10 +139,11 @@ RethinkDB::RethinkDB(EmbeddedNetworkController *const nc,const Identity &myId,co
|
|||
try {
|
||||
json &ov = tmp["old_val"];
|
||||
json &nv = tmp["new_val"];
|
||||
if (ov.is_object()||nv.is_object()) {
|
||||
//if (nv.is_object()) printf("NETWORK: %s" ZT_EOL_S,nv.dump().c_str());
|
||||
this->_networkChanged(ov,nv,(this->_ready <= 0));
|
||||
}
|
||||
json oldConfig,newConfig;
|
||||
if (ov.is_object()) oldConfig = ov["config"];
|
||||
if (nv.is_object()) newConfig = nv["config"];
|
||||
if (oldConfig.is_object()||newConfig.is_object())
|
||||
this->_networkChanged(oldConfig,newConfig,(this->_ready <= 0));
|
||||
} catch ( ... ) {} // ignore bad records
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* ZeroTier One - Network Virtualization Everywhere
|
||||
* Copyright (C) 2011-2015 ZeroTier, Inc.
|
||||
* Copyright (C) 2011-2018 ZeroTier, Inc.
|
||||
*
|
||||
* 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
|
||||
|
|
|
@ -1,318 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
var sqlite3 = require('sqlite3').verbose();
|
||||
var fs = require('fs');
|
||||
var async = require('async');
|
||||
|
||||
function blobToIPv4(b)
|
||||
{
|
||||
if (!b)
|
||||
return null;
|
||||
if (b.length !== 16)
|
||||
return null;
|
||||
return b.readUInt8(12).toString()+'.'+b.readUInt8(13).toString()+'.'+b.readUInt8(14).toString()+'.'+b.readUInt8(15).toString();
|
||||
}
|
||||
function blobToIPv6(b)
|
||||
{
|
||||
if (!b)
|
||||
return null;
|
||||
if (b.length !== 16)
|
||||
return null;
|
||||
var s = '';
|
||||
for(var i=0;i<16;++i) {
|
||||
var x = b.readUInt8(i).toString(16);
|
||||
if (x.length === 1)
|
||||
s += '0';
|
||||
s += x;
|
||||
if ((((i+1) & 1) === 0)&&(i !== 15))
|
||||
s += ':';
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
if (process.argv.length !== 4) {
|
||||
console.log('ZeroTier Old Sqlite3 Controller DB Migration Utility');
|
||||
console.log('(c)2017 ZeroTier, Inc. [GPL3]');
|
||||
console.log('');
|
||||
console.log('Usage: node migrate.js </path/to/controller.db> </path/to/controller.d>');
|
||||
console.log('');
|
||||
console.log('The first argument must be the path to the old Sqlite3 controller.db');
|
||||
console.log('file. The second must be the path to the EMPTY controller.d database');
|
||||
console.log('directory for a new (1.1.17 or newer) controller. If this path does');
|
||||
console.log('not exist it will be created.');
|
||||
console.log('');
|
||||
console.log('WARNING: this will ONLY work correctly on a 1.1.14 controller database.');
|
||||
console.log('If your controller is old you should first upgrade to 1.1.14 and run the');
|
||||
console.log('controller so that it will brings its Sqlite3 database up to the latest');
|
||||
console.log('version before running this migration.');
|
||||
console.log('');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
var oldDbPath = process.argv[2];
|
||||
var newDbPath = process.argv[3];
|
||||
|
||||
console.log('Starting migrate of "'+oldDbPath+'" to "'+newDbPath+'"...');
|
||||
console.log('');
|
||||
|
||||
var old = new sqlite3.Database(oldDbPath);
|
||||
|
||||
var networks = {};
|
||||
|
||||
var nodeIdentities = {};
|
||||
var networkCount = 0;
|
||||
var memberCount = 0;
|
||||
var routeCount = 0;
|
||||
var ipAssignmentPoolCount = 0;
|
||||
var ipAssignmentCount = 0;
|
||||
var ruleCount = 0;
|
||||
var oldSchemaVersion = -1;
|
||||
|
||||
async.series([function(nextStep) {
|
||||
|
||||
old.each('SELECT v from Config WHERE k = \'schemaVersion\'',function(err,row) {
|
||||
oldSchemaVersion = parseInt(row.v)||-1;
|
||||
},nextStep);
|
||||
|
||||
},function(nextStep) {
|
||||
|
||||
if (oldSchemaVersion !== 4) {
|
||||
console.log('FATAL: this MUST be run on a 1.1.14 controller.db! Upgrade your old');
|
||||
console.log('controller to 1.1.14 first and run it once to bring its DB up to date.');
|
||||
return process.exit(1);
|
||||
}
|
||||
|
||||
console.log('Reading networks...');
|
||||
old.each('SELECT * FROM Network',function(err,row) {
|
||||
if ((typeof row.id === 'string')&&(row.id.length === 16)) {
|
||||
var flags = parseInt(row.flags)||0;
|
||||
networks[row.id] = {
|
||||
id: row.id,
|
||||
nwid: row.id,
|
||||
objtype: 'network',
|
||||
authTokens: [],
|
||||
capabilities: [],
|
||||
creationTime: parseInt(row.creationTime)||0,
|
||||
enableBroadcast: !!row.enableBroadcast,
|
||||
ipAssignmentPools: [],
|
||||
multicastLimit: row.multicastLimit||32,
|
||||
name: row.name||'',
|
||||
private: !!row.private,
|
||||
revision: parseInt(row.revision)||1,
|
||||
rules: [{ 'type': 'ACTION_ACCEPT' }], // populated later if there are defined rules, otherwise default is allow all
|
||||
routes: [],
|
||||
v4AssignMode: {
|
||||
'zt': ((flags & 1) !== 0)
|
||||
},
|
||||
v6AssignMode: {
|
||||
'6plane': ((flags & 4) !== 0),
|
||||
'rfc4193': ((flags & 2) !== 0),
|
||||
'zt': ((flags & 8) !== 0)
|
||||
},
|
||||
_members: {} // temporary
|
||||
};
|
||||
++networkCount;
|
||||
//console.log(networks[row.id]);
|
||||
}
|
||||
},nextStep);
|
||||
|
||||
},function(nextStep) {
|
||||
|
||||
console.log(' '+networkCount+' networks.');
|
||||
console.log('Reading network route definitions...');
|
||||
old.each('SELECT * from Route WHERE ipVersion = 4 OR ipVersion = 6',function(err,row) {
|
||||
var network = networks[row.networkId];
|
||||
if (network) {
|
||||
var rt = {
|
||||
target: (((row.ipVersion == 4) ? blobToIPv4(row.target) : blobToIPv6(row.target))+'/'+row.targetNetmaskBits),
|
||||
via: ((row.via) ? ((row.ipVersion == 4) ? blobToIPv4(row.via) : blobToIPv6(row.via)) : null)
|
||||
};
|
||||
network.routes.push(rt);
|
||||
++routeCount;
|
||||
}
|
||||
},nextStep);
|
||||
|
||||
},function(nextStep) {
|
||||
|
||||
console.log(' '+routeCount+' routes in '+networkCount+' networks.');
|
||||
console.log('Reading IP assignment pools...');
|
||||
old.each('SELECT * FROM IpAssignmentPool WHERE ipVersion = 4 OR ipVersion = 6',function(err,row) {
|
||||
var network = networks[row.networkId];
|
||||
if (network) {
|
||||
var p = {
|
||||
ipRangeStart: ((row.ipVersion == 4) ? blobToIPv4(row.ipRangeStart) : blobToIPv6(row.ipRangeStart)),
|
||||
ipRangeEnd: ((row.ipVersion == 4) ? blobToIPv4(row.ipRangeEnd) : blobToIPv6(row.ipRangeEnd))
|
||||
};
|
||||
network.ipAssignmentPools.push(p);
|
||||
++ipAssignmentPoolCount;
|
||||
}
|
||||
},nextStep);
|
||||
|
||||
},function(nextStep) {
|
||||
|
||||
console.log(' '+ipAssignmentPoolCount+' IP assignment pools in '+networkCount+' networks.');
|
||||
console.log('Reading known node identities...');
|
||||
old.each('SELECT * FROM Node',function(err,row) {
|
||||
nodeIdentities[row.id] = row.identity;
|
||||
},nextStep);
|
||||
|
||||
},function(nextStep) {
|
||||
|
||||
console.log(' '+Object.keys(nodeIdentities).length+' known identities.');
|
||||
console.log('Reading network members...');
|
||||
old.each('SELECT * FROM Member',function(err,row) {
|
||||
var network = networks[row.networkId];
|
||||
if (network) {
|
||||
network._members[row.nodeId] = {
|
||||
id: row.nodeId,
|
||||
address: row.nodeId,
|
||||
objtype: 'member',
|
||||
authorized: !!row.authorized,
|
||||
activeBridge: !!row.activeBridge,
|
||||
authHistory: [],
|
||||
capabilities: [],
|
||||
creationTime: 0,
|
||||
identity: nodeIdentities[row.nodeId]||null,
|
||||
ipAssignments: [],
|
||||
lastAuthorizedTime: (row.authorized) ? Date.now() : 0,
|
||||
lastDeauthorizedTime: (row.authorized) ? 0 : Date.now(),
|
||||
lastRequestMetaData: '',
|
||||
noAutoAssignIps: false,
|
||||
nwid: row.networkId,
|
||||
revision: parseInt(row.memberRevision)||1,
|
||||
tags: [],
|
||||
recentLog: []
|
||||
};
|
||||
++memberCount;
|
||||
//console.log(network._members[row.nodeId]);
|
||||
}
|
||||
},nextStep);
|
||||
|
||||
},function(nextStep) {
|
||||
|
||||
console.log(' '+memberCount+' members of '+networkCount+' networks.');
|
||||
console.log('Reading static IP assignments...');
|
||||
old.each('SELECT * FROM IpAssignment WHERE ipVersion = 4 OR ipVersion = 6',function(err,row) {
|
||||
var network = networks[row.networkId];
|
||||
if (network) {
|
||||
var member = network._members[row.nodeId];
|
||||
if ((member)&&((member.authorized)||(!network['private']))) { // don't mirror assignments to unauthorized members to avoid conflicts
|
||||
if (row.ipVersion == 4) {
|
||||
member.ipAssignments.push(blobToIPv4(row.ip));
|
||||
++ipAssignmentCount;
|
||||
} else if (row.ipVersion == 6) {
|
||||
member.ipAssignments.push(blobToIPv6(row.ip));
|
||||
++ipAssignmentCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
},nextStep);
|
||||
|
||||
},function(nextStep) {
|
||||
|
||||
// Old versions only supported Ethertype whitelisting, so that's
|
||||
// all we mirror forward. The other fields were always unused.
|
||||
|
||||
console.log(' '+ipAssignmentCount+' IP assignments for '+memberCount+' authorized members of '+networkCount+' networks.');
|
||||
console.log('Reading allowed Ethernet types (old basic rules)...');
|
||||
var etherTypesByNetwork = {};
|
||||
old.each('SELECT DISTINCT networkId,ruleNo,etherType FROM Rule WHERE "action" = \'accept\'',function(err,row) {
|
||||
if (row.networkId in networks) {
|
||||
var et = parseInt(row.etherType)||0;
|
||||
var ets = etherTypesByNetwork[row.networkId];
|
||||
if (!ets)
|
||||
etherTypesByNetwork[row.networkId] = [ et ];
|
||||
else ets.push(et);
|
||||
}
|
||||
},function(err) {
|
||||
if (err) return nextStep(err);
|
||||
for(var nwid in etherTypesByNetwork) {
|
||||
var ets = etherTypesByNetwork[nwid].sort();
|
||||
var network = networks[nwid];
|
||||
if (network) {
|
||||
var rules = [];
|
||||
if (ets.indexOf(0) >= 0) {
|
||||
// If 0 is in the list, all Ethernet types are allowed so we accept all.
|
||||
rules.push({ 'type': 'ACTION_ACCEPT' });
|
||||
} else {
|
||||
// Otherwise we whitelist.
|
||||
for(var i=0;i<ets.length;++i) {
|
||||
rules.push({
|
||||
'etherType': ets[i],
|
||||
'not': true,
|
||||
'or': false,
|
||||
'type': 'MATCH_ETHERTYPE'
|
||||
});
|
||||
}
|
||||
rules.push({ 'type': 'ACTION_DROP' });
|
||||
rules.push({ 'type': 'ACTION_ACCEPT' });
|
||||
}
|
||||
network.rules = rules;
|
||||
++ruleCount;
|
||||
}
|
||||
}
|
||||
return nextStep(null);
|
||||
});
|
||||
|
||||
}],function(err) {
|
||||
|
||||
if (err) {
|
||||
console.log('FATAL: '+err.toString());
|
||||
return process.exit(1);
|
||||
}
|
||||
|
||||
console.log(' '+ruleCount+' ethernet type whitelists converted to new format rules.');
|
||||
old.close();
|
||||
console.log('Done reading and converting Sqlite3 database! Writing JSONDB files...');
|
||||
|
||||
try {
|
||||
fs.mkdirSync(newDbPath,0o700);
|
||||
} catch (e) {}
|
||||
var nwBase = newDbPath+'/network';
|
||||
try {
|
||||
fs.mkdirSync(nwBase,0o700);
|
||||
} catch (e) {}
|
||||
nwBase = nwBase + '/';
|
||||
var nwids = Object.keys(networks).sort();
|
||||
var fileCount = 0;
|
||||
for(var ni=0;ni<nwids.length;++ni) {
|
||||
var network = networks[nwids[ni]];
|
||||
|
||||
var mids = Object.keys(network._members).sort();
|
||||
if (mids.length > 0) {
|
||||
try {
|
||||
fs.mkdirSync(nwBase+network.id);
|
||||
} catch (e) {}
|
||||
var mbase = nwBase+network.id+'/member';
|
||||
try {
|
||||
fs.mkdirSync(mbase,0o700);
|
||||
} catch (e) {}
|
||||
mbase = mbase + '/';
|
||||
|
||||
for(var mi=0;mi<mids.length;++mi) {
|
||||
var member = network._members[mids[mi]];
|
||||
fs.writeFileSync(mbase+member.id+'.json',JSON.stringify(member,null,1),{ mode: 0o600 });
|
||||
++fileCount;
|
||||
//console.log(mbase+member.id+'.json');
|
||||
}
|
||||
}
|
||||
|
||||
delete network._members; // temporary field, not part of actual JSONDB, so don't write
|
||||
fs.writeFileSync(nwBase+network.id+'.json',JSON.stringify(network,null,1),{ mode: 0o600 });
|
||||
++fileCount;
|
||||
//console.log(nwBase+network.id+'.json');
|
||||
}
|
||||
|
||||
console.log('');
|
||||
console.log('SUCCESS! Wrote '+fileCount+' JSONDB files.');
|
||||
|
||||
console.log('');
|
||||
console.log('You should still inspect the new DB before going live. Also be sure');
|
||||
console.log('to "chown -R" and "chgrp -R" the new DB to the user and group under');
|
||||
console.log('which the ZeroTier One instance acting as controller will be running.');
|
||||
console.log('The controller must be able to read and write the DB, of course.');
|
||||
console.log('');
|
||||
console.log('Have fun!');
|
||||
|
||||
return process.exit(0);
|
||||
});
|
|
@ -1,15 +0,0 @@
|
|||
{
|
||||
"name": "migrate-sqlite",
|
||||
"version": "1.0.0",
|
||||
"description": "Migrate old SQLite to new JSON filesystem DB for ZeroTier network controller",
|
||||
"main": "migrate.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "Adam Ierymenko <adam.ierymenko@zerotier.com>",
|
||||
"license": "GPL-3.0",
|
||||
"dependencies": {
|
||||
"async": "^2.1.4",
|
||||
"sqlite3": "^3.1.8"
|
||||
}
|
||||
}
|
114
include/ZeroTierDebug.h
Normal file
114
include/ZeroTierDebug.h
Normal file
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* ZeroTier One - Network Virtualization Everywhere
|
||||
* Copyright (C) 2011-2018 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Debug macros
|
||||
*/
|
||||
|
||||
#ifndef ZT_DEBUG_H
|
||||
#define ZT_DEBUG_H
|
||||
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
#include <sys/syscall.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define ZT_MSG_INFO true
|
||||
#define ZT_COLOR true
|
||||
|
||||
// Debug output colors
|
||||
#if defined(__APPLE__)
|
||||
#include "TargetConditionals.h"
|
||||
#endif
|
||||
#if defined(ZT_COLOR) && !defined(_WIN32) && !defined(__ANDROID__) && !defined(TARGET_OS_IPHONE) && !defined(TARGET_IPHONE_SIMULATOR) && !defined(__APP_FRAMEWORK__)
|
||||
#define ZT_RED "\x1B[31m"
|
||||
#define ZT_GRN "\x1B[32m"
|
||||
#define ZT_YEL "\x1B[33m"
|
||||
#define ZT_BLU "\x1B[34m"
|
||||
#define ZT_MAG "\x1B[35m"
|
||||
#define ZT_CYN "\x1B[36m"
|
||||
#define ZT_WHT "\x1B[37m"
|
||||
#define ZT_RESET "\x1B[0m"
|
||||
#else
|
||||
#define ZT_RED
|
||||
#define ZT_GRN
|
||||
#define ZT_YEL
|
||||
#define ZT_BLU
|
||||
#define ZT_MAG
|
||||
#define ZT_CYN
|
||||
#define ZT_WHT
|
||||
#define ZT_RESET
|
||||
#endif
|
||||
|
||||
#define ZT_FILENAME (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) // short
|
||||
|
||||
#ifdef __linux__
|
||||
#define ZT_THREAD_ID (long)0 // syscall(SYS_gettid)
|
||||
#endif
|
||||
#ifdef __APPLE__
|
||||
#define ZT_THREAD_ID (long)0 // (long)gettid()
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
#define ZT_THREAD_ID (long)0 //
|
||||
#endif
|
||||
#if defined(__JNI_LIB__)
|
||||
#include <jni.h>
|
||||
#endif
|
||||
#if defined(__ANDROID__)
|
||||
#include <android/log.h>
|
||||
#define ZT_LOG_TAG "ZTSDK"
|
||||
#endif
|
||||
#if defined(ZT_TRACE)
|
||||
#if ZT_MSG_INFO == true
|
||||
#if defined(__ANDROID__)
|
||||
#define DEBUG_INFO(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \
|
||||
"INFO : %17s:%5d:%20s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args))
|
||||
#endif
|
||||
#if defined(_WIN32)
|
||||
#define DEBUG_INFO(fmt, ...) fprintf(stderr, ZT_GRN "INFO [%ld]: %17s:%5d:%25s: " fmt "\n" \
|
||||
ZT_RESET, ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, __VA_ARGS__)
|
||||
#endif
|
||||
#if defined(__linux__) or defined(__APPLE__)
|
||||
#define DEBUG_INFO(fmt, args ...) fprintf(stderr, ZT_GRN "INFO [%ld]: %17s:%5d:%25s: " fmt "\n" \
|
||||
ZT_RESET, ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args)
|
||||
#endif
|
||||
#else
|
||||
#define DEBUG_INFO(fmt, args...)
|
||||
#endif
|
||||
#else // blank
|
||||
#if defined(_WIN32)
|
||||
#define DEBUG_INFO(...)
|
||||
#else
|
||||
#define DEBUG_INFO(fmt, args...)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // _H
|
148
node/Network.cpp
148
node/Network.cpp
|
@ -1072,15 +1072,89 @@ void Network::requestConfiguration(void *tPtr)
|
|||
if (_destroyed)
|
||||
return;
|
||||
|
||||
/* ZeroTier addresses can't begin with 0xff, so this is used to mark controllerless
|
||||
* network IDs. Controllerless network IDs only support unicast IPv6 using the 6plane
|
||||
* addressing scheme and have the following format: 0xffSSSSEEEE000000 where SSSS
|
||||
* is the 16-bit starting IP port range allowed and EEEE is the 16-bit ending IP port
|
||||
* range allowed. Remaining digits are reserved for future use and must be zero. */
|
||||
if ((_id >> 56) == 0xff) {
|
||||
const uint16_t startPortRange = (uint16_t)((_id >> 40) & 0xffff);
|
||||
const uint16_t endPortRange = (uint16_t)((_id >> 24) & 0xffff);
|
||||
if (((_id & 0xffffff) == 0)&&(endPortRange >= startPortRange)) {
|
||||
if ((_id & 0xffffff) == 0) {
|
||||
const uint16_t startPortRange = (uint16_t)((_id >> 40) & 0xffff);
|
||||
const uint16_t endPortRange = (uint16_t)((_id >> 24) & 0xffff);
|
||||
if (endPortRange >= startPortRange) {
|
||||
NetworkConfig *const nconf = new NetworkConfig();
|
||||
|
||||
nconf->networkId = _id;
|
||||
nconf->timestamp = RR->node->now();
|
||||
nconf->credentialTimeMaxDelta = ZT_NETWORKCONFIG_DEFAULT_CREDENTIAL_TIME_MAX_MAX_DELTA;
|
||||
nconf->revision = 1;
|
||||
nconf->issuedTo = RR->identity.address();
|
||||
nconf->flags = ZT_NETWORKCONFIG_FLAG_ENABLE_IPV6_NDP_EMULATION;
|
||||
nconf->mtu = ZT_DEFAULT_MTU;
|
||||
nconf->multicastLimit = 0;
|
||||
nconf->staticIpCount = 1;
|
||||
nconf->ruleCount = 14;
|
||||
nconf->staticIps[0] = InetAddress::makeIpv66plane(_id,RR->identity.address().toInt());
|
||||
|
||||
// Drop everything but IPv6
|
||||
nconf->rules[0].t = (uint8_t)ZT_NETWORK_RULE_MATCH_ETHERTYPE | 0x80; // NOT
|
||||
nconf->rules[0].v.etherType = 0x86dd; // IPv6
|
||||
nconf->rules[1].t = (uint8_t)ZT_NETWORK_RULE_ACTION_DROP;
|
||||
|
||||
// Allow ICMPv6
|
||||
nconf->rules[2].t = (uint8_t)ZT_NETWORK_RULE_MATCH_IP_PROTOCOL;
|
||||
nconf->rules[2].v.ipProtocol = 0x3a; // ICMPv6
|
||||
nconf->rules[3].t = (uint8_t)ZT_NETWORK_RULE_ACTION_ACCEPT;
|
||||
|
||||
// Allow destination ports within range
|
||||
nconf->rules[4].t = (uint8_t)ZT_NETWORK_RULE_MATCH_IP_PROTOCOL;
|
||||
nconf->rules[4].v.ipProtocol = 0x11; // UDP
|
||||
nconf->rules[5].t = (uint8_t)ZT_NETWORK_RULE_MATCH_IP_PROTOCOL | 0x40; // OR
|
||||
nconf->rules[5].v.ipProtocol = 0x06; // TCP
|
||||
nconf->rules[6].t = (uint8_t)ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE;
|
||||
nconf->rules[6].v.port[0] = startPortRange;
|
||||
nconf->rules[6].v.port[1] = endPortRange;
|
||||
nconf->rules[7].t = (uint8_t)ZT_NETWORK_RULE_ACTION_ACCEPT;
|
||||
|
||||
// Allow non-SYN TCP packets to permit non-connection-initiating traffic
|
||||
nconf->rules[8].t = (uint8_t)ZT_NETWORK_RULE_MATCH_CHARACTERISTICS | 0x80; // NOT
|
||||
nconf->rules[8].v.characteristics = ZT_RULE_PACKET_CHARACTERISTICS_TCP_SYN;
|
||||
nconf->rules[9].t = (uint8_t)ZT_NETWORK_RULE_ACTION_ACCEPT;
|
||||
|
||||
// Also allow SYN+ACK which are replies to SYN
|
||||
nconf->rules[10].t = (uint8_t)ZT_NETWORK_RULE_MATCH_CHARACTERISTICS;
|
||||
nconf->rules[10].v.characteristics = ZT_RULE_PACKET_CHARACTERISTICS_TCP_SYN;
|
||||
nconf->rules[11].t = (uint8_t)ZT_NETWORK_RULE_MATCH_CHARACTERISTICS;
|
||||
nconf->rules[11].v.characteristics = ZT_RULE_PACKET_CHARACTERISTICS_TCP_ACK;
|
||||
nconf->rules[12].t = (uint8_t)ZT_NETWORK_RULE_ACTION_ACCEPT;
|
||||
|
||||
nconf->rules[13].t = (uint8_t)ZT_NETWORK_RULE_ACTION_DROP;
|
||||
|
||||
nconf->type = ZT_NETWORK_TYPE_PUBLIC;
|
||||
|
||||
nconf->name[0] = 'a';
|
||||
nconf->name[1] = 'd';
|
||||
nconf->name[2] = 'h';
|
||||
nconf->name[3] = 'o';
|
||||
nconf->name[4] = 'c';
|
||||
nconf->name[5] = '-';
|
||||
Utils::hex((uint16_t)startPortRange,nconf->name + 6);
|
||||
nconf->name[10] = '-';
|
||||
Utils::hex((uint16_t)endPortRange,nconf->name + 11);
|
||||
nconf->name[15] = (char)0;
|
||||
|
||||
this->setConfiguration(tPtr,*nconf,false);
|
||||
delete nconf;
|
||||
} else {
|
||||
this->setNotFound();
|
||||
}
|
||||
} else if ((_id & 0xff) == 0x01) {
|
||||
// ffAA__________01
|
||||
const uint64_t myAddress = RR->identity.address().toInt();
|
||||
uint8_t ipv4[4];
|
||||
ipv4[0] = (uint8_t)((_id >> 48) & 0xff);
|
||||
ipv4[1] = (uint8_t)((myAddress >> 16) & 0xff);
|
||||
ipv4[2] = (uint8_t)((myAddress >> 8) & 0xff);
|
||||
ipv4[3] = (uint8_t)(myAddress & 0xff);
|
||||
|
||||
char v4ascii[24];
|
||||
Utils::decimal(ipv4[0],v4ascii);
|
||||
|
||||
NetworkConfig *const nconf = new NetworkConfig();
|
||||
|
||||
nconf->networkId = _id;
|
||||
|
@ -1090,44 +1164,13 @@ void Network::requestConfiguration(void *tPtr)
|
|||
nconf->issuedTo = RR->identity.address();
|
||||
nconf->flags = ZT_NETWORKCONFIG_FLAG_ENABLE_IPV6_NDP_EMULATION;
|
||||
nconf->mtu = ZT_DEFAULT_MTU;
|
||||
nconf->multicastLimit = 0;
|
||||
nconf->staticIpCount = 1;
|
||||
nconf->ruleCount = 14;
|
||||
nconf->staticIps[0] = InetAddress::makeIpv66plane(_id,RR->identity.address().toInt());
|
||||
nconf->multicastLimit = 1024;
|
||||
nconf->staticIpCount = 2;
|
||||
nconf->ruleCount = 1;
|
||||
nconf->staticIps[0] = InetAddress::makeIpv66plane(_id,myAddress);
|
||||
nconf->staticIps[1].set(ipv4,4,8);
|
||||
|
||||
// Drop everything but IPv6
|
||||
nconf->rules[0].t = (uint8_t)ZT_NETWORK_RULE_MATCH_ETHERTYPE | 0x80; // NOT
|
||||
nconf->rules[0].v.etherType = 0x86dd; // IPv6
|
||||
nconf->rules[1].t = (uint8_t)ZT_NETWORK_RULE_ACTION_DROP;
|
||||
|
||||
// Allow ICMPv6
|
||||
nconf->rules[2].t = (uint8_t)ZT_NETWORK_RULE_MATCH_IP_PROTOCOL;
|
||||
nconf->rules[2].v.ipProtocol = 0x3a; // ICMPv6
|
||||
nconf->rules[3].t = (uint8_t)ZT_NETWORK_RULE_ACTION_ACCEPT;
|
||||
|
||||
// Allow destination ports within range
|
||||
nconf->rules[4].t = (uint8_t)ZT_NETWORK_RULE_MATCH_IP_PROTOCOL;
|
||||
nconf->rules[4].v.ipProtocol = 0x11; // UDP
|
||||
nconf->rules[5].t = (uint8_t)ZT_NETWORK_RULE_MATCH_IP_PROTOCOL | 0x40; // OR
|
||||
nconf->rules[5].v.ipProtocol = 0x06; // TCP
|
||||
nconf->rules[6].t = (uint8_t)ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE;
|
||||
nconf->rules[6].v.port[0] = startPortRange;
|
||||
nconf->rules[6].v.port[1] = endPortRange;
|
||||
nconf->rules[7].t = (uint8_t)ZT_NETWORK_RULE_ACTION_ACCEPT;
|
||||
|
||||
// Allow non-SYN TCP packets to permit non-connection-initiating traffic
|
||||
nconf->rules[8].t = (uint8_t)ZT_NETWORK_RULE_MATCH_CHARACTERISTICS | 0x80; // NOT
|
||||
nconf->rules[8].v.characteristics = ZT_RULE_PACKET_CHARACTERISTICS_TCP_SYN;
|
||||
nconf->rules[9].t = (uint8_t)ZT_NETWORK_RULE_ACTION_ACCEPT;
|
||||
|
||||
// Also allow SYN+ACK which are replies to SYN
|
||||
nconf->rules[10].t = (uint8_t)ZT_NETWORK_RULE_MATCH_CHARACTERISTICS;
|
||||
nconf->rules[10].v.characteristics = ZT_RULE_PACKET_CHARACTERISTICS_TCP_SYN;
|
||||
nconf->rules[11].t = (uint8_t)ZT_NETWORK_RULE_MATCH_CHARACTERISTICS;
|
||||
nconf->rules[11].v.characteristics = ZT_RULE_PACKET_CHARACTERISTICS_TCP_ACK;
|
||||
nconf->rules[12].t = (uint8_t)ZT_NETWORK_RULE_ACTION_ACCEPT;
|
||||
|
||||
nconf->rules[13].t = (uint8_t)ZT_NETWORK_RULE_ACTION_DROP;
|
||||
nconf->rules[0].t = (uint8_t)ZT_NETWORK_RULE_ACTION_ACCEPT;
|
||||
|
||||
nconf->type = ZT_NETWORK_TYPE_PUBLIC;
|
||||
|
||||
|
@ -1137,15 +1180,18 @@ void Network::requestConfiguration(void *tPtr)
|
|||
nconf->name[3] = 'o';
|
||||
nconf->name[4] = 'c';
|
||||
nconf->name[5] = '-';
|
||||
Utils::hex((uint16_t)startPortRange,nconf->name + 6);
|
||||
nconf->name[10] = '-';
|
||||
Utils::hex((uint16_t)endPortRange,nconf->name + 11);
|
||||
nconf->name[15] = (char)0;
|
||||
unsigned long nn = 6;
|
||||
while ((nconf->name[nn] = v4ascii[nn - 6])) ++nn;
|
||||
nconf->name[nn++] = '.';
|
||||
nconf->name[nn++] = '0';
|
||||
nconf->name[nn++] = '.';
|
||||
nconf->name[nn++] = '0';
|
||||
nconf->name[nn++] = '.';
|
||||
nconf->name[nn++] = '0';
|
||||
nconf->name[nn++] = (char)0;
|
||||
|
||||
this->setConfiguration(tPtr,*nconf,false);
|
||||
delete nconf;
|
||||
} else {
|
||||
this->setNotFound();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -841,7 +841,7 @@ void WindowsEthernetTap::scanMulticastGroups(std::vector<MulticastGroup> &added,
|
|||
// pretty much anything work... IPv4, IPv6, IPX, oldskool Netbios, who knows...
|
||||
unsigned char mcastbuf[TAP_WIN_IOCTL_GET_MULTICAST_MEMBERSHIPS_OUTPUT_BUF_SIZE];
|
||||
DWORD bytesReturned = 0;
|
||||
if (DeviceIoControl(t,TAP_WIN_IOCTL_GET_MULTICAST_MEMBERSHIPS,(LPVOID)0,0,(LPVOID)mcastbuf,sizeof(mcastbuf),&bytesReturned,NULL)) {
|
||||
if (DeviceIoControl(t,TAP_WIN_IOCTL_GET_MULTICAST_MEMBERSHIPS,(LPVOID)mcastbuf,sizeof(mcastbuf),(LPVOID)mcastbuf,sizeof(mcastbuf),&bytesReturned,NULL)) {
|
||||
if ((bytesReturned > 0)&&(bytesReturned <= TAP_WIN_IOCTL_GET_MULTICAST_MEMBERSHIPS_OUTPUT_BUF_SIZE)) { // sanity check
|
||||
MAC mac;
|
||||
DWORD i = 0;
|
||||
|
|
Loading…
Add table
Reference in a new issue