mirror of
https://github.com/ZeroTier/ZeroTierOne
synced 2025-08-22 22:33:58 -07:00
Merge 8fa9248615
into bd7e4ab695
This commit is contained in:
commit
6de91ba3fe
52 changed files with 967 additions and 1173 deletions
41
AUTHORS.md
Normal file
41
AUTHORS.md
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
## Authors
|
||||||
|
|
||||||
|
* ZeroTier protocol design and core network virtualization engine, ZeroTier One service, React web UI, packaging for most platforms, kitchen sink...<br>
|
||||||
|
Adam Ierymenko / adam.ierymenko@zerotier.com
|
||||||
|
|
||||||
|
* Java JNI Interface to enable Android application development, and Android app itself (code for that is elsewhere)<br>
|
||||||
|
Grant Limberg / glimberg@gmail.com
|
||||||
|
|
||||||
|
## Contributors
|
||||||
|
|
||||||
|
* A number of fixes and improvements to the new controller, other stuff.<br>
|
||||||
|
Kees Bos / https://github.com/keesbos
|
||||||
|
|
||||||
|
* Debugging and testing, OpenWRT support fixes.<br>
|
||||||
|
Moritz Warning / moritzwarning@web.de
|
||||||
|
|
||||||
|
* Several others made smaller contributions, which GitHub tracks here:<br>
|
||||||
|
https://github.com/zerotier/ZeroTierOne/graphs/contributors
|
||||||
|
|
||||||
|
## Third Party Code
|
||||||
|
|
||||||
|
* LZ4 compression algorithm by Yann Collet (BSD license)<br>
|
||||||
|
http://code.google.com/p/lz4/
|
||||||
|
|
||||||
|
* http-parser by many authors (MIT license)<br>
|
||||||
|
https://github.com/joyent/http-parser
|
||||||
|
|
||||||
|
* json-parser by James McLaughlin (BSD license)<br>
|
||||||
|
https://github.com/udp/json-parser
|
||||||
|
|
||||||
|
* TunTapOSX by Mattias Nissler (BSD license)<br>
|
||||||
|
http://tuntaposx.sourceforge.net
|
||||||
|
|
||||||
|
* tap-windows and tap-windows6 by the OpenVPN project (GPL)<br>
|
||||||
|
https://github.com/OpenVPN/tap-windows<br>
|
||||||
|
https://github.com/OpenVPN/tap-windows6
|
||||||
|
|
||||||
|
* Salsa20 stream cipher, Curve25519 elliptic curve cipher, Ed25519
|
||||||
|
digital signature algorithm, and Poly1305 MAC algorithm, all by
|
||||||
|
Daniel J. Bernstein (public domain)<br>
|
||||||
|
http://cr.yp.to/
|
27
AUTHORS.txt
27
AUTHORS.txt
|
@ -1,27 +0,0 @@
|
||||||
ZeroTier One is designed and written by Adam Ierymenko, with a few bug
|
|
||||||
fixes and other contributions from other users. Information about all
|
|
||||||
contributors can be found on the GitHub home page at:
|
|
||||||
|
|
||||||
https://github.com/zerotier/ZeroTierOne
|
|
||||||
|
|
||||||
ZeroTier One includes the following third party code:
|
|
||||||
|
|
||||||
* LZ4 compression algorithm by Yann Collet (BSD license)
|
|
||||||
http://code.google.com/p/lz4/
|
|
||||||
|
|
||||||
* http-parser by many authors (MIT license)
|
|
||||||
https://github.com/joyent/http-parser
|
|
||||||
|
|
||||||
* json-parser by James McLaughlin (BSD license)
|
|
||||||
https://github.com/udp/json-parser
|
|
||||||
|
|
||||||
* TunTapOSX by Mattias Nissler (forked for ZT1) (BSD license)
|
|
||||||
http://tuntaposx.sourceforge.net
|
|
||||||
|
|
||||||
* tap-windows by the OpenVPN project (forked for ZT1) (GPL)
|
|
||||||
https://github.com/OpenVPN/tap-windows
|
|
||||||
|
|
||||||
* Salsa20 stream cipher, Curve25519 elliptic curve cipher, Ed25519
|
|
||||||
digital signature algorithm, and Poly1305 MAC algorithm, all by
|
|
||||||
Daniel J. Bernstein (public domain)
|
|
||||||
http://cr.yp.to/
|
|
|
@ -164,7 +164,7 @@ Users behind certain types of firewalls and "symmetric" NAT devices may not able
|
||||||
|
|
||||||
If you're interested, there's a [technical deep dive about NAT traversal on our blog](https://www.zerotier.com/blog/?p=226). A troubleshooting tool to help you diagnose NAT issues is planned for the future as are uPnP/IGD/NAT-PMP and IPv6 transport.
|
If you're interested, there's a [technical deep dive about NAT traversal on our blog](https://www.zerotier.com/blog/?p=226). A troubleshooting tool to help you diagnose NAT issues is planned for the future as are uPnP/IGD/NAT-PMP and IPv6 transport.
|
||||||
|
|
||||||
If a firewall between you and the Internet blocks ZeroTier's UDP traffic, you will fall back to last-resort TCP tunneling to supernodes over port 443 (https impersonation). This will work almost anywhere but is *very slow* compared to UDP or direct peer to peer connectivity.
|
If a firewall between you and the Internet blocks ZeroTier's UDP traffic, you will fall back to last-resort TCP tunneling to rootservers over port 443 (https impersonation). This will work almost anywhere but is *very slow* compared to UDP or direct peer to peer connectivity.
|
||||||
|
|
||||||
### License
|
### License
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,7 @@
|
||||||
#include "../node/InetAddress.hpp"
|
#include "../node/InetAddress.hpp"
|
||||||
#include "../node/MAC.hpp"
|
#include "../node/MAC.hpp"
|
||||||
#include "../node/Address.hpp"
|
#include "../node/Address.hpp"
|
||||||
|
#include "../node/Switch.hpp"
|
||||||
#include "../osdep/OSUtils.hpp"
|
#include "../osdep/OSUtils.hpp"
|
||||||
|
|
||||||
// Include ZT_NETCONF_SCHEMA_SQL constant to init database
|
// Include ZT_NETCONF_SCHEMA_SQL constant to init database
|
||||||
|
@ -155,7 +156,6 @@ SqliteNetworkController::SqliteNetworkController(const char *dbPath) :
|
||||||
||(sqlite3_prepare_v2(_db,"UPDATE Node SET lastAt = ?,lastSeen = ? WHERE id = ?",-1,&_sUpdateNode,(const char **)0) != SQLITE_OK)
|
||(sqlite3_prepare_v2(_db,"UPDATE Node SET lastAt = ?,lastSeen = ? WHERE id = ?",-1,&_sUpdateNode,(const char **)0) != SQLITE_OK)
|
||||||
||(sqlite3_prepare_v2(_db,"UPDATE Node SET lastSeen = ? WHERE id = ?",-1,&_sUpdateNode2,(const char **)0) != SQLITE_OK)
|
||(sqlite3_prepare_v2(_db,"UPDATE Node SET lastSeen = ? WHERE id = ?",-1,&_sUpdateNode2,(const char **)0) != SQLITE_OK)
|
||||||
||(sqlite3_prepare_v2(_db,"SELECT etherType FROM Rule WHERE networkId = ? AND \"action\" = 'accept'",-1,&_sGetEtherTypesFromRuleTable,(const char **)0) != SQLITE_OK)
|
||(sqlite3_prepare_v2(_db,"SELECT etherType FROM Rule WHERE networkId = ? AND \"action\" = 'accept'",-1,&_sGetEtherTypesFromRuleTable,(const char **)0) != SQLITE_OK)
|
||||||
||(sqlite3_prepare_v2(_db,"SELECT mgMac,mgAdi,preload,maxBalance,accrual FROM MulticastRate WHERE networkId = ?",-1,&_sGetMulticastRates,(const char **)0) != SQLITE_OK)
|
|
||||||
||(sqlite3_prepare_v2(_db,"SELECT nodeId FROM Member WHERE networkId = ? AND activeBridge > 0 AND authorized > 0",-1,&_sGetActiveBridges,(const char **)0) != SQLITE_OK)
|
||(sqlite3_prepare_v2(_db,"SELECT nodeId FROM Member WHERE networkId = ? AND activeBridge > 0 AND authorized > 0",-1,&_sGetActiveBridges,(const char **)0) != SQLITE_OK)
|
||||||
||(sqlite3_prepare_v2(_db,"SELECT ip,ipNetmaskBits FROM IpAssignment WHERE networkId = ? AND nodeId = ? AND ipVersion = ?",-1,&_sGetIpAssignmentsForNode,(const char **)0) != SQLITE_OK)
|
||(sqlite3_prepare_v2(_db,"SELECT ip,ipNetmaskBits FROM IpAssignment WHERE networkId = ? AND nodeId = ? AND ipVersion = ?",-1,&_sGetIpAssignmentsForNode,(const char **)0) != SQLITE_OK)
|
||||||
||(sqlite3_prepare_v2(_db,"SELECT ipNetwork,ipNetmaskBits FROM IpAssignmentPool WHERE networkId = ? AND ipVersion = ?",-1,&_sGetIpAssignmentPools,(const char **)0) != SQLITE_OK)
|
||(sqlite3_prepare_v2(_db,"SELECT ipNetwork,ipNetmaskBits FROM IpAssignmentPool WHERE networkId = ? AND ipVersion = ?",-1,&_sGetIpAssignmentPools,(const char **)0) != SQLITE_OK)
|
||||||
|
@ -164,11 +164,11 @@ SqliteNetworkController::SqliteNetworkController(const char *dbPath) :
|
||||||
||(sqlite3_prepare_v2(_db,"DELETE FROM IpAssignment WHERE networkId = ? AND nodeId = ?",-1,&_sDeleteIpAllocations,(const char **)0) != SQLITE_OK)
|
||(sqlite3_prepare_v2(_db,"DELETE FROM IpAssignment WHERE networkId = ? AND nodeId = ?",-1,&_sDeleteIpAllocations,(const char **)0) != SQLITE_OK)
|
||||||
||(sqlite3_prepare_v2(_db,"SELECT nodeId,phyAddress FROM Relay WHERE networkId = ? ORDER BY nodeId ASC",-1,&_sGetRelays,(const char **)0) != SQLITE_OK)
|
||(sqlite3_prepare_v2(_db,"SELECT nodeId,phyAddress FROM Relay WHERE networkId = ? ORDER BY nodeId ASC",-1,&_sGetRelays,(const char **)0) != SQLITE_OK)
|
||||||
||(sqlite3_prepare_v2(_db,"SELECT id FROM Network ORDER BY id ASC",-1,&_sListNetworks,(const char **)0) != SQLITE_OK)
|
||(sqlite3_prepare_v2(_db,"SELECT id FROM Network ORDER BY id ASC",-1,&_sListNetworks,(const char **)0) != SQLITE_OK)
|
||||||
||(sqlite3_prepare_v2(_db,"SELECT n.id FROM Member AS m,Node AS n WHERE m.networkId = ? AND n.id = m.nodeId ORDER BY n.id ASC",-1,&_sListNetworkMembers,(const char **)0) != SQLITE_OK)
|
||(sqlite3_prepare_v2(_db,"SELECT m.nodeId FROM Member AS m WHERE m.networkId = ? ORDER BY m.nodeId ASC",-1,&_sListNetworkMembers,(const char **)0) != SQLITE_OK)
|
||||||
||(sqlite3_prepare_v2(_db,"SELECT m.authorized,m.activeBridge,n.identity,n.lastAt,n.lastSeen,n.firstSeen FROM Member AS m,Node AS n WHERE m.networkId = ? AND m.nodeId = ?",-1,&_sGetMember2,(const char **)0) != SQLITE_OK)
|
||(sqlite3_prepare_v2(_db,"SELECT m.authorized,m.activeBridge,n.identity,n.lastAt,n.lastSeen,n.firstSeen FROM Member AS m JOIN Node AS n ON n.id = m.nodeId WHERE m.networkId = ? AND m.nodeId = ?",-1,&_sGetMember2,(const char **)0) != SQLITE_OK)
|
||||||
||(sqlite3_prepare_v2(_db,"SELECT ipNetwork,ipNetmaskBits,ipVersion FROM IpAssignmentPool WHERE networkId = ? ORDER BY ipNetwork ASC",-1,&_sGetIpAssignmentPools2,(const char **)0) != SQLITE_OK)
|
||(sqlite3_prepare_v2(_db,"SELECT ipNetwork,ipNetmaskBits,ipVersion FROM IpAssignmentPool WHERE networkId = ? ORDER BY ipNetwork ASC",-1,&_sGetIpAssignmentPools2,(const char **)0) != SQLITE_OK)
|
||||||
||(sqlite3_prepare_v2(_db,"SELECT ruleId,nodeId,vlanId,vlanPcp,etherType,macSource,macDest,ipSource,ipDest,ipTos,ipProtocol,ipSourcePort,ipDestPort,\"flags\",invFlags,\"action\" FROM Rule WHERE networkId = ? ORDER BY ruleId ASC",-1,&_sListRules,(const char **)0) != SQLITE_OK)
|
||(sqlite3_prepare_v2(_db,"SELECT ruleNo,nodeId,vlanId,vlanPcp,etherType,macSource,macDest,ipSource,ipDest,ipTos,ipProtocol,ipSourcePort,ipDestPort,\"flags\",invFlags,\"action\" FROM Rule WHERE networkId = ? ORDER BY ruleNo ASC",-1,&_sListRules,(const char **)0) != SQLITE_OK)
|
||||||
||(sqlite3_prepare_v2(_db,"INSERT INTO Rule (networkId,ruleId,nodeId,vlanId,vlanPcP,etherType,macSource,macDest,ipSource,ipDest,ipTos,ipProtocol,ipSourcePort,ipDestPort,\"action\") VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",-1,&_sCreateRule,(const char **)0) != SQLITE_OK)
|
||(sqlite3_prepare_v2(_db,"INSERT INTO Rule (networkId,ruleNo,nodeId,vlanId,vlanPcP,etherType,macSource,macDest,ipSource,ipDest,ipTos,ipProtocol,ipSourcePort,ipDestPort,\"action\") VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",-1,&_sCreateRule,(const char **)0) != SQLITE_OK)
|
||||||
||(sqlite3_prepare_v2(_db,"INSERT INTO Network (id,name,creationTime,revision) VALUES (?,?,?,1)",-1,&_sCreateNetwork,(const char **)0) != SQLITE_OK)
|
||(sqlite3_prepare_v2(_db,"INSERT INTO Network (id,name,creationTime,revision) VALUES (?,?,?,1)",-1,&_sCreateNetwork,(const char **)0) != SQLITE_OK)
|
||||||
||(sqlite3_prepare_v2(_db,"SELECT revision FROM Network WHERE id = ?",-1,&_sGetNetworkRevision,(const char **)0) != SQLITE_OK)
|
||(sqlite3_prepare_v2(_db,"SELECT revision FROM Network WHERE id = ?",-1,&_sGetNetworkRevision,(const char **)0) != SQLITE_OK)
|
||||||
||(sqlite3_prepare_v2(_db,"UPDATE Network SET revision = ? WHERE id = ?",-1,&_sSetNetworkRevision,(const char **)0) != SQLITE_OK)
|
||(sqlite3_prepare_v2(_db,"UPDATE Network SET revision = ? WHERE id = ?",-1,&_sSetNetworkRevision,(const char **)0) != SQLITE_OK)
|
||||||
|
@ -178,8 +178,13 @@ SqliteNetworkController::SqliteNetworkController(const char *dbPath) :
|
||||||
||(sqlite3_prepare_v2(_db,"DELETE FROM IpAssignmentPool WHERE networkId = ?",-1,&_sDeleteIpAssignmentPoolsForNetwork,(const char **)0) != SQLITE_OK)
|
||(sqlite3_prepare_v2(_db,"DELETE FROM IpAssignmentPool WHERE networkId = ?",-1,&_sDeleteIpAssignmentPoolsForNetwork,(const char **)0) != SQLITE_OK)
|
||||||
||(sqlite3_prepare_v2(_db,"DELETE FROM Rule WHERE networkId = ?",-1,&_sDeleteRulesForNetwork,(const char **)0) != SQLITE_OK)
|
||(sqlite3_prepare_v2(_db,"DELETE FROM Rule WHERE networkId = ?",-1,&_sDeleteRulesForNetwork,(const char **)0) != SQLITE_OK)
|
||||||
||(sqlite3_prepare_v2(_db,"INSERT INTO IpAssignmentPool (networkId,ipNetwork,ipNetmaskBits,ipVersion) VALUES (?,?,?,?)",-1,&_sCreateIpAssignmentPool,(const char **)0) != SQLITE_OK)
|
||(sqlite3_prepare_v2(_db,"INSERT INTO IpAssignmentPool (networkId,ipNetwork,ipNetmaskBits,ipVersion) VALUES (?,?,?,?)",-1,&_sCreateIpAssignmentPool,(const char **)0) != SQLITE_OK)
|
||||||
|
||(sqlite3_prepare_v2(_db,"UPDATE Member SET authorized = ? WHERE rowid = ?",-1,&_sUpdateMemberAuthorized,(const char **)0) != SQLITE_OK)
|
||||||
|
||(sqlite3_prepare_v2(_db,"UPDATE Member SET activeBridge = ? WHERE rowid = ?",-1,&_sUpdateMemberActiveBridge,(const char **)0) != SQLITE_OK)
|
||||||
||(sqlite3_prepare_v2(_db,"DELETE FROM Member WHERE networkId = ? AND nodeId = ?",-1,&_sDeleteMember,(const char **)0) != SQLITE_OK)
|
||(sqlite3_prepare_v2(_db,"DELETE FROM Member WHERE networkId = ? AND nodeId = ?",-1,&_sDeleteMember,(const char **)0) != SQLITE_OK)
|
||||||
||(sqlite3_prepare_v2(_db,"DELETE FROM IpAssignment WHERE networkId = ?; DELETE FROM IpAssignmentPool WHERE networkId = ?; DELETE FROM Member WHERE networkId = ?; DELETE FROM MulticastRate WHERE networkId = ?; DELETE FROM Relay WHERE networkId = ?; DELETE FROM Rule WHERE networkId = ?; DELETE FROM Network WHERE id = ?;",-1,&_sDeleteNetworkAndRelated,(const char **)0) != SQLITE_OK)
|
||(sqlite3_prepare_v2(_db,"DELETE FROM Network WHERE id = ?",-1,&_sDeleteNetwork,(const char **)0) != SQLITE_OK)
|
||||||
|
||(sqlite3_prepare_v2(_db,"SELECT ip,ipVersion,metric FROM Gateway WHERE networkId = ? ORDER BY metric ASC",-1,&_sGetGateways,(const char **)0) != SQLITE_OK)
|
||||||
|
||(sqlite3_prepare_v2(_db,"DELETE FROM Gateway WHERE networkId = ?",-1,&_sDeleteGateways,(const char **)0) != SQLITE_OK)
|
||||||
|
||(sqlite3_prepare_v2(_db,"INSERT INTO Gateway (networkId,ip,ipVersion,metric) VALUES (?,?,?,?)",-1,&_sCreateGateway,(const char **)0) != SQLITE_OK)
|
||||||
) {
|
) {
|
||||||
//printf("!!! %s\n",sqlite3_errmsg(_db));
|
//printf("!!! %s\n",sqlite3_errmsg(_db));
|
||||||
sqlite3_close(_db);
|
sqlite3_close(_db);
|
||||||
|
@ -199,7 +204,6 @@ SqliteNetworkController::~SqliteNetworkController()
|
||||||
sqlite3_finalize(_sUpdateNode);
|
sqlite3_finalize(_sUpdateNode);
|
||||||
sqlite3_finalize(_sUpdateNode2);
|
sqlite3_finalize(_sUpdateNode2);
|
||||||
sqlite3_finalize(_sGetEtherTypesFromRuleTable);
|
sqlite3_finalize(_sGetEtherTypesFromRuleTable);
|
||||||
sqlite3_finalize(_sGetMulticastRates);
|
|
||||||
sqlite3_finalize(_sGetActiveBridges);
|
sqlite3_finalize(_sGetActiveBridges);
|
||||||
sqlite3_finalize(_sGetIpAssignmentsForNode);
|
sqlite3_finalize(_sGetIpAssignmentsForNode);
|
||||||
sqlite3_finalize(_sGetIpAssignmentPools);
|
sqlite3_finalize(_sGetIpAssignmentPools);
|
||||||
|
@ -222,7 +226,13 @@ SqliteNetworkController::~SqliteNetworkController()
|
||||||
sqlite3_finalize(_sDeleteIpAssignmentPoolsForNetwork);
|
sqlite3_finalize(_sDeleteIpAssignmentPoolsForNetwork);
|
||||||
sqlite3_finalize(_sDeleteRulesForNetwork);
|
sqlite3_finalize(_sDeleteRulesForNetwork);
|
||||||
sqlite3_finalize(_sCreateIpAssignmentPool);
|
sqlite3_finalize(_sCreateIpAssignmentPool);
|
||||||
sqlite3_finalize(_sDeleteNetworkAndRelated);
|
sqlite3_finalize(_sUpdateMemberAuthorized);
|
||||||
|
sqlite3_finalize(_sUpdateMemberActiveBridge);
|
||||||
|
sqlite3_finalize(_sDeleteMember);
|
||||||
|
sqlite3_finalize(_sDeleteNetwork);
|
||||||
|
sqlite3_finalize(_sGetGateways);
|
||||||
|
sqlite3_finalize(_sDeleteGateways);
|
||||||
|
sqlite3_finalize(_sCreateGateway);
|
||||||
sqlite3_close(_db);
|
sqlite3_close(_db);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -336,7 +346,7 @@ NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(co
|
||||||
sqlite3_reset(_sCreateMember);
|
sqlite3_reset(_sCreateMember);
|
||||||
sqlite3_bind_text(_sCreateMember,1,network.id,16,SQLITE_STATIC);
|
sqlite3_bind_text(_sCreateMember,1,network.id,16,SQLITE_STATIC);
|
||||||
sqlite3_bind_text(_sCreateMember,2,member.nodeId,10,SQLITE_STATIC);
|
sqlite3_bind_text(_sCreateMember,2,member.nodeId,10,SQLITE_STATIC);
|
||||||
sqlite3_bind_int(_sCreateMember,3,(member.authorized ? 0 : 1));
|
sqlite3_bind_int(_sCreateMember,3,(member.authorized ? 1 : 0));
|
||||||
if (sqlite3_step(_sCreateMember) != SQLITE_DONE) {
|
if (sqlite3_step(_sCreateMember) != SQLITE_DONE) {
|
||||||
netconf["error"] = "unable to create new member record";
|
netconf["error"] = "unable to create new member record";
|
||||||
return NetworkController::NETCONF_QUERY_INTERNAL_SERVER_ERROR;
|
return NetworkController::NETCONF_QUERY_INTERNAL_SERVER_ERROR;
|
||||||
|
@ -379,6 +389,14 @@ NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(co
|
||||||
if ((et >= 0)&&(et <= 0xffff))
|
if ((et >= 0)&&(et <= 0xffff))
|
||||||
allowedEtherTypes.push_back(et);
|
allowedEtherTypes.push_back(et);
|
||||||
}
|
}
|
||||||
|
if (!allowedEtherTypes.size()) {
|
||||||
|
// Nothing permitted is not usefull
|
||||||
|
// Just supply a default config allowing ARP, IPv4, IPv6
|
||||||
|
// allowedEtherTypes.push_back(0); this would allow anything
|
||||||
|
allowedEtherTypes.push_back(ZT_ETHERTYPE_IPV4);
|
||||||
|
allowedEtherTypes.push_back(ZT_ETHERTYPE_ARP);
|
||||||
|
allowedEtherTypes.push_back(ZT_ETHERTYPE_IPV6);
|
||||||
|
}
|
||||||
std::sort(allowedEtherTypes.begin(),allowedEtherTypes.end());
|
std::sort(allowedEtherTypes.begin(),allowedEtherTypes.end());
|
||||||
std::unique(allowedEtherTypes.begin(),allowedEtherTypes.end());
|
std::unique(allowedEtherTypes.begin(),allowedEtherTypes.end());
|
||||||
std::string allowedEtherTypesCsv;
|
std::string allowedEtherTypesCsv;
|
||||||
|
@ -392,26 +410,10 @@ NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(co
|
||||||
netconf[ZT_NETWORKCONFIG_DICT_KEY_ALLOWED_ETHERNET_TYPES] = allowedEtherTypesCsv;
|
netconf[ZT_NETWORKCONFIG_DICT_KEY_ALLOWED_ETHERNET_TYPES] = allowedEtherTypesCsv;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
if (network.multicastLimit > 0) {
|
||||||
std::string multicastRates;
|
char ml[16];
|
||||||
sqlite3_reset(_sGetMulticastRates);
|
Utils::snprintf(ml,sizeof(ml),"%lx",(unsigned long)network.multicastLimit);
|
||||||
sqlite3_bind_text(_sGetMulticastRates,1,network.id,16,SQLITE_STATIC);
|
netconf[ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT] = ml;
|
||||||
while (sqlite3_step(_sGetMulticastRates) == SQLITE_ROW) {
|
|
||||||
const char *mac = (const char *)sqlite3_column_text(_sGetMulticastRates,0);
|
|
||||||
if ((mac)&&(strlen(mac) == 12)) {
|
|
||||||
unsigned long adi = ((unsigned long)sqlite3_column_int64(_sGetMulticastRates,1)) & 0xffffffff;
|
|
||||||
char tmp[256];
|
|
||||||
Utils::snprintf(tmp,sizeof(tmp),"%s/%.4lx=%x,%x,%x\n",mac,adi,sqlite3_column_int(_sGetMulticastRates,2),sqlite3_column_int(_sGetMulticastRates,3),sqlite3_column_int(_sGetMulticastRates,4));
|
|
||||||
multicastRates.append(tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (multicastRates.length() > 0)
|
|
||||||
netconf[ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_RATES] = multicastRates;
|
|
||||||
if (network.multicastLimit > 0) {
|
|
||||||
char ml[16];
|
|
||||||
Utils::snprintf(ml,sizeof(ml),"%lx",(unsigned long)network.multicastLimit);
|
|
||||||
netconf[ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT] = ml;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -455,6 +457,52 @@ NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(co
|
||||||
netconf[ZT_NETWORKCONFIG_DICT_KEY_RELAYS] = relays;
|
netconf[ZT_NETWORKCONFIG_DICT_KEY_RELAYS] = relays;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
char tmp[128];
|
||||||
|
std::string gateways;
|
||||||
|
sqlite3_reset(_sGetGateways);
|
||||||
|
sqlite3_bind_text(_sGetGateways,1,network.id,16,SQLITE_STATIC);
|
||||||
|
while (sqlite3_step(_sGetGateways) == SQLITE_ROW) {
|
||||||
|
const unsigned char *ip = (const unsigned char *)sqlite3_column_blob(_sGetGateways,0);
|
||||||
|
switch(sqlite3_column_int(_sGetGateways,1)) { // ipVersion
|
||||||
|
case 4:
|
||||||
|
Utils::snprintf(tmp,sizeof(tmp),"%s%d.%d.%d.%d/%d",
|
||||||
|
(gateways.length() > 0) ? "," : "",
|
||||||
|
(int)ip[0],
|
||||||
|
(int)ip[1],
|
||||||
|
(int)ip[2],
|
||||||
|
(int)ip[3],
|
||||||
|
(int)sqlite3_column_int(_sGetGateways,2)); // metric
|
||||||
|
gateways.append(tmp);
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
Utils::snprintf(tmp,sizeof(tmp),"%s%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x/%d",
|
||||||
|
(gateways.length() > 0) ? "," : "",
|
||||||
|
(int)ip[0],
|
||||||
|
(int)ip[1],
|
||||||
|
(int)ip[2],
|
||||||
|
(int)ip[3],
|
||||||
|
(int)ip[4],
|
||||||
|
(int)ip[5],
|
||||||
|
(int)ip[6],
|
||||||
|
(int)ip[7],
|
||||||
|
(int)ip[8],
|
||||||
|
(int)ip[9],
|
||||||
|
(int)ip[10],
|
||||||
|
(int)ip[11],
|
||||||
|
(int)ip[12],
|
||||||
|
(int)ip[13],
|
||||||
|
(int)ip[14],
|
||||||
|
(int)ip[15],
|
||||||
|
(int)sqlite3_column_int(_sGetGateways,2)); // metric
|
||||||
|
gateways.append(tmp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (gateways.length())
|
||||||
|
netconf[ZT_NETWORKCONFIG_DICT_KEY_GATEWAYS] = gateways;
|
||||||
|
}
|
||||||
|
|
||||||
if ((network.v4AssignMode)&&(!strcmp(network.v4AssignMode,"zt"))) {
|
if ((network.v4AssignMode)&&(!strcmp(network.v4AssignMode,"zt"))) {
|
||||||
std::string v4s;
|
std::string v4s;
|
||||||
|
|
||||||
|
@ -467,7 +515,7 @@ NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(co
|
||||||
int ipNetmaskBits = sqlite3_column_int(_sGetIpAssignmentsForNode,1);
|
int ipNetmaskBits = sqlite3_column_int(_sGetIpAssignmentsForNode,1);
|
||||||
if ((ip)&&(sqlite3_column_bytes(_sGetIpAssignmentsForNode,0) >= 4)&&(ipNetmaskBits > 0)&&(ipNetmaskBits <= 32)) {
|
if ((ip)&&(sqlite3_column_bytes(_sGetIpAssignmentsForNode,0) >= 4)&&(ipNetmaskBits > 0)&&(ipNetmaskBits <= 32)) {
|
||||||
char tmp[32];
|
char tmp[32];
|
||||||
Utils::snprintf(tmp,sizeof(tmp),"%d.%d.%d.%d/%d",(int)ip[0],(int)ip[1],(int)ip[2],(int)ip[3],ipNetmaskBits);
|
Utils::snprintf(tmp,sizeof(tmp),"%d.%d.%d.%d/%d",(int)ip[12+0],(int)ip[12+1],(int)ip[12+2],(int)ip[12+3],ipNetmaskBits);
|
||||||
if (v4s.length())
|
if (v4s.length())
|
||||||
v4s.push_back(',');
|
v4s.push_back(',');
|
||||||
v4s.append(tmp);
|
v4s.append(tmp);
|
||||||
|
@ -628,29 +676,27 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(
|
||||||
|
|
||||||
if (!strcmp(j->u.object.values[k].name,"authorized")) {
|
if (!strcmp(j->u.object.values[k].name,"authorized")) {
|
||||||
if (j->u.object.values[k].value->type == json_boolean) {
|
if (j->u.object.values[k].value->type == json_boolean) {
|
||||||
sqlite3_stmt *stmt = (sqlite3_stmt *)0;
|
sqlite3_reset(_sUpdateMemberAuthorized);
|
||||||
if (sqlite3_prepare_v2(_db,"UPDATE Member SET authorized = ? WHERE rowid = ?",-1,&stmt,(const char **)0) == SQLITE_OK)
|
sqlite3_bind_int(_sUpdateMemberAuthorized,1,(j->u.object.values[k].value->u.boolean == 0) ? 0 : 1);
|
||||||
sqlite3_bind_int(stmt,1,(j->u.object.values[k].value->u.boolean == 0) ? 0 : 1);
|
sqlite3_bind_int64(_sUpdateMemberAuthorized,2,memberRowId);
|
||||||
sqlite3_bind_int64(stmt,2,memberRowId);
|
if (sqlite3_step(_sUpdateMemberAuthorized) != SQLITE_DONE)
|
||||||
sqlite3_step(stmt);
|
return 500;
|
||||||
sqlite3_finalize(stmt);
|
|
||||||
}
|
}
|
||||||
} else if (!strcmp(j->u.object.values[k].name,"activeBridge")) {
|
} else if (!strcmp(j->u.object.values[k].name,"activeBridge")) {
|
||||||
if (j->u.object.values[k].value->type == json_boolean) {
|
if (j->u.object.values[k].value->type == json_boolean) {
|
||||||
sqlite3_stmt *stmt = (sqlite3_stmt *)0;
|
sqlite3_reset(_sUpdateMemberActiveBridge);
|
||||||
if (sqlite3_prepare_v2(_db,"UPDATE Member SET activeBridge = ? WHERE rowid = ?",-1,&stmt,(const char **)0) == SQLITE_OK) {
|
sqlite3_bind_int(_sUpdateMemberActiveBridge,1,(j->u.object.values[k].value->u.boolean == 0) ? 0 : 1);
|
||||||
sqlite3_bind_int(stmt,1,(j->u.object.values[k].value->u.boolean == 0) ? 0 : 1);
|
sqlite3_bind_int64(_sUpdateMemberActiveBridge,2,memberRowId);
|
||||||
sqlite3_bind_int64(stmt,2,memberRowId);
|
if (sqlite3_step(_sUpdateMemberActiveBridge) != SQLITE_DONE)
|
||||||
sqlite3_step(stmt);
|
return 500;
|
||||||
sqlite3_finalize(stmt);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if (!strcmp(j->u.object.values[k].name,"ipAssignments")) {
|
} else if (!strcmp(j->u.object.values[k].name,"ipAssignments")) {
|
||||||
if (j->u.object.values[k].value->type == json_array) {
|
if (j->u.object.values[k].value->type == json_array) {
|
||||||
sqlite3_reset(_sDeleteIpAllocations);
|
sqlite3_reset(_sDeleteIpAllocations);
|
||||||
sqlite3_bind_text(_sDeleteIpAllocations,1,nwids,16,SQLITE_STATIC);
|
sqlite3_bind_text(_sDeleteIpAllocations,1,nwids,16,SQLITE_STATIC);
|
||||||
sqlite3_bind_text(_sDeleteIpAllocations,2,addrs,10,SQLITE_STATIC);
|
sqlite3_bind_text(_sDeleteIpAllocations,2,addrs,10,SQLITE_STATIC);
|
||||||
sqlite3_step(_sDeleteIpAllocations);
|
if (sqlite3_step(_sDeleteIpAllocations) != SQLITE_DONE)
|
||||||
|
return 500;
|
||||||
for(unsigned int kk=0;kk<j->u.object.values[k].value->u.array.length;++kk) {
|
for(unsigned int kk=0;kk<j->u.object.values[k].value->u.array.length;++kk) {
|
||||||
json_value *ipalloc = j->u.object.values[k].value->u.array.values[kk];
|
json_value *ipalloc = j->u.object.values[k].value->u.array.values[kk];
|
||||||
if (ipalloc->type == json_string) {
|
if (ipalloc->type == json_string) {
|
||||||
|
@ -679,7 +725,8 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(
|
||||||
sqlite3_bind_blob(_sAllocateIp,3,(const void *)ipBlob,16,SQLITE_STATIC);
|
sqlite3_bind_blob(_sAllocateIp,3,(const void *)ipBlob,16,SQLITE_STATIC);
|
||||||
sqlite3_bind_int(_sAllocateIp,4,(int)a.netmaskBits());
|
sqlite3_bind_int(_sAllocateIp,4,(int)a.netmaskBits());
|
||||||
sqlite3_bind_int(_sAllocateIp,5,ipVersion);
|
sqlite3_bind_int(_sAllocateIp,5,ipVersion);
|
||||||
sqlite3_step(_sAllocateIp);
|
if (sqlite3_step(_sAllocateIp) != SQLITE_DONE)
|
||||||
|
return 500;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -695,6 +742,7 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(
|
||||||
} // else 404
|
} // else 404
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
std::vector<std::string> path_copy(path);
|
||||||
|
|
||||||
if (!networkExists) {
|
if (!networkExists) {
|
||||||
if (path[1].substr(10) == "______") {
|
if (path[1].substr(10) == "______") {
|
||||||
|
@ -734,6 +782,7 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(
|
||||||
sqlite3_bind_int64(_sCreateNetwork,3,(long long)OSUtils::now());
|
sqlite3_bind_int64(_sCreateNetwork,3,(long long)OSUtils::now());
|
||||||
if (sqlite3_step(_sCreateNetwork) != SQLITE_DONE)
|
if (sqlite3_step(_sCreateNetwork) != SQLITE_DONE)
|
||||||
return 500;
|
return 500;
|
||||||
|
path_copy[1].assign(nwids);
|
||||||
}
|
}
|
||||||
|
|
||||||
json_value *j = json_parse(body.c_str(),body.length());
|
json_value *j = json_parse(body.c_str(),body.length());
|
||||||
|
@ -808,6 +857,31 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(
|
||||||
sqlite3_step(_sCreateRelay);
|
sqlite3_step(_sCreateRelay);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (!strcmp(j->u.object.values[k].name,"gateways")) {
|
||||||
|
sqlite3_reset(_sDeleteGateways);
|
||||||
|
sqlite3_bind_text(_sDeleteGateways,1,nwids,16,SQLITE_STATIC);
|
||||||
|
sqlite3_step(_sDeleteGateways);
|
||||||
|
if (j->u.object.values[k].value->type == json_array) {
|
||||||
|
for(unsigned int kk=0;kk<j->u.object.values[k].value->u.array.length;++kk) {
|
||||||
|
json_value *gateway = j->u.object.values[k].value->u.array.values[kk];
|
||||||
|
if ((gateway)&&(gateway->type == json_string)) {
|
||||||
|
InetAddress gwip(gateway->u.string.ptr);
|
||||||
|
int ipVersion = 0;
|
||||||
|
if (gwip.ss_family == AF_INET)
|
||||||
|
ipVersion = 4;
|
||||||
|
else if (gwip.ss_family == AF_INET6)
|
||||||
|
ipVersion = 6;
|
||||||
|
if (ipVersion) {
|
||||||
|
sqlite3_reset(_sCreateGateway);
|
||||||
|
sqlite3_bind_text(_sCreateGateway,1,nwids,16,SQLITE_STATIC);
|
||||||
|
sqlite3_bind_blob(_sCreateGateway,2,gwip.rawIpData(),(gwip.ss_family == AF_INET6) ? 16 : 4,SQLITE_STATIC);
|
||||||
|
sqlite3_bind_int(_sCreateGateway,3,ipVersion);
|
||||||
|
sqlite3_bind_int(_sCreateGateway,4,(int)gwip.metric());
|
||||||
|
sqlite3_step(_sCreateGateway);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (!strcmp(j->u.object.values[k].name,"ipAssignmentPools")) {
|
} else if (!strcmp(j->u.object.values[k].name,"ipAssignmentPools")) {
|
||||||
if (j->u.object.values[k].value->type == json_array) {
|
if (j->u.object.values[k].value->type == json_array) {
|
||||||
std::set<InetAddress> pools;
|
std::set<InetAddress> pools;
|
||||||
|
@ -855,7 +929,7 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(
|
||||||
json_value *rj = j->u.object.values[k].value->u.array.values[kk];
|
json_value *rj = j->u.object.values[k].value->u.array.values[kk];
|
||||||
if ((rj)&&(rj->type == json_object)) {
|
if ((rj)&&(rj->type == json_object)) {
|
||||||
struct { // NULL pointers indicate missing or NULL -- wildcards
|
struct { // NULL pointers indicate missing or NULL -- wildcards
|
||||||
const json_int_t *ruleId;
|
const json_int_t *ruleNo;
|
||||||
const char *nodeId;
|
const char *nodeId;
|
||||||
const json_int_t *vlanId;
|
const json_int_t *vlanId;
|
||||||
const json_int_t *vlanPcp;
|
const json_int_t *vlanPcp;
|
||||||
|
@ -875,8 +949,8 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(
|
||||||
memset(&rule,0,sizeof(rule));
|
memset(&rule,0,sizeof(rule));
|
||||||
|
|
||||||
for(unsigned int rk=0;rk<rj->u.object.length;++rk) {
|
for(unsigned int rk=0;rk<rj->u.object.length;++rk) {
|
||||||
if ((!strcmp(rj->u.object.values[rk].name,"ruleId"))&&(rj->u.object.values[rk].value->type == json_integer))
|
if ((!strcmp(rj->u.object.values[rk].name,"ruleNo"))&&(rj->u.object.values[rk].value->type == json_integer))
|
||||||
rule.ruleId = &(rj->u.object.values[rk].value->u.integer);
|
rule.ruleNo = &(rj->u.object.values[rk].value->u.integer);
|
||||||
else if ((!strcmp(rj->u.object.values[rk].name,"nodeId"))&&(rj->u.object.values[rk].value->type == json_string))
|
else if ((!strcmp(rj->u.object.values[rk].name,"nodeId"))&&(rj->u.object.values[rk].value->type == json_string))
|
||||||
rule.nodeId = rj->u.object.values[rk].value->u.string.ptr;
|
rule.nodeId = rj->u.object.values[rk].value->u.string.ptr;
|
||||||
else if ((!strcmp(rj->u.object.values[rk].name,"vlanId"))&&(rj->u.object.values[rk].value->type == json_integer))
|
else if ((!strcmp(rj->u.object.values[rk].name,"vlanId"))&&(rj->u.object.values[rk].value->type == json_integer))
|
||||||
|
@ -909,11 +983,11 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(
|
||||||
rule.action = rj->u.object.values[rk].value->u.string.ptr;
|
rule.action = rj->u.object.values[rk].value->u.string.ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((rule.ruleId)&&(rule.action)&&(rule.action[0])) {
|
if ((rule.ruleNo)&&(rule.action)&&(rule.action[0])) {
|
||||||
char mactmp1[16],mactmp2[16];
|
char mactmp1[16],mactmp2[16];
|
||||||
sqlite3_reset(_sCreateRule);
|
sqlite3_reset(_sCreateRule);
|
||||||
sqlite3_bind_text(_sCreateRule,1,nwids,16,SQLITE_STATIC);
|
sqlite3_bind_text(_sCreateRule,1,nwids,16,SQLITE_STATIC);
|
||||||
sqlite3_bind_int64(_sCreateRule,2,*rule.ruleId);
|
sqlite3_bind_int64(_sCreateRule,2,*rule.ruleNo);
|
||||||
|
|
||||||
// Optional values: null by default
|
// Optional values: null by default
|
||||||
for(int i=3;i<=16;++i)
|
for(int i=3;i<=16;++i)
|
||||||
|
@ -964,7 +1038,7 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(
|
||||||
sqlite3_bind_text(_sSetNetworkRevision,2,nwids,16,SQLITE_STATIC);
|
sqlite3_bind_text(_sSetNetworkRevision,2,nwids,16,SQLITE_STATIC);
|
||||||
sqlite3_step(_sSetNetworkRevision);
|
sqlite3_step(_sSetNetworkRevision);
|
||||||
|
|
||||||
return _doCPGet(path,urlArgs,headers,body,responseBody,responseContentType);
|
return _doCPGet(path_copy,urlArgs,headers,body,responseBody,responseContentType);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // else 404
|
} // else 404
|
||||||
|
@ -993,6 +1067,11 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpDELETE(
|
||||||
char nwids[24];
|
char nwids[24];
|
||||||
Utils::snprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)nwid);
|
Utils::snprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)nwid);
|
||||||
|
|
||||||
|
sqlite3_reset(_sGetNetworkById);
|
||||||
|
sqlite3_bind_text(_sGetNetworkById,1,nwids,16,SQLITE_STATIC);
|
||||||
|
if (sqlite3_step(_sGetNetworkById) != SQLITE_ROW)
|
||||||
|
return 404;
|
||||||
|
|
||||||
if (path.size() >= 3) {
|
if (path.size() >= 3) {
|
||||||
|
|
||||||
if ((path.size() == 4)&&(path[2] == "member")&&(path[3].length() == 10)) {
|
if ((path.size() == 4)&&(path[2] == "member")&&(path[3].length() == 10)) {
|
||||||
|
@ -1000,6 +1079,12 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpDELETE(
|
||||||
char addrs[24];
|
char addrs[24];
|
||||||
Utils::snprintf(addrs,sizeof(addrs),"%.10llx",address);
|
Utils::snprintf(addrs,sizeof(addrs),"%.10llx",address);
|
||||||
|
|
||||||
|
sqlite3_reset(_sGetMember);
|
||||||
|
sqlite3_bind_text(_sGetMember,1,nwids,16,SQLITE_STATIC);
|
||||||
|
sqlite3_bind_text(_sGetMember,2,addrs,10,SQLITE_STATIC);
|
||||||
|
if (sqlite3_step(_sGetMember) != SQLITE_ROW)
|
||||||
|
return 404;
|
||||||
|
|
||||||
sqlite3_reset(_sDeleteIpAllocations);
|
sqlite3_reset(_sDeleteIpAllocations);
|
||||||
sqlite3_bind_text(_sDeleteIpAllocations,1,nwids,16,SQLITE_STATIC);
|
sqlite3_bind_text(_sDeleteIpAllocations,1,nwids,16,SQLITE_STATIC);
|
||||||
sqlite3_bind_text(_sDeleteIpAllocations,2,addrs,10,SQLITE_STATIC);
|
sqlite3_bind_text(_sDeleteIpAllocations,2,addrs,10,SQLITE_STATIC);
|
||||||
|
@ -1016,10 +1101,9 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpDELETE(
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
sqlite3_reset(_sDeleteNetworkAndRelated);
|
sqlite3_reset(_sDeleteNetwork);
|
||||||
for(int i=1;i<=7;++i)
|
sqlite3_bind_text(_sDeleteNetwork,1,nwids,16,SQLITE_STATIC);
|
||||||
sqlite3_bind_text(_sDeleteNetworkAndRelated,i,nwids,16,SQLITE_STATIC);
|
return ((sqlite3_step(_sDeleteNetwork) == SQLITE_DONE) ? 200 : 500);
|
||||||
return ((sqlite3_step(_sDeleteNetworkAndRelated) == SQLITE_DONE) ? 200 : 500);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
} // else 404
|
} // else 404
|
||||||
|
@ -1082,8 +1166,15 @@ unsigned int SqliteNetworkController::_doCPGet(
|
||||||
sqlite3_bind_text(_sGetIpAssignmentsForNode2,1,nwids,16,SQLITE_STATIC);
|
sqlite3_bind_text(_sGetIpAssignmentsForNode2,1,nwids,16,SQLITE_STATIC);
|
||||||
sqlite3_bind_text(_sGetIpAssignmentsForNode2,2,addrs,10,SQLITE_STATIC);
|
sqlite3_bind_text(_sGetIpAssignmentsForNode2,2,addrs,10,SQLITE_STATIC);
|
||||||
bool firstIp = true;
|
bool firstIp = true;
|
||||||
while (sqlite3_step(_sGetIpAssignmentPools2) == SQLITE_ROW) {
|
while (sqlite3_step(_sGetIpAssignmentsForNode2) == SQLITE_ROW) {
|
||||||
InetAddress ip((const void *)sqlite3_column_blob(_sGetIpAssignmentsForNode2,0),(sqlite3_column_int(_sGetIpAssignmentsForNode2,2) == 6) ? 16 : 4,(unsigned int)sqlite3_column_int(_sGetIpAssignmentPools2,1));
|
int ipversion = sqlite3_column_int(_sGetIpAssignmentsForNode2,2);
|
||||||
|
char ipBlob[16];
|
||||||
|
memcpy(ipBlob,(const void *)sqlite3_column_blob(_sGetIpAssignmentsForNode2,0),16);
|
||||||
|
InetAddress ip(
|
||||||
|
(const void *)(ipversion == 6 ? ipBlob : &ipBlob[12]),
|
||||||
|
(ipversion == 6 ? 16 : 4),
|
||||||
|
(unsigned int)sqlite3_column_int(_sGetIpAssignmentsForNode2,1)
|
||||||
|
);
|
||||||
responseBody.append(firstIp ? "\"" : ",\"");
|
responseBody.append(firstIp ? "\"" : ",\"");
|
||||||
firstIp = false;
|
firstIp = false;
|
||||||
responseBody.append(_jsonEscape(ip.toString()));
|
responseBody.append(_jsonEscape(ip.toString()));
|
||||||
|
@ -1202,6 +1293,49 @@ unsigned int SqliteNetworkController::_doCPGet(
|
||||||
responseBody.append(_jsonEscape((const char *)sqlite3_column_text(_sGetRelays,1)));
|
responseBody.append(_jsonEscape((const char *)sqlite3_column_text(_sGetRelays,1)));
|
||||||
responseBody.append("\"}");
|
responseBody.append("\"}");
|
||||||
}
|
}
|
||||||
|
responseBody.append("],\n\t\"gateways\": [");
|
||||||
|
|
||||||
|
sqlite3_reset(_sGetGateways);
|
||||||
|
sqlite3_bind_text(_sGetGateways,1,nwids,16,SQLITE_STATIC);
|
||||||
|
bool firstGateway = true;
|
||||||
|
while (sqlite3_step(_sGetGateways) == SQLITE_ROW) {
|
||||||
|
char tmp[128];
|
||||||
|
const unsigned char *ip = (const unsigned char *)sqlite3_column_blob(_sGetGateways,0);
|
||||||
|
switch(sqlite3_column_int(_sGetGateways,1)) { // ipVersion
|
||||||
|
case 4:
|
||||||
|
Utils::snprintf(tmp,sizeof(tmp),"%s%d.%d.%d.%d/%d\"",
|
||||||
|
(firstGateway) ? "\"" : ",\"",
|
||||||
|
(int)ip[0],
|
||||||
|
(int)ip[1],
|
||||||
|
(int)ip[2],
|
||||||
|
(int)ip[3],
|
||||||
|
(int)sqlite3_column_int(_sGetGateways,2)); // metric
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
Utils::snprintf(tmp,sizeof(tmp),"%s%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x/%d\"",
|
||||||
|
(firstGateway) ? "\"" : ",\"",
|
||||||
|
(int)ip[0],
|
||||||
|
(int)ip[1],
|
||||||
|
(int)ip[2],
|
||||||
|
(int)ip[3],
|
||||||
|
(int)ip[4],
|
||||||
|
(int)ip[5],
|
||||||
|
(int)ip[6],
|
||||||
|
(int)ip[7],
|
||||||
|
(int)ip[8],
|
||||||
|
(int)ip[9],
|
||||||
|
(int)ip[10],
|
||||||
|
(int)ip[11],
|
||||||
|
(int)ip[12],
|
||||||
|
(int)ip[13],
|
||||||
|
(int)ip[14],
|
||||||
|
(int)ip[15],
|
||||||
|
(int)sqlite3_column_int(_sGetGateways,2)); // metric
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
responseBody.append(tmp);
|
||||||
|
firstGateway = false;
|
||||||
|
}
|
||||||
responseBody.append("],\n\t\"ipAssignmentPools\": [");
|
responseBody.append("],\n\t\"ipAssignmentPools\": [");
|
||||||
|
|
||||||
sqlite3_reset(_sGetIpAssignmentPools2);
|
sqlite3_reset(_sGetIpAssignmentPools2);
|
||||||
|
@ -1223,7 +1357,7 @@ unsigned int SqliteNetworkController::_doCPGet(
|
||||||
bool firstRule = true;
|
bool firstRule = true;
|
||||||
while (sqlite3_step(_sListRules) == SQLITE_ROW) {
|
while (sqlite3_step(_sListRules) == SQLITE_ROW) {
|
||||||
responseBody.append(firstRule ? "\n\t{\n" : ",{\n");
|
responseBody.append(firstRule ? "\n\t{\n" : ",{\n");
|
||||||
Utils::snprintf(json,sizeof(json),"\t\t\"ruleId\": %lld,\n",sqlite3_column_int64(_sListRules,0));
|
Utils::snprintf(json,sizeof(json),"\t\t\"ruleNo\": %lld,\n",sqlite3_column_int64(_sListRules,0));
|
||||||
responseBody.append(json);
|
responseBody.append(json);
|
||||||
if (sqlite3_column_type(_sListRules,1) != SQLITE_NULL) {
|
if (sqlite3_column_type(_sListRules,1) != SQLITE_NULL) {
|
||||||
Utils::snprintf(json,sizeof(json),"\t\t\"nodeId\": \"%s\",\n",(const char *)sqlite3_column_text(_sListRules,1));
|
Utils::snprintf(json,sizeof(json),"\t\t\"nodeId\": \"%s\",\n",(const char *)sqlite3_column_text(_sListRules,1));
|
||||||
|
|
|
@ -99,7 +99,6 @@ private:
|
||||||
sqlite3_stmt *_sUpdateNode;
|
sqlite3_stmt *_sUpdateNode;
|
||||||
sqlite3_stmt *_sUpdateNode2;
|
sqlite3_stmt *_sUpdateNode2;
|
||||||
sqlite3_stmt *_sGetEtherTypesFromRuleTable;
|
sqlite3_stmt *_sGetEtherTypesFromRuleTable;
|
||||||
sqlite3_stmt *_sGetMulticastRates;
|
|
||||||
sqlite3_stmt *_sGetActiveBridges;
|
sqlite3_stmt *_sGetActiveBridges;
|
||||||
sqlite3_stmt *_sGetIpAssignmentsForNode;
|
sqlite3_stmt *_sGetIpAssignmentsForNode;
|
||||||
sqlite3_stmt *_sGetIpAssignmentPools;
|
sqlite3_stmt *_sGetIpAssignmentPools;
|
||||||
|
@ -122,8 +121,13 @@ private:
|
||||||
sqlite3_stmt *_sDeleteIpAssignmentPoolsForNetwork;
|
sqlite3_stmt *_sDeleteIpAssignmentPoolsForNetwork;
|
||||||
sqlite3_stmt *_sDeleteRulesForNetwork;
|
sqlite3_stmt *_sDeleteRulesForNetwork;
|
||||||
sqlite3_stmt *_sCreateIpAssignmentPool;
|
sqlite3_stmt *_sCreateIpAssignmentPool;
|
||||||
|
sqlite3_stmt *_sUpdateMemberAuthorized;
|
||||||
|
sqlite3_stmt *_sUpdateMemberActiveBridge;
|
||||||
sqlite3_stmt *_sDeleteMember;
|
sqlite3_stmt *_sDeleteMember;
|
||||||
sqlite3_stmt *_sDeleteNetworkAndRelated;
|
sqlite3_stmt *_sDeleteNetwork;
|
||||||
|
sqlite3_stmt *_sGetGateways;
|
||||||
|
sqlite3_stmt *_sDeleteGateways;
|
||||||
|
sqlite3_stmt *_sCreateGateway;
|
||||||
|
|
||||||
Mutex _lock;
|
Mutex _lock;
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,53 +3,6 @@ CREATE TABLE Config (
|
||||||
v varchar(1024) NOT NULL
|
v varchar(1024) NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE IpAssignment (
|
|
||||||
networkId char(16) NOT NULL,
|
|
||||||
nodeId char(10) NOT NULL,
|
|
||||||
ip blob(16) NOT NULL,
|
|
||||||
ipNetmaskBits integer NOT NULL DEFAULT(0),
|
|
||||||
ipVersion integer NOT NULL DEFAULT(4)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE INDEX IpAssignment_networkId_ip ON IpAssignment (networkId, ip);
|
|
||||||
|
|
||||||
CREATE INDEX IpAssignment_networkId_nodeId ON IpAssignment (networkId, nodeId);
|
|
||||||
|
|
||||||
CREATE INDEX IpAssignment_networkId ON IpAssignment (networkId);
|
|
||||||
|
|
||||||
CREATE TABLE IpAssignmentPool (
|
|
||||||
networkId char(16) NOT NULL,
|
|
||||||
ipNetwork blob(16) NOT NULL,
|
|
||||||
ipNetmaskBits integer NOT NULL,
|
|
||||||
ipVersion integer NOT NULL DEFAULT(4)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE INDEX IpAssignmentPool_networkId ON IpAssignmentPool (networkId);
|
|
||||||
|
|
||||||
CREATE TABLE Member (
|
|
||||||
networkId char(16) NOT NULL,
|
|
||||||
nodeId char(10) NOT NULL,
|
|
||||||
authorized integer NOT NULL DEFAULT(0),
|
|
||||||
activeBridge integer NOT NULL DEFAULT(0)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE INDEX Member_networkId ON Member (networkId);
|
|
||||||
|
|
||||||
CREATE INDEX Member_networkId_activeBridge ON Member(networkId, activeBridge);
|
|
||||||
|
|
||||||
CREATE UNIQUE INDEX Member_networkId_nodeId ON Member (networkId, nodeId);
|
|
||||||
|
|
||||||
CREATE TABLE MulticastRate (
|
|
||||||
networkId char(16) NOT NULL,
|
|
||||||
mgMac char(12) NOT NULL,
|
|
||||||
mgAdi integer NOT NULL DEFAULT(0),
|
|
||||||
preload integer NOT NULL,
|
|
||||||
maxBalance integer NOT NULL,
|
|
||||||
accrual integer NOT NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE INDEX MulticastRate_networkId ON MulticastRate (networkId);
|
|
||||||
|
|
||||||
CREATE TABLE Network (
|
CREATE TABLE Network (
|
||||||
id char(16) PRIMARY KEY NOT NULL,
|
id char(16) PRIMARY KEY NOT NULL,
|
||||||
name varchar(128) NOT NULL,
|
name varchar(128) NOT NULL,
|
||||||
|
@ -63,16 +16,6 @@ CREATE TABLE Network (
|
||||||
revision integer NOT NULL DEFAULT(1)
|
revision integer NOT NULL DEFAULT(1)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE Relay (
|
|
||||||
networkId char(16) NOT NULL,
|
|
||||||
nodeId char(10) NOT NULL,
|
|
||||||
phyAddress varchar(64) NOT NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE INDEX Relay_networkId ON Relay (networkId);
|
|
||||||
|
|
||||||
CREATE UNIQUE INDEX Relay_networkId_nodeId ON Relay (networkId, nodeId);
|
|
||||||
|
|
||||||
CREATE TABLE Node (
|
CREATE TABLE Node (
|
||||||
id char(10) PRIMARY KEY NOT NULL,
|
id char(10) PRIMARY KEY NOT NULL,
|
||||||
identity varchar(4096) NOT NULL,
|
identity varchar(4096) NOT NULL,
|
||||||
|
@ -81,10 +24,59 @@ CREATE TABLE Node (
|
||||||
firstSeen integer NOT NULL DEFAULT(0)
|
firstSeen integer NOT NULL DEFAULT(0)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE TABLE Gateway (
|
||||||
|
networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,
|
||||||
|
ip blob(16) NOT NULL,
|
||||||
|
ipVersion integer NOT NULL DEFAULT(4),
|
||||||
|
metric integer NOT NULL DEFAULT(0)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX Gateway_networkId_ip ON Gateway (networkId, ip);
|
||||||
|
|
||||||
|
CREATE TABLE IpAssignment (
|
||||||
|
networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,
|
||||||
|
nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE,
|
||||||
|
ip blob(16) NOT NULL,
|
||||||
|
ipNetmaskBits integer NOT NULL DEFAULT(0),
|
||||||
|
ipVersion integer NOT NULL DEFAULT(4)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX IpAssignment_networkId_ip ON IpAssignment (networkId, ip);
|
||||||
|
|
||||||
|
CREATE INDEX IpAssignment_networkId_nodeId ON IpAssignment (networkId, nodeId);
|
||||||
|
|
||||||
|
CREATE TABLE IpAssignmentPool (
|
||||||
|
networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,
|
||||||
|
ipNetwork blob(16) NOT NULL,
|
||||||
|
ipNetmaskBits integer NOT NULL,
|
||||||
|
ipVersion integer NOT NULL DEFAULT(4)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IpAssignmentPool_networkId ON IpAssignmentPool (networkId);
|
||||||
|
|
||||||
|
CREATE TABLE Member (
|
||||||
|
networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,
|
||||||
|
nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE,
|
||||||
|
authorized integer NOT NULL DEFAULT(0),
|
||||||
|
activeBridge integer NOT NULL DEFAULT(0),
|
||||||
|
PRIMARY KEY (networkId, nodeId)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX Member_networkId_activeBridge ON Member(networkId, activeBridge);
|
||||||
|
|
||||||
|
CREATE TABLE Relay (
|
||||||
|
networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,
|
||||||
|
nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE,
|
||||||
|
phyAddress varchar(64) NOT NULL,
|
||||||
|
PRIMARY KEY (networkId, nodeId)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX Relay_networkId ON Relay (networkId);
|
||||||
|
|
||||||
CREATE TABLE Rule (
|
CREATE TABLE Rule (
|
||||||
networkId char(16) NOT NULL,
|
networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,
|
||||||
ruleId integer NOT NULL,
|
ruleNo integer NOT NULL,
|
||||||
nodeId char(10),
|
nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE,
|
||||||
vlanId integer,
|
vlanId integer,
|
||||||
vlanPcp integer,
|
vlanPcp integer,
|
||||||
etherType integer,
|
etherType integer,
|
||||||
|
@ -101,4 +93,4 @@ CREATE TABLE Rule (
|
||||||
"action" varchar(4096) NOT NULL DEFAULT('accept')
|
"action" varchar(4096) NOT NULL DEFAULT('accept')
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE INDEX Rule_networkId ON Rule (networkId);
|
CREATE UNIQUE INDEX Rule_networkId_ruleNo ON Rule (networkId, ruleNo);
|
||||||
|
|
|
@ -4,53 +4,6 @@
|
||||||
" v varchar(1024) NOT NULL\n"\
|
" v varchar(1024) NOT NULL\n"\
|
||||||
");\n"\
|
");\n"\
|
||||||
"\n"\
|
"\n"\
|
||||||
"CREATE TABLE IpAssignment (\n"\
|
|
||||||
" networkId char(16) NOT NULL,\n"\
|
|
||||||
" nodeId char(10) NOT NULL,\n"\
|
|
||||||
" ip blob(16) NOT NULL,\n"\
|
|
||||||
" ipNetmaskBits integer NOT NULL DEFAULT(0),\n"\
|
|
||||||
" ipVersion integer NOT NULL DEFAULT(4)\n"\
|
|
||||||
");\n"\
|
|
||||||
"\n"\
|
|
||||||
"CREATE INDEX IpAssignment_networkId_ip ON IpAssignment (networkId, ip);\n"\
|
|
||||||
"\n"\
|
|
||||||
"CREATE INDEX IpAssignment_networkId_nodeId ON IpAssignment (networkId, nodeId);\n"\
|
|
||||||
"\n"\
|
|
||||||
"CREATE INDEX IpAssignment_networkId ON IpAssignment (networkId);\n"\
|
|
||||||
"\n"\
|
|
||||||
"CREATE TABLE IpAssignmentPool (\n"\
|
|
||||||
" networkId char(16) NOT NULL,\n"\
|
|
||||||
" ipNetwork blob(16) NOT NULL,\n"\
|
|
||||||
" ipNetmaskBits integer NOT NULL,\n"\
|
|
||||||
" ipVersion integer NOT NULL DEFAULT(4)\n"\
|
|
||||||
");\n"\
|
|
||||||
"\n"\
|
|
||||||
"CREATE INDEX IpAssignmentPool_networkId ON IpAssignmentPool (networkId);\n"\
|
|
||||||
"\n"\
|
|
||||||
"CREATE TABLE Member (\n"\
|
|
||||||
" networkId char(16) NOT NULL,\n"\
|
|
||||||
" nodeId char(10) NOT NULL,\n"\
|
|
||||||
" authorized integer NOT NULL DEFAULT(0),\n"\
|
|
||||||
" activeBridge integer NOT NULL DEFAULT(0)\n"\
|
|
||||||
");\n"\
|
|
||||||
"\n"\
|
|
||||||
"CREATE INDEX Member_networkId ON Member (networkId);\n"\
|
|
||||||
"\n"\
|
|
||||||
"CREATE INDEX Member_networkId_activeBridge ON Member(networkId, activeBridge);\n"\
|
|
||||||
"\n"\
|
|
||||||
"CREATE UNIQUE INDEX Member_networkId_nodeId ON Member (networkId, nodeId);\n"\
|
|
||||||
"\n"\
|
|
||||||
"CREATE TABLE MulticastRate (\n"\
|
|
||||||
" networkId char(16) NOT NULL,\n"\
|
|
||||||
" mgMac char(12) NOT NULL,\n"\
|
|
||||||
" mgAdi integer NOT NULL DEFAULT(0),\n"\
|
|
||||||
" preload integer NOT NULL,\n"\
|
|
||||||
" maxBalance integer NOT NULL,\n"\
|
|
||||||
" accrual integer NOT NULL\n"\
|
|
||||||
");\n"\
|
|
||||||
"\n"\
|
|
||||||
"CREATE INDEX MulticastRate_networkId ON MulticastRate (networkId);\n"\
|
|
||||||
"\n"\
|
|
||||||
"CREATE TABLE Network (\n"\
|
"CREATE TABLE Network (\n"\
|
||||||
" id char(16) PRIMARY KEY NOT NULL,\n"\
|
" id char(16) PRIMARY KEY NOT NULL,\n"\
|
||||||
" name varchar(128) NOT NULL,\n"\
|
" name varchar(128) NOT NULL,\n"\
|
||||||
|
@ -64,16 +17,6 @@
|
||||||
" revision integer NOT NULL DEFAULT(1)\n"\
|
" revision integer NOT NULL DEFAULT(1)\n"\
|
||||||
");\n"\
|
");\n"\
|
||||||
"\n"\
|
"\n"\
|
||||||
"CREATE TABLE Relay (\n"\
|
|
||||||
" networkId char(16) NOT NULL,\n"\
|
|
||||||
" nodeId char(10) NOT NULL,\n"\
|
|
||||||
" phyAddress varchar(64) NOT NULL\n"\
|
|
||||||
");\n"\
|
|
||||||
"\n"\
|
|
||||||
"CREATE INDEX Relay_networkId ON Relay (networkId);\n"\
|
|
||||||
"\n"\
|
|
||||||
"CREATE UNIQUE INDEX Relay_networkId_nodeId ON Relay (networkId, nodeId);\n"\
|
|
||||||
"\n"\
|
|
||||||
"CREATE TABLE Node (\n"\
|
"CREATE TABLE Node (\n"\
|
||||||
" id char(10) PRIMARY KEY NOT NULL,\n"\
|
" id char(10) PRIMARY KEY NOT NULL,\n"\
|
||||||
" identity varchar(4096) NOT NULL,\n"\
|
" identity varchar(4096) NOT NULL,\n"\
|
||||||
|
@ -82,10 +25,59 @@
|
||||||
" firstSeen integer NOT NULL DEFAULT(0)\n"\
|
" firstSeen integer NOT NULL DEFAULT(0)\n"\
|
||||||
");\n"\
|
");\n"\
|
||||||
"\n"\
|
"\n"\
|
||||||
|
"CREATE TABLE Gateway (\n"\
|
||||||
|
" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\
|
||||||
|
" ip blob(16) NOT NULL,\n"\
|
||||||
|
" ipVersion integer NOT NULL DEFAULT(4),\n"\
|
||||||
|
" metric integer NOT NULL DEFAULT(0)\n"\
|
||||||
|
");\n"\
|
||||||
|
"\n"\
|
||||||
|
"CREATE UNIQUE INDEX Gateway_networkId_ip ON Gateway (networkId, ip);\n"\
|
||||||
|
"\n"\
|
||||||
|
"CREATE TABLE IpAssignment (\n"\
|
||||||
|
" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\
|
||||||
|
" nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE,\n"\
|
||||||
|
" ip blob(16) NOT NULL,\n"\
|
||||||
|
" ipNetmaskBits integer NOT NULL DEFAULT(0),\n"\
|
||||||
|
" ipVersion integer NOT NULL DEFAULT(4)\n"\
|
||||||
|
");\n"\
|
||||||
|
"\n"\
|
||||||
|
"CREATE UNIQUE INDEX IpAssignment_networkId_ip ON IpAssignment (networkId, ip);\n"\
|
||||||
|
"\n"\
|
||||||
|
"CREATE INDEX IpAssignment_networkId_nodeId ON IpAssignment (networkId, nodeId);\n"\
|
||||||
|
"\n"\
|
||||||
|
"CREATE TABLE IpAssignmentPool (\n"\
|
||||||
|
" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\
|
||||||
|
" ipNetwork blob(16) NOT NULL,\n"\
|
||||||
|
" ipNetmaskBits integer NOT NULL,\n"\
|
||||||
|
" ipVersion integer NOT NULL DEFAULT(4)\n"\
|
||||||
|
");\n"\
|
||||||
|
"\n"\
|
||||||
|
"CREATE INDEX IpAssignmentPool_networkId ON IpAssignmentPool (networkId);\n"\
|
||||||
|
"\n"\
|
||||||
|
"CREATE TABLE Member (\n"\
|
||||||
|
" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\
|
||||||
|
" nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE,\n"\
|
||||||
|
" authorized integer NOT NULL DEFAULT(0),\n"\
|
||||||
|
" activeBridge integer NOT NULL DEFAULT(0),\n"\
|
||||||
|
" PRIMARY KEY (networkId, nodeId)\n"\
|
||||||
|
");\n"\
|
||||||
|
"\n"\
|
||||||
|
"CREATE INDEX Member_networkId_activeBridge ON Member(networkId, activeBridge);\n"\
|
||||||
|
"\n"\
|
||||||
|
"CREATE TABLE Relay (\n"\
|
||||||
|
" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\
|
||||||
|
" nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE,\n"\
|
||||||
|
" phyAddress varchar(64) NOT NULL,\n"\
|
||||||
|
" PRIMARY KEY (networkId, nodeId)\n"\
|
||||||
|
");\n"\
|
||||||
|
"\n"\
|
||||||
|
"CREATE INDEX Relay_networkId ON Relay (networkId);\n"\
|
||||||
|
"\n"\
|
||||||
"CREATE TABLE Rule (\n"\
|
"CREATE TABLE Rule (\n"\
|
||||||
" networkId char(16) NOT NULL,\n"\
|
" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\
|
||||||
" ruleId integer NOT NULL,\n"\
|
" ruleNo integer NOT NULL,\n"\
|
||||||
" nodeId char(10),\n"\
|
" nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE,\n"\
|
||||||
" vlanId integer,\n"\
|
" vlanId integer,\n"\
|
||||||
" vlanPcp integer,\n"\
|
" vlanPcp integer,\n"\
|
||||||
" etherType integer,\n"\
|
" etherType integer,\n"\
|
||||||
|
@ -102,5 +94,5 @@
|
||||||
" \"action\" varchar(4096) NOT NULL DEFAULT('accept')\n"\
|
" \"action\" varchar(4096) NOT NULL DEFAULT('accept')\n"\
|
||||||
");\n"\
|
");\n"\
|
||||||
"\n"\
|
"\n"\
|
||||||
"CREATE INDEX Rule_networkId ON Rule (networkId);\n"\
|
"CREATE UNIQUE INDEX Rule_networkId_ruleNo ON Rule (networkId, ruleNo);\n"\
|
||||||
""
|
""
|
||||||
|
|
|
@ -49,9 +49,12 @@ case "$system" in
|
||||||
|
|
||||||
echo "Assembling Linux installer for $machine and version $vmajor.$vminor.$revision"
|
echo "Assembling Linux installer for $machine and version $vmajor.$vminor.$revision"
|
||||||
|
|
||||||
mkdir -p 'build-installer/var/lib/zerotier-one'
|
mkdir -p 'build-installer/var/lib/zerotier-one/ui'
|
||||||
cp -fp 'ext/installfiles/linux/uninstall.sh' 'build-installer/var/lib/zerotier-one'
|
cp -fp 'ext/installfiles/linux/uninstall.sh' 'build-installer/var/lib/zerotier-one'
|
||||||
cp -fp 'zerotier-one' 'build-installer/var/lib/zerotier-one'
|
cp -fp 'zerotier-one' 'build-installer/var/lib/zerotier-one'
|
||||||
|
for f in ui/*.html ui/*.js ui/*.css ui/*.jsx ; do
|
||||||
|
cp -fp "$f" 'build-installer/var/lib/zerotier-one/ui'
|
||||||
|
done
|
||||||
mkdir -p 'build-installer/tmp'
|
mkdir -p 'build-installer/tmp'
|
||||||
cp -fp 'ext/installfiles/linux/init.d/zerotier-one' 'build-installer/tmp/init.d_zerotier-one'
|
cp -fp 'ext/installfiles/linux/init.d/zerotier-one' 'build-installer/tmp/init.d_zerotier-one'
|
||||||
cp -fp 'ext/installfiles/linux/systemd/zerotier-one.service' 'build-installer/tmp/systemd_zerotier-one.service'
|
cp -fp 'ext/installfiles/linux/systemd/zerotier-one.service' 'build-installer/tmp/systemd_zerotier-one.service'
|
||||||
|
|
|
@ -251,7 +251,7 @@ enum ZT1_Event
|
||||||
/**
|
/**
|
||||||
* A more recent version was observed on the network
|
* A more recent version was observed on the network
|
||||||
*
|
*
|
||||||
* Right now this is only triggered if a hub or supernode reports a
|
* Right now this is only triggered if a hub or rootserver reports a
|
||||||
* more recent version, and only once. It can be used to trigger a
|
* more recent version, and only once. It can be used to trigger a
|
||||||
* software update check.
|
* software update check.
|
||||||
*
|
*
|
||||||
|
@ -559,8 +559,8 @@ typedef struct
|
||||||
*/
|
*/
|
||||||
enum ZT1_PeerRole {
|
enum ZT1_PeerRole {
|
||||||
ZT1_PEER_ROLE_LEAF = 0, // ordinary node
|
ZT1_PEER_ROLE_LEAF = 0, // ordinary node
|
||||||
ZT1_PEER_ROLE_HUB = 1, // locally federated hub
|
ZT1_PEER_ROLE_RELAY = 1, // relay node
|
||||||
ZT1_PEER_ROLE_SUPERNODE = 2 // planetary supernode
|
ZT1_PEER_ROLE_ROOT = 2 // root server
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -174,8 +174,8 @@ jobject createPeerRole(JNIEnv *env, ZT1_PeerRole role)
|
||||||
case ZT1_PEER_ROLE_HUB:
|
case ZT1_PEER_ROLE_HUB:
|
||||||
fieldName = "PEER_ROLE_HUB";
|
fieldName = "PEER_ROLE_HUB";
|
||||||
break;
|
break;
|
||||||
case ZT1_PEER_ROLE_SUPERNODE:
|
case ZT1_PEER_ROLE_ROOTSERVER:
|
||||||
fieldName = "PEER_ROLE_SUPERNODE";
|
fieldName = "PEER_ROLE_ROOTSERVER";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -90,7 +90,7 @@ public enum Event {
|
||||||
/**
|
/**
|
||||||
* A more recent version was observed on the network
|
* A more recent version was observed on the network
|
||||||
*
|
*
|
||||||
* <p>Right now this is only triggered if a hub or supernode reports a
|
* <p>Right now this is only triggered if a hub or rootserver reports a
|
||||||
* more recent version, and only once. It can be used to trigger a
|
* more recent version, and only once. It can be used to trigger a
|
||||||
* software update check.</p>
|
* software update check.</p>
|
||||||
*
|
*
|
||||||
|
|
|
@ -39,7 +39,7 @@ public enum PeerRole {
|
||||||
PEER_ROLE_HUB,
|
PEER_ROLE_HUB,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* planetary supernode
|
* planetary rootserver
|
||||||
*/
|
*/
|
||||||
PEER_ROLE_SUPERNODE
|
PEER_ROLE_ROOTSERVER
|
||||||
}
|
}
|
|
@ -1,58 +0,0 @@
|
||||||
'use strict'
|
|
||||||
|
|
||||||
function convertType(v,t)
|
|
||||||
{
|
|
||||||
if (Array.isArray(t)) {
|
|
||||||
var r = v;
|
|
||||||
if (t.length !== 0) {
|
|
||||||
if (Array.isArray(v)) {
|
|
||||||
r = [];
|
|
||||||
for(var i=0;i<v.length;++i)
|
|
||||||
r.push(convertType(v[i],t[0]));
|
|
||||||
} else r = [ convertType(v,t[0]) ];
|
|
||||||
} else r = [ v ];
|
|
||||||
return r;
|
|
||||||
} else if (t === 'string') {
|
|
||||||
if (typeof v === 'string')
|
|
||||||
return v;
|
|
||||||
else if ((typeof v === 'boolean')||(typeof v === 'number'))
|
|
||||||
return v.toString();
|
|
||||||
else if (Array.isArray(v)||(typeof v === 'object'))
|
|
||||||
return JSON.stringify(v);
|
|
||||||
else return '';
|
|
||||||
} else if (t === 'integer') {
|
|
||||||
if (typeof v === 'number')
|
|
||||||
return Math.round(v);
|
|
||||||
else if (typeof v === 'string')
|
|
||||||
return parseInt(v);
|
|
||||||
else if (typeof v === 'boolean')
|
|
||||||
return ((v) ? 1 : 0);
|
|
||||||
else return 0;
|
|
||||||
} else if (t === 'number') {
|
|
||||||
if (typeof v === 'number')
|
|
||||||
return v;
|
|
||||||
else if (typeof v === 'string')
|
|
||||||
return parseFloat(v);
|
|
||||||
else if (typeof v === 'boolean')
|
|
||||||
return ((v) ? 1 : 0);
|
|
||||||
else return 0;
|
|
||||||
} else if (t === 'boolean') {
|
|
||||||
return ((v) ? true : false);
|
|
||||||
} else if (typeof t === 'object') {
|
|
||||||
if ((v !== null)&&(typeof v === 'object'))
|
|
||||||
return constrainTypes(v,t);
|
|
||||||
else return {};
|
|
||||||
} else return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
function constrainTypes(obj,typeMap)
|
|
||||||
{
|
|
||||||
var r = {};
|
|
||||||
for(var k in obj) {
|
|
||||||
var t = typeMap[k];
|
|
||||||
r[k] = convertType(v,t);
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
exports = constrainTypes;
|
|
|
@ -1,231 +0,0 @@
|
||||||
'use strict'
|
|
||||||
|
|
||||||
var request = require('request');
|
|
||||||
var constrainTypes = require('./constrain-types.js');
|
|
||||||
|
|
||||||
// Types that fields must be in submissions -- used with constrainTypes to
|
|
||||||
// ensure that submitted JSON objects are correctly typed since the JSON
|
|
||||||
// API is very sensitive to this. This only includes writable fields since
|
|
||||||
// non-writable and unknown fields are ignored.
|
|
||||||
var REQUEST_TYPE_MAPS = {
|
|
||||||
'controller/network/*/relay': {
|
|
||||||
'address': 'string',
|
|
||||||
'phyAddress': 'string'
|
|
||||||
},
|
|
||||||
'controller/network/*/rule': {
|
|
||||||
'ruleId': 'integer',
|
|
||||||
'nodeId': 'string',
|
|
||||||
'vlanId': 'integer',
|
|
||||||
'vlanPcp': 'integer',
|
|
||||||
'etherType': 'integer',
|
|
||||||
'macSource': 'string',
|
|
||||||
'macDest': 'string',
|
|
||||||
'ipSource': 'string',
|
|
||||||
'ipDest': 'string',
|
|
||||||
'ipTos': 'integer',
|
|
||||||
'ipProtocol': 'integer',
|
|
||||||
'ipSourcePort': 'integer',
|
|
||||||
'ipDestPort': 'integer',
|
|
||||||
'flags': 'integer',
|
|
||||||
'invFlags': 'integer',
|
|
||||||
'action': 'string'
|
|
||||||
},
|
|
||||||
'controller/network/*/ipAssignmentPool': {
|
|
||||||
'network': 'string',
|
|
||||||
'netmaskBits': 'integer'
|
|
||||||
},
|
|
||||||
'controller/network/*/member': {
|
|
||||||
'authorized': 'boolean',
|
|
||||||
'activeBridge': 'boolean',
|
|
||||||
'ipAssignments': [ 'string' ]
|
|
||||||
},
|
|
||||||
'controller/network/*': {
|
|
||||||
'name': 'string',
|
|
||||||
'private': 'boolean',
|
|
||||||
'enableBroadcast': 'boolean',
|
|
||||||
'allowPassiveBridging': 'boolean',
|
|
||||||
'v4AssignMode': 'string',
|
|
||||||
'v6AssignMode': 'string',
|
|
||||||
'multicastLimit': 'integer',
|
|
||||||
'relays': [ this['controller/network/*/relay'] ],
|
|
||||||
'ipAssignmentPools': [ this['controller/network/*/ipAssignmentPool'] ],
|
|
||||||
'rules': [ this['controller/network/*/rule'] ]
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// URL must end with trailing slash e.g. http://127.0.0.1:9993/
|
|
||||||
function ZT1ApiClient(url,authToken)
|
|
||||||
{
|
|
||||||
this.url = url;
|
|
||||||
this.authToken = authToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Simple JSON URI getter, for internal use.
|
|
||||||
ZT1ApiClient.prototype._jsonGet = function(getPath,callback)
|
|
||||||
{
|
|
||||||
request({
|
|
||||||
url: this.url + getPath,
|
|
||||||
method: 'GET',
|
|
||||||
headers: {
|
|
||||||
'X-ZT1-Auth': this.authToken
|
|
||||||
}
|
|
||||||
},function(error,response,body) {
|
|
||||||
if (error)
|
|
||||||
return callback(error,null);
|
|
||||||
if (response.statusCode !== 200)
|
|
||||||
return callback(new Error('server responded with error: '+response.statusCode),null);
|
|
||||||
return callback(null,(typeof body === 'string') ? JSON.parse(body) : null);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Generate new ZeroTier identity -- mostly for testing
|
|
||||||
ZT1ApiClient.prototype.newIdentity = function(callback)
|
|
||||||
{
|
|
||||||
request({
|
|
||||||
url: this.url + 'newIdentity',
|
|
||||||
method: 'GET',
|
|
||||||
json: false,
|
|
||||||
headers: {
|
|
||||||
'X-ZT1-Auth': this.authToken
|
|
||||||
}
|
|
||||||
},function(error,response,body) {
|
|
||||||
if (error)
|
|
||||||
return callback(error,null);
|
|
||||||
if (response.statusCode === 200)
|
|
||||||
return callback(null,body);
|
|
||||||
return callback(new Error('server responded with error: '+response.statusCode),'');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get node status -- returns a combination of regular status and (if present) controller info
|
|
||||||
ZT1ApiClient.prototype.status = function(callback)
|
|
||||||
{
|
|
||||||
request({
|
|
||||||
url: this.url + 'controller',
|
|
||||||
method: 'GET',
|
|
||||||
headers: {
|
|
||||||
'X-ZT1-Auth': this.authToken
|
|
||||||
}
|
|
||||||
},function(error,response,body) {
|
|
||||||
if (error)
|
|
||||||
return callback(error,null);
|
|
||||||
var controllerStatus = {};
|
|
||||||
if ((typeof body === 'string')&&(response.statusCode === 200))
|
|
||||||
controllerStatus = JSON.parse(body);
|
|
||||||
request({
|
|
||||||
url: this.url + 'status',
|
|
||||||
method: 'GET',
|
|
||||||
headers: {
|
|
||||||
'X-ZT1-Auth': this.authToken
|
|
||||||
}
|
|
||||||
},function(error,response,body) {
|
|
||||||
if (error)
|
|
||||||
return callback(error,{});
|
|
||||||
if (response.statusCode !== 200)
|
|
||||||
return callback(new Error('server responded with '+response.statusCode),{});
|
|
||||||
var nodeStatus = JSON.parse(body);
|
|
||||||
for(var k in controllerStatus)
|
|
||||||
nodeStatus[k] = controllerStatus[k];
|
|
||||||
return callback(null,nodeStatus);
|
|
||||||
}.bind(this));
|
|
||||||
}.bind(this));
|
|
||||||
};
|
|
||||||
|
|
||||||
ZT1ApiClient.prototype.getNetworks = function(callback)
|
|
||||||
{
|
|
||||||
this._jsonGet('network',callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
ZT1ApiClient.prototype.getPeers = function(callback)
|
|
||||||
{
|
|
||||||
this._jsonGet('peer',callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
ZT1ApiClient.prototype.listControllerNetworks = function(callback)
|
|
||||||
{
|
|
||||||
this._jsonGet('controller/network',callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
ZT1ApiClient.prototype.getControllerNetwork = function(nwid,callback)
|
|
||||||
{
|
|
||||||
this._jsonGet('controller/network/' + nwid,callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
// If NWID is the special ##########______ format, a new NWID will
|
|
||||||
// be generated server side and filled in in returned object.
|
|
||||||
ZT1ApiClient.prototype.saveControllerNetwork = function(network,callback)
|
|
||||||
{
|
|
||||||
request({
|
|
||||||
url: this.url + 'controller/network/' + n.nwid,
|
|
||||||
method: 'POST',
|
|
||||||
json: true,
|
|
||||||
body: constrainTypes(network,REQUEST_TYPE_MAPS['controller/network/*']),
|
|
||||||
headers: {
|
|
||||||
'X-ZT1-Auth': this.authToken
|
|
||||||
}
|
|
||||||
},function(err,response,body) {
|
|
||||||
if (err)
|
|
||||||
return callback(err,null);
|
|
||||||
if (response.statusCode !== 200)
|
|
||||||
return callback(new Error('server responded with error: '+response.statusCode),null);
|
|
||||||
return callback(null,(typeof body === 'string') ? JSON.parse(body) : body);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
ZT1ApiClient.prototype.deleteControllerNetwork = function(nwid,callback) {
|
|
||||||
request({
|
|
||||||
url: this.url + 'controller/network/'+ nwid,
|
|
||||||
method: 'DELETE',
|
|
||||||
headers: {
|
|
||||||
'X-ZT1-Auth': this.authToken
|
|
||||||
}
|
|
||||||
},function(err,response,body) {
|
|
||||||
if (err)
|
|
||||||
return callback(err);
|
|
||||||
else if (response.statusCode === 200)
|
|
||||||
return callback(null);
|
|
||||||
else return callback(new Error('server responded with error: '+response.statusCode));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
ZT1ApiClient.prototype.getControllerNetworkMember = function(nwid,address,callback) {
|
|
||||||
this._jsonGet('controller/network/' + nwid + '/member/' + address,callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
ZT1ApiClient.prototype.saveControllerNetworkMember = function(nwid,member,callback) {
|
|
||||||
var m = constrainTypes(member,REQUEST_TYPE_MAPS['controller/network/*/member']);
|
|
||||||
m.nwid = nwid;
|
|
||||||
request({
|
|
||||||
url: this.url + 'controller/network' + nwid + '/member/' + member.address,
|
|
||||||
method: 'POST',
|
|
||||||
json: true,
|
|
||||||
body: m,
|
|
||||||
headers: {
|
|
||||||
'X-ZT1-Auth': this.authToken
|
|
||||||
}
|
|
||||||
},function(err,response,body) {
|
|
||||||
if (err)
|
|
||||||
return callback(err,null);
|
|
||||||
if (response.statusCode !== 200)
|
|
||||||
return callback(new Error('server responded with error: '+response.statusCode),null);
|
|
||||||
return callback(null,(typeof body === 'string') ? JSON.parse(body) : body);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
ZT1ApiClient.prototype.deleteControllerNetworkMember = function(nwid,address,callback) {
|
|
||||||
request({
|
|
||||||
url: this.url + 'controller/network/' + nwid + '/member/' + address,
|
|
||||||
method: 'DELETE',
|
|
||||||
headers: {
|
|
||||||
'X-ZT1-Auth': this.authToken
|
|
||||||
}
|
|
||||||
},function(err,response,body) {
|
|
||||||
if (err)
|
|
||||||
return callback(err);
|
|
||||||
else if (response.statusCode === 200)
|
|
||||||
return callback(null);
|
|
||||||
else return callback(new Error('server responded with error: '+response.statusCode));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.ZT1ApiClient = ZT1ApiClient;
|
|
|
@ -1,15 +0,0 @@
|
||||||
{
|
|
||||||
"name": "zt1-api-client",
|
|
||||||
"version": "0.0.1",
|
|
||||||
"description": "ZeroTier One JSON API Client",
|
|
||||||
"main": "index.js",
|
|
||||||
"scripts": {
|
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
|
||||||
},
|
|
||||||
"author": "ZeroTier, Inc.",
|
|
||||||
"license": "BSD",
|
|
||||||
"dependencies": {
|
|
||||||
"async": "^0.9.0",
|
|
||||||
"request": "^2.55.0"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -254,7 +254,7 @@
|
||||||
/**
|
/**
|
||||||
* Delay between scans of the topology active peer DB for peers that need ping
|
* Delay between scans of the topology active peer DB for peers that need ping
|
||||||
*
|
*
|
||||||
* This is also how often pings will be retried to upstream peers (supernodes)
|
* This is also how often pings will be retried to upstream peers (relays, roots)
|
||||||
* constantly until something is heard.
|
* constantly until something is heard.
|
||||||
*/
|
*/
|
||||||
#define ZT_PING_CHECK_INVERVAL 6250
|
#define ZT_PING_CHECK_INVERVAL 6250
|
||||||
|
@ -279,9 +279,9 @@
|
||||||
*
|
*
|
||||||
* When we send something (including frames), we generally expect a response.
|
* When we send something (including frames), we generally expect a response.
|
||||||
* Switching relays if no response in a short period of time causes more
|
* Switching relays if no response in a short period of time causes more
|
||||||
* rapid failover if a supernode goes down or becomes unreachable. In the
|
* rapid failover if a root server goes down or becomes unreachable. In the
|
||||||
* mistaken case, little harm is done as it'll pick the next-fastest
|
* mistaken case, little harm is done as it'll pick the next-fastest
|
||||||
* supernode and will switch back eventually.
|
* root server and will switch back eventually.
|
||||||
*/
|
*/
|
||||||
#define ZT_PEER_RELAY_CONVERSATION_LATENCY_THRESHOLD 10000
|
#define ZT_PEER_RELAY_CONVERSATION_LATENCY_THRESHOLD 10000
|
||||||
|
|
||||||
|
|
|
@ -32,9 +32,8 @@
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
void Dictionary::fromString(const char *s,unsigned int maxlen)
|
void Dictionary::updateFromString(const char *s,unsigned int maxlen)
|
||||||
{
|
{
|
||||||
clear();
|
|
||||||
bool escapeState = false;
|
bool escapeState = false;
|
||||||
std::string keyBuf;
|
std::string keyBuf;
|
||||||
std::string *element = &keyBuf;
|
std::string *element = &keyBuf;
|
||||||
|
@ -75,6 +74,12 @@ void Dictionary::fromString(const char *s,unsigned int maxlen)
|
||||||
(*this)[keyBuf];
|
(*this)[keyBuf];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Dictionary::fromString(const char *s,unsigned int maxlen)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
updateFromString(s,maxlen);
|
||||||
|
}
|
||||||
|
|
||||||
bool Dictionary::sign(const Identity &id,uint64_t now)
|
bool Dictionary::sign(const Identity &id,uint64_t now)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -259,6 +259,9 @@ public:
|
||||||
*/
|
*/
|
||||||
void fromString(const char *s,unsigned int maxlen);
|
void fromString(const char *s,unsigned int maxlen);
|
||||||
inline void fromString(const std::string &s) { fromString(s.c_str(),(unsigned int)s.length()); }
|
inline void fromString(const std::string &s) { fromString(s.c_str(),(unsigned int)s.length()); }
|
||||||
|
void updateFromString(const char *s,unsigned int maxlen);
|
||||||
|
inline void update(const char *s,unsigned int maxlen) { updateFromString(s, maxlen); }
|
||||||
|
inline void update(const std::string &s) { updateFromString(s.c_str(),(unsigned int)s.length()); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return True if this dictionary is cryptographically signed
|
* @return True if this dictionary is cryptographically signed
|
||||||
|
|
|
@ -110,7 +110,7 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,const SharedPtr<Peer>
|
||||||
|
|
||||||
case Packet::ERROR_OBJ_NOT_FOUND:
|
case Packet::ERROR_OBJ_NOT_FOUND:
|
||||||
if (inReVerb == Packet::VERB_WHOIS) {
|
if (inReVerb == Packet::VERB_WHOIS) {
|
||||||
if (RR->topology->isSupernode(peer->address()))
|
if (RR->topology->isRoot(peer->identity()))
|
||||||
RR->sw->cancelWhoisRequest(Address(field(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH));
|
RR->sw->cancelWhoisRequest(Address(field(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH));
|
||||||
} else if (inReVerb == Packet::VERB_NETWORK_CONFIG_REQUEST) {
|
} else if (inReVerb == Packet::VERB_NETWORK_CONFIG_REQUEST) {
|
||||||
SharedPtr<Network> network(RR->node->network(at<uint64_t>(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD)));
|
SharedPtr<Network> network(RR->node->network(at<uint64_t>(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD)));
|
||||||
|
@ -128,7 +128,7 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,const SharedPtr<Peer>
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Packet::ERROR_IDENTITY_COLLISION:
|
case Packet::ERROR_IDENTITY_COLLISION:
|
||||||
if (RR->topology->isSupernode(peer->address()))
|
if (RR->topology->isRoot(peer->identity()))
|
||||||
RR->node->postEvent(ZT1_EVENT_FATAL_ERROR_IDENTITY_COLLISION);
|
RR->node->postEvent(ZT1_EVENT_FATAL_ERROR_IDENTITY_COLLISION);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -268,7 +268,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR)
|
||||||
peer->setRemoteVersion(protoVersion,vMajor,vMinor,vRevision);
|
peer->setRemoteVersion(protoVersion,vMajor,vMinor,vRevision);
|
||||||
|
|
||||||
bool trusted = false;
|
bool trusted = false;
|
||||||
if (RR->topology->isSupernode(id.address())) {
|
if (RR->topology->isRoot(id)) {
|
||||||
RR->node->postNewerVersionIfNewer(vMajor,vMinor,vRevision);
|
RR->node->postNewerVersionIfNewer(vMajor,vMinor,vRevision);
|
||||||
trusted = true;
|
trusted = true;
|
||||||
}
|
}
|
||||||
|
@ -353,7 +353,7 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &p
|
||||||
peer->setRemoteVersion(vProto,vMajor,vMinor,vRevision);
|
peer->setRemoteVersion(vProto,vMajor,vMinor,vRevision);
|
||||||
|
|
||||||
bool trusted = false;
|
bool trusted = false;
|
||||||
if (RR->topology->isSupernode(peer->address())) {
|
if (RR->topology->isRoot(peer->identity())) {
|
||||||
RR->node->postNewerVersionIfNewer(vMajor,vMinor,vRevision);
|
RR->node->postNewerVersionIfNewer(vMajor,vMinor,vRevision);
|
||||||
trusted = true;
|
trusted = true;
|
||||||
}
|
}
|
||||||
|
@ -362,10 +362,10 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &p
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Packet::VERB_WHOIS: {
|
case Packet::VERB_WHOIS: {
|
||||||
// Right now only supernodes are allowed to send OK(WHOIS) to prevent
|
/* Right now only root servers are allowed to send OK(WHOIS) to prevent
|
||||||
// poisoning attacks. Further decentralization will require some other
|
* poisoning attacks. Further decentralization will require some other
|
||||||
// kind of trust mechanism.
|
* kind of trust mechanism. */
|
||||||
if (RR->topology->isSupernode(peer->address())) {
|
if (RR->topology->isRoot(peer->identity())) {
|
||||||
const Identity id(*this,ZT_PROTO_VERB_WHOIS__OK__IDX_IDENTITY);
|
const Identity id(*this,ZT_PROTO_VERB_WHOIS__OK__IDX_IDENTITY);
|
||||||
if (id.locallyValidate())
|
if (id.locallyValidate())
|
||||||
RR->sw->doAnythingWaitingForPeer(RR->topology->addPeer(SharedPtr<Peer>(new Peer(RR->identity,id))));
|
RR->sw->doAnythingWaitingForPeer(RR->topology->addPeer(SharedPtr<Peer>(new Peer(RR->identity,id))));
|
||||||
|
@ -689,6 +689,7 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons
|
||||||
outp.append((uint16_t)netconfStr.length());
|
outp.append((uint16_t)netconfStr.length());
|
||||||
outp.append(netconfStr.data(),(unsigned int)netconfStr.length());
|
outp.append(netconfStr.data(),(unsigned int)netconfStr.length());
|
||||||
outp.compress();
|
outp.compress();
|
||||||
|
outp.armor(peer->key(),true);
|
||||||
if (outp.size() > ZT_PROTO_MAX_PACKET_LENGTH) {
|
if (outp.size() > ZT_PROTO_MAX_PACKET_LENGTH) {
|
||||||
TRACE("NETWORK_CONFIG_REQUEST failed: internal error: netconf size %u is too large",(unsigned int)netconfStr.length());
|
TRACE("NETWORK_CONFIG_REQUEST failed: internal error: netconf size %u is too large",(unsigned int)netconfStr.length());
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -265,6 +265,16 @@ struct InetAddress : public sockaddr_storage
|
||||||
*/
|
*/
|
||||||
inline unsigned int netmaskBits() const throw() { return port(); }
|
inline unsigned int netmaskBits() const throw() { return port(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for port()
|
||||||
|
*
|
||||||
|
* This just aliases port() because for gateways we use this field to
|
||||||
|
* store the gateway metric.
|
||||||
|
*
|
||||||
|
* @return Gateway metric
|
||||||
|
*/
|
||||||
|
inline unsigned int metric() const throw() { return port(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a full netmask as an InetAddress
|
* Construct a full netmask as an InetAddress
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -216,7 +216,7 @@ void Multicaster::send(
|
||||||
|
|
||||||
if ((now - gs.lastExplicitGather) >= ZT_MULTICAST_EXPLICIT_GATHER_DELAY) {
|
if ((now - gs.lastExplicitGather) >= ZT_MULTICAST_EXPLICIT_GATHER_DELAY) {
|
||||||
gs.lastExplicitGather = now;
|
gs.lastExplicitGather = now;
|
||||||
SharedPtr<Peer> sn(RR->topology->getBestSupernode());
|
SharedPtr<Peer> sn(RR->topology->getBestRoot());
|
||||||
if (sn) {
|
if (sn) {
|
||||||
TRACE(">>MC upstream GATHER up to %u for group %.16llx/%s",gatherLimit,nwid,mg.toString().c_str());
|
TRACE(">>MC upstream GATHER up to %u for group %.16llx/%s",gatherLimit,nwid,mg.toString().c_str());
|
||||||
|
|
||||||
|
@ -269,61 +269,18 @@ void Multicaster::send(
|
||||||
// Free allocated memory buffer if any
|
// Free allocated memory buffer if any
|
||||||
if (indexes != idxbuf)
|
if (indexes != idxbuf)
|
||||||
delete [] indexes;
|
delete [] indexes;
|
||||||
|
|
||||||
#ifdef ZT_SUPPORT_LEGACY_MULTICAST
|
|
||||||
// This sends a P5 multicast up to our supernode, who then
|
|
||||||
// redistributes it manually down to all <1.0.0 peers for
|
|
||||||
// legacy support. These peers don't support the new multicast
|
|
||||||
// frame type, so even if they receive it they will ignore it.
|
|
||||||
{
|
|
||||||
SharedPtr<Peer> sn(RR->topology->getBestSupernode());
|
|
||||||
if (sn) {
|
|
||||||
uint32_t rn = RR->prng->next32();
|
|
||||||
Packet outp(sn->address(),RR->identity.address(),Packet::VERB_P5_MULTICAST_FRAME);
|
|
||||||
|
|
||||||
outp.append((uint16_t)0xffff); // do not forward
|
|
||||||
outp.append((unsigned char)0,320 + 1024); // empty queue and bloom filter
|
|
||||||
|
|
||||||
outp.append((unsigned char)((com) ? ZT_PROTO_VERB_P5_MULTICAST_FRAME_FLAGS_HAS_MEMBERSHIP_CERTIFICATE : 0));
|
|
||||||
outp.append((uint64_t)nwid);
|
|
||||||
outp.append((uint16_t)0);
|
|
||||||
outp.append((unsigned char)0);
|
|
||||||
outp.append((unsigned char)0);
|
|
||||||
RR->identity.address().appendTo(outp);
|
|
||||||
outp.append((const void *)&rn,3); // random multicast ID
|
|
||||||
if (src)
|
|
||||||
src.appendTo(outp);
|
|
||||||
else MAC(RR->identity.address(),nwid).appendTo(outp);
|
|
||||||
mg.mac().appendTo(outp);
|
|
||||||
outp.append((uint32_t)mg.adi());
|
|
||||||
outp.append((uint16_t)etherType);
|
|
||||||
outp.append((uint16_t)len);
|
|
||||||
outp.append(data,len);
|
|
||||||
unsigned int signedPortionLen = outp.size() - ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX__START_OF_SIGNED_PORTION;
|
|
||||||
|
|
||||||
C25519::Signature sig(RR->identity.sign(outp.field(ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX__START_OF_SIGNED_PORTION,signedPortionLen),signedPortionLen));
|
|
||||||
|
|
||||||
outp.append((uint16_t)sig.size());
|
|
||||||
outp.append(sig.data,(unsigned int)sig.size());
|
|
||||||
|
|
||||||
if (com) com->serialize(outp);
|
|
||||||
|
|
||||||
outp.compress();
|
|
||||||
outp.armor(sn->key(),true);
|
|
||||||
sn->send(RR,outp.data(),outp.size(),now);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // ZT_SUPPORT_LEGACY_MULTICAST
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Multicaster::clean(uint64_t now)
|
void Multicaster::clean(uint64_t now)
|
||||||
{
|
{
|
||||||
Mutex::Lock _l(_groups_m);
|
Mutex::Lock _l(_groups_m);
|
||||||
for(std::map< std::pair<uint64_t,MulticastGroup>,MulticastGroupStatus >::iterator mm(_groups.begin());mm!=_groups.end();) {
|
for(std::map< std::pair<uint64_t,MulticastGroup>,MulticastGroupStatus >::iterator mm(_groups.begin());mm!=_groups.end();) {
|
||||||
for(std::list<OutboundMulticast>::iterator tx(mm->second.txQueue.begin());tx!=mm->second.txQueue.end();) {
|
for(std::vector<OutboundMulticast>::iterator tx(mm->second.txQueue.begin());tx!=mm->second.txQueue.end();) {
|
||||||
if ((tx->expired(now))||(tx->atLimit()))
|
if ((tx->expired(now))||(tx->atLimit())) {
|
||||||
mm->second.txQueue.erase(tx++);
|
// erase element (replace by last)
|
||||||
else ++tx;
|
*tx = mm->second.txQueue.back();
|
||||||
|
mm->second.txQueue.pop_back();
|
||||||
|
} else ++tx;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long count = 0;
|
unsigned long count = 0;
|
||||||
|
@ -371,14 +328,18 @@ void Multicaster::_add(uint64_t now,uint64_t nwid,const MulticastGroup &mg,Multi
|
||||||
|
|
||||||
//TRACE("..MC %s joined multicast group %.16llx/%s via %s",member.toString().c_str(),nwid,mg.toString().c_str(),((learnedFrom) ? learnedFrom.toString().c_str() : "(direct)"));
|
//TRACE("..MC %s joined multicast group %.16llx/%s via %s",member.toString().c_str(),nwid,mg.toString().c_str(),((learnedFrom) ? learnedFrom.toString().c_str() : "(direct)"));
|
||||||
|
|
||||||
for(std::list<OutboundMulticast>::iterator tx(gs.txQueue.begin());tx!=gs.txQueue.end();) {
|
for(std::vector<OutboundMulticast>::iterator tx(gs.txQueue.begin());tx!=gs.txQueue.end();) {
|
||||||
if (tx->atLimit()) {
|
if (tx->atLimit()) {
|
||||||
gs.txQueue.erase(tx++);
|
// erase element (replace by last)
|
||||||
|
*tx = gs.txQueue.back();
|
||||||
|
gs.txQueue.pop_back();
|
||||||
} else {
|
} else {
|
||||||
tx->sendIfNew(RR,member);
|
tx->sendIfNew(RR,member);
|
||||||
if (tx->atLimit())
|
if (tx->atLimit()) {
|
||||||
gs.txQueue.erase(tx++);
|
// erase element (replace by last)
|
||||||
else ++tx;
|
*tx = gs.txQueue.back();
|
||||||
|
gs.txQueue.pop_back();
|
||||||
|
} else ++tx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@ private:
|
||||||
MulticastGroupStatus() : lastExplicitGather(0) {}
|
MulticastGroupStatus() : lastExplicitGather(0) {}
|
||||||
|
|
||||||
uint64_t lastExplicitGather;
|
uint64_t lastExplicitGather;
|
||||||
std::list<OutboundMulticast> txQueue; // pending outbound multicasts
|
std::vector<OutboundMulticast> txQueue; // pending outbound multicasts
|
||||||
std::vector<MulticastGroupMember> members; // members of this group
|
std::vector<MulticastGroupMember> members; // members of this group
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -286,18 +286,28 @@ void Network::addMembershipCertificate(const CertificateOfMembership &cert,bool
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedPtr<Peer> signer(RR->topology->getPeer(cert.signedBy()));
|
if (cert.signedBy() == RR->identity.address()) {
|
||||||
|
// We are the controller: RR->identity.address() == controller() == cert.signedBy()
|
||||||
|
// So, verify that we signed th cert ourself
|
||||||
|
if (!cert.verify(RR->identity)) {
|
||||||
|
TRACE("rejected network membership certificate for %.16llx self signed by %s: signature check failed",(unsigned long long)_id,cert.signedBy().toString().c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
if (!signer) {
|
SharedPtr<Peer> signer(RR->topology->getPeer(cert.signedBy()));
|
||||||
// This would be rather odd, since this is our controller... could happen
|
|
||||||
// if we get packets before we've gotten config.
|
|
||||||
RR->sw->requestWhois(cert.signedBy());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!cert.verify(signer->identity())) {
|
if (!signer) {
|
||||||
TRACE("rejected network membership certificate for %.16llx signed by %s: signature check failed",(unsigned long long)_id,cert.signedBy().toString().c_str());
|
// This would be rather odd, since this is our controller... could happen
|
||||||
return;
|
// if we get packets before we've gotten config.
|
||||||
|
RR->sw->requestWhois(cert.signedBy());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cert.verify(signer->identity())) {
|
||||||
|
TRACE("rejected network membership certificate for %.16llx signed by %s: signature check failed",(unsigned long long)_id,cert.signedBy().toString().c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -357,20 +367,6 @@ void Network::clean()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Network::updateAndCheckMulticastBalance(const MulticastGroup &mg,unsigned int bytes)
|
|
||||||
{
|
|
||||||
const uint64_t now = RR->node->now();
|
|
||||||
Mutex::Lock _l(_lock);
|
|
||||||
if (!_config)
|
|
||||||
return false;
|
|
||||||
std::map< MulticastGroup,BandwidthAccount >::iterator bal(_multicastRateAccounts.find(mg));
|
|
||||||
if (bal == _multicastRateAccounts.end()) {
|
|
||||||
NetworkConfig::MulticastRate r(_config->multicastRate(mg));
|
|
||||||
bal = _multicastRateAccounts.insert(std::pair< MulticastGroup,BandwidthAccount >(mg,BandwidthAccount(r.preload,r.maxBalance,r.accrual,now))).first;
|
|
||||||
}
|
|
||||||
return bal->second.deduct(bytes,now);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Network::learnBridgeRoute(const MAC &mac,const Address &addr)
|
void Network::learnBridgeRoute(const MAC &mac,const Address &addr)
|
||||||
{
|
{
|
||||||
Mutex::Lock _l(_lock);
|
Mutex::Lock _l(_lock);
|
||||||
|
@ -518,13 +514,13 @@ public:
|
||||||
RR(renv),
|
RR(renv),
|
||||||
_now(renv->node->now()),
|
_now(renv->node->now()),
|
||||||
_network(nw),
|
_network(nw),
|
||||||
_supernodeAddresses(renv->topology->supernodeAddresses()),
|
_rootAddresses(renv->topology->rootAddresses()),
|
||||||
_allMulticastGroups(nw->_allMulticastGroups())
|
_allMulticastGroups(nw->_allMulticastGroups())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
inline void operator()(Topology &t,const SharedPtr<Peer> &p)
|
inline void operator()(Topology &t,const SharedPtr<Peer> &p)
|
||||||
{
|
{
|
||||||
if ( ( (p->hasActiveDirectPath(_now)) && (_network->_isAllowed(p->address())) ) || (std::find(_supernodeAddresses.begin(),_supernodeAddresses.end(),p->address()) != _supernodeAddresses.end()) ) {
|
if ( ( (p->hasActiveDirectPath(_now)) && (_network->_isAllowed(p->address())) ) || (std::find(_rootAddresses.begin(),_rootAddresses.end(),p->address()) != _rootAddresses.end()) ) {
|
||||||
Packet outp(p->address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE);
|
Packet outp(p->address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE);
|
||||||
|
|
||||||
for(std::vector<MulticastGroup>::iterator mg(_allMulticastGroups.begin());mg!=_allMulticastGroups.end();++mg) {
|
for(std::vector<MulticastGroup>::iterator mg(_allMulticastGroups.begin());mg!=_allMulticastGroups.end();++mg) {
|
||||||
|
@ -551,7 +547,7 @@ private:
|
||||||
const RuntimeEnvironment *RR;
|
const RuntimeEnvironment *RR;
|
||||||
uint64_t _now;
|
uint64_t _now;
|
||||||
Network *_network;
|
Network *_network;
|
||||||
std::vector<Address> _supernodeAddresses;
|
std::vector<Address> _rootAddresses;
|
||||||
std::vector<MulticastGroup> _allMulticastGroups;
|
std::vector<MulticastGroup> _allMulticastGroups;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,6 @@
|
||||||
#include "MulticastGroup.hpp"
|
#include "MulticastGroup.hpp"
|
||||||
#include "MAC.hpp"
|
#include "MAC.hpp"
|
||||||
#include "Dictionary.hpp"
|
#include "Dictionary.hpp"
|
||||||
#include "BandwidthAccount.hpp"
|
|
||||||
#include "Multicaster.hpp"
|
#include "Multicaster.hpp"
|
||||||
#include "NetworkConfig.hpp"
|
#include "NetworkConfig.hpp"
|
||||||
#include "CertificateOfMembership.hpp"
|
#include "CertificateOfMembership.hpp"
|
||||||
|
@ -237,15 +236,6 @@ public:
|
||||||
_externalConfig(ec);
|
_externalConfig(ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Update and check multicast rate balance for a multicast group
|
|
||||||
*
|
|
||||||
* @param mg Multicast group
|
|
||||||
* @param bytes Size of packet
|
|
||||||
* @return True if packet is within budget
|
|
||||||
*/
|
|
||||||
bool updateAndCheckMulticastBalance(const MulticastGroup &mg,unsigned int bytes);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get current network config or throw exception
|
* Get current network config or throw exception
|
||||||
*
|
*
|
||||||
|
@ -370,7 +360,6 @@ private:
|
||||||
|
|
||||||
std::vector< MulticastGroup > _myMulticastGroups; // multicast groups that we belong to including those behind us (updated periodically)
|
std::vector< MulticastGroup > _myMulticastGroups; // multicast groups that we belong to including those behind us (updated periodically)
|
||||||
std::map< MulticastGroup,uint64_t > _multicastGroupsBehindMe; // multicast groups bridged to us and when we last saw activity on each
|
std::map< MulticastGroup,uint64_t > _multicastGroupsBehindMe; // multicast groups bridged to us and when we last saw activity on each
|
||||||
std::map< MulticastGroup,BandwidthAccount > _multicastRateAccounts;
|
|
||||||
|
|
||||||
std::map<MAC,Address> _remoteBridgeRoutes; // remote addresses where given MACs are reachable
|
std::map<MAC,Address> _remoteBridgeRoutes; // remote addresses where given MACs are reachable
|
||||||
|
|
||||||
|
|
|
@ -32,10 +32,6 @@
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
// This is fast enough for things like Apple's mDNS spam, so it should serve
|
|
||||||
// as a good default for your average network.
|
|
||||||
const NetworkConfig::MulticastRate NetworkConfig::DEFAULT_MULTICAST_RATE(40000,60000,80);
|
|
||||||
|
|
||||||
SharedPtr<NetworkConfig> NetworkConfig::createTestNetworkConfig(const Address &self)
|
SharedPtr<NetworkConfig> NetworkConfig::createTestNetworkConfig(const Address &self)
|
||||||
{
|
{
|
||||||
SharedPtr<NetworkConfig> nc(new NetworkConfig());
|
SharedPtr<NetworkConfig> nc(new NetworkConfig());
|
||||||
|
@ -85,18 +81,6 @@ std::vector<unsigned int> NetworkConfig::allowedEtherTypes() const
|
||||||
return ets;
|
return ets;
|
||||||
}
|
}
|
||||||
|
|
||||||
const NetworkConfig::MulticastRate &NetworkConfig::multicastRate(const MulticastGroup &mg) const
|
|
||||||
throw()
|
|
||||||
{
|
|
||||||
std::map<MulticastGroup,MulticastRate>::const_iterator r(_multicastRates.find(mg));
|
|
||||||
if (r == _multicastRates.end()) {
|
|
||||||
r = _multicastRates.find(MulticastGroup()); // zero MG signifies network's default rate
|
|
||||||
if (r == _multicastRates.end())
|
|
||||||
return DEFAULT_MULTICAST_RATE; // neither specific nor default found in network config
|
|
||||||
}
|
|
||||||
return r->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NetworkConfig::_fromDictionary(const Dictionary &d)
|
void NetworkConfig::_fromDictionary(const Dictionary &d)
|
||||||
{
|
{
|
||||||
static const std::string zero("0");
|
static const std::string zero("0");
|
||||||
|
@ -163,6 +147,13 @@ void NetworkConfig::_fromDictionary(const Dictionary &d)
|
||||||
std::sort(_staticIps.begin(),_staticIps.end());
|
std::sort(_staticIps.begin(),_staticIps.end());
|
||||||
std::unique(_staticIps.begin(),_staticIps.end());
|
std::unique(_staticIps.begin(),_staticIps.end());
|
||||||
|
|
||||||
|
std::vector<std::string> gatewaysSplit(Utils::split(d.get(ZT_NETWORKCONFIG_DICT_KEY_GATEWAYS,"").c_str(),",","",""));
|
||||||
|
for(std::vector<std::string>::const_iterator gwstr(gatewaysSplit.begin());gwstr!=gatewaysSplit.end();++gwstr) {
|
||||||
|
InetAddress gw(*gwstr);
|
||||||
|
if ((std::find(_gateways.begin(),_gateways.end(),gw) == _gateways.end())&&((gw.ss_family == AF_INET)||(gw.ss_family == AF_INET6)))
|
||||||
|
_gateways.push_back(gw);
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<std::string> activeBridgesSplit(Utils::split(d.get(ZT_NETWORKCONFIG_DICT_KEY_ACTIVE_BRIDGES,"").c_str(),",","",""));
|
std::vector<std::string> activeBridgesSplit(Utils::split(d.get(ZT_NETWORKCONFIG_DICT_KEY_ACTIVE_BRIDGES,"").c_str(),",","",""));
|
||||||
for(std::vector<std::string>::const_iterator a(activeBridgesSplit.begin());a!=activeBridgesSplit.end();++a) {
|
for(std::vector<std::string>::const_iterator a(activeBridgesSplit.begin());a!=activeBridgesSplit.end();++a) {
|
||||||
if (a->length() == ZT_ADDRESS_LENGTH_HEX) { // ignore empty or garbage fields
|
if (a->length() == ZT_ADDRESS_LENGTH_HEX) { // ignore empty or garbage fields
|
||||||
|
@ -174,13 +165,6 @@ void NetworkConfig::_fromDictionary(const Dictionary &d)
|
||||||
std::sort(_activeBridges.begin(),_activeBridges.end());
|
std::sort(_activeBridges.begin(),_activeBridges.end());
|
||||||
std::unique(_activeBridges.begin(),_activeBridges.end());
|
std::unique(_activeBridges.begin(),_activeBridges.end());
|
||||||
|
|
||||||
Dictionary multicastRateEntries(d.get(ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_RATES,std::string()));
|
|
||||||
for(Dictionary::const_iterator i(multicastRateEntries.begin());i!=multicastRateEntries.end();++i) {
|
|
||||||
std::vector<std::string> params(Utils::split(i->second.c_str(),",","",""));
|
|
||||||
if (params.size() >= 3)
|
|
||||||
_multicastRates[MulticastGroup(i->first)] = MulticastRate(Utils::hexStrToUInt(params[0].c_str()),Utils::hexStrToUInt(params[1].c_str()),Utils::hexStrToUInt(params[2].c_str()));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::string> relaysSplit(Utils::split(d.get(ZT_NETWORKCONFIG_DICT_KEY_RELAYS,"").c_str(),",","",""));
|
std::vector<std::string> relaysSplit(Utils::split(d.get(ZT_NETWORKCONFIG_DICT_KEY_RELAYS,"").c_str(),",","",""));
|
||||||
for(std::vector<std::string>::const_iterator r(relaysSplit.begin());r!=relaysSplit.end();++r) {
|
for(std::vector<std::string>::const_iterator r(relaysSplit.begin());r!=relaysSplit.end();++r) {
|
||||||
std::size_t semi(r->find(';')); // address;ip/port,...
|
std::size_t semi(r->find(';')); // address;ip/port,...
|
||||||
|
@ -211,15 +195,9 @@ bool NetworkConfig::operator==(const NetworkConfig &nc) const
|
||||||
if (_name != nc._name) return false;
|
if (_name != nc._name) return false;
|
||||||
if (_description != nc._description) return false;
|
if (_description != nc._description) return false;
|
||||||
if (_staticIps != nc._staticIps) return false;
|
if (_staticIps != nc._staticIps) return false;
|
||||||
|
if (_gateways != nc._gateways) return false;
|
||||||
if (_activeBridges != nc._activeBridges) return false;
|
if (_activeBridges != nc._activeBridges) return false;
|
||||||
if (_multicastRates.size() == nc._multicastRates.size()) {
|
if (_relays != nc._relays) return false;
|
||||||
// uclibc++ doesn't seem to implement map<> != map<> correctly, so do
|
|
||||||
// it ourselves. Note that this depends on the maps being sorted.
|
|
||||||
for(std::map<MulticastGroup,MulticastRate>::const_iterator a(_multicastRates.begin()),b(nc._multicastRates.begin());a!=_multicastRates.end();++a,++b) {
|
|
||||||
if ((a->first != b->first)||(a->second != b->second))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else return false;
|
|
||||||
if (_com != nc._com) return false;
|
if (_com != nc._com) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,24 +49,58 @@ namespace ZeroTier {
|
||||||
|
|
||||||
// These dictionary keys are short so they don't take up much room in
|
// These dictionary keys are short so they don't take up much room in
|
||||||
// netconf response packets.
|
// netconf response packets.
|
||||||
|
|
||||||
|
// integer(hex)[,integer(hex),...]
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_ALLOWED_ETHERNET_TYPES "et"
|
#define ZT_NETWORKCONFIG_DICT_KEY_ALLOWED_ETHERNET_TYPES "et"
|
||||||
|
|
||||||
|
// network ID
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_NETWORK_ID "nwid"
|
#define ZT_NETWORKCONFIG_DICT_KEY_NETWORK_ID "nwid"
|
||||||
|
|
||||||
|
// integer(hex)
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_TIMESTAMP "ts"
|
#define ZT_NETWORKCONFIG_DICT_KEY_TIMESTAMP "ts"
|
||||||
|
|
||||||
|
// integer(hex)
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_REVISION "r"
|
#define ZT_NETWORKCONFIG_DICT_KEY_REVISION "r"
|
||||||
|
|
||||||
|
// address of member
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO "id"
|
#define ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO "id"
|
||||||
|
|
||||||
|
// integer(hex)
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT "ml"
|
#define ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT "ml"
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_RATES "mr"
|
|
||||||
|
// 0/1
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_PRIVATE "p"
|
#define ZT_NETWORKCONFIG_DICT_KEY_PRIVATE "p"
|
||||||
|
|
||||||
|
// text
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_NAME "n"
|
#define ZT_NETWORKCONFIG_DICT_KEY_NAME "n"
|
||||||
|
|
||||||
|
// text
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_DESC "d"
|
#define ZT_NETWORKCONFIG_DICT_KEY_DESC "d"
|
||||||
|
|
||||||
|
// IP/bits[,IP/bits,...]
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_IPV4_STATIC "v4s"
|
#define ZT_NETWORKCONFIG_DICT_KEY_IPV4_STATIC "v4s"
|
||||||
|
|
||||||
|
// IP/bits[,IP/bits,...]
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_IPV6_STATIC "v6s"
|
#define ZT_NETWORKCONFIG_DICT_KEY_IPV6_STATIC "v6s"
|
||||||
|
|
||||||
|
// serialized CertificateOfMembership
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATE_OF_MEMBERSHIP "com"
|
#define ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATE_OF_MEMBERSHIP "com"
|
||||||
|
|
||||||
|
// 0/1
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_ENABLE_BROADCAST "eb"
|
#define ZT_NETWORKCONFIG_DICT_KEY_ENABLE_BROADCAST "eb"
|
||||||
|
|
||||||
|
// 0/1
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_ALLOW_PASSIVE_BRIDGING "pb"
|
#define ZT_NETWORKCONFIG_DICT_KEY_ALLOW_PASSIVE_BRIDGING "pb"
|
||||||
|
|
||||||
|
// node[,node,...]
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_ACTIVE_BRIDGES "ab"
|
#define ZT_NETWORKCONFIG_DICT_KEY_ACTIVE_BRIDGES "ab"
|
||||||
|
|
||||||
|
// node;IP/port[,node;IP/port]
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_RELAYS "rl"
|
#define ZT_NETWORKCONFIG_DICT_KEY_RELAYS "rl"
|
||||||
|
|
||||||
|
// IP/metric[,IP/metric,...]
|
||||||
|
#define ZT_NETWORKCONFIG_DICT_KEY_GATEWAYS "gw"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Network configuration received from network controller nodes
|
* Network configuration received from network controller nodes
|
||||||
*
|
*
|
||||||
|
@ -77,27 +111,6 @@ class NetworkConfig
|
||||||
friend class SharedPtr<NetworkConfig>;
|
friend class SharedPtr<NetworkConfig>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
|
||||||
* Tuple of multicast rate parameters
|
|
||||||
*/
|
|
||||||
struct MulticastRate
|
|
||||||
{
|
|
||||||
MulticastRate() throw() {}
|
|
||||||
MulticastRate(uint32_t pl,uint32_t maxb,uint32_t acc) throw() : preload(pl),maxBalance(maxb),accrual(acc) {}
|
|
||||||
|
|
||||||
uint32_t preload;
|
|
||||||
uint32_t maxBalance;
|
|
||||||
uint32_t accrual;
|
|
||||||
|
|
||||||
inline bool operator==(const MulticastRate &mr) const { return ((preload == mr.preload)&&(maxBalance == mr.maxBalance)&&(accrual == mr.accrual)); }
|
|
||||||
inline bool operator!=(const MulticastRate &mr) const { return (!(*this == mr)); }
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A hard-coded default multicast rate for networks that don't specify
|
|
||||||
*/
|
|
||||||
static const MulticastRate DEFAULT_MULTICAST_RATE;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an instance of a NetworkConfig for the test network ID
|
* Create an instance of a NetworkConfig for the test network ID
|
||||||
*
|
*
|
||||||
|
@ -139,13 +152,13 @@ public:
|
||||||
inline uint64_t revision() const throw() { return _revision; }
|
inline uint64_t revision() const throw() { return _revision; }
|
||||||
inline const Address &issuedTo() const throw() { return _issuedTo; }
|
inline const Address &issuedTo() const throw() { return _issuedTo; }
|
||||||
inline unsigned int multicastLimit() const throw() { return _multicastLimit; }
|
inline unsigned int multicastLimit() const throw() { return _multicastLimit; }
|
||||||
inline const std::map<MulticastGroup,MulticastRate> &multicastRates() const throw() { return _multicastRates; }
|
|
||||||
inline bool allowPassiveBridging() const throw() { return _allowPassiveBridging; }
|
inline bool allowPassiveBridging() const throw() { return _allowPassiveBridging; }
|
||||||
inline bool isPublic() const throw() { return (!_private); }
|
inline bool isPublic() const throw() { return (!_private); }
|
||||||
inline bool isPrivate() const throw() { return _private; }
|
inline bool isPrivate() const throw() { return _private; }
|
||||||
inline const std::string &name() const throw() { return _name; }
|
inline const std::string &name() const throw() { return _name; }
|
||||||
inline const std::string &description() const throw() { return _description; }
|
inline const std::string &description() const throw() { return _description; }
|
||||||
inline const std::vector<InetAddress> &staticIps() const throw() { return _staticIps; }
|
inline const std::vector<InetAddress> &staticIps() const throw() { return _staticIps; }
|
||||||
|
inline const std::vector<InetAddress> &gateways() const throw() { return _gateways; }
|
||||||
inline const std::vector<Address> &activeBridges() const throw() { return _activeBridges; }
|
inline const std::vector<Address> &activeBridges() const throw() { return _activeBridges; }
|
||||||
inline const std::vector< std::pair<Address,InetAddress> > &relays() const throw() { return _relays; }
|
inline const std::vector< std::pair<Address,InetAddress> > &relays() const throw() { return _relays; }
|
||||||
inline const CertificateOfMembership &com() const throw() { return _com; }
|
inline const CertificateOfMembership &com() const throw() { return _com; }
|
||||||
|
@ -160,13 +173,6 @@ public:
|
||||||
return ( (_allowPassiveBridging) || (std::find(_activeBridges.begin(),_activeBridges.end(),fromPeer) != _activeBridges.end()) );
|
return ( (_allowPassiveBridging) || (std::find(_activeBridges.begin(),_activeBridges.end(),fromPeer) != _activeBridges.end()) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param mg Multicast group
|
|
||||||
* @return Multicast rate or DEFAULT_MULTICAST_RATE if not set
|
|
||||||
*/
|
|
||||||
const MulticastRate &multicastRate(const MulticastGroup &mg) const
|
|
||||||
throw();
|
|
||||||
|
|
||||||
bool operator==(const NetworkConfig &nc) const;
|
bool operator==(const NetworkConfig &nc) const;
|
||||||
inline bool operator!=(const NetworkConfig &nc) const { return (!(*this == nc)); }
|
inline bool operator!=(const NetworkConfig &nc) const { return (!(*this == nc)); }
|
||||||
|
|
||||||
|
@ -188,9 +194,9 @@ private:
|
||||||
std::string _name;
|
std::string _name;
|
||||||
std::string _description;
|
std::string _description;
|
||||||
std::vector<InetAddress> _staticIps;
|
std::vector<InetAddress> _staticIps;
|
||||||
|
std::vector<InetAddress> _gateways;
|
||||||
std::vector<Address> _activeBridges;
|
std::vector<Address> _activeBridges;
|
||||||
std::vector< std::pair<Address,InetAddress> > _relays;
|
std::vector< std::pair<Address,InetAddress> > _relays;
|
||||||
std::map<MulticastGroup,MulticastRate> _multicastRates;
|
|
||||||
CertificateOfMembership _com;
|
CertificateOfMembership _com;
|
||||||
|
|
||||||
AtomicCounter __refCount;
|
AtomicCounter __refCount;
|
||||||
|
|
|
@ -133,7 +133,7 @@ Node::Node(
|
||||||
if (!rt.size())
|
if (!rt.size())
|
||||||
rt.fromString(ZT_DEFAULTS.defaultRootTopology);
|
rt.fromString(ZT_DEFAULTS.defaultRootTopology);
|
||||||
}
|
}
|
||||||
RR->topology->setSupernodes(Dictionary(rt.get("supernodes","")));
|
RR->topology->setRootServers(Dictionary(rt.get("rootservers","")));
|
||||||
|
|
||||||
postEvent(ZT1_EVENT_UP);
|
postEvent(ZT1_EVENT_UP);
|
||||||
}
|
}
|
||||||
|
@ -141,7 +141,7 @@ Node::Node(
|
||||||
Node::~Node()
|
Node::~Node()
|
||||||
{
|
{
|
||||||
Mutex::Lock _l(_networks_m);
|
Mutex::Lock _l(_networks_m);
|
||||||
_networks.clear();
|
_networks.clear(); // ensure that networks are destroyed before shutdown
|
||||||
delete RR->sa;
|
delete RR->sa;
|
||||||
delete RR->topology;
|
delete RR->topology;
|
||||||
delete RR->antiRec;
|
delete RR->antiRec;
|
||||||
|
@ -189,7 +189,7 @@ public:
|
||||||
RR(renv),
|
RR(renv),
|
||||||
_now(now),
|
_now(now),
|
||||||
_relays(relays),
|
_relays(relays),
|
||||||
_supernodes(RR->topology->supernodeAddresses())
|
_rootAddresses(RR->topology->rootAddresses())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,7 +205,7 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((isRelay)||(std::find(_supernodes.begin(),_supernodes.end(),p->address()) != _supernodes.end())) {
|
if ((isRelay)||(std::find(_rootAddresses.begin(),_rootAddresses.end(),p->address()) != _rootAddresses.end())) {
|
||||||
p->doPingAndKeepalive(RR,_now);
|
p->doPingAndKeepalive(RR,_now);
|
||||||
if (p->lastReceive() > lastReceiveFromUpstream)
|
if (p->lastReceive() > lastReceiveFromUpstream)
|
||||||
lastReceiveFromUpstream = p->lastReceive();
|
lastReceiveFromUpstream = p->lastReceive();
|
||||||
|
@ -219,7 +219,7 @@ private:
|
||||||
const RuntimeEnvironment *RR;
|
const RuntimeEnvironment *RR;
|
||||||
uint64_t _now;
|
uint64_t _now;
|
||||||
const std::vector< std::pair<Address,InetAddress> > &_relays;
|
const std::vector< std::pair<Address,InetAddress> > &_relays;
|
||||||
std::vector<Address> _supernodes;
|
std::vector<Address> _rootAddresses;
|
||||||
};
|
};
|
||||||
|
|
||||||
ZT1_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline)
|
ZT1_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline)
|
||||||
|
@ -236,7 +236,7 @@ ZT1_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *next
|
||||||
std::vector< SharedPtr<Network> > needConfig;
|
std::vector< SharedPtr<Network> > needConfig;
|
||||||
{
|
{
|
||||||
Mutex::Lock _l(_networks_m);
|
Mutex::Lock _l(_networks_m);
|
||||||
for(std::map< uint64_t,SharedPtr<Network> >::const_iterator n(_networks.begin());n!=_networks.end();++n) {
|
for(std::vector< std::pair< uint64_t,SharedPtr<Network> > >::const_iterator n(_networks.begin());n!=_networks.end();++n) {
|
||||||
SharedPtr<NetworkConfig> nc(n->second->config2());
|
SharedPtr<NetworkConfig> nc(n->second->config2());
|
||||||
if (((now - n->second->lastConfigUpdate()) >= ZT_NETWORK_AUTOCONF_DELAY)||(!nc))
|
if (((now - n->second->lastConfigUpdate()) >= ZT_NETWORK_AUTOCONF_DELAY)||(!nc))
|
||||||
needConfig.push_back(n->second);
|
needConfig.push_back(n->second);
|
||||||
|
@ -260,7 +260,7 @@ ZT1_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *next
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ping living or supernode/relay peers
|
// Ping living or root server/relay peers
|
||||||
_PingPeersThatNeedPing pfunc(RR,now,networkRelays);
|
_PingPeersThatNeedPing pfunc(RR,now,networkRelays);
|
||||||
RR->topology->eachPeer<_PingPeersThatNeedPing &>(pfunc);
|
RR->topology->eachPeer<_PingPeersThatNeedPing &>(pfunc);
|
||||||
|
|
||||||
|
@ -310,20 +310,22 @@ ZT1_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *next
|
||||||
ZT1_ResultCode Node::join(uint64_t nwid)
|
ZT1_ResultCode Node::join(uint64_t nwid)
|
||||||
{
|
{
|
||||||
Mutex::Lock _l(_networks_m);
|
Mutex::Lock _l(_networks_m);
|
||||||
SharedPtr<Network> &nwe = _networks[nwid];
|
SharedPtr<Network> nw = _network(nwid);
|
||||||
if (!nwe)
|
if(!nw)
|
||||||
nwe = SharedPtr<Network>(new Network(RR,nwid));
|
_networks.push_back(std::pair< uint64_t,SharedPtr<Network> >(nwid,SharedPtr<Network>(new Network(RR,nwid))));
|
||||||
|
std::sort(_networks.begin(),_networks.end()); // will sort by nwid since it's the first in a pair<>
|
||||||
return ZT1_RESULT_OK;
|
return ZT1_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZT1_ResultCode Node::leave(uint64_t nwid)
|
ZT1_ResultCode Node::leave(uint64_t nwid)
|
||||||
{
|
{
|
||||||
|
std::vector< std::pair< uint64_t,SharedPtr<Network> > > newn;
|
||||||
Mutex::Lock _l(_networks_m);
|
Mutex::Lock _l(_networks_m);
|
||||||
std::map< uint64_t,SharedPtr<Network> >::iterator nw(_networks.find(nwid));
|
for(std::vector< std::pair< uint64_t,SharedPtr<Network> > >::const_iterator n(_networks.begin());n!=_networks.end();++n) {
|
||||||
if (nw != _networks.end()) {
|
if (n->first != nwid)
|
||||||
nw->second->destroy();
|
newn.push_back(*n);
|
||||||
_networks.erase(nw);
|
|
||||||
}
|
}
|
||||||
|
_networks.swap(newn);
|
||||||
return ZT1_RESULT_OK;
|
return ZT1_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -384,7 +386,7 @@ ZT1_PeerList *Node::peers() const
|
||||||
p->versionRev = -1;
|
p->versionRev = -1;
|
||||||
}
|
}
|
||||||
p->latency = pi->second->latency();
|
p->latency = pi->second->latency();
|
||||||
p->role = RR->topology->isSupernode(pi->second->address()) ? ZT1_PEER_ROLE_SUPERNODE : ZT1_PEER_ROLE_LEAF;
|
p->role = RR->topology->isRoot(pi->second->identity()) ? ZT1_PEER_ROLE_ROOT : ZT1_PEER_ROLE_LEAF;
|
||||||
|
|
||||||
std::vector<Path> paths(pi->second->paths());
|
std::vector<Path> paths(pi->second->paths());
|
||||||
Path *bestPath = pi->second->getBestPath(_now);
|
Path *bestPath = pi->second->getBestPath(_now);
|
||||||
|
@ -406,10 +408,10 @@ ZT1_PeerList *Node::peers() const
|
||||||
ZT1_VirtualNetworkConfig *Node::networkConfig(uint64_t nwid) const
|
ZT1_VirtualNetworkConfig *Node::networkConfig(uint64_t nwid) const
|
||||||
{
|
{
|
||||||
Mutex::Lock _l(_networks_m);
|
Mutex::Lock _l(_networks_m);
|
||||||
std::map< uint64_t,SharedPtr<Network> >::const_iterator nw(_networks.find(nwid));
|
SharedPtr<Network> nw = _network(nwid);
|
||||||
if (nw != _networks.end()) {
|
if(nw) {
|
||||||
ZT1_VirtualNetworkConfig *nc = (ZT1_VirtualNetworkConfig *)::malloc(sizeof(ZT1_VirtualNetworkConfig));
|
ZT1_VirtualNetworkConfig *nc = (ZT1_VirtualNetworkConfig *)::malloc(sizeof(ZT1_VirtualNetworkConfig));
|
||||||
nw->second->externalConfig(nc);
|
nw->externalConfig(nc);
|
||||||
return nc;
|
return nc;
|
||||||
}
|
}
|
||||||
return (ZT1_VirtualNetworkConfig *)0;
|
return (ZT1_VirtualNetworkConfig *)0;
|
||||||
|
@ -426,7 +428,7 @@ ZT1_VirtualNetworkList *Node::networks() const
|
||||||
nl->networks = (ZT1_VirtualNetworkConfig *)(buf + sizeof(ZT1_VirtualNetworkList));
|
nl->networks = (ZT1_VirtualNetworkConfig *)(buf + sizeof(ZT1_VirtualNetworkList));
|
||||||
|
|
||||||
nl->networkCount = 0;
|
nl->networkCount = 0;
|
||||||
for(std::map< uint64_t,SharedPtr<Network> >::const_iterator n(_networks.begin());n!=_networks.end();++n)
|
for(std::vector< std::pair< uint64_t,SharedPtr<Network> > >::const_iterator n(_networks.begin());n!=_networks.end();++n)
|
||||||
n->second->externalConfig(&(nl->networks[nl->networkCount++]));
|
n->second->externalConfig(&(nl->networks[nl->networkCount++]));
|
||||||
|
|
||||||
return nl;
|
return nl;
|
||||||
|
|
|
@ -155,19 +155,19 @@ public:
|
||||||
len);
|
len);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline SharedPtr<Network> network(uint64_t nwid)
|
inline SharedPtr<Network> network(uint64_t nwid) const
|
||||||
{
|
{
|
||||||
Mutex::Lock _l(_networks_m);
|
Mutex::Lock _l(_networks_m);
|
||||||
std::map< uint64_t,SharedPtr<Network> >::iterator nw(_networks.find(nwid));
|
return _network(nwid);
|
||||||
return ((nw == _networks.end()) ? SharedPtr<Network>() : nw->second);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::vector< SharedPtr<Network> > allNetworks() const
|
inline std::vector< SharedPtr<Network> > allNetworks() const
|
||||||
{
|
{
|
||||||
Mutex::Lock _l(_networks_m);
|
|
||||||
std::vector< SharedPtr<Network> > nw;
|
std::vector< SharedPtr<Network> > nw;
|
||||||
for(std::map< uint64_t,SharedPtr<Network> >::const_iterator n(_networks.begin());n!=_networks.end();++n)
|
Mutex::Lock _l(_networks_m);
|
||||||
nw.push_back(n->second);
|
nw.reserve(_networks.size());
|
||||||
|
for(std::vector< std::pair< uint64_t, SharedPtr<Network> > >::const_iterator i=_networks.begin();i!=_networks.end();++i)
|
||||||
|
nw.push_back(i->second);
|
||||||
return nw;
|
return nw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,6 +208,16 @@ public:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
inline SharedPtr<Network> _network(uint64_t nwid) const
|
||||||
|
{
|
||||||
|
// assumes _networks_m is locked
|
||||||
|
for(std::vector< std::pair< uint64_t, SharedPtr<Network> > >::const_iterator i=_networks.begin();i!=_networks.end();++i) {
|
||||||
|
if (i->first == nwid)
|
||||||
|
return i->second;
|
||||||
|
}
|
||||||
|
return SharedPtr<Network>();
|
||||||
|
}
|
||||||
|
|
||||||
RuntimeEnvironment _RR;
|
RuntimeEnvironment _RR;
|
||||||
RuntimeEnvironment *RR;
|
RuntimeEnvironment *RR;
|
||||||
|
|
||||||
|
@ -223,7 +233,7 @@ private:
|
||||||
//Dictionary _localConfig; // persisted as local.conf
|
//Dictionary _localConfig; // persisted as local.conf
|
||||||
//Mutex _localConfig_m;
|
//Mutex _localConfig_m;
|
||||||
|
|
||||||
std::map< uint64_t,SharedPtr<Network> > _networks;
|
std::vector< std::pair< uint64_t, SharedPtr<Network> > > _networks;
|
||||||
Mutex _networks_m;
|
Mutex _networks_m;
|
||||||
|
|
||||||
Mutex _backgroundTasksLock;
|
Mutex _backgroundTasksLock;
|
||||||
|
|
|
@ -51,6 +51,7 @@ const char *Packet::verbString(Verb v)
|
||||||
case VERB_MULTICAST_GATHER: return "MULTICAST_GATHER";
|
case VERB_MULTICAST_GATHER: return "MULTICAST_GATHER";
|
||||||
case VERB_MULTICAST_FRAME: return "MULTICAST_FRAME";
|
case VERB_MULTICAST_FRAME: return "MULTICAST_FRAME";
|
||||||
case VERB_SET_EPHEMERAL_KEY: return "SET_EPHEMERAL_KEY";
|
case VERB_SET_EPHEMERAL_KEY: return "SET_EPHEMERAL_KEY";
|
||||||
|
case VERB_CMA: return "CMA";
|
||||||
}
|
}
|
||||||
return "(unknown)";
|
return "(unknown)";
|
||||||
}
|
}
|
||||||
|
|
|
@ -513,8 +513,8 @@ public:
|
||||||
* Destination address types and formats (not all of these are used now):
|
* Destination address types and formats (not all of these are used now):
|
||||||
* 0 - None -- no destination address data present
|
* 0 - None -- no destination address data present
|
||||||
* 1 - Ethernet address -- format: <[6] Ethernet MAC>
|
* 1 - Ethernet address -- format: <[6] Ethernet MAC>
|
||||||
* 4 - 6-byte IPv4 address -- format: <[4] IP>, <[2] port>
|
* 4 - 6-byte IPv4 UDP address/port -- format: <[4] IP>, <[2] port>
|
||||||
* 6 - 18-byte IPv6 address -- format: <[16] IP>, <[2] port>
|
* 6 - 18-byte IPv6 UDP address/port -- format: <[16] IP>, <[2] port>
|
||||||
*
|
*
|
||||||
* OK payload:
|
* OK payload:
|
||||||
* <[8] timestamp (echoed from original HELLO)>
|
* <[8] timestamp (echoed from original HELLO)>
|
||||||
|
@ -626,7 +626,7 @@ public:
|
||||||
* [... additional tuples of network/address/adi ...]
|
* [... additional tuples of network/address/adi ...]
|
||||||
*
|
*
|
||||||
* LIKEs are sent to peers with whom you have a direct peer to peer
|
* LIKEs are sent to peers with whom you have a direct peer to peer
|
||||||
* connection, and always including supernodes.
|
* connection, and always including root servers.
|
||||||
*
|
*
|
||||||
* OK/ERROR are not generated.
|
* OK/ERROR are not generated.
|
||||||
*/
|
*/
|
||||||
|
@ -770,6 +770,9 @@ public:
|
||||||
VERB_MULTICAST_FRAME = 14,
|
VERB_MULTICAST_FRAME = 14,
|
||||||
|
|
||||||
/* Ephemeral (PFS) key push:
|
/* Ephemeral (PFS) key push:
|
||||||
|
* <[2] flags (unused and reserved, must be 0)>
|
||||||
|
* <[2] length of padding / extra field section>
|
||||||
|
* <[...] padding / extra field section>
|
||||||
* <[8] 64-bit PFS key set ID sender holds for recipient (0==none)>
|
* <[8] 64-bit PFS key set ID sender holds for recipient (0==none)>
|
||||||
* <[8] 64-bit PFS key set ID of this key set>
|
* <[8] 64-bit PFS key set ID of this key set>
|
||||||
* [... begin PFS key record ...]
|
* [... begin PFS key record ...]
|
||||||
|
@ -791,6 +794,12 @@ public:
|
||||||
* the first record with common symmetric cipher, public key type,
|
* the first record with common symmetric cipher, public key type,
|
||||||
* and relevant flags must be used.
|
* and relevant flags must be used.
|
||||||
*
|
*
|
||||||
|
* The padding section may be filled with an arbitrary amount of random
|
||||||
|
* or empty payload. This may be used as a countermeasure to prevent PFS
|
||||||
|
* key pushes from being recognized by packet size vs. other packets in
|
||||||
|
* the stream. This also provides potential space for additional fields
|
||||||
|
* that might be indicated in the future by flags.
|
||||||
|
*
|
||||||
* Flags (all unspecified flags must be zero):
|
* Flags (all unspecified flags must be zero):
|
||||||
* 0x01 - FIPS mode, only use record if FIPS compliant crypto in use
|
* 0x01 - FIPS mode, only use record if FIPS compliant crypto in use
|
||||||
*
|
*
|
||||||
|
@ -814,7 +823,24 @@ public:
|
||||||
* <[8] PFS key set ID of received key set>
|
* <[8] PFS key set ID of received key set>
|
||||||
* <[1] index in record list of chosen key record>
|
* <[1] index in record list of chosen key record>
|
||||||
*/
|
*/
|
||||||
VERB_SET_EPHEMERAL_KEY = 15
|
VERB_SET_EPHEMERAL_KEY = 15,
|
||||||
|
|
||||||
|
/* "Call me at" -- push of potential endpoints for direct communication:
|
||||||
|
* <[1] flags>
|
||||||
|
* <[2] number of addresses>
|
||||||
|
* <[...] address types and addresses>
|
||||||
|
*
|
||||||
|
* Address types and addresses are of the same format as the destination
|
||||||
|
* address type and address in HELLO.
|
||||||
|
*
|
||||||
|
* The receiver may, upon receiving a CMA push, attempt to establish a
|
||||||
|
* direct link to one or more of the indicated addresses. Senders should
|
||||||
|
* only send CMA pushes to peers that they have some relationship
|
||||||
|
* with such as a shared network membership or a mutual trust.
|
||||||
|
*
|
||||||
|
* OK/ERROR are not generated.
|
||||||
|
*/
|
||||||
|
VERB_CMA = 16
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -122,16 +122,16 @@ void Peer::received(
|
||||||
|
|
||||||
/* Announce multicast groups of interest to direct peers if they are
|
/* Announce multicast groups of interest to direct peers if they are
|
||||||
* considered authorized members of a given network. Also announce to
|
* considered authorized members of a given network. Also announce to
|
||||||
* supernodes and network controllers. */
|
* root servers and network controllers. */
|
||||||
if ((pathIsConfirmed)&&((now - _lastAnnouncedTo) >= ((ZT_MULTICAST_LIKE_EXPIRE / 2) - 1000))) {
|
if ((pathIsConfirmed)&&((now - _lastAnnouncedTo) >= ((ZT_MULTICAST_LIKE_EXPIRE / 2) - 1000))) {
|
||||||
_lastAnnouncedTo = now;
|
_lastAnnouncedTo = now;
|
||||||
|
|
||||||
const bool isSupernode = RR->topology->isSupernode(_id.address());
|
const bool isRoot = RR->topology->isRoot(_id);
|
||||||
|
|
||||||
Packet outp(_id.address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE);
|
Packet outp(_id.address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE);
|
||||||
const std::vector< SharedPtr<Network> > networks(RR->node->allNetworks());
|
const std::vector< SharedPtr<Network> > networks(RR->node->allNetworks());
|
||||||
for(std::vector< SharedPtr<Network> >::const_iterator n(networks.begin());n!=networks.end();++n) {
|
for(std::vector< SharedPtr<Network> >::const_iterator n(networks.begin());n!=networks.end();++n) {
|
||||||
if ( (isSupernode) || ((*n)->isAllowed(_id.address())) ) {
|
if ( (isRoot) || ((*n)->isAllowed(_id.address())) ) {
|
||||||
const std::vector<MulticastGroup> mgs((*n)->allMulticastGroups());
|
const std::vector<MulticastGroup> mgs((*n)->allMulticastGroups());
|
||||||
for(std::vector<MulticastGroup>::const_iterator mg(mgs.begin());mg!=mgs.end();++mg) {
|
for(std::vector<MulticastGroup>::const_iterator mg(mgs.begin());mg!=mgs.end();++mg) {
|
||||||
if ((outp.size() + 18) > ZT_UDP_DEFAULT_PAYLOAD_MTU) {
|
if ((outp.size() + 18) > ZT_UDP_DEFAULT_PAYLOAD_MTU) {
|
||||||
|
|
|
@ -118,7 +118,7 @@ void SelfAwareness::iam(const Address &reporter,const InetAddress &reporterPhysi
|
||||||
|
|
||||||
// For all peers for whom we forgot an address, send a packet indirectly if
|
// For all peers for whom we forgot an address, send a packet indirectly if
|
||||||
// they are still considered alive so that we will re-establish direct links.
|
// they are still considered alive so that we will re-establish direct links.
|
||||||
SharedPtr<Peer> sn(RR->topology->getBestSupernode());
|
SharedPtr<Peer> sn(RR->topology->getBestRoot());
|
||||||
if (sn) {
|
if (sn) {
|
||||||
Path *snp = sn->getBestPath(now);
|
Path *snp = sn->getBestPath(now);
|
||||||
if (snp) {
|
if (snp) {
|
||||||
|
|
|
@ -145,12 +145,6 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
|
||||||
if (fromBridged)
|
if (fromBridged)
|
||||||
network->learnBridgedMulticastGroup(mg,RR->node->now());
|
network->learnBridgedMulticastGroup(mg,RR->node->now());
|
||||||
|
|
||||||
// Check multicast/broadcast bandwidth quotas and reject if quota exceeded
|
|
||||||
if (!network->updateAndCheckMulticastBalance(mg,len)) {
|
|
||||||
TRACE("%.16llx: didn't multicast %u bytes, quota exceeded for multicast group %s",network->id(),len,mg.toString().c_str());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//TRACE("%.16llx: MULTICAST %s -> %s %s %u",network->id(),from.toString().c_str(),mg.toString().c_str(),etherTypeName(etherType),len);
|
//TRACE("%.16llx: MULTICAST %s -> %s %s %u",network->id(),from.toString().c_str(),mg.toString().c_str(),etherTypeName(etherType),len);
|
||||||
|
|
||||||
RR->mc->send(
|
RR->mc->send(
|
||||||
|
@ -320,8 +314,8 @@ bool Switch::unite(const Address &p1,const Address &p2,bool force)
|
||||||
* P2 in randomized order in terms of which gets sent first. This is done
|
* P2 in randomized order in terms of which gets sent first. This is done
|
||||||
* since in a few cases NAT-t can be sensitive to slight timing differences
|
* since in a few cases NAT-t can be sensitive to slight timing differences
|
||||||
* in terms of when the two peers initiate. Normally this is accounted for
|
* in terms of when the two peers initiate. Normally this is accounted for
|
||||||
* by the nearly-simultaneous RENDEZVOUS kickoff from the supernode, but
|
* by the nearly-simultaneous RENDEZVOUS kickoff from the relay, but
|
||||||
* given that supernodes are hosted on cloud providers this can in some
|
* given that relay are hosted on cloud providers this can in some
|
||||||
* cases have a few ms of latency between packet departures. By randomizing
|
* cases have a few ms of latency between packet departures. By randomizing
|
||||||
* the order we make each attempted NAT-t favor one or the other going
|
* the order we make each attempted NAT-t favor one or the other going
|
||||||
* first, meaning if it doesn't succeed the first time it might the second
|
* first, meaning if it doesn't succeed the first time it might the second
|
||||||
|
@ -565,8 +559,8 @@ void Switch::_handleRemotePacketFragment(const InetAddress &fromAddr,const void
|
||||||
// It wouldn't hurt anything, just redundant and unnecessary.
|
// It wouldn't hurt anything, just redundant and unnecessary.
|
||||||
SharedPtr<Peer> relayTo = RR->topology->getPeer(destination);
|
SharedPtr<Peer> relayTo = RR->topology->getPeer(destination);
|
||||||
if ((!relayTo)||(!relayTo->send(RR,fragment.data(),fragment.size(),RR->node->now()))) {
|
if ((!relayTo)||(!relayTo->send(RR,fragment.data(),fragment.size(),RR->node->now()))) {
|
||||||
// Don't know peer or no direct path -- so relay via supernode
|
// Don't know peer or no direct path -- so relay via root server
|
||||||
relayTo = RR->topology->getBestSupernode();
|
relayTo = RR->topology->getBestRoot();
|
||||||
if (relayTo)
|
if (relayTo)
|
||||||
relayTo->send(RR,fragment.data(),fragment.size(),RR->node->now());
|
relayTo->send(RR,fragment.data(),fragment.size(),RR->node->now());
|
||||||
}
|
}
|
||||||
|
@ -641,8 +635,8 @@ void Switch::_handleRemotePacketHead(const InetAddress &fromAddr,const void *dat
|
||||||
if ((relayTo)&&((relayTo->send(RR,packet->data(),packet->size(),RR->node->now())))) {
|
if ((relayTo)&&((relayTo->send(RR,packet->data(),packet->size(),RR->node->now())))) {
|
||||||
unite(source,destination,false);
|
unite(source,destination,false);
|
||||||
} else {
|
} else {
|
||||||
// Don't know peer or no direct path -- so relay via supernode
|
// Don't know peer or no direct path -- so relay via root server
|
||||||
relayTo = RR->topology->getBestSupernode(&source,1,true);
|
relayTo = RR->topology->getBestRoot(&source,1,true);
|
||||||
if (relayTo)
|
if (relayTo)
|
||||||
relayTo->send(RR,packet->data(),packet->size(),RR->node->now());
|
relayTo->send(RR,packet->data(),packet->size(),RR->node->now());
|
||||||
}
|
}
|
||||||
|
@ -712,13 +706,13 @@ void Switch::_handleBeacon(const InetAddress &fromAddr,const Buffer<ZT_PROTO_BEA
|
||||||
|
|
||||||
Address Switch::_sendWhoisRequest(const Address &addr,const Address *peersAlreadyConsulted,unsigned int numPeersAlreadyConsulted)
|
Address Switch::_sendWhoisRequest(const Address &addr,const Address *peersAlreadyConsulted,unsigned int numPeersAlreadyConsulted)
|
||||||
{
|
{
|
||||||
SharedPtr<Peer> supernode(RR->topology->getBestSupernode(peersAlreadyConsulted,numPeersAlreadyConsulted,false));
|
SharedPtr<Peer> root(RR->topology->getBestRoot(peersAlreadyConsulted,numPeersAlreadyConsulted,false));
|
||||||
if (supernode) {
|
if (root) {
|
||||||
Packet outp(supernode->address(),RR->identity.address(),Packet::VERB_WHOIS);
|
Packet outp(root->address(),RR->identity.address(),Packet::VERB_WHOIS);
|
||||||
addr.appendTo(outp);
|
addr.appendTo(outp);
|
||||||
outp.armor(supernode->key(),true);
|
outp.armor(root->key(),true);
|
||||||
if (supernode->send(RR,outp.data(),outp.size(),RR->node->now()))
|
if (root->send(RR,outp.data(),outp.size(),RR->node->now()))
|
||||||
return supernode->address();
|
return root->address();
|
||||||
}
|
}
|
||||||
return Address();
|
return Address();
|
||||||
}
|
}
|
||||||
|
@ -752,7 +746,7 @@ bool Switch::_trySend(const Packet &packet,bool encrypt,uint64_t nwid)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!relay)
|
if (!relay)
|
||||||
relay = RR->topology->getBestSupernode();
|
relay = RR->topology->getBestRoot();
|
||||||
|
|
||||||
if (!(relay)||(!(viaPath = relay->getBestPath(now))))
|
if (!(relay)||(!(viaPath = relay->getBestPath(now))))
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -36,7 +36,7 @@ namespace ZeroTier {
|
||||||
|
|
||||||
Topology::Topology(const RuntimeEnvironment *renv) :
|
Topology::Topology(const RuntimeEnvironment *renv) :
|
||||||
RR(renv),
|
RR(renv),
|
||||||
_amSupernode(false)
|
_amRoot(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,16 +44,16 @@ Topology::~Topology()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Topology::setSupernodes(const std::map< Identity,std::vector<InetAddress> > &sn)
|
void Topology::setRootServers(const std::map< Identity,std::vector<InetAddress> > &sn)
|
||||||
{
|
{
|
||||||
Mutex::Lock _l(_lock);
|
Mutex::Lock _l(_lock);
|
||||||
|
|
||||||
if (_supernodes == sn)
|
if (_roots == sn)
|
||||||
return; // no change
|
return; // no change
|
||||||
|
|
||||||
_supernodes = sn;
|
_roots = sn;
|
||||||
_supernodeAddresses.clear();
|
_rootAddresses.clear();
|
||||||
_supernodePeers.clear();
|
_rootPeers.clear();
|
||||||
const uint64_t now = RR->node->now();
|
const uint64_t now = RR->node->now();
|
||||||
|
|
||||||
for(std::map< Identity,std::vector<InetAddress> >::const_iterator i(sn.begin());i!=sn.end();++i) {
|
for(std::map< Identity,std::vector<InetAddress> >::const_iterator i(sn.begin());i!=sn.end();++i) {
|
||||||
|
@ -64,17 +64,17 @@ void Topology::setSupernodes(const std::map< Identity,std::vector<InetAddress> >
|
||||||
for(std::vector<InetAddress>::const_iterator j(i->second.begin());j!=i->second.end();++j)
|
for(std::vector<InetAddress>::const_iterator j(i->second.begin());j!=i->second.end();++j)
|
||||||
p->addPath(Path(*j,true));
|
p->addPath(Path(*j,true));
|
||||||
p->use(now);
|
p->use(now);
|
||||||
_supernodePeers.push_back(p);
|
_rootPeers.push_back(p);
|
||||||
}
|
}
|
||||||
_supernodeAddresses.push_back(i->first.address());
|
_rootAddresses.push_back(i->first.address());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::sort(_supernodeAddresses.begin(),_supernodeAddresses.end());
|
std::sort(_rootAddresses.begin(),_rootAddresses.end());
|
||||||
|
|
||||||
_amSupernode = (_supernodes.find(RR->identity) != _supernodes.end());
|
_amRoot = (_roots.find(RR->identity) != _roots.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Topology::setSupernodes(const Dictionary &sn)
|
void Topology::setRootServers(const Dictionary &sn)
|
||||||
{
|
{
|
||||||
std::map< Identity,std::vector<InetAddress> > m;
|
std::map< Identity,std::vector<InetAddress> > m;
|
||||||
for(Dictionary::const_iterator d(sn.begin());d!=sn.end();++d) {
|
for(Dictionary::const_iterator d(sn.begin());d!=sn.end();++d) {
|
||||||
|
@ -86,11 +86,11 @@ void Topology::setSupernodes(const Dictionary &sn)
|
||||||
if (udp.length() > 0)
|
if (udp.length() > 0)
|
||||||
a.push_back(InetAddress(udp));
|
a.push_back(InetAddress(udp));
|
||||||
} catch ( ... ) {
|
} catch ( ... ) {
|
||||||
TRACE("supernode list contained invalid entry for: %s",d->first.c_str());
|
TRACE("root server list contained invalid entry for: %s",d->first.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this->setSupernodes(m);
|
this->setRootServers(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedPtr<Peer> Topology::addPeer(const SharedPtr<Peer> &peer)
|
SharedPtr<Peer> Topology::addPeer(const SharedPtr<Peer> &peer)
|
||||||
|
@ -141,28 +141,28 @@ SharedPtr<Peer> Topology::getPeer(const Address &zta)
|
||||||
return SharedPtr<Peer>();
|
return SharedPtr<Peer>();
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedPtr<Peer> Topology::getBestSupernode(const Address *avoid,unsigned int avoidCount,bool strictAvoid)
|
SharedPtr<Peer> Topology::getBestRoot(const Address *avoid,unsigned int avoidCount,bool strictAvoid)
|
||||||
{
|
{
|
||||||
SharedPtr<Peer> bestSupernode;
|
SharedPtr<Peer> bestRoot;
|
||||||
const uint64_t now = RR->node->now();
|
const uint64_t now = RR->node->now();
|
||||||
Mutex::Lock _l(_lock);
|
Mutex::Lock _l(_lock);
|
||||||
|
|
||||||
if (_amSupernode) {
|
if (_amRoot) {
|
||||||
/* If I am a supernode, the "best" supernode is the one whose address
|
/* If I am a root server, the "best" root server is the one whose address
|
||||||
* is numerically greater than mine (with wrap at top of list). This
|
* is numerically greater than mine (with wrap at top of list). This
|
||||||
* causes packets searching for a route to pretty much literally
|
* causes packets searching for a route to pretty much literally
|
||||||
* circumnavigate the globe rather than bouncing between just two. */
|
* circumnavigate the globe rather than bouncing between just two. */
|
||||||
|
|
||||||
if (_supernodeAddresses.size() > 1) { // gotta be one other than me for this to work
|
if (_rootAddresses.size() > 1) { // gotta be one other than me for this to work
|
||||||
std::vector<Address>::const_iterator sna(std::find(_supernodeAddresses.begin(),_supernodeAddresses.end(),RR->identity.address()));
|
std::vector<Address>::const_iterator sna(std::find(_rootAddresses.begin(),_rootAddresses.end(),RR->identity.address()));
|
||||||
if (sna != _supernodeAddresses.end()) { // sanity check -- _amSupernode should've been false in this case
|
if (sna != _rootAddresses.end()) { // sanity check -- _amRoot should've been false in this case
|
||||||
for(;;) {
|
for(;;) {
|
||||||
if (++sna == _supernodeAddresses.end())
|
if (++sna == _rootAddresses.end())
|
||||||
sna = _supernodeAddresses.begin(); // wrap around at end
|
sna = _rootAddresses.begin(); // wrap around at end
|
||||||
if (*sna != RR->identity.address()) { // pick one other than us -- starting from me+1 in sorted set order
|
if (*sna != RR->identity.address()) { // pick one other than us -- starting from me+1 in sorted set order
|
||||||
std::map< Address,SharedPtr<Peer> >::const_iterator p(_activePeers.find(*sna));
|
std::map< Address,SharedPtr<Peer> >::const_iterator p(_activePeers.find(*sna));
|
||||||
if ((p != _activePeers.end())&&(p->second->hasActiveDirectPath(now))) {
|
if ((p != _activePeers.end())&&(p->second->hasActiveDirectPath(now))) {
|
||||||
bestSupernode = p->second;
|
bestRoot = p->second;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -170,80 +170,87 @@ SharedPtr<Peer> Topology::getBestSupernode(const Address *avoid,unsigned int avo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* If I am not a supernode, the best supernode is the active one with
|
/* If I am not a root server, the best root server is the active one with
|
||||||
* the lowest latency. */
|
* the lowest latency. */
|
||||||
|
|
||||||
unsigned int l,bestSupernodeLatency = 65536;
|
unsigned int l,bestLatency = 65536;
|
||||||
uint64_t lds,ldr;
|
uint64_t lds,ldr;
|
||||||
|
|
||||||
// First look for a best supernode by comparing latencies, but exclude
|
// First look for a best root by comparing latencies, but exclude
|
||||||
// supernodes that have not responded to direct messages in order to
|
// root servers that have not responded to direct messages in order to
|
||||||
// try to exclude any that are dead or unreachable.
|
// try to exclude any that are dead or unreachable.
|
||||||
for(std::vector< SharedPtr<Peer> >::const_iterator sn(_supernodePeers.begin());sn!=_supernodePeers.end();) {
|
for(std::vector< SharedPtr<Peer> >::const_iterator sn(_rootPeers.begin());sn!=_rootPeers.end();) {
|
||||||
// Skip explicitly avoided relays
|
// Skip explicitly avoided relays
|
||||||
for(unsigned int i=0;i<avoidCount;++i) {
|
for(unsigned int i=0;i<avoidCount;++i) {
|
||||||
if (avoid[i] == (*sn)->address())
|
if (avoid[i] == (*sn)->address())
|
||||||
goto keep_searching_for_supernodes;
|
goto keep_searching_for_roots;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip possibly comatose or unreachable relays
|
// Skip possibly comatose or unreachable relays
|
||||||
lds = (*sn)->lastDirectSend();
|
lds = (*sn)->lastDirectSend();
|
||||||
ldr = (*sn)->lastDirectReceive();
|
ldr = (*sn)->lastDirectReceive();
|
||||||
if ((lds)&&(lds > ldr)&&((lds - ldr) > ZT_PEER_RELAY_CONVERSATION_LATENCY_THRESHOLD))
|
if ((lds)&&(lds > ldr)&&((lds - ldr) > ZT_PEER_RELAY_CONVERSATION_LATENCY_THRESHOLD))
|
||||||
goto keep_searching_for_supernodes;
|
goto keep_searching_for_roots;
|
||||||
|
|
||||||
if ((*sn)->hasActiveDirectPath(now)) {
|
if ((*sn)->hasActiveDirectPath(now)) {
|
||||||
l = (*sn)->latency();
|
l = (*sn)->latency();
|
||||||
if (bestSupernode) {
|
if (bestRoot) {
|
||||||
if ((l)&&(l < bestSupernodeLatency)) {
|
if ((l)&&(l < bestLatency)) {
|
||||||
bestSupernodeLatency = l;
|
bestLatency = l;
|
||||||
bestSupernode = *sn;
|
bestRoot = *sn;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (l)
|
if (l)
|
||||||
bestSupernodeLatency = l;
|
bestLatency = l;
|
||||||
bestSupernode = *sn;
|
bestRoot = *sn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
keep_searching_for_supernodes:
|
keep_searching_for_roots:
|
||||||
++sn;
|
++sn;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bestSupernode) {
|
if (bestRoot) {
|
||||||
bestSupernode->use(now);
|
bestRoot->use(now);
|
||||||
return bestSupernode;
|
return bestRoot;
|
||||||
} else if (strictAvoid)
|
} else if (strictAvoid)
|
||||||
return SharedPtr<Peer>();
|
return SharedPtr<Peer>();
|
||||||
|
|
||||||
// If we have nothing from above, just pick one without avoidance criteria.
|
// If we have nothing from above, just pick one without avoidance criteria.
|
||||||
for(std::vector< SharedPtr<Peer> >::const_iterator sn=_supernodePeers.begin();sn!=_supernodePeers.end();++sn) {
|
for(std::vector< SharedPtr<Peer> >::const_iterator sn=_rootPeers.begin();sn!=_rootPeers.end();++sn) {
|
||||||
if ((*sn)->hasActiveDirectPath(now)) {
|
if ((*sn)->hasActiveDirectPath(now)) {
|
||||||
unsigned int l = (*sn)->latency();
|
unsigned int l = (*sn)->latency();
|
||||||
if (bestSupernode) {
|
if (bestRoot) {
|
||||||
if ((l)&&(l < bestSupernodeLatency)) {
|
if ((l)&&(l < bestLatency)) {
|
||||||
bestSupernodeLatency = l;
|
bestLatency = l;
|
||||||
bestSupernode = *sn;
|
bestRoot = *sn;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (l)
|
if (l)
|
||||||
bestSupernodeLatency = l;
|
bestLatency = l;
|
||||||
bestSupernode = *sn;
|
bestRoot = *sn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bestSupernode)
|
if (bestRoot)
|
||||||
bestSupernode->use(now);
|
bestRoot->use(now);
|
||||||
return bestSupernode;
|
return bestRoot;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Topology::isRoot(const Identity &id) const
|
||||||
|
throw()
|
||||||
|
{
|
||||||
|
Mutex::Lock _l(_lock);
|
||||||
|
return (_roots.count(id) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Topology::clean(uint64_t now)
|
void Topology::clean(uint64_t now)
|
||||||
{
|
{
|
||||||
Mutex::Lock _l(_lock);
|
Mutex::Lock _l(_lock);
|
||||||
for(std::map< Address,SharedPtr<Peer> >::iterator p(_activePeers.begin());p!=_activePeers.end();) {
|
for(std::map< Address,SharedPtr<Peer> >::iterator p(_activePeers.begin());p!=_activePeers.end();) {
|
||||||
if (((now - p->second->lastUsed()) >= ZT_PEER_IN_MEMORY_EXPIRATION)&&(std::find(_supernodeAddresses.begin(),_supernodeAddresses.end(),p->first) == _supernodeAddresses.end())) {
|
if (((now - p->second->lastUsed()) >= ZT_PEER_IN_MEMORY_EXPIRATION)&&(std::find(_rootAddresses.begin(),_rootAddresses.end(),p->first) == _rootAddresses.end())) {
|
||||||
_activePeers.erase(p++);
|
_activePeers.erase(p++);
|
||||||
} else ++p;
|
} else ++p;
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,21 +59,19 @@ public:
|
||||||
~Topology();
|
~Topology();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set up supernodes for this network
|
* @param sn Root server identities and addresses
|
||||||
*
|
|
||||||
* @param sn Supernodes for this network
|
|
||||||
*/
|
*/
|
||||||
void setSupernodes(const std::map< Identity,std::vector<InetAddress> > &sn);
|
void setRootServers(const std::map< Identity,std::vector<InetAddress> > &sn);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set up supernodes for this network
|
* Set up root servers for this network
|
||||||
*
|
*
|
||||||
* This performs no signature verification of any kind. The caller must
|
* This performs no signature verification of any kind. The caller must
|
||||||
* check the signature of the root topology dictionary first.
|
* check the signature of the root topology dictionary first.
|
||||||
*
|
*
|
||||||
* @param sn Supernodes dictionary from root-topology
|
* @param sn 'rootservers' key from root-topology Dictionary (deserialized as Dictionary)
|
||||||
*/
|
*/
|
||||||
void setSupernodes(const Dictionary &sn);
|
void setRootServers(const Dictionary &sn);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a peer to database
|
* Add a peer to database
|
||||||
|
@ -95,65 +93,52 @@ public:
|
||||||
SharedPtr<Peer> getPeer(const Address &zta);
|
SharedPtr<Peer> getPeer(const Address &zta);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Vector of peers that are supernodes
|
* @return Vector of peers that are root servers
|
||||||
*/
|
*/
|
||||||
inline std::vector< SharedPtr<Peer> > supernodePeers() const
|
inline std::vector< SharedPtr<Peer> > rootPeers() const
|
||||||
{
|
{
|
||||||
Mutex::Lock _l(_lock);
|
Mutex::Lock _l(_lock);
|
||||||
return _supernodePeers;
|
return _rootPeers;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Number of supernodes
|
* Get the current favorite root server
|
||||||
*/
|
|
||||||
inline unsigned int numSupernodes() const
|
|
||||||
{
|
|
||||||
Mutex::Lock _l(_lock);
|
|
||||||
return (unsigned int)_supernodePeers.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the current favorite supernode
|
|
||||||
*
|
*
|
||||||
* @return Supernode with lowest latency or NULL if none
|
* @return Root server with lowest latency or NULL if none
|
||||||
*/
|
*/
|
||||||
inline SharedPtr<Peer> getBestSupernode()
|
inline SharedPtr<Peer> getBestRoot()
|
||||||
{
|
{
|
||||||
return getBestSupernode((const Address *)0,0,false);
|
return getBestRoot((const Address *)0,0,false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the best supernode, avoiding supernodes listed in an array
|
* Get the best root server, avoiding root servers listed in an array
|
||||||
*
|
*
|
||||||
* This will get the best supernode (lowest latency, etc.) but will
|
* This will get the best root server (lowest latency, etc.) but will
|
||||||
* try to avoid the listed supernodes, only using them if no others
|
* try to avoid the listed root servers, only using them if no others
|
||||||
* are available.
|
* are available.
|
||||||
*
|
*
|
||||||
* @param avoid Nodes to avoid
|
* @param avoid Nodes to avoid
|
||||||
* @param avoidCount Number of nodes to avoid
|
* @param avoidCount Number of nodes to avoid
|
||||||
* @param strictAvoid If false, consider avoided supernodes anyway if no non-avoid supernodes are available
|
* @param strictAvoid If false, consider avoided root servers anyway if no non-avoid root servers are available
|
||||||
* @return Supernode or NULL if none
|
* @return Root server or NULL if none available
|
||||||
*/
|
*/
|
||||||
SharedPtr<Peer> getBestSupernode(const Address *avoid,unsigned int avoidCount,bool strictAvoid);
|
SharedPtr<Peer> getBestRoot(const Address *avoid,unsigned int avoidCount,bool strictAvoid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param zta ZeroTier address
|
* @param id Identity to check
|
||||||
* @return True if this is a designated supernode
|
* @return True if this is a designated root server
|
||||||
*/
|
*/
|
||||||
inline bool isSupernode(const Address &zta) const
|
bool isRoot(const Identity &id) const
|
||||||
throw()
|
throw();
|
||||||
{
|
|
||||||
Mutex::Lock _l(_lock);
|
|
||||||
return (std::find(_supernodeAddresses.begin(),_supernodeAddresses.end(),zta) != _supernodeAddresses.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Vector of supernode addresses
|
* @return Vector of root server addresses
|
||||||
*/
|
*/
|
||||||
inline std::vector<Address> supernodeAddresses() const
|
inline std::vector<Address> rootAddresses() const
|
||||||
{
|
{
|
||||||
Mutex::Lock _l(_lock);
|
Mutex::Lock _l(_lock);
|
||||||
return _supernodeAddresses;
|
return _rootAddresses;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -206,13 +191,13 @@ private:
|
||||||
const RuntimeEnvironment *RR;
|
const RuntimeEnvironment *RR;
|
||||||
|
|
||||||
std::map< Address,SharedPtr<Peer> > _activePeers;
|
std::map< Address,SharedPtr<Peer> > _activePeers;
|
||||||
std::map< Identity,std::vector<InetAddress> > _supernodes;
|
std::map< Identity,std::vector<InetAddress> > _roots;
|
||||||
std::vector< Address > _supernodeAddresses;
|
std::vector< Address > _rootAddresses;
|
||||||
std::vector< SharedPtr<Peer> > _supernodePeers;
|
std::vector< SharedPtr<Peer> > _rootPeers;
|
||||||
|
|
||||||
Mutex _lock;
|
Mutex _lock;
|
||||||
|
|
||||||
bool _amSupernode;
|
bool _amRoot;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ZeroTier
|
} // namespace ZeroTier
|
||||||
|
|
|
@ -123,12 +123,13 @@ private:
|
||||||
|
|
||||||
enum PhySocketType
|
enum PhySocketType
|
||||||
{
|
{
|
||||||
ZT_PHY_SOCKET_TCP_OUT_PENDING = 0x00,
|
ZT_PHY_SOCKET_CLOSED = 0x00, // socket is closed, will be removed on next poll()
|
||||||
ZT_PHY_SOCKET_TCP_OUT_CONNECTED = 0x01,
|
ZT_PHY_SOCKET_TCP_OUT_PENDING = 0x01,
|
||||||
ZT_PHY_SOCKET_TCP_IN = 0x02,
|
ZT_PHY_SOCKET_TCP_OUT_CONNECTED = 0x02,
|
||||||
ZT_PHY_SOCKET_TCP_LISTEN = 0x03,
|
ZT_PHY_SOCKET_TCP_IN = 0x03,
|
||||||
ZT_PHY_SOCKET_RAW = 0x04,
|
ZT_PHY_SOCKET_TCP_LISTEN = 0x04,
|
||||||
ZT_PHY_SOCKET_UDP = 0x05
|
ZT_PHY_SOCKET_RAW = 0x05,
|
||||||
|
ZT_PHY_SOCKET_UDP = 0x06
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PhySocketImpl
|
struct PhySocketImpl
|
||||||
|
@ -205,8 +206,10 @@ public:
|
||||||
|
|
||||||
~Phy()
|
~Phy()
|
||||||
{
|
{
|
||||||
while (!_socks.empty())
|
for(typename std::list<PhySocketImpl>::const_iterator s(_socks.begin());s!=_socks.end();++s) {
|
||||||
this->close((PhySocket *)&(_socks.front()),true);
|
if (s->type != ZT_PHY_SOCKET_CLOSED)
|
||||||
|
this->close((PhySocket *)&(*s),true);
|
||||||
|
}
|
||||||
ZT_PHY_CLOSE_SOCKET(_whackReceiveSocket);
|
ZT_PHY_CLOSE_SOCKET(_whackReceiveSocket);
|
||||||
ZT_PHY_CLOSE_SOCKET(_whackSendSocket);
|
ZT_PHY_CLOSE_SOCKET(_whackSendSocket);
|
||||||
}
|
}
|
||||||
|
@ -620,11 +623,7 @@ public:
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool atEnd = false;
|
for(typename std::list<PhySocketImpl>::iterator s(_socks.begin());s!=_socks.end();) {
|
||||||
for(typename std::list<PhySocketImpl>::iterator s(_socks.begin()),nexts;(!atEnd);s=nexts) {
|
|
||||||
nexts = s; ++nexts; // we can delete the linked list item, so traverse now
|
|
||||||
atEnd = (nexts == _socks.end()); // if we delete the last element, s!=_socks.end() will no longer terminate our loop
|
|
||||||
|
|
||||||
switch (s->type) {
|
switch (s->type) {
|
||||||
|
|
||||||
case ZT_PHY_SOCKET_TCP_OUT_PENDING:
|
case ZT_PHY_SOCKET_TCP_OUT_PENDING:
|
||||||
|
@ -724,6 +723,10 @@ public:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s->type == ZT_PHY_SOCKET_CLOSED)
|
||||||
|
_socks.erase(s++);
|
||||||
|
else ++s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -736,6 +739,8 @@ public:
|
||||||
if (!sock)
|
if (!sock)
|
||||||
return;
|
return;
|
||||||
PhySocketImpl &sws = *(reinterpret_cast<PhySocketImpl *>(sock));
|
PhySocketImpl &sws = *(reinterpret_cast<PhySocketImpl *>(sock));
|
||||||
|
if (sws.type == ZT_PHY_SOCKET_CLOSED)
|
||||||
|
return;
|
||||||
|
|
||||||
FD_CLR(sws.sock,&_readfds);
|
FD_CLR(sws.sock,&_readfds);
|
||||||
FD_CLR(sws.sock,&_writefds);
|
FD_CLR(sws.sock,&_writefds);
|
||||||
|
@ -765,21 +770,15 @@ public:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
long oldSock = (long)sws.sock;
|
// Causes entry to be deleted from list in poll(), ignored elsewhere
|
||||||
|
sws.type = ZT_PHY_SOCKET_CLOSED;
|
||||||
|
|
||||||
for(typename std::list<PhySocketImpl>::iterator s(_socks.begin());s!=_socks.end();++s) {
|
if (sws.sock >= _nfds) {
|
||||||
if (reinterpret_cast<PhySocket *>(&(*s)) == sock) {
|
|
||||||
_socks.erase(s);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (oldSock >= _nfds) {
|
|
||||||
long nfds = (long)_whackSendSocket;
|
long nfds = (long)_whackSendSocket;
|
||||||
if ((long)_whackReceiveSocket > nfds)
|
if ((long)_whackReceiveSocket > nfds)
|
||||||
nfds = (long)_whackReceiveSocket;
|
nfds = (long)_whackReceiveSocket;
|
||||||
for(typename std::list<PhySocketImpl>::iterator s(_socks.begin());s!=_socks.end();++s) {
|
for(typename std::list<PhySocketImpl>::iterator s(_socks.begin());s!=_socks.end();++s) {
|
||||||
if ((long)s->sock > nfds)
|
if ((s->type != ZT_PHY_SOCKET_CLOSED)&&((long)s->sock > nfds))
|
||||||
nfds = (long)s->sock;
|
nfds = (long)s->sock;
|
||||||
}
|
}
|
||||||
_nfds = nfds;
|
_nfds = nfds;
|
||||||
|
|
|
@ -92,9 +92,6 @@ static const WindowsEthernetTapEnv WINENV;
|
||||||
// Only create or delete devices one at a time
|
// Only create or delete devices one at a time
|
||||||
static Mutex _systemTapInitLock;
|
static Mutex _systemTapInitLock;
|
||||||
|
|
||||||
// Incrementing this causes everyone currently open to close and reopen
|
|
||||||
static volatile int _systemTapResetStatus = 0;
|
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
WindowsEthernetTap::WindowsEthernetTap(
|
WindowsEthernetTap::WindowsEthernetTap(
|
||||||
|
@ -268,12 +265,6 @@ WindowsEthernetTap::WindowsEthernetTap(
|
||||||
}
|
}
|
||||||
} else break; // no more keys or error occurred
|
} else break; // no more keys or error occurred
|
||||||
}
|
}
|
||||||
|
|
||||||
// When we create a new tap device from scratch, existing taps for
|
|
||||||
// some reason go into 'unplugged' state. This can be fixed by
|
|
||||||
// closing and re-opening them. Incrementing this causes all
|
|
||||||
// existing tap threads to do this.
|
|
||||||
++_systemTapResetStatus;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_netCfgInstanceId.length() > 0) {
|
if (_netCfgInstanceId.length() > 0) {
|
||||||
|
@ -299,7 +290,6 @@ WindowsEthernetTap::WindowsEthernetTap(
|
||||||
throw std::runtime_error("unable to find or create tap adapter");
|
throw std::runtime_error("unable to find or create tap adapter");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert device GUID junk... blech... is there an easier way to do this?
|
|
||||||
{
|
{
|
||||||
char nobraces[128];
|
char nobraces[128];
|
||||||
const char *nbtmp1 = _netCfgInstanceId.c_str();
|
const char *nbtmp1 = _netCfgInstanceId.c_str();
|
||||||
|
@ -573,191 +563,199 @@ void WindowsEthernetTap::scanMulticastGroups(std::vector<MulticastGroup> &added,
|
||||||
void WindowsEthernetTap::threadMain()
|
void WindowsEthernetTap::threadMain()
|
||||||
throw()
|
throw()
|
||||||
{
|
{
|
||||||
char tapPath[256];
|
char tapReadBuf[ZT_IF_MTU + 32];
|
||||||
OVERLAPPED tapOvlRead,tapOvlWrite;
|
char tapPath[128];
|
||||||
HANDLE wait4[3];
|
HANDLE wait4[3];
|
||||||
char *tapReadBuf = (char *)0;
|
OVERLAPPED tapOvlRead,tapOvlWrite;
|
||||||
|
|
||||||
/* No idea why I did this. I did it a long time ago and there was only a
|
|
||||||
* a snarky comment. But I'd never do crap like this without a reason, so
|
|
||||||
* I am leaving it alone with a more descriptive snarky comment. */
|
|
||||||
while (!tapReadBuf) {
|
|
||||||
tapReadBuf = (char *)::malloc(ZT_IF_MTU + 32);
|
|
||||||
if (!tapReadBuf)
|
|
||||||
Sleep(1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
Utils::snprintf(tapPath,sizeof(tapPath),"\\\\.\\Global\\%s.tap",_netCfgInstanceId.c_str());
|
Utils::snprintf(tapPath,sizeof(tapPath),"\\\\.\\Global\\%s.tap",_netCfgInstanceId.c_str());
|
||||||
int prevTapResetStatus = _systemTapResetStatus;
|
|
||||||
bool throwOneAway = true; // Restart once on startup, because Windows.
|
try {
|
||||||
bool powerCycle = true; // If true, "power cycle" the device, because Windows.
|
while (_run) {
|
||||||
while (_run) {
|
|
||||||
if (powerCycle) {
|
|
||||||
_disableTapDevice();
|
|
||||||
Sleep(500);
|
|
||||||
_enableTapDevice();
|
_enableTapDevice();
|
||||||
Sleep(500);
|
Sleep(500);
|
||||||
}
|
|
||||||
|
|
||||||
_tap = CreateFileA(tapPath,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_SYSTEM|FILE_FLAG_OVERLAPPED,NULL);
|
_tap = CreateFileA(tapPath,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_SYSTEM|FILE_FLAG_OVERLAPPED,NULL);
|
||||||
if (_tap == INVALID_HANDLE_VALUE) {
|
if (_tap == INVALID_HANDLE_VALUE) {
|
||||||
fprintf(stderr,"Error opening %s -- retrying.\r\n",tapPath);
|
_disableTapDevice();
|
||||||
powerCycle = true;
|
_enableTapDevice();
|
||||||
continue;
|
Sleep(1000);
|
||||||
}
|
continue;
|
||||||
|
|
||||||
{
|
|
||||||
uint32_t tmpi = 1;
|
|
||||||
DWORD bytesReturned = 0;
|
|
||||||
DeviceIoControl(_tap,TAP_WIN_IOCTL_SET_MEDIA_STATUS,&tmpi,sizeof(tmpi),&tmpi,sizeof(tmpi),&bytesReturned,NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
#ifdef ZT_WINDOWS_CREATE_FAKE_DEFAULT_ROUTE
|
|
||||||
/* This inserts a fake default route and a fake ARP entry, forcing
|
|
||||||
* Windows to detect this as a "real" network and apply proper
|
|
||||||
* firewall rules.
|
|
||||||
*
|
|
||||||
* This hack is completely stupid, but Windows made me do it
|
|
||||||
* by being broken and insane.
|
|
||||||
*
|
|
||||||
* Background: Windows tries to detect its network location by
|
|
||||||
* matching it to the ARP address of the default route. Networks
|
|
||||||
* without default routes are "unidentified networks" and cannot
|
|
||||||
* have their firewall classification changed by the user (easily).
|
|
||||||
*
|
|
||||||
* Yes, you read that right.
|
|
||||||
*
|
|
||||||
* The common workaround is to set *NdisDeviceType to 1, which
|
|
||||||
* totally disables all Windows firewall functionality. This is
|
|
||||||
* the answer you'll find on most forums for things like OpenVPN.
|
|
||||||
*
|
|
||||||
* Yes, you read that right.
|
|
||||||
*
|
|
||||||
* The default route workaround is also known, but for this to
|
|
||||||
* work there must be a known default IP that resolves to a known
|
|
||||||
* ARP address. This works for an OpenVPN tunnel, but not here
|
|
||||||
* because this isn't a tunnel. It's a mesh. There is no "other
|
|
||||||
* end," or any other known always on IP.
|
|
||||||
*
|
|
||||||
* So let's make a fake one and shove it in there along with its
|
|
||||||
* fake static ARP entry. Also makes it instant-on and static.
|
|
||||||
*
|
|
||||||
* We'll have to see what DHCP does with this. In the future we
|
|
||||||
* probably will not want to do this on DHCP-enabled networks, so
|
|
||||||
* when we enable DHCP we will go in and yank this wacko hacko from
|
|
||||||
* the routing table before doing so.
|
|
||||||
*
|
|
||||||
* Like Jesse Pinkman would say: "YEEEEAAH BITCH!" */
|
|
||||||
const uint32_t fakeIp = htonl(0x19fffffe); // 25.255.255.254 -- unrouted IPv4 block
|
|
||||||
for(int i=0;i<8;++i) {
|
|
||||||
MIB_IPNET_ROW2 ipnr;
|
|
||||||
memset(&ipnr,0,sizeof(ipnr));
|
|
||||||
ipnr.Address.si_family = AF_INET;
|
|
||||||
ipnr.Address.Ipv4.sin_addr.s_addr = fakeIp;
|
|
||||||
ipnr.InterfaceLuid.Value = _deviceLuid.Value;
|
|
||||||
ipnr.PhysicalAddress[0] = _mac[0] ^ 0x10; // just make something up that's consistent and not part of this net
|
|
||||||
ipnr.PhysicalAddress[1] = 0x00;
|
|
||||||
ipnr.PhysicalAddress[2] = (UCHAR)((_deviceGuid.Data1 >> 24) & 0xff);
|
|
||||||
ipnr.PhysicalAddress[3] = (UCHAR)((_deviceGuid.Data1 >> 16) & 0xff);
|
|
||||||
ipnr.PhysicalAddress[4] = (UCHAR)((_deviceGuid.Data1 >> 8) & 0xff);
|
|
||||||
ipnr.PhysicalAddress[5] = (UCHAR)(_deviceGuid.Data1 & 0xff);
|
|
||||||
ipnr.PhysicalAddressLength = 6;
|
|
||||||
ipnr.State = NlnsPermanent;
|
|
||||||
ipnr.IsRouter = 1;
|
|
||||||
ipnr.IsUnreachable = 0;
|
|
||||||
ipnr.ReachabilityTime.LastReachable = 0x0fffffff;
|
|
||||||
ipnr.ReachabilityTime.LastUnreachable = 1;
|
|
||||||
DWORD result = CreateIpNetEntry2(&ipnr);
|
|
||||||
if (result != NO_ERROR)
|
|
||||||
Sleep(500);
|
|
||||||
else break;
|
|
||||||
}
|
}
|
||||||
for(int i=0;i<8;++i) {
|
|
||||||
MIB_IPFORWARD_ROW2 nr;
|
{
|
||||||
memset(&nr,0,sizeof(nr));
|
uint32_t tmpi = 1;
|
||||||
InitializeIpForwardEntry(&nr);
|
DWORD bytesReturned = 0;
|
||||||
nr.InterfaceLuid.Value = _deviceLuid.Value;
|
DeviceIoControl(_tap,TAP_WIN_IOCTL_SET_MEDIA_STATUS,&tmpi,sizeof(tmpi),&tmpi,sizeof(tmpi),&bytesReturned,NULL);
|
||||||
nr.DestinationPrefix.Prefix.si_family = AF_INET; // rest is left as 0.0.0.0/0
|
}
|
||||||
nr.NextHop.si_family = AF_INET;
|
|
||||||
nr.NextHop.Ipv4.sin_addr.s_addr = fakeIp;
|
#ifdef ZT_WINDOWS_CREATE_FAKE_DEFAULT_ROUTE
|
||||||
nr.Metric = 9999; // do not use as real default route
|
{
|
||||||
nr.Protocol = MIB_IPPROTO_NETMGMT;
|
/* This inserts a fake default route and a fake ARP entry, forcing
|
||||||
DWORD result = CreateIpForwardEntry2(&nr);
|
* Windows to detect this as a "real" network and apply proper
|
||||||
if (result != NO_ERROR)
|
* firewall rules.
|
||||||
Sleep(500);
|
*
|
||||||
else break;
|
* This hack is completely stupid, but Windows made me do it
|
||||||
|
* by being broken and insane.
|
||||||
|
*
|
||||||
|
* Background: Windows tries to detect its network location by
|
||||||
|
* matching it to the ARP address of the default route. Networks
|
||||||
|
* without default routes are "unidentified networks" and cannot
|
||||||
|
* have their firewall classification changed by the user (easily).
|
||||||
|
*
|
||||||
|
* Yes, you read that right.
|
||||||
|
*
|
||||||
|
* The common workaround is to set *NdisDeviceType to 1, which
|
||||||
|
* totally disables all Windows firewall functionality. This is
|
||||||
|
* the answer you'll find on most forums for things like OpenVPN.
|
||||||
|
*
|
||||||
|
* Yes, you read that right.
|
||||||
|
*
|
||||||
|
* The default route workaround is also known, but for this to
|
||||||
|
* work there must be a known default IP that resolves to a known
|
||||||
|
* ARP address. This works for an OpenVPN tunnel, but not here
|
||||||
|
* because this isn't a tunnel. It's a mesh. There is no "other
|
||||||
|
* end," or any other known always on IP.
|
||||||
|
*
|
||||||
|
* So let's make a fake one and shove it in there along with its
|
||||||
|
* fake static ARP entry. Also makes it instant-on and static.
|
||||||
|
*
|
||||||
|
* We'll have to see what DHCP does with this. In the future we
|
||||||
|
* probably will not want to do this on DHCP-enabled networks, so
|
||||||
|
* when we enable DHCP we will go in and yank this wacko hacko from
|
||||||
|
* the routing table before doing so.
|
||||||
|
*
|
||||||
|
* Like Jesse Pinkman would say: "YEEEEAAH BITCH!" */
|
||||||
|
const uint32_t fakeIp = htonl(0x19fffffe); // 25.255.255.254 -- unrouted IPv4 block
|
||||||
|
for(int i=0;i<8;++i) {
|
||||||
|
MIB_IPNET_ROW2 ipnr;
|
||||||
|
memset(&ipnr,0,sizeof(ipnr));
|
||||||
|
ipnr.Address.si_family = AF_INET;
|
||||||
|
ipnr.Address.Ipv4.sin_addr.s_addr = fakeIp;
|
||||||
|
ipnr.InterfaceLuid.Value = _deviceLuid.Value;
|
||||||
|
ipnr.PhysicalAddress[0] = _mac[0] ^ 0x10; // just make something up that's consistent and not part of this net
|
||||||
|
ipnr.PhysicalAddress[1] = 0x00;
|
||||||
|
ipnr.PhysicalAddress[2] = (UCHAR)((_deviceGuid.Data1 >> 24) & 0xff);
|
||||||
|
ipnr.PhysicalAddress[3] = (UCHAR)((_deviceGuid.Data1 >> 16) & 0xff);
|
||||||
|
ipnr.PhysicalAddress[4] = (UCHAR)((_deviceGuid.Data1 >> 8) & 0xff);
|
||||||
|
ipnr.PhysicalAddress[5] = (UCHAR)(_deviceGuid.Data1 & 0xff);
|
||||||
|
ipnr.PhysicalAddressLength = 6;
|
||||||
|
ipnr.State = NlnsPermanent;
|
||||||
|
ipnr.IsRouter = 1;
|
||||||
|
ipnr.IsUnreachable = 0;
|
||||||
|
ipnr.ReachabilityTime.LastReachable = 0x0fffffff;
|
||||||
|
ipnr.ReachabilityTime.LastUnreachable = 1;
|
||||||
|
DWORD result = CreateIpNetEntry2(&ipnr);
|
||||||
|
if (result != NO_ERROR)
|
||||||
|
Sleep(500);
|
||||||
|
else break;
|
||||||
|
}
|
||||||
|
for(int i=0;i<8;++i) {
|
||||||
|
MIB_IPFORWARD_ROW2 nr;
|
||||||
|
memset(&nr,0,sizeof(nr));
|
||||||
|
InitializeIpForwardEntry(&nr);
|
||||||
|
nr.InterfaceLuid.Value = _deviceLuid.Value;
|
||||||
|
nr.DestinationPrefix.Prefix.si_family = AF_INET; // rest is left as 0.0.0.0/0
|
||||||
|
nr.NextHop.si_family = AF_INET;
|
||||||
|
nr.NextHop.Ipv4.sin_addr.s_addr = fakeIp;
|
||||||
|
nr.Metric = 9999; // do not use as real default route
|
||||||
|
nr.Protocol = MIB_IPPROTO_NETMGMT;
|
||||||
|
DWORD result = CreateIpForwardEntry2(&nr);
|
||||||
|
if (result != NO_ERROR)
|
||||||
|
Sleep(500);
|
||||||
|
else break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
memset(&tapOvlRead,0,sizeof(tapOvlRead));
|
memset(&tapOvlRead,0,sizeof(tapOvlRead));
|
||||||
tapOvlRead.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
tapOvlRead.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
||||||
memset(&tapOvlWrite,0,sizeof(tapOvlWrite));
|
memset(&tapOvlWrite,0,sizeof(tapOvlWrite));
|
||||||
tapOvlWrite.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
tapOvlWrite.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
||||||
|
|
||||||
wait4[0] = _injectSemaphore;
|
wait4[0] = _injectSemaphore;
|
||||||
wait4[1] = tapOvlRead.hEvent;
|
wait4[1] = tapOvlRead.hEvent;
|
||||||
wait4[2] = tapOvlWrite.hEvent; // only included if writeInProgress is true
|
wait4[2] = tapOvlWrite.hEvent; // only included if writeInProgress is true
|
||||||
|
|
||||||
ReadFile(_tap,tapReadBuf,sizeof(tapReadBuf),NULL,&tapOvlRead);
|
ReadFile(_tap,tapReadBuf,sizeof(tapReadBuf),NULL,&tapOvlRead);
|
||||||
bool writeInProgress = false;
|
bool writeInProgress = false;
|
||||||
while (_run) {
|
ULONGLONG timeOfLastBorkCheck = GetTickCount64();
|
||||||
if ((prevTapResetStatus != _systemTapResetStatus)||(throwOneAway)) {
|
while (_run) {
|
||||||
powerCycle = throwOneAway;
|
DWORD waitResult = WaitForMultipleObjectsEx(writeInProgress ? 3 : 2,wait4,FALSE,2500,TRUE);
|
||||||
throwOneAway = false;
|
if (!_run) break; // will also break outer while(_run)
|
||||||
prevTapResetStatus = _systemTapResetStatus;
|
|
||||||
break; // this will cause us to close and reopen the tap
|
|
||||||
}
|
|
||||||
DWORD r = WaitForMultipleObjectsEx(writeInProgress ? 3 : 2,wait4,FALSE,2500,TRUE);
|
|
||||||
if (!_run) break; // will also break outer while(_run)
|
|
||||||
|
|
||||||
if ((r == WAIT_TIMEOUT)||(r == WAIT_FAILED))
|
// Check for issues with adapter and close/reopen if any are detected. This
|
||||||
continue;
|
// check fixes a while boatload of Windows adapter 'coma' issues after
|
||||||
|
// sleep/wake and when adapters are added/removed. Basically if the tap
|
||||||
if (HasOverlappedIoCompleted(&tapOvlRead)) {
|
// device is borked, whack it.
|
||||||
DWORD bytesRead = 0;
|
{
|
||||||
if (GetOverlappedResult(_tap,&tapOvlRead,&bytesRead,FALSE)) {
|
ULONGLONG tc = GetTickCount64();
|
||||||
if ((bytesRead > 14)&&(_enabled)) {
|
if ((tc - timeOfLastBorkCheck) >= 2500) {
|
||||||
MAC to(tapReadBuf,6);
|
timeOfLastBorkCheck = tc;
|
||||||
MAC from(tapReadBuf + 6,6);
|
MIB_IF_TABLE2 *ift = NULL;
|
||||||
unsigned int etherType = ((((unsigned int)tapReadBuf[12]) & 0xff) << 8) | (((unsigned int)tapReadBuf[13]) & 0xff);
|
if ((GetIfTable2(&ift) == NO_ERROR)&&(ift)) {
|
||||||
try {
|
bool isBorked = false;
|
||||||
// TODO: decode vlans
|
for(ULONG r=0;r<ift->NumEntries;++r) {
|
||||||
_handler(_arg,_nwid,from,to,etherType,0,tapReadBuf + 14,bytesRead - 14);
|
if (ift->Table[r].InterfaceLuid.Value == _deviceLuid.Value) {
|
||||||
} catch ( ... ) {} // handlers should not throw
|
if ((ift->Table[r].InterfaceAndOperStatusFlags.NotMediaConnected)||(ift->Table[r].MediaConnectState == MediaConnectStateDisconnected))
|
||||||
|
isBorked = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FreeMibTable(ift);
|
||||||
|
if (isBorked) {
|
||||||
|
// Close and reopen tap device if there's an issue (outer loop)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ReadFile(_tap,tapReadBuf,ZT_IF_MTU + 32,NULL,&tapOvlRead);
|
|
||||||
|
if ((waitResult == WAIT_TIMEOUT)||(waitResult == WAIT_FAILED))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (HasOverlappedIoCompleted(&tapOvlRead)) {
|
||||||
|
DWORD bytesRead = 0;
|
||||||
|
if (GetOverlappedResult(_tap,&tapOvlRead,&bytesRead,FALSE)) {
|
||||||
|
if ((bytesRead > 14)&&(_enabled)) {
|
||||||
|
MAC to(tapReadBuf,6);
|
||||||
|
MAC from(tapReadBuf + 6,6);
|
||||||
|
unsigned int etherType = ((((unsigned int)tapReadBuf[12]) & 0xff) << 8) | (((unsigned int)tapReadBuf[13]) & 0xff);
|
||||||
|
try {
|
||||||
|
// TODO: decode vlans
|
||||||
|
_handler(_arg,_nwid,from,to,etherType,0,tapReadBuf + 14,bytesRead - 14);
|
||||||
|
} catch ( ... ) {} // handlers should not throw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ReadFile(_tap,tapReadBuf,ZT_IF_MTU + 32,NULL,&tapOvlRead);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (writeInProgress) {
|
||||||
|
if (HasOverlappedIoCompleted(&tapOvlWrite)) {
|
||||||
|
writeInProgress = false;
|
||||||
|
_injectPending_m.lock();
|
||||||
|
_injectPending.pop();
|
||||||
|
} else continue; // still writing, so skip code below and wait
|
||||||
|
} else _injectPending_m.lock();
|
||||||
|
|
||||||
|
if (!_injectPending.empty()) {
|
||||||
|
WriteFile(_tap,_injectPending.front().first.data,_injectPending.front().second,NULL,&tapOvlWrite);
|
||||||
|
writeInProgress = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_injectPending_m.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (writeInProgress) {
|
CancelIo(_tap);
|
||||||
if (HasOverlappedIoCompleted(&tapOvlWrite)) {
|
|
||||||
writeInProgress = false;
|
|
||||||
_injectPending_m.lock();
|
|
||||||
_injectPending.pop();
|
|
||||||
} else continue; // still writing, so skip code below and wait
|
|
||||||
} else _injectPending_m.lock();
|
|
||||||
|
|
||||||
if (!_injectPending.empty()) {
|
CloseHandle(tapOvlRead.hEvent);
|
||||||
WriteFile(_tap,_injectPending.front().first.data,_injectPending.front().second,NULL,&tapOvlWrite);
|
CloseHandle(tapOvlWrite.hEvent);
|
||||||
writeInProgress = true;
|
CloseHandle(_tap);
|
||||||
}
|
_tap = INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
_injectPending_m.unlock();
|
// We will restart and re-open the tap unless _run == false
|
||||||
}
|
}
|
||||||
|
} catch ( ... ) {} // catch unexpected exceptions -- this should not happen but would prevent program crash or other weird issues since threads should not throw
|
||||||
CancelIo(_tap);
|
|
||||||
|
|
||||||
CloseHandle(tapOvlRead.hEvent);
|
|
||||||
CloseHandle(tapOvlWrite.hEvent);
|
|
||||||
CloseHandle(_tap);
|
|
||||||
_tap = INVALID_HANDLE_VALUE;
|
|
||||||
|
|
||||||
// We will restart and re-open the tap unless _run == false
|
|
||||||
}
|
|
||||||
|
|
||||||
::free(tapReadBuf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowsEthernetTap::destroyAllPersistentTapDevices(const char *pathToHelpers)
|
void WindowsEthernetTap::destroyAllPersistentTapDevices(const char *pathToHelpers)
|
||||||
|
|
|
@ -98,8 +98,8 @@ private:
|
||||||
|
|
||||||
GUID _deviceGuid;
|
GUID _deviceGuid;
|
||||||
NET_LUID _deviceLuid;
|
NET_LUID _deviceLuid;
|
||||||
std::string _netCfgInstanceId; // NetCfgInstanceId, a GUID
|
std::string _netCfgInstanceId;
|
||||||
std::string _deviceInstanceId; // DeviceInstanceID, another kind of "instance ID"
|
std::string _deviceInstanceId;
|
||||||
|
|
||||||
std::vector<MulticastGroup> _multicastGroups;
|
std::vector<MulticastGroup> _multicastGroups;
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,9 @@ This folder contains the source files to compile the signed network root topolog
|
||||||
|
|
||||||
Keys in the root topology dictionary are:
|
Keys in the root topology dictionary are:
|
||||||
|
|
||||||
* **supernodes**: contains another Dictionary mapping supernode address to supernode definition
|
* **rootservers**: contains another Dictionary mapping rootserver address to rootserver definition
|
||||||
* **##########**: supernode address, contains supernode definition
|
* **##########**: rootserver address, contains rootserver definition
|
||||||
* **id**: supernode identity (public) in string-serialized format
|
* **id**: rootserver identity (public) in string-serialized format
|
||||||
* **udp**: comma-delimited list of ip/port UDP addresses of node
|
* **udp**: comma-delimited list of ip/port UDP addresses of node
|
||||||
* **tcp**: *DEPRECATED* comma-delimited list of ip/port TCP addresses of node
|
* **tcp**: *DEPRECATED* comma-delimited list of ip/port TCP addresses of node
|
||||||
* **desc**: human-readable description (optional)
|
* **desc**: human-readable description (optional)
|
||||||
|
|
|
@ -1,98 +1,90 @@
|
||||||
static unsigned char ZT_DEFAULT_ROOT_TOPOLOGY[] = {
|
static unsigned char ZT_DEFAULT_ROOT_TOPOLOGY[] = {
|
||||||
0x73, 0x75, 0x70, 0x65, 0x72, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x3d, 0x37, 0x65, 0x31, 0x39, 0x38,
|
0x72, 0x6f, 0x6f, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x3d, 0x37, 0x65, 0x31, 0x39,
|
||||||
0x37, 0x36, 0x61, 0x62, 0x61, 0x5c, 0x3d, 0x69, 0x64, 0x5c, 0x5c, 0x5c, 0x3d, 0x37, 0x65, 0x31,
|
0x38, 0x37, 0x36, 0x61, 0x62, 0x61, 0x5c, 0x3d, 0x69, 0x64, 0x5c, 0x5c, 0x5c, 0x3d, 0x37, 0x65,
|
||||||
0x39, 0x38, 0x37, 0x36, 0x61, 0x62, 0x61, 0x3a, 0x30, 0x3a, 0x32, 0x61, 0x36, 0x65, 0x32, 0x62,
|
0x31, 0x39, 0x38, 0x37, 0x36, 0x61, 0x62, 0x61, 0x3a, 0x30, 0x3a, 0x32, 0x61, 0x36, 0x65, 0x32,
|
||||||
0x32, 0x33, 0x31, 0x38, 0x39, 0x33, 0x30, 0x66, 0x36, 0x30, 0x65, 0x62, 0x30, 0x39, 0x37, 0x66,
|
0x62, 0x32, 0x33, 0x31, 0x38, 0x39, 0x33, 0x30, 0x66, 0x36, 0x30, 0x65, 0x62, 0x30, 0x39, 0x37,
|
||||||
0x37, 0x30, 0x64, 0x30, 0x66, 0x34, 0x62, 0x30, 0x32, 0x38, 0x62, 0x32, 0x63, 0x64, 0x36, 0x64,
|
0x66, 0x37, 0x30, 0x64, 0x30, 0x66, 0x34, 0x62, 0x30, 0x32, 0x38, 0x62, 0x32, 0x63, 0x64, 0x36,
|
||||||
0x33, 0x64, 0x30, 0x63, 0x36, 0x33, 0x63, 0x30, 0x31, 0x34, 0x62, 0x39, 0x30, 0x33, 0x39, 0x66,
|
0x64, 0x33, 0x64, 0x30, 0x63, 0x36, 0x33, 0x63, 0x30, 0x31, 0x34, 0x62, 0x39, 0x30, 0x33, 0x39,
|
||||||
0x66, 0x33, 0x35, 0x33, 0x39, 0x30, 0x65, 0x34, 0x31, 0x31, 0x38, 0x31, 0x66, 0x32, 0x31, 0x36,
|
0x66, 0x66, 0x33, 0x35, 0x33, 0x39, 0x30, 0x65, 0x34, 0x31, 0x31, 0x38, 0x31, 0x66, 0x32, 0x31,
|
||||||
0x66, 0x62, 0x32, 0x65, 0x36, 0x66, 0x61, 0x38, 0x64, 0x39, 0x35, 0x63, 0x31, 0x65, 0x65, 0x39,
|
0x36, 0x66, 0x62, 0x32, 0x65, 0x36, 0x66, 0x61, 0x38, 0x64, 0x39, 0x35, 0x63, 0x31, 0x65, 0x65,
|
||||||
0x36, 0x36, 0x37, 0x31, 0x35, 0x36, 0x34, 0x31, 0x31, 0x39, 0x30, 0x35, 0x63, 0x33, 0x64, 0x63,
|
0x39, 0x36, 0x36, 0x37, 0x31, 0x35, 0x36, 0x34, 0x31, 0x31, 0x39, 0x30, 0x35, 0x63, 0x33, 0x64,
|
||||||
0x63, 0x66, 0x65, 0x61, 0x37, 0x38, 0x64, 0x38, 0x63, 0x36, 0x64, 0x66, 0x61, 0x66, 0x62, 0x61,
|
0x63, 0x63, 0x66, 0x65, 0x61, 0x37, 0x38, 0x64, 0x38, 0x63, 0x36, 0x64, 0x66, 0x61, 0x66, 0x62,
|
||||||
0x36, 0x38, 0x38, 0x31, 0x37, 0x30, 0x62, 0x33, 0x66, 0x61, 0x5c, 0x5c, 0x6e, 0x75, 0x64, 0x70,
|
0x61, 0x36, 0x38, 0x38, 0x31, 0x37, 0x30, 0x62, 0x33, 0x66, 0x61, 0x5c, 0x5c, 0x6e, 0x75, 0x64,
|
||||||
0x5c, 0x5c, 0x5c, 0x3d, 0x31, 0x39, 0x38, 0x2e, 0x31, 0x39, 0x39, 0x2e, 0x39, 0x37, 0x2e, 0x32,
|
0x70, 0x5c, 0x5c, 0x5c, 0x3d, 0x31, 0x39, 0x38, 0x2e, 0x31, 0x39, 0x39, 0x2e, 0x39, 0x37, 0x2e,
|
||||||
0x32, 0x30, 0x2f, 0x39, 0x39, 0x39, 0x33, 0x5c, 0x5c, 0x6e, 0x74, 0x63, 0x70, 0x5c, 0x5c, 0x5c,
|
0x32, 0x32, 0x30, 0x2f, 0x39, 0x39, 0x39, 0x33, 0x5c, 0x5c, 0x6e, 0x74, 0x63, 0x70, 0x5c, 0x5c,
|
||||||
0x3d, 0x31, 0x39, 0x38, 0x2e, 0x31, 0x39, 0x39, 0x2e, 0x39, 0x37, 0x2e, 0x32, 0x32, 0x30, 0x2f,
|
0x5c, 0x3d, 0x31, 0x39, 0x38, 0x2e, 0x31, 0x39, 0x39, 0x2e, 0x39, 0x37, 0x2e, 0x32, 0x32, 0x30,
|
||||||
0x34, 0x34, 0x33, 0x5c, 0x5c, 0x6e, 0x64, 0x65, 0x73, 0x63, 0x5c, 0x5c, 0x5c, 0x3d, 0x53, 0x61,
|
0x2f, 0x34, 0x34, 0x33, 0x5c, 0x5c, 0x6e, 0x64, 0x65, 0x73, 0x63, 0x5c, 0x5c, 0x5c, 0x3d, 0x53,
|
||||||
0x6e, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x69, 0x73, 0x63, 0x6f, 0x2c, 0x20, 0x43, 0x61, 0x6c,
|
0x61, 0x6e, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x69, 0x73, 0x63, 0x6f, 0x2c, 0x20, 0x43, 0x61,
|
||||||
0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x2c, 0x20, 0x55, 0x53, 0x41, 0x5c, 0x5c, 0x6e, 0x64,
|
0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x2c, 0x20, 0x55, 0x53, 0x41, 0x5c, 0x5c, 0x6e,
|
||||||
0x6e, 0x73, 0x5c, 0x5c, 0x5c, 0x3d, 0x6e, 0x79, 0x61, 0x72, 0x6c, 0x61, 0x74, 0x68, 0x6f, 0x74,
|
0x5c, 0x6e, 0x38, 0x38, 0x34, 0x31, 0x34, 0x30, 0x38, 0x61, 0x32, 0x65, 0x5c, 0x3d, 0x69, 0x64,
|
||||||
0x65, 0x70, 0x2e, 0x7a, 0x65, 0x72, 0x6f, 0x74, 0x69, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x5c,
|
0x5c, 0x5c, 0x5c, 0x3d, 0x38, 0x38, 0x34, 0x31, 0x34, 0x30, 0x38, 0x61, 0x32, 0x65, 0x3a, 0x30,
|
||||||
0x5c, 0x6e, 0x5c, 0x6e, 0x38, 0x38, 0x34, 0x31, 0x34, 0x30, 0x38, 0x61, 0x32, 0x65, 0x5c, 0x3d,
|
0x3a, 0x62, 0x62, 0x31, 0x64, 0x33, 0x31, 0x66, 0x32, 0x63, 0x33, 0x32, 0x33, 0x65, 0x32, 0x36,
|
||||||
0x69, 0x64, 0x5c, 0x5c, 0x5c, 0x3d, 0x38, 0x38, 0x34, 0x31, 0x34, 0x30, 0x38, 0x61, 0x32, 0x65,
|
0x34, 0x65, 0x39, 0x65, 0x36, 0x34, 0x31, 0x37, 0x32, 0x63, 0x31, 0x61, 0x37, 0x34, 0x66, 0x37,
|
||||||
0x3a, 0x30, 0x3a, 0x62, 0x62, 0x31, 0x64, 0x33, 0x31, 0x66, 0x32, 0x63, 0x33, 0x32, 0x33, 0x65,
|
0x37, 0x38, 0x39, 0x39, 0x35, 0x35, 0x35, 0x65, 0x64, 0x31, 0x30, 0x37, 0x35, 0x31, 0x63, 0x64,
|
||||||
0x32, 0x36, 0x34, 0x65, 0x39, 0x65, 0x36, 0x34, 0x31, 0x37, 0x32, 0x63, 0x31, 0x61, 0x37, 0x34,
|
0x35, 0x36, 0x65, 0x38, 0x36, 0x34, 0x30, 0x35, 0x63, 0x64, 0x65, 0x31, 0x31, 0x38, 0x64, 0x30,
|
||||||
0x66, 0x37, 0x37, 0x38, 0x39, 0x39, 0x35, 0x35, 0x35, 0x65, 0x64, 0x31, 0x30, 0x37, 0x35, 0x31,
|
0x32, 0x64, 0x66, 0x66, 0x65, 0x35, 0x35, 0x35, 0x64, 0x34, 0x36, 0x32, 0x63, 0x63, 0x66, 0x36,
|
||||||
0x63, 0x64, 0x35, 0x36, 0x65, 0x38, 0x36, 0x34, 0x30, 0x35, 0x63, 0x64, 0x65, 0x31, 0x31, 0x38,
|
0x61, 0x38, 0x35, 0x62, 0x35, 0x36, 0x33, 0x31, 0x63, 0x31, 0x32, 0x33, 0x35, 0x30, 0x63, 0x38,
|
||||||
0x64, 0x30, 0x32, 0x64, 0x66, 0x66, 0x65, 0x35, 0x35, 0x35, 0x64, 0x34, 0x36, 0x32, 0x63, 0x63,
|
0x64, 0x35, 0x64, 0x63, 0x34, 0x30, 0x39, 0x62, 0x61, 0x31, 0x30, 0x62, 0x39, 0x30, 0x32, 0x35,
|
||||||
0x66, 0x36, 0x61, 0x38, 0x35, 0x62, 0x35, 0x36, 0x33, 0x31, 0x63, 0x31, 0x32, 0x33, 0x35, 0x30,
|
0x64, 0x30, 0x66, 0x34, 0x34, 0x35, 0x63, 0x66, 0x34, 0x34, 0x39, 0x64, 0x39, 0x32, 0x62, 0x31,
|
||||||
0x63, 0x38, 0x64, 0x35, 0x64, 0x63, 0x34, 0x30, 0x39, 0x62, 0x61, 0x31, 0x30, 0x62, 0x39, 0x30,
|
0x63, 0x5c, 0x5c, 0x6e, 0x75, 0x64, 0x70, 0x5c, 0x5c, 0x5c, 0x3d, 0x31, 0x30, 0x37, 0x2e, 0x31,
|
||||||
0x32, 0x35, 0x64, 0x30, 0x66, 0x34, 0x34, 0x35, 0x63, 0x66, 0x34, 0x34, 0x39, 0x64, 0x39, 0x32,
|
0x39, 0x31, 0x2e, 0x34, 0x36, 0x2e, 0x32, 0x31, 0x30, 0x2f, 0x39, 0x39, 0x39, 0x33, 0x5c, 0x5c,
|
||||||
0x62, 0x31, 0x63, 0x5c, 0x5c, 0x6e, 0x75, 0x64, 0x70, 0x5c, 0x5c, 0x5c, 0x3d, 0x31, 0x30, 0x37,
|
0x6e, 0x74, 0x63, 0x70, 0x5c, 0x5c, 0x5c, 0x3d, 0x31, 0x30, 0x37, 0x2e, 0x31, 0x39, 0x31, 0x2e,
|
||||||
0x2e, 0x31, 0x39, 0x31, 0x2e, 0x34, 0x36, 0x2e, 0x32, 0x31, 0x30, 0x2f, 0x39, 0x39, 0x39, 0x33,
|
0x34, 0x36, 0x2e, 0x32, 0x31, 0x30, 0x2f, 0x34, 0x34, 0x33, 0x5c, 0x5c, 0x6e, 0x64, 0x65, 0x73,
|
||||||
0x5c, 0x5c, 0x6e, 0x74, 0x63, 0x70, 0x5c, 0x5c, 0x5c, 0x3d, 0x31, 0x30, 0x37, 0x2e, 0x31, 0x39,
|
0x63, 0x5c, 0x5c, 0x5c, 0x3d, 0x50, 0x61, 0x72, 0x69, 0x73, 0x2c, 0x20, 0x46, 0x72, 0x61, 0x6e,
|
||||||
0x31, 0x2e, 0x34, 0x36, 0x2e, 0x32, 0x31, 0x30, 0x2f, 0x34, 0x34, 0x33, 0x5c, 0x5c, 0x6e, 0x64,
|
0x63, 0x65, 0x5c, 0x5c, 0x6e, 0x5c, 0x6e, 0x38, 0x61, 0x63, 0x66, 0x30, 0x35, 0x39, 0x66, 0x65,
|
||||||
0x65, 0x73, 0x63, 0x5c, 0x5c, 0x5c, 0x3d, 0x50, 0x61, 0x72, 0x69, 0x73, 0x2c, 0x20, 0x46, 0x72,
|
0x33, 0x5c, 0x3d, 0x69, 0x64, 0x5c, 0x5c, 0x5c, 0x3d, 0x38, 0x61, 0x63, 0x66, 0x30, 0x35, 0x39,
|
||||||
0x61, 0x6e, 0x63, 0x65, 0x5c, 0x5c, 0x6e, 0x64, 0x6e, 0x73, 0x5c, 0x5c, 0x5c, 0x3d, 0x73, 0x68,
|
0x66, 0x65, 0x33, 0x3a, 0x30, 0x3a, 0x34, 0x38, 0x32, 0x66, 0x36, 0x65, 0x65, 0x35, 0x64, 0x66,
|
||||||
0x6f, 0x67, 0x67, 0x6f, 0x74, 0x68, 0x2e, 0x7a, 0x65, 0x72, 0x6f, 0x74, 0x69, 0x65, 0x72, 0x2e,
|
0x65, 0x39, 0x30, 0x32, 0x33, 0x31, 0x39, 0x62, 0x34, 0x31, 0x39, 0x64, 0x65, 0x35, 0x62, 0x64,
|
||||||
0x63, 0x6f, 0x6d, 0x5c, 0x5c, 0x6e, 0x5c, 0x6e, 0x38, 0x61, 0x63, 0x66, 0x30, 0x35, 0x39, 0x66,
|
0x63, 0x37, 0x36, 0x35, 0x32, 0x30, 0x39, 0x63, 0x30, 0x65, 0x63, 0x64, 0x61, 0x33, 0x38, 0x63,
|
||||||
0x65, 0x33, 0x5c, 0x3d, 0x69, 0x64, 0x5c, 0x5c, 0x5c, 0x3d, 0x38, 0x61, 0x63, 0x66, 0x30, 0x35,
|
0x34, 0x64, 0x36, 0x65, 0x34, 0x66, 0x63, 0x66, 0x30, 0x64, 0x33, 0x33, 0x36, 0x35, 0x38, 0x33,
|
||||||
0x39, 0x66, 0x65, 0x33, 0x3a, 0x30, 0x3a, 0x34, 0x38, 0x32, 0x66, 0x36, 0x65, 0x65, 0x35, 0x64,
|
0x39, 0x38, 0x62, 0x34, 0x35, 0x32, 0x37, 0x64, 0x63, 0x64, 0x32, 0x32, 0x66, 0x39, 0x33, 0x31,
|
||||||
0x66, 0x65, 0x39, 0x30, 0x32, 0x33, 0x31, 0x39, 0x62, 0x34, 0x31, 0x39, 0x64, 0x65, 0x35, 0x62,
|
0x31, 0x32, 0x66, 0x62, 0x39, 0x62, 0x65, 0x66, 0x64, 0x30, 0x32, 0x66, 0x64, 0x37, 0x38, 0x62,
|
||||||
0x64, 0x63, 0x37, 0x36, 0x35, 0x32, 0x30, 0x39, 0x63, 0x30, 0x65, 0x63, 0x64, 0x61, 0x33, 0x38,
|
0x66, 0x37, 0x32, 0x36, 0x31, 0x62, 0x33, 0x33, 0x33, 0x66, 0x63, 0x31, 0x30, 0x35, 0x64, 0x31,
|
||||||
0x63, 0x34, 0x64, 0x36, 0x65, 0x34, 0x66, 0x63, 0x66, 0x30, 0x64, 0x33, 0x33, 0x36, 0x35, 0x38,
|
0x39, 0x32, 0x61, 0x36, 0x32, 0x33, 0x63, 0x61, 0x39, 0x65, 0x35, 0x30, 0x66, 0x63, 0x36, 0x30,
|
||||||
0x33, 0x39, 0x38, 0x62, 0x34, 0x35, 0x32, 0x37, 0x64, 0x63, 0x64, 0x32, 0x32, 0x66, 0x39, 0x33,
|
0x62, 0x33, 0x37, 0x34, 0x61, 0x35, 0x5c, 0x5c, 0x6e, 0x75, 0x64, 0x70, 0x5c, 0x5c, 0x5c, 0x3d,
|
||||||
0x31, 0x31, 0x32, 0x66, 0x62, 0x39, 0x62, 0x65, 0x66, 0x64, 0x30, 0x32, 0x66, 0x64, 0x37, 0x38,
|
0x31, 0x36, 0x32, 0x2e, 0x32, 0x34, 0x33, 0x2e, 0x37, 0x37, 0x2e, 0x31, 0x31, 0x31, 0x2f, 0x39,
|
||||||
0x62, 0x66, 0x37, 0x32, 0x36, 0x31, 0x62, 0x33, 0x33, 0x33, 0x66, 0x63, 0x31, 0x30, 0x35, 0x64,
|
0x39, 0x39, 0x33, 0x5c, 0x5c, 0x6e, 0x74, 0x63, 0x70, 0x5c, 0x5c, 0x5c, 0x3d, 0x31, 0x36, 0x32,
|
||||||
0x31, 0x39, 0x32, 0x61, 0x36, 0x32, 0x33, 0x63, 0x61, 0x39, 0x65, 0x35, 0x30, 0x66, 0x63, 0x36,
|
0x2e, 0x32, 0x34, 0x33, 0x2e, 0x37, 0x37, 0x2e, 0x31, 0x31, 0x31, 0x2f, 0x34, 0x34, 0x33, 0x5c,
|
||||||
0x30, 0x62, 0x33, 0x37, 0x34, 0x61, 0x35, 0x5c, 0x5c, 0x6e, 0x75, 0x64, 0x70, 0x5c, 0x5c, 0x5c,
|
0x5c, 0x6e, 0x64, 0x65, 0x73, 0x63, 0x5c, 0x5c, 0x5c, 0x3d, 0x4e, 0x65, 0x77, 0x20, 0x59, 0x6f,
|
||||||
0x3d, 0x31, 0x36, 0x32, 0x2e, 0x32, 0x34, 0x33, 0x2e, 0x37, 0x37, 0x2e, 0x31, 0x31, 0x31, 0x2f,
|
0x72, 0x6b, 0x2c, 0x20, 0x4e, 0x65, 0x77, 0x20, 0x59, 0x6f, 0x72, 0x6b, 0x2c, 0x20, 0x55, 0x53,
|
||||||
0x39, 0x39, 0x39, 0x33, 0x5c, 0x5c, 0x6e, 0x74, 0x63, 0x70, 0x5c, 0x5c, 0x5c, 0x3d, 0x31, 0x36,
|
0x41, 0x5c, 0x5c, 0x6e, 0x5c, 0x6e, 0x39, 0x64, 0x32, 0x31, 0x39, 0x30, 0x33, 0x39, 0x66, 0x33,
|
||||||
0x32, 0x2e, 0x32, 0x34, 0x33, 0x2e, 0x37, 0x37, 0x2e, 0x31, 0x31, 0x31, 0x2f, 0x34, 0x34, 0x33,
|
0x5c, 0x3d, 0x69, 0x64, 0x5c, 0x5c, 0x5c, 0x3d, 0x39, 0x64, 0x32, 0x31, 0x39, 0x30, 0x33, 0x39,
|
||||||
0x5c, 0x5c, 0x6e, 0x64, 0x65, 0x73, 0x63, 0x5c, 0x5c, 0x5c, 0x3d, 0x4e, 0x65, 0x77, 0x20, 0x59,
|
0x66, 0x33, 0x3a, 0x30, 0x3a, 0x30, 0x31, 0x66, 0x30, 0x39, 0x32, 0x32, 0x61, 0x39, 0x38, 0x65,
|
||||||
0x6f, 0x72, 0x6b, 0x2c, 0x20, 0x4e, 0x65, 0x77, 0x20, 0x59, 0x6f, 0x72, 0x6b, 0x2c, 0x20, 0x55,
|
0x33, 0x62, 0x33, 0x34, 0x65, 0x62, 0x63, 0x62, 0x66, 0x66, 0x33, 0x33, 0x33, 0x32, 0x36, 0x39,
|
||||||
0x53, 0x41, 0x5c, 0x5c, 0x6e, 0x64, 0x6e, 0x73, 0x5c, 0x5c, 0x5c, 0x3d, 0x63, 0x74, 0x68, 0x75,
|
0x64, 0x63, 0x32, 0x36, 0x35, 0x64, 0x37, 0x61, 0x30, 0x32, 0x30, 0x61, 0x61, 0x62, 0x36, 0x39,
|
||||||
0x6c, 0x68, 0x75, 0x2e, 0x7a, 0x65, 0x72, 0x6f, 0x74, 0x69, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d,
|
0x64, 0x37, 0x32, 0x62, 0x65, 0x34, 0x64, 0x34, 0x61, 0x63, 0x63, 0x39, 0x63, 0x38, 0x63, 0x39,
|
||||||
0x5c, 0x5c, 0x6e, 0x5c, 0x6e, 0x39, 0x64, 0x32, 0x31, 0x39, 0x30, 0x33, 0x39, 0x66, 0x33, 0x5c,
|
0x32, 0x39, 0x34, 0x37, 0x38, 0x35, 0x37, 0x37, 0x31, 0x32, 0x35, 0x36, 0x63, 0x64, 0x31, 0x64,
|
||||||
0x3d, 0x69, 0x64, 0x5c, 0x5c, 0x5c, 0x3d, 0x39, 0x64, 0x32, 0x31, 0x39, 0x30, 0x33, 0x39, 0x66,
|
0x39, 0x34, 0x32, 0x61, 0x39, 0x30, 0x64, 0x31, 0x62, 0x64, 0x31, 0x64, 0x32, 0x64, 0x63, 0x61,
|
||||||
0x33, 0x3a, 0x30, 0x3a, 0x30, 0x31, 0x66, 0x30, 0x39, 0x32, 0x32, 0x61, 0x39, 0x38, 0x65, 0x33,
|
0x33, 0x65, 0x61, 0x38, 0x34, 0x65, 0x66, 0x37, 0x64, 0x38, 0x35, 0x61, 0x66, 0x65, 0x36, 0x36,
|
||||||
0x62, 0x33, 0x34, 0x65, 0x62, 0x63, 0x62, 0x66, 0x66, 0x33, 0x33, 0x33, 0x32, 0x36, 0x39, 0x64,
|
0x31, 0x31, 0x66, 0x62, 0x34, 0x33, 0x66, 0x66, 0x30, 0x62, 0x37, 0x34, 0x31, 0x32, 0x36, 0x64,
|
||||||
0x63, 0x32, 0x36, 0x35, 0x64, 0x37, 0x61, 0x30, 0x32, 0x30, 0x61, 0x61, 0x62, 0x36, 0x39, 0x64,
|
0x39, 0x30, 0x61, 0x36, 0x65, 0x5c, 0x5c, 0x6e, 0x75, 0x64, 0x70, 0x5c, 0x5c, 0x5c, 0x3d, 0x31,
|
||||||
0x37, 0x32, 0x62, 0x65, 0x34, 0x64, 0x34, 0x61, 0x63, 0x63, 0x39, 0x63, 0x38, 0x63, 0x39, 0x32,
|
0x32, 0x38, 0x2e, 0x31, 0x39, 0x39, 0x2e, 0x31, 0x39, 0x37, 0x2e, 0x32, 0x31, 0x37, 0x2f, 0x39,
|
||||||
0x39, 0x34, 0x37, 0x38, 0x35, 0x37, 0x37, 0x31, 0x32, 0x35, 0x36, 0x63, 0x64, 0x31, 0x64, 0x39,
|
0x39, 0x39, 0x33, 0x5c, 0x5c, 0x6e, 0x74, 0x63, 0x70, 0x5c, 0x5c, 0x5c, 0x3d, 0x31, 0x32, 0x38,
|
||||||
0x34, 0x32, 0x61, 0x39, 0x30, 0x64, 0x31, 0x62, 0x64, 0x31, 0x64, 0x32, 0x64, 0x63, 0x61, 0x33,
|
0x2e, 0x31, 0x39, 0x39, 0x2e, 0x31, 0x39, 0x37, 0x2e, 0x32, 0x31, 0x37, 0x2f, 0x34, 0x34, 0x33,
|
||||||
0x65, 0x61, 0x38, 0x34, 0x65, 0x66, 0x37, 0x64, 0x38, 0x35, 0x61, 0x66, 0x65, 0x36, 0x36, 0x31,
|
0x5c, 0x5c, 0x6e, 0x64, 0x65, 0x73, 0x63, 0x5c, 0x5c, 0x5c, 0x3d, 0x53, 0x69, 0x6e, 0x67, 0x61,
|
||||||
0x31, 0x66, 0x62, 0x34, 0x33, 0x66, 0x66, 0x30, 0x62, 0x37, 0x34, 0x31, 0x32, 0x36, 0x64, 0x39,
|
0x70, 0x6f, 0x72, 0x65, 0x5c, 0x5c, 0x6e, 0x5c, 0x6e, 0x0a, 0x7e, 0x21, 0x65, 0x64, 0x32, 0x35,
|
||||||
0x30, 0x61, 0x36, 0x65, 0x5c, 0x5c, 0x6e, 0x75, 0x64, 0x70, 0x5c, 0x5c, 0x5c, 0x3d, 0x31, 0x32,
|
0x35, 0x31, 0x39, 0x3d, 0x38, 0x33, 0x32, 0x62, 0x33, 0x35, 0x64, 0x61, 0x64, 0x64, 0x37, 0x66,
|
||||||
0x38, 0x2e, 0x31, 0x39, 0x39, 0x2e, 0x31, 0x39, 0x37, 0x2e, 0x32, 0x31, 0x37, 0x2f, 0x39, 0x39,
|
0x35, 0x36, 0x66, 0x66, 0x33, 0x38, 0x31, 0x66, 0x61, 0x37, 0x32, 0x31, 0x64, 0x65, 0x37, 0x64,
|
||||||
0x39, 0x33, 0x5c, 0x5c, 0x6e, 0x74, 0x63, 0x70, 0x5c, 0x5c, 0x5c, 0x3d, 0x31, 0x32, 0x38, 0x2e,
|
0x35, 0x62, 0x65, 0x34, 0x63, 0x65, 0x62, 0x66, 0x63, 0x63, 0x63, 0x32, 0x30, 0x30, 0x32, 0x30,
|
||||||
0x31, 0x39, 0x39, 0x2e, 0x31, 0x39, 0x37, 0x2e, 0x32, 0x31, 0x37, 0x2f, 0x34, 0x34, 0x33, 0x5c,
|
0x38, 0x33, 0x38, 0x30, 0x64, 0x33, 0x30, 0x38, 0x34, 0x66, 0x36, 0x34, 0x38, 0x65, 0x32, 0x63,
|
||||||
0x5c, 0x6e, 0x64, 0x65, 0x73, 0x63, 0x5c, 0x5c, 0x5c, 0x3d, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70,
|
0x31, 0x61, 0x35, 0x63, 0x66, 0x34, 0x33, 0x65, 0x35, 0x39, 0x66, 0x39, 0x32, 0x61, 0x36, 0x36,
|
||||||
0x6f, 0x72, 0x65, 0x5c, 0x5c, 0x6e, 0x64, 0x6e, 0x73, 0x5c, 0x5c, 0x5c, 0x3d, 0x6d, 0x69, 0x2d,
|
0x35, 0x64, 0x66, 0x34, 0x64, 0x62, 0x63, 0x62, 0x38, 0x33, 0x37, 0x38, 0x38, 0x66, 0x36, 0x62,
|
||||||
0x67, 0x6f, 0x2e, 0x7a, 0x65, 0x72, 0x6f, 0x74, 0x69, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x5c,
|
0x64, 0x36, 0x37, 0x37, 0x66, 0x30, 0x32, 0x62, 0x32, 0x31, 0x30, 0x65, 0x35, 0x30, 0x63, 0x61,
|
||||||
0x5c, 0x6e, 0x5c, 0x6e, 0x0a, 0x7e, 0x21, 0x65, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x3d, 0x62,
|
0x66, 0x65, 0x66, 0x64, 0x32, 0x65, 0x66, 0x31, 0x38, 0x39, 0x62, 0x62, 0x66, 0x34, 0x38, 0x31,
|
||||||
0x37, 0x34, 0x39, 0x33, 0x66, 0x35, 0x61, 0x34, 0x62, 0x37, 0x39, 0x61, 0x31, 0x64, 0x63, 0x63,
|
0x62, 0x64, 0x30, 0x32, 0x63, 0x64, 0x63, 0x39, 0x38, 0x34, 0x35, 0x33, 0x38, 0x37, 0x64, 0x38,
|
||||||
0x34, 0x32, 0x33, 0x66, 0x64, 0x32, 0x35, 0x64, 0x32, 0x64, 0x38, 0x61, 0x61, 0x38, 0x64, 0x36,
|
0x34, 0x39, 0x62, 0x63, 0x35, 0x36, 0x66, 0x39, 0x63, 0x37, 0x32, 0x35, 0x31, 0x65, 0x35, 0x64,
|
||||||
0x32, 0x39, 0x33, 0x63, 0x34, 0x39, 0x30, 0x61, 0x31, 0x32, 0x63, 0x65, 0x62, 0x36, 0x33, 0x39,
|
0x30, 0x65, 0x61, 0x34, 0x34, 0x34, 0x66, 0x66, 0x63, 0x66, 0x38, 0x66, 0x37, 0x32, 0x32, 0x63,
|
||||||
0x35, 0x34, 0x31, 0x37, 0x64, 0x64, 0x35, 0x38, 0x36, 0x38, 0x63, 0x31, 0x37, 0x62, 0x66, 0x62,
|
0x32, 0x66, 0x65, 0x62, 0x38, 0x39, 0x36, 0x30, 0x33, 0x61, 0x30, 0x65, 0x35, 0x62, 0x61, 0x32,
|
||||||
0x63, 0x65, 0x65, 0x36, 0x38, 0x35, 0x64, 0x65, 0x35, 0x38, 0x30, 0x31, 0x39, 0x64, 0x32, 0x31,
|
0x39, 0x35, 0x66, 0x63, 0x0a, 0x7e, 0x21, 0x73, 0x69, 0x67, 0x69, 0x64, 0x3d, 0x37, 0x37, 0x37,
|
||||||
0x66, 0x39, 0x32, 0x35, 0x37, 0x36, 0x61, 0x37, 0x38, 0x61, 0x34, 0x35, 0x32, 0x33, 0x35, 0x64,
|
0x39, 0x32, 0x62, 0x31, 0x63, 0x30, 0x32, 0x3a, 0x30, 0x3a, 0x62, 0x35, 0x63, 0x33, 0x36, 0x31,
|
||||||
0x33, 0x34, 0x32, 0x65, 0x66, 0x61, 0x32, 0x61, 0x30, 0x30, 0x61, 0x35, 0x34, 0x34, 0x64, 0x65,
|
0x65, 0x38, 0x65, 0x39, 0x63, 0x32, 0x31, 0x35, 0x34, 0x65, 0x38, 0x32, 0x63, 0x33, 0x65, 0x39,
|
||||||
0x64, 0x33, 0x34, 0x37, 0x36, 0x36, 0x64, 0x64, 0x33, 0x32, 0x64, 0x36, 0x66, 0x30, 0x65, 0x31,
|
0x30, 0x32, 0x66, 0x64, 0x66, 0x63, 0x33, 0x33, 0x37, 0x34, 0x36, 0x38, 0x62, 0x30, 0x39, 0x32,
|
||||||
0x31, 0x38, 0x30, 0x39, 0x31, 0x39, 0x37, 0x66, 0x39, 0x62, 0x61, 0x65, 0x65, 0x64, 0x66, 0x34,
|
0x61, 0x37, 0x63, 0x34, 0x64, 0x38, 0x64, 0x63, 0x36, 0x38, 0x35, 0x63, 0x33, 0x37, 0x65, 0x62,
|
||||||
0x63, 0x36, 0x61, 0x30, 0x65, 0x38, 0x64, 0x32, 0x64, 0x36, 0x35, 0x37, 0x64, 0x32, 0x38, 0x30,
|
0x31, 0x30, 0x65, 0x65, 0x34, 0x66, 0x33, 0x63, 0x31, 0x37, 0x63, 0x63, 0x30, 0x62, 0x62, 0x31,
|
||||||
0x61, 0x35, 0x37, 0x39, 0x66, 0x32, 0x66, 0x32, 0x34, 0x37, 0x38, 0x62, 0x32, 0x66, 0x37, 0x63,
|
0x64, 0x30, 0x32, 0x34, 0x31, 0x36, 0x37, 0x65, 0x38, 0x63, 0x62, 0x30, 0x38, 0x32, 0x34, 0x64,
|
||||||
0x37, 0x61, 0x30, 0x38, 0x30, 0x38, 0x39, 0x61, 0x35, 0x30, 0x31, 0x36, 0x62, 0x35, 0x35, 0x0a,
|
0x31, 0x32, 0x32, 0x36, 0x33, 0x34, 0x32, 0x38, 0x33, 0x37, 0x33, 0x35, 0x38, 0x32, 0x64, 0x61,
|
||||||
0x7e, 0x21, 0x73, 0x69, 0x67, 0x69, 0x64, 0x3d, 0x37, 0x37, 0x37, 0x39, 0x32, 0x62, 0x31, 0x63,
|
0x33, 0x64, 0x30, 0x61, 0x39, 0x61, 0x31, 0x34, 0x62, 0x33, 0x36, 0x65, 0x34, 0x35, 0x34, 0x36,
|
||||||
0x30, 0x32, 0x3a, 0x30, 0x3a, 0x62, 0x35, 0x63, 0x33, 0x36, 0x31, 0x65, 0x38, 0x65, 0x39, 0x63,
|
0x63, 0x33, 0x31, 0x37, 0x65, 0x38, 0x31, 0x31, 0x65, 0x36, 0x0a, 0x7e, 0x21, 0x73, 0x69, 0x67,
|
||||||
0x32, 0x31, 0x35, 0x34, 0x65, 0x38, 0x32, 0x63, 0x33, 0x65, 0x39, 0x30, 0x32, 0x66, 0x64, 0x66,
|
0x74, 0x73, 0x3d, 0x31, 0x34, 0x65, 0x30, 0x63, 0x62, 0x62, 0x39, 0x38, 0x64, 0x36, 0x0a
|
||||||
0x63, 0x33, 0x33, 0x37, 0x34, 0x36, 0x38, 0x62, 0x30, 0x39, 0x32, 0x61, 0x37, 0x63, 0x34, 0x64,
|
|
||||||
0x38, 0x64, 0x63, 0x36, 0x38, 0x35, 0x63, 0x33, 0x37, 0x65, 0x62, 0x31, 0x30, 0x65, 0x65, 0x34,
|
|
||||||
0x66, 0x33, 0x63, 0x31, 0x37, 0x63, 0x63, 0x30, 0x62, 0x62, 0x31, 0x64, 0x30, 0x32, 0x34, 0x31,
|
|
||||||
0x36, 0x37, 0x65, 0x38, 0x63, 0x62, 0x30, 0x38, 0x32, 0x34, 0x64, 0x31, 0x32, 0x32, 0x36, 0x33,
|
|
||||||
0x34, 0x32, 0x38, 0x33, 0x37, 0x33, 0x35, 0x38, 0x32, 0x64, 0x61, 0x33, 0x64, 0x30, 0x61, 0x39,
|
|
||||||
0x61, 0x31, 0x34, 0x62, 0x33, 0x36, 0x65, 0x34, 0x35, 0x34, 0x36, 0x63, 0x33, 0x31, 0x37, 0x65,
|
|
||||||
0x38, 0x31, 0x31, 0x65, 0x36, 0x0a, 0x7e, 0x21, 0x73, 0x69, 0x67, 0x74, 0x73, 0x3d, 0x31, 0x34,
|
|
||||||
0x61, 0x65, 0x34, 0x32, 0x64, 0x30, 0x33, 0x31, 0x34, 0x0a
|
|
||||||
};
|
};
|
||||||
#define ZT_DEFAULT_ROOT_TOPOLOGY_LEN 1514
|
#define ZT_DEFAULT_ROOT_TOPOLOGY_LEN 1391
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
supernodes=7e19876aba\=id\\\=7e19876aba:0:2a6e2b2318930f60eb097f70d0f4b028b2cd6d3d0c63c014b9039ff35390e41181f216fb2e6fa8d95c1ee9667156411905c3dccfea78d8c6dfafba688170b3fa\\nudp\\\=198.199.97.220/9993\\ntcp\\\=198.199.97.220/443\\ndesc\\\=San Francisco, California, USA\\ndns\\\=nyarlathotep.zerotier.com\\n\n8841408a2e\=id\\\=8841408a2e:0:bb1d31f2c323e264e9e64172c1a74f77899555ed10751cd56e86405cde118d02dffe555d462ccf6a85b5631c12350c8d5dc409ba10b9025d0f445cf449d92b1c\\nudp\\\=107.191.46.210/9993\\ntcp\\\=107.191.46.210/443\\ndesc\\\=Paris, France\\ndns\\\=shoggoth.zerotier.com\\n\n8acf059fe3\=id\\\=8acf059fe3:0:482f6ee5dfe902319b419de5bdc765209c0ecda38c4d6e4fcf0d33658398b4527dcd22f93112fb9befd02fd78bf7261b333fc105d192a623ca9e50fc60b374a5\\nudp\\\=162.243.77.111/9993\\ntcp\\\=162.243.77.111/443\\ndesc\\\=New York, New York, USA\\ndns\\\=cthulhu.zerotier.com\\n\n9d219039f3\=id\\\=9d219039f3:0:01f0922a98e3b34ebcbff333269dc265d7a020aab69d72be4d4acc9c8c9294785771256cd1d942a90d1bd1d2dca3ea84ef7d85afe6611fb43ff0b74126d90a6e\\nudp\\\=128.199.197.217/9993\\ntcp\\\=128.199.197.217/443\\ndesc\\\=Singapore\\ndns\\\=mi-go.zerotier.com\\n\n
|
rootservers=7e19876aba\=id\\\=7e19876aba:0:2a6e2b2318930f60eb097f70d0f4b028b2cd6d3d0c63c014b9039ff35390e41181f216fb2e6fa8d95c1ee9667156411905c3dccfea78d8c6dfafba688170b3fa\\nudp\\\=198.199.97.220/9993\\ntcp\\\=198.199.97.220/443\\ndesc\\\=San Francisco, California, USA\\n\n8841408a2e\=id\\\=8841408a2e:0:bb1d31f2c323e264e9e64172c1a74f77899555ed10751cd56e86405cde118d02dffe555d462ccf6a85b5631c12350c8d5dc409ba10b9025d0f445cf449d92b1c\\nudp\\\=107.191.46.210/9993\\ntcp\\\=107.191.46.210/443\\ndesc\\\=Paris, France\\n\n8acf059fe3\=id\\\=8acf059fe3:0:482f6ee5dfe902319b419de5bdc765209c0ecda38c4d6e4fcf0d33658398b4527dcd22f93112fb9befd02fd78bf7261b333fc105d192a623ca9e50fc60b374a5\\nudp\\\=162.243.77.111/9993\\ntcp\\\=162.243.77.111/443\\ndesc\\\=New York, New York, USA\\n\n9d219039f3\=id\\\=9d219039f3:0:01f0922a98e3b34ebcbff333269dc265d7a020aab69d72be4d4acc9c8c9294785771256cd1d942a90d1bd1d2dca3ea84ef7d85afe6611fb43ff0b74126d90a6e\\nudp\\\=128.199.197.217/9993\\ntcp\\\=128.199.197.217/443\\ndesc\\\=Singapore\\n\n
|
||||||
~!ed25519=b7493f5a4b79a1dcc423fd25d2d8aa8d6293c490a12ceb6395417dd5868c17bfbcee685de58019d21f92576a78a45235d342efa2a00a544ded34766dd32d6f0e11809197f9baeedf4c6a0e8d2d657d280a579f2f2478b2f7c7a08089a5016b55
|
~!ed25519=832b35dadd7f56ff381fa721de7d5be4cebfccc200208380d3084f648e2c1a5cf43e59f92a665df4dbcb83788f6bd677f02b210e50cafefd2ef189bbf481bd02cdc9845387d849bc56f9c7251e5d0ea444ffcf8f722c2feb89603a0e5ba295fc
|
||||||
~!sigid=77792b1c02:0:b5c361e8e9c2154e82c3e902fdfc337468b092a7c4d8dc685c37eb10ee4f3c17cc0bb1d024167e8cb0824d12263428373582da3d0a9a14b36e4546c317e811e6
|
~!sigid=77792b1c02:0:b5c361e8e9c2154e82c3e902fdfc337468b092a7c4d8dc685c37eb10ee4f3c17cc0bb1d024167e8cb0824d12263428373582da3d0a9a14b36e4546c317e811e6
|
||||||
~!sigts=14ae42d0314
|
~!sigts=14e0cbb98d6
|
||||||
|
|
|
@ -30,21 +30,21 @@ int main(int argc,char **argv)
|
||||||
if (OSUtils::readFile("template.dict",buf))
|
if (OSUtils::readFile("template.dict",buf))
|
||||||
topology.fromString(buf);
|
topology.fromString(buf);
|
||||||
|
|
||||||
// Read all entries in supernodes/ that correspond to supernode entry dictionaries
|
// Read all entries in rootservers/ that correspond to rootserver entry dictionaries
|
||||||
// and add them to topology under supernodes/ subkey.
|
// and add them to topology under rootservers/ subkey.
|
||||||
Dictionary supernodes;
|
Dictionary rootservers;
|
||||||
std::vector<std::string> supernodeDictionaries(OSUtils::listDirectory("supernodes"));
|
std::vector<std::string> rootserverDictionaries(OSUtils::listDirectory("rootservers"));
|
||||||
for(std::vector<std::string>::const_iterator sn(supernodeDictionaries.begin());sn!=supernodeDictionaries.end();++sn) {
|
for(std::vector<std::string>::const_iterator sn(rootserverDictionaries.begin());sn!=rootserverDictionaries.end();++sn) {
|
||||||
if (sn->length() == 10) {
|
if (sn->length() == 10) {
|
||||||
buf.clear();
|
buf.clear();
|
||||||
if (!OSUtils::readFile((std::string("supernodes/")+(*sn)).c_str(),buf)) {
|
if (!OSUtils::readFile((std::string("rootservers/")+(*sn)).c_str(),buf)) {
|
||||||
std::cerr << "Cannot read supernodes/" << *sn << std::endl;
|
std::cerr << "Cannot read rootservers/" << *sn << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
supernodes[*sn] = buf;
|
rootservers[*sn] = buf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
topology["supernodes"] = supernodes.toString();
|
topology["rootservers"] = rootservers.toString();
|
||||||
|
|
||||||
if ((topologyAuthority)&&(topologyAuthority.hasPrivate())) {
|
if ((topologyAuthority)&&(topologyAuthority.hasPrivate())) {
|
||||||
// Sign topology with root-topology-authority.secret
|
// Sign topology with root-topology-authority.secret
|
||||||
|
|
|
@ -2,4 +2,3 @@ id=7e19876aba:0:2a6e2b2318930f60eb097f70d0f4b028b2cd6d3d0c63c014b9039ff35390e411
|
||||||
udp=198.199.97.220/9993
|
udp=198.199.97.220/9993
|
||||||
tcp=198.199.97.220/443
|
tcp=198.199.97.220/443
|
||||||
desc=San Francisco, California, USA
|
desc=San Francisco, California, USA
|
||||||
dns=nyarlathotep.zerotier.com
|
|
|
@ -2,4 +2,3 @@ id=8841408a2e:0:bb1d31f2c323e264e9e64172c1a74f77899555ed10751cd56e86405cde118d02
|
||||||
udp=107.191.46.210/9993
|
udp=107.191.46.210/9993
|
||||||
tcp=107.191.46.210/443
|
tcp=107.191.46.210/443
|
||||||
desc=Paris, France
|
desc=Paris, France
|
||||||
dns=shoggoth.zerotier.com
|
|
|
@ -2,4 +2,3 @@ id=8acf059fe3:0:482f6ee5dfe902319b419de5bdc765209c0ecda38c4d6e4fcf0d33658398b452
|
||||||
udp=162.243.77.111/9993
|
udp=162.243.77.111/9993
|
||||||
tcp=162.243.77.111/443
|
tcp=162.243.77.111/443
|
||||||
desc=New York, New York, USA
|
desc=New York, New York, USA
|
||||||
dns=cthulhu.zerotier.com
|
|
|
@ -2,4 +2,3 @@ id=9d219039f3:0:01f0922a98e3b34ebcbff333269dc265d7a020aab69d72be4d4acc9c8c929478
|
||||||
udp=128.199.197.217/9993
|
udp=128.199.197.217/9993
|
||||||
tcp=128.199.197.217/443
|
tcp=128.199.197.217/443
|
||||||
desc=Singapore
|
desc=Singapore
|
||||||
dns=mi-go.zerotier.com
|
|
|
@ -1,6 +1,6 @@
|
||||||
Test Root Topology Script
|
Test Root Topology Script
|
||||||
======
|
======
|
||||||
|
|
||||||
This builds a test-root-topology from any number of running test-supernode-# Docker containers. This can then be used with the (undocumented) -T (override root topology) option to run test networks under Docker.
|
This builds a test-root-topology from any number of running test-rootserver-# Docker containers. This can then be used with the (undocumented) -T (override root topology) option to run test networks under Docker.
|
||||||
|
|
||||||
Once you have a local Docker test network running you can use iptables rules to simulate a variety of network pathologies, or you can just use it to test any new changes to the protocol or node behavior at some limited scale.
|
Once you have a local Docker test network running you can use iptables rules to simulate a variety of network pathologies, or you can just use it to test any new changes to the protocol or node behavior at some limited scale.
|
||||||
|
|
|
@ -5,18 +5,18 @@ if [ ! -e ../mktopology ]; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo 'Populating supernodes/* with all Docker test-supernode-* container IPs and identities...'
|
echo 'Populating rootservers/* with all Docker test-rootserver-* container IPs and identities...'
|
||||||
|
|
||||||
rm -rf supernodes
|
rm -rf rootservers
|
||||||
mkdir supernodes
|
mkdir rootservers
|
||||||
|
|
||||||
for cid in `docker ps -f 'name=test-supernode-*' -q`; do
|
for cid in `docker ps -f 'name=test-rootserver-*' -q`; do
|
||||||
id=`docker exec $cid cat /var/lib/zerotier-one/identity.secret | cut -d : -f 1-3`
|
id=`docker exec $cid cat /var/lib/zerotier-one/identity.secret | cut -d : -f 1-3`
|
||||||
ztaddr=`echo $id | cut -d : -f 1`
|
ztaddr=`echo $id | cut -d : -f 1`
|
||||||
ip=`docker exec $cid ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p'`
|
ip=`docker exec $cid ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p'`
|
||||||
echo $cid $ztaddr $id $ip
|
echo $cid $ztaddr $id $ip
|
||||||
echo "id=$id" >supernodes/$ztaddr
|
echo "id=$id" >rootservers/$ztaddr
|
||||||
echo "udp=$ip/9993" >>supernodes/$ztaddr
|
echo "udp=$ip/9993" >>rootservers/$ztaddr
|
||||||
done
|
done
|
||||||
|
|
||||||
echo 'Creating test-root-topology...'
|
echo 'Creating test-root-topology...'
|
||||||
|
|
|
@ -211,9 +211,9 @@ static void _jsonAppend(unsigned int depth,std::string &buf,const ZT1_Peer *peer
|
||||||
|
|
||||||
const char *prole = "";
|
const char *prole = "";
|
||||||
switch(peer->role) {
|
switch(peer->role) {
|
||||||
case ZT1_PEER_ROLE_LEAF: prole = "LEAF"; break;
|
case ZT1_PEER_ROLE_LEAF: prole = "LEAF"; break;
|
||||||
case ZT1_PEER_ROLE_HUB: prole = "HUB"; break;
|
case ZT1_PEER_ROLE_RELAY: prole = "RELAY"; break;
|
||||||
case ZT1_PEER_ROLE_SUPERNODE: prole = "SUPERNODE"; break;
|
case ZT1_PEER_ROLE_ROOT: prole = "ROOT"; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Utils::snprintf(json,sizeof(json),
|
Utils::snprintf(json,sizeof(json),
|
||||||
|
@ -454,7 +454,7 @@ unsigned int ControlPlane::handleRequest(
|
||||||
} else {
|
} else {
|
||||||
#ifdef ZT_ENABLE_NETWORK_CONTROLLER
|
#ifdef ZT_ENABLE_NETWORK_CONTROLLER
|
||||||
if (_controller)
|
if (_controller)
|
||||||
_controller->handleControlPlaneHttpGET(std::vector<std::string>(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType);
|
scode = _controller->handleControlPlaneHttpGET(std::vector<std::string>(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType);
|
||||||
else scode = 404;
|
else scode = 404;
|
||||||
#else
|
#else
|
||||||
scode = 404;
|
scode = 404;
|
||||||
|
@ -490,7 +490,7 @@ unsigned int ControlPlane::handleRequest(
|
||||||
} else {
|
} else {
|
||||||
#ifdef ZT_ENABLE_NETWORK_CONTROLLER
|
#ifdef ZT_ENABLE_NETWORK_CONTROLLER
|
||||||
if (_controller)
|
if (_controller)
|
||||||
_controller->handleControlPlaneHttpPOST(std::vector<std::string>(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType);
|
scode = _controller->handleControlPlaneHttpPOST(std::vector<std::string>(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType);
|
||||||
else scode = 404;
|
else scode = 404;
|
||||||
#else
|
#else
|
||||||
scode = 404;
|
scode = 404;
|
||||||
|
@ -525,7 +525,7 @@ unsigned int ControlPlane::handleRequest(
|
||||||
} else {
|
} else {
|
||||||
#ifdef ZT_ENABLE_NETWORK_CONTROLLER
|
#ifdef ZT_ENABLE_NETWORK_CONTROLLER
|
||||||
if (_controller)
|
if (_controller)
|
||||||
_controller->handleControlPlaneHttpDELETE(std::vector<std::string>(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType);
|
scode = _controller->handleControlPlaneHttpDELETE(std::vector<std::string>(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType);
|
||||||
else scode = 404;
|
else scode = 404;
|
||||||
#else
|
#else
|
||||||
scode = 404;
|
scode = 404;
|
||||||
|
|
|
@ -106,7 +106,7 @@ Getting /peer returns an array of peer objects for all current peers. See below
|
||||||
<tr><td>versionRev</td><td>integer</td><td>Revision of remote if known</td><td>no</td></tr>
|
<tr><td>versionRev</td><td>integer</td><td>Revision of remote if known</td><td>no</td></tr>
|
||||||
<tr><td>version</td><td>string</td><td>Version in major.minor.rev format</td><td>no</td></tr>
|
<tr><td>version</td><td>string</td><td>Version in major.minor.rev format</td><td>no</td></tr>
|
||||||
<tr><td>latency</td><td>integer</td><td>Latency in milliseconds if known</td><td>no</td></tr>
|
<tr><td>latency</td><td>integer</td><td>Latency in milliseconds if known</td><td>no</td></tr>
|
||||||
<tr><td>role</td><td>string</td><td>LEAF, HUB, or SUPERNODE</td><td>no</td></tr>
|
<tr><td>role</td><td>string</td><td>LEAF, HUB, or ROOTSERVER</td><td>no</td></tr>
|
||||||
<tr><td>paths</td><td>[object]</td><td>Array of path objects (see below)</td><td>no</td></tr>
|
<tr><td>paths</td><td>[object]</td><td>Array of path objects (see below)</td><td>no</td></tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
@ -184,7 +184,7 @@ Relays, IP assignment pools, and rules are edited via direct POSTs to the networ
|
||||||
|
|
||||||
**Relay object format:**
|
**Relay object format:**
|
||||||
|
|
||||||
Relay objects define network-specific preferred relay nodes. Traffic to peers on this network will preferentially use these relays if they are available, and otherwise will fall back to the global supernode infrastructure.
|
Relay objects define network-specific preferred relay nodes. Traffic to peers on this network will preferentially use these relays if they are available, and otherwise will fall back to the global rootserver infrastructure.
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
<tr><td><b>Field</b></td><td><b>Type</b></td><td><b>Description</b></td></tr>
|
<tr><td><b>Field</b></td><td><b>Type</b></td><td><b>Description</b></td></tr>
|
||||||
|
@ -204,7 +204,7 @@ Relay objects define network-specific preferred relay nodes. Traffic to peers on
|
||||||
|
|
||||||
* **Note**: at the moment, <u>only rules specifying allowed Ethernet types are used</u>. The database supports a richer rule set, but this is not implemented yet in the client. <u>Other types of rules will have no effect</u> (yet).
|
* **Note**: at the moment, <u>only rules specifying allowed Ethernet types are used</u>. The database supports a richer rule set, but this is not implemented yet in the client. <u>Other types of rules will have no effect</u> (yet).
|
||||||
|
|
||||||
Rules are matched in order of ruleId. If no rules match, the default action is 'drop'. To allow all traffic, create a single rule with all *null* fields and an action of 'accept'.
|
Rules are matched in order of ruleNo. If no rules match, the default action is 'drop'. To allow all traffic, create a single rule with all *null* fields and an action of 'accept'.
|
||||||
|
|
||||||
Rule object fields can be *null*, in which case they are omitted from the object. A null field indicates "no match on this criteria."
|
Rule object fields can be *null*, in which case they are omitted from the object. A null field indicates "no match on this criteria."
|
||||||
|
|
||||||
|
@ -212,7 +212,7 @@ IP related fields apply only to Ethernet frames of type IPv4 or IPV6. Otherwise
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
<tr><td><b>Field</b></td><td><b>Type</b></td><td><b>Description</b></td></tr>
|
<tr><td><b>Field</b></td><td><b>Type</b></td><td><b>Description</b></td></tr>
|
||||||
<tr><td>ruleId</td><td>integer</td><td>User-defined rule ID and sort order</td></tr>
|
<tr><td>ruleNo</td><td>integer</td><td>User-defined rule ID and sort order</td></tr>
|
||||||
<tr><td>nodeId</td><td>string</td><td>10-digit hex ZeroTier address of node (a.k.a. "port on switch")</td></tr>
|
<tr><td>nodeId</td><td>string</td><td>10-digit hex ZeroTier address of node (a.k.a. "port on switch")</td></tr>
|
||||||
<tr><td>vlanId</td><td>integer</td><td>Ethernet VLAN ID</td></tr>
|
<tr><td>vlanId</td><td>integer</td><td>Ethernet VLAN ID</td></tr>
|
||||||
<tr><td>vlanPcp</td><td>integer</td><td>Ethernet VLAN priority code point (PCP) ID</td></tr>
|
<tr><td>vlanPcp</td><td>integer</td><td>Ethernet VLAN priority code point (PCP) ID</td></tr>
|
||||||
|
|
|
@ -85,7 +85,7 @@ using namespace ZeroTier;
|
||||||
* in which every encapsulated ZT packet is prepended by an IP address where
|
* in which every encapsulated ZT packet is prepended by an IP address where
|
||||||
* it should be forwarded (or where it came from for replies). This causes
|
* it should be forwarded (or where it came from for replies). This causes
|
||||||
* this proxy to act as a remote UDP socket similar to a socks proxy, which
|
* this proxy to act as a remote UDP socket similar to a socks proxy, which
|
||||||
* will allow us to move this function off the supernodes and onto dedicated
|
* will allow us to move this function off the rootservers and onto dedicated
|
||||||
* proxy nodes.
|
* proxy nodes.
|
||||||
*
|
*
|
||||||
* Older ZT clients that do not send this message get their packets relayed
|
* Older ZT clients that do not send this message get their packets relayed
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue