diff options
author | Adam Ierymenko <adam.ierymenko@gmail.com> | 2018-03-09 07:50:38 -0800 |
---|---|---|
committer | Adam Ierymenko <adam.ierymenko@gmail.com> | 2018-03-09 07:50:38 -0800 |
commit | 0945d6ec0d7b94ba76b5f9490540d35212d21763 (patch) | |
tree | 46b8937f430b51c6c7e24c8b871c9a4769d7267f | |
parent | 77930607230eccdcb7011f6c70465bab3c32cc38 (diff) | |
parent | 78d9cee4168ddccbdf6d6ea0eed05daa0dac92a4 (diff) | |
download | infinitytier-0945d6ec0d7b94ba76b5f9490540d35212d21763.tar.gz infinitytier-0945d6ec0d7b94ba76b5f9490540d35212d21763.zip |
Merge branch 'dev' into edge
-rw-r--r-- | controller/DB.cpp | 136 | ||||
-rw-r--r-- | controller/DB.hpp | 6 | ||||
-rw-r--r-- | controller/EmbeddedNetworkController.cpp | 2 | ||||
-rw-r--r-- | controller/EmbeddedNetworkController.hpp | 2 | ||||
-rw-r--r-- | controller/FileDB.cpp | 2 | ||||
-rw-r--r-- | controller/FileDB.hpp | 2 | ||||
-rw-r--r-- | controller/RethinkDB.cpp | 20 | ||||
-rw-r--r-- | controller/RethinkDB.hpp | 2 | ||||
-rw-r--r-- | controller/migrate-sqlite/migrate.js | 318 | ||||
-rw-r--r-- | controller/migrate-sqlite/package.json | 15 | ||||
-rw-r--r-- | include/ZeroTierDebug.h | 114 | ||||
-rw-r--r-- | node/Network.cpp | 150 | ||||
-rw-r--r-- | osdep/WindowsEthernetTap.cpp | 2 |
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; |