summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--controller/DB.cpp136
-rw-r--r--controller/DB.hpp6
-rw-r--r--controller/EmbeddedNetworkController.cpp2
-rw-r--r--controller/EmbeddedNetworkController.hpp2
-rw-r--r--controller/FileDB.cpp2
-rw-r--r--controller/FileDB.hpp2
-rw-r--r--controller/RethinkDB.cpp20
-rw-r--r--controller/RethinkDB.hpp2
-rw-r--r--controller/migrate-sqlite/migrate.js318
-rw-r--r--controller/migrate-sqlite/package.json15
-rw-r--r--include/ZeroTierDebug.h114
-rw-r--r--node/Network.cpp150
-rw-r--r--osdep/WindowsEthernetTap.cpp2
13 files changed, 363 insertions, 408 deletions
diff --git a/controller/DB.cpp b/controller/DB.cpp
index 70472e57..b2e8878a 100644
--- a/controller/DB.cpp
+++ b/controller/DB.cpp
@@ -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;
@@ -231,6 +230,102 @@ void DB::_memberChanged(nlohmann::json &old,nlohmann::json &member,bool push)
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()) {
memberId = OSUtils::jsonIntHex(config["id"],0ULL);
@@ -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)
diff --git a/controller/DB.hpp b/controller/DB.hpp
index abd1483e..4757bb40 100644
--- a/controller/DB.hpp
+++ b/controller/DB.hpp
@@ -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;
diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp
index f88f8cff..9a07b285 100644
--- a/controller/EmbeddedNetworkController.cpp
+++ b/controller/EmbeddedNetworkController.cpp
@@ -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
diff --git a/controller/EmbeddedNetworkController.hpp b/controller/EmbeddedNetworkController.hpp
index 1dda9f45..417005a4 100644
--- a/controller/EmbeddedNetworkController.hpp
+++ b/controller/EmbeddedNetworkController.hpp
@@ -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
diff --git a/controller/FileDB.cpp b/controller/FileDB.cpp
index 40b9f914..a7b59cbf 100644
--- a/controller/FileDB.cpp
+++ b/controller/FileDB.cpp
@@ -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
diff --git a/controller/FileDB.hpp b/controller/FileDB.hpp
index b02da8cb..1e275a36 100644
--- a/controller/FileDB.hpp
+++ b/controller/FileDB.hpp
@@ -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
diff --git a/controller/RethinkDB.cpp b/controller/RethinkDB.cpp
index a3bdfbc9..f6c8a59c 100644
--- a/controller/RethinkDB.cpp
+++ b/controller/RethinkDB.cpp
@@ -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
}
}
diff --git a/controller/RethinkDB.hpp b/controller/RethinkDB.hpp
index 01b46a47..b1049ac3 100644
--- a/controller/RethinkDB.hpp
+++ b/controller/RethinkDB.hpp
@@ -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
diff --git a/controller/migrate-sqlite/migrate.js b/controller/migrate-sqlite/migrate.js
deleted file mode 100644
index 2f2462c9..00000000
--- a/controller/migrate-sqlite/migrate.js
+++ /dev/null
@@ -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);
-});
diff --git a/controller/migrate-sqlite/package.json b/controller/migrate-sqlite/package.json
deleted file mode 100644
index 0dac008f..00000000
--- a/controller/migrate-sqlite/package.json
+++ /dev/null
@@ -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"
- }
-}
diff --git a/include/ZeroTierDebug.h b/include/ZeroTierDebug.h
new file mode 100644
index 00000000..8e5366f0
--- /dev/null
+++ b/include/ZeroTierDebug.h
@@ -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
diff --git a/node/Network.cpp b/node/Network.cpp
index c12df6c1..0015f2bf 100644
--- a/node/Network.cpp
+++ b/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());
-
- // 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->multicastLimit = 1024;
+ nconf->staticIpCount = 2;
+ nconf->ruleCount = 1;
+ nconf->staticIps[0] = InetAddress::makeIpv66plane(_id,myAddress);
+ nconf->staticIps[1].set(ipv4,4,8);
+
+ 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;
}
diff --git a/osdep/WindowsEthernetTap.cpp b/osdep/WindowsEthernetTap.cpp
index 64ab3943..aa96d33a 100644
--- a/osdep/WindowsEthernetTap.cpp
+++ b/osdep/WindowsEthernetTap.cpp
@@ -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;