diff --git a/AUTHORS.md b/AUTHORS.md new file mode 100644 index 000000000..4900aab54 --- /dev/null +++ b/AUTHORS.md @@ -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...
+ Adam Ierymenko / adam.ierymenko@zerotier.com + + * Java JNI Interface to enable Android application development, and Android app itself (code for that is elsewhere)
+ Grant Limberg / glimberg@gmail.com + +## Contributors + + * A number of fixes and improvements to the new controller, other stuff.
+ Kees Bos / https://github.com/keesbos + + * Debugging and testing, OpenWRT support fixes.
+ Moritz Warning / moritzwarning@web.de + + * Several others made smaller contributions, which GitHub tracks here:
+ https://github.com/zerotier/ZeroTierOne/graphs/contributors + +## 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 (BSD license)
+ http://tuntaposx.sourceforge.net + + * tap-windows and tap-windows6 by the OpenVPN project (GPL)
+ https://github.com/OpenVPN/tap-windows
+ 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)
+ http://cr.yp.to/ diff --git a/AUTHORS.txt b/AUTHORS.txt deleted file mode 100644 index 4ac870f1e..000000000 --- a/AUTHORS.txt +++ /dev/null @@ -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/ diff --git a/README.md b/README.md index f2ae10528..248065047 100644 --- a/README.md +++ b/README.md @@ -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 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 diff --git a/node/BandwidthAccount.hpp b/attic/BandwidthAccount.hpp similarity index 100% rename from node/BandwidthAccount.hpp rename to attic/BandwidthAccount.hpp diff --git a/controller/SqliteNetworkController.cpp b/controller/SqliteNetworkController.cpp index a1905221f..37466e19a 100644 --- a/controller/SqliteNetworkController.cpp +++ b/controller/SqliteNetworkController.cpp @@ -50,6 +50,7 @@ #include "../node/InetAddress.hpp" #include "../node/MAC.hpp" #include "../node/Address.hpp" +#include "../node/Switch.hpp" #include "../osdep/OSUtils.hpp" // 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 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 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 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) @@ -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,"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 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.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.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 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 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,"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,"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,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,"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) @@ -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 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,"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 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)); sqlite3_close(_db); @@ -199,7 +204,6 @@ SqliteNetworkController::~SqliteNetworkController() sqlite3_finalize(_sUpdateNode); sqlite3_finalize(_sUpdateNode2); sqlite3_finalize(_sGetEtherTypesFromRuleTable); - sqlite3_finalize(_sGetMulticastRates); sqlite3_finalize(_sGetActiveBridges); sqlite3_finalize(_sGetIpAssignmentsForNode); sqlite3_finalize(_sGetIpAssignmentPools); @@ -222,7 +226,13 @@ SqliteNetworkController::~SqliteNetworkController() sqlite3_finalize(_sDeleteIpAssignmentPoolsForNetwork); sqlite3_finalize(_sDeleteRulesForNetwork); 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); } } @@ -336,7 +346,7 @@ NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(co sqlite3_reset(_sCreateMember); sqlite3_bind_text(_sCreateMember,1,network.id,16,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) { netconf["error"] = "unable to create new member record"; return NetworkController::NETCONF_QUERY_INTERNAL_SERVER_ERROR; @@ -379,6 +389,14 @@ NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(co if ((et >= 0)&&(et <= 0xffff)) 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::unique(allowedEtherTypes.begin(),allowedEtherTypes.end()); std::string allowedEtherTypesCsv; @@ -392,26 +410,10 @@ NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(co netconf[ZT_NETWORKCONFIG_DICT_KEY_ALLOWED_ETHERNET_TYPES] = allowedEtherTypesCsv; } - { - std::string multicastRates; - sqlite3_reset(_sGetMulticastRates); - sqlite3_bind_text(_sGetMulticastRates,1,network.id,16,SQLITE_STATIC); - 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; - } + 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; } + { + 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"))) { std::string v4s; @@ -467,7 +515,7 @@ NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(co int ipNetmaskBits = sqlite3_column_int(_sGetIpAssignmentsForNode,1); if ((ip)&&(sqlite3_column_bytes(_sGetIpAssignmentsForNode,0) >= 4)&&(ipNetmaskBits > 0)&&(ipNetmaskBits <= 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()) v4s.push_back(','); v4s.append(tmp); @@ -628,29 +676,27 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST( if (!strcmp(j->u.object.values[k].name,"authorized")) { if (j->u.object.values[k].value->type == json_boolean) { - sqlite3_stmt *stmt = (sqlite3_stmt *)0; - if (sqlite3_prepare_v2(_db,"UPDATE Member SET authorized = ? WHERE rowid = ?",-1,&stmt,(const char **)0) == SQLITE_OK) - sqlite3_bind_int(stmt,1,(j->u.object.values[k].value->u.boolean == 0) ? 0 : 1); - sqlite3_bind_int64(stmt,2,memberRowId); - sqlite3_step(stmt); - sqlite3_finalize(stmt); + sqlite3_reset(_sUpdateMemberAuthorized); + sqlite3_bind_int(_sUpdateMemberAuthorized,1,(j->u.object.values[k].value->u.boolean == 0) ? 0 : 1); + sqlite3_bind_int64(_sUpdateMemberAuthorized,2,memberRowId); + if (sqlite3_step(_sUpdateMemberAuthorized) != SQLITE_DONE) + return 500; } } else if (!strcmp(j->u.object.values[k].name,"activeBridge")) { if (j->u.object.values[k].value->type == json_boolean) { - sqlite3_stmt *stmt = (sqlite3_stmt *)0; - if (sqlite3_prepare_v2(_db,"UPDATE Member SET activeBridge = ? WHERE rowid = ?",-1,&stmt,(const char **)0) == SQLITE_OK) { - sqlite3_bind_int(stmt,1,(j->u.object.values[k].value->u.boolean == 0) ? 0 : 1); - sqlite3_bind_int64(stmt,2,memberRowId); - sqlite3_step(stmt); - sqlite3_finalize(stmt); - } + sqlite3_reset(_sUpdateMemberActiveBridge); + sqlite3_bind_int(_sUpdateMemberActiveBridge,1,(j->u.object.values[k].value->u.boolean == 0) ? 0 : 1); + sqlite3_bind_int64(_sUpdateMemberActiveBridge,2,memberRowId); + if (sqlite3_step(_sUpdateMemberActiveBridge) != SQLITE_DONE) + return 500; } } else if (!strcmp(j->u.object.values[k].name,"ipAssignments")) { if (j->u.object.values[k].value->type == json_array) { sqlite3_reset(_sDeleteIpAllocations); sqlite3_bind_text(_sDeleteIpAllocations,1,nwids,16,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;kku.object.values[k].value->u.array.length;++kk) { json_value *ipalloc = j->u.object.values[k].value->u.array.values[kk]; 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_int(_sAllocateIp,4,(int)a.netmaskBits()); 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 { + std::vector path_copy(path); if (!networkExists) { if (path[1].substr(10) == "______") { @@ -734,6 +782,7 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST( sqlite3_bind_int64(_sCreateNetwork,3,(long long)OSUtils::now()); if (sqlite3_step(_sCreateNetwork) != SQLITE_DONE) return 500; + path_copy[1].assign(nwids); } json_value *j = json_parse(body.c_str(),body.length()); @@ -808,6 +857,31 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST( 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;kku.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")) { if (j->u.object.values[k].value->type == json_array) { std::set pools; @@ -855,7 +929,7 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST( json_value *rj = j->u.object.values[k].value->u.array.values[kk]; if ((rj)&&(rj->type == json_object)) { struct { // NULL pointers indicate missing or NULL -- wildcards - const json_int_t *ruleId; + const json_int_t *ruleNo; const char *nodeId; const json_int_t *vlanId; const json_int_t *vlanPcp; @@ -875,8 +949,8 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST( memset(&rule,0,sizeof(rule)); for(unsigned int rk=0;rku.object.length;++rk) { - if ((!strcmp(rj->u.object.values[rk].name,"ruleId"))&&(rj->u.object.values[rk].value->type == json_integer)) - rule.ruleId = &(rj->u.object.values[rk].value->u.integer); + if ((!strcmp(rj->u.object.values[rk].name,"ruleNo"))&&(rj->u.object.values[rk].value->type == json_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)) 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)) @@ -909,11 +983,11 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST( 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]; sqlite3_reset(_sCreateRule); 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 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_step(_sSetNetworkRevision); - return _doCPGet(path,urlArgs,headers,body,responseBody,responseContentType); + return _doCPGet(path_copy,urlArgs,headers,body,responseBody,responseContentType); } } // else 404 @@ -993,6 +1067,11 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpDELETE( char nwids[24]; 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() == 4)&&(path[2] == "member")&&(path[3].length() == 10)) { @@ -1000,6 +1079,12 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpDELETE( char addrs[24]; 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_bind_text(_sDeleteIpAllocations,1,nwids,16,SQLITE_STATIC); sqlite3_bind_text(_sDeleteIpAllocations,2,addrs,10,SQLITE_STATIC); @@ -1016,10 +1101,9 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpDELETE( } else { - sqlite3_reset(_sDeleteNetworkAndRelated); - for(int i=1;i<=7;++i) - sqlite3_bind_text(_sDeleteNetworkAndRelated,i,nwids,16,SQLITE_STATIC); - return ((sqlite3_step(_sDeleteNetworkAndRelated) == SQLITE_DONE) ? 200 : 500); + sqlite3_reset(_sDeleteNetwork); + sqlite3_bind_text(_sDeleteNetwork,1,nwids,16,SQLITE_STATIC); + return ((sqlite3_step(_sDeleteNetwork) == SQLITE_DONE) ? 200 : 500); } } // else 404 @@ -1082,8 +1166,15 @@ unsigned int SqliteNetworkController::_doCPGet( sqlite3_bind_text(_sGetIpAssignmentsForNode2,1,nwids,16,SQLITE_STATIC); sqlite3_bind_text(_sGetIpAssignmentsForNode2,2,addrs,10,SQLITE_STATIC); bool firstIp = true; - while (sqlite3_step(_sGetIpAssignmentPools2) == 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)); + while (sqlite3_step(_sGetIpAssignmentsForNode2) == SQLITE_ROW) { + 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 ? "\"" : ",\""); firstIp = false; 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("\"}"); } + 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\": ["); sqlite3_reset(_sGetIpAssignmentPools2); @@ -1223,7 +1357,7 @@ unsigned int SqliteNetworkController::_doCPGet( bool firstRule = true; while (sqlite3_step(_sListRules) == SQLITE_ROW) { 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); 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)); diff --git a/controller/SqliteNetworkController.hpp b/controller/SqliteNetworkController.hpp index 5c92cc0b1..9cdbc4040 100644 --- a/controller/SqliteNetworkController.hpp +++ b/controller/SqliteNetworkController.hpp @@ -99,7 +99,6 @@ private: sqlite3_stmt *_sUpdateNode; sqlite3_stmt *_sUpdateNode2; sqlite3_stmt *_sGetEtherTypesFromRuleTable; - sqlite3_stmt *_sGetMulticastRates; sqlite3_stmt *_sGetActiveBridges; sqlite3_stmt *_sGetIpAssignmentsForNode; sqlite3_stmt *_sGetIpAssignmentPools; @@ -122,8 +121,13 @@ private: sqlite3_stmt *_sDeleteIpAssignmentPoolsForNetwork; sqlite3_stmt *_sDeleteRulesForNetwork; sqlite3_stmt *_sCreateIpAssignmentPool; + sqlite3_stmt *_sUpdateMemberAuthorized; + sqlite3_stmt *_sUpdateMemberActiveBridge; sqlite3_stmt *_sDeleteMember; - sqlite3_stmt *_sDeleteNetworkAndRelated; + sqlite3_stmt *_sDeleteNetwork; + sqlite3_stmt *_sGetGateways; + sqlite3_stmt *_sDeleteGateways; + sqlite3_stmt *_sCreateGateway; Mutex _lock; }; diff --git a/controller/schema.sql b/controller/schema.sql index b5646ee90..d2261b2af 100644 --- a/controller/schema.sql +++ b/controller/schema.sql @@ -3,53 +3,6 @@ CREATE TABLE Config ( 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 ( id char(16) PRIMARY KEY NOT NULL, name varchar(128) NOT NULL, @@ -63,16 +16,6 @@ CREATE TABLE Network ( 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 ( id char(10) PRIMARY KEY NOT NULL, identity varchar(4096) NOT NULL, @@ -81,10 +24,59 @@ CREATE TABLE Node ( 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 ( - networkId char(16) NOT NULL, - ruleId integer NOT NULL, - nodeId char(10), + networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE, + ruleNo integer NOT NULL, + nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE, vlanId integer, vlanPcp integer, etherType integer, @@ -101,4 +93,4 @@ CREATE TABLE Rule ( "action" varchar(4096) NOT NULL DEFAULT('accept') ); -CREATE INDEX Rule_networkId ON Rule (networkId); \ No newline at end of file +CREATE UNIQUE INDEX Rule_networkId_ruleNo ON Rule (networkId, ruleNo); diff --git a/controller/schema.sql.c b/controller/schema.sql.c index 1384b9008..1157facc5 100644 --- a/controller/schema.sql.c +++ b/controller/schema.sql.c @@ -4,53 +4,6 @@ " v varchar(1024) NOT NULL\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"\ " id char(16) PRIMARY KEY NOT NULL,\n"\ " name varchar(128) NOT NULL,\n"\ @@ -64,16 +17,6 @@ " revision integer NOT NULL DEFAULT(1)\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"\ " id char(10) PRIMARY KEY NOT NULL,\n"\ " identity varchar(4096) NOT NULL,\n"\ @@ -82,10 +25,59 @@ " firstSeen integer NOT NULL DEFAULT(0)\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"\ -" networkId char(16) NOT NULL,\n"\ -" ruleId integer NOT NULL,\n"\ -" nodeId char(10),\n"\ +" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\ +" ruleNo integer NOT NULL,\n"\ +" nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE,\n"\ " vlanId integer,\n"\ " vlanPcp integer,\n"\ " etherType integer,\n"\ @@ -102,5 +94,5 @@ " \"action\" varchar(4096) NOT NULL DEFAULT('accept')\n"\ ");\n"\ "\n"\ -"CREATE INDEX Rule_networkId ON Rule (networkId);\n"\ +"CREATE UNIQUE INDEX Rule_networkId_ruleNo ON Rule (networkId, ruleNo);\n"\ "" diff --git a/ext/installfiles/linux/buildinstaller.sh b/ext/installfiles/linux/buildinstaller.sh index 496ba32ce..4f661b8d5 100755 --- a/ext/installfiles/linux/buildinstaller.sh +++ b/ext/installfiles/linux/buildinstaller.sh @@ -49,9 +49,12 @@ case "$system" in 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 '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' 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' diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index 9b82c8d6f..b6ff69abe 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -251,7 +251,7 @@ enum ZT1_Event /** * 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 * software update check. * @@ -559,8 +559,8 @@ typedef struct */ enum ZT1_PeerRole { ZT1_PEER_ROLE_LEAF = 0, // ordinary node - ZT1_PEER_ROLE_HUB = 1, // locally federated hub - ZT1_PEER_ROLE_SUPERNODE = 2 // planetary supernode + ZT1_PEER_ROLE_RELAY = 1, // relay node + ZT1_PEER_ROLE_ROOT = 2 // root server }; /** diff --git a/java/jni/ZT1_jniutils.cpp b/java/jni/ZT1_jniutils.cpp index e6404e87e..8779c3c35 100644 --- a/java/jni/ZT1_jniutils.cpp +++ b/java/jni/ZT1_jniutils.cpp @@ -174,8 +174,8 @@ jobject createPeerRole(JNIEnv *env, ZT1_PeerRole role) case ZT1_PEER_ROLE_HUB: fieldName = "PEER_ROLE_HUB"; break; - case ZT1_PEER_ROLE_SUPERNODE: - fieldName = "PEER_ROLE_SUPERNODE"; + case ZT1_PEER_ROLE_ROOTSERVER: + fieldName = "PEER_ROLE_ROOTSERVER"; break; } diff --git a/java/src/com/zerotier/sdk/Event.java b/java/src/com/zerotier/sdk/Event.java index d315990b1..436b1b226 100644 --- a/java/src/com/zerotier/sdk/Event.java +++ b/java/src/com/zerotier/sdk/Event.java @@ -90,7 +90,7 @@ public enum Event { /** * 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 * software update check.

* diff --git a/java/src/com/zerotier/sdk/PeerRole.java b/java/src/com/zerotier/sdk/PeerRole.java index 56c3ac0c8..7a5156e1b 100644 --- a/java/src/com/zerotier/sdk/PeerRole.java +++ b/java/src/com/zerotier/sdk/PeerRole.java @@ -39,7 +39,7 @@ public enum PeerRole { PEER_ROLE_HUB, /** - * planetary supernode + * planetary rootserver */ - PEER_ROLE_SUPERNODE + PEER_ROLE_ROOTSERVER } \ No newline at end of file diff --git a/js/zt1-api-client/constrain-types.js b/js/zt1-api-client/constrain-types.js deleted file mode 100644 index 5b1137d59..000000000 --- a/js/zt1-api-client/constrain-types.js +++ /dev/null @@ -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 case Packet::ERROR_OBJ_NOT_FOUND: 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)); } else if (inReVerb == Packet::VERB_NETWORK_CONFIG_REQUEST) { SharedPtr network(RR->node->network(at(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD))); @@ -128,7 +128,7 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,const SharedPtr break; 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); break; @@ -268,7 +268,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR) peer->setRemoteVersion(protoVersion,vMajor,vMinor,vRevision); bool trusted = false; - if (RR->topology->isSupernode(id.address())) { + if (RR->topology->isRoot(id)) { RR->node->postNewerVersionIfNewer(vMajor,vMinor,vRevision); trusted = true; } @@ -353,7 +353,7 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr &p peer->setRemoteVersion(vProto,vMajor,vMinor,vRevision); bool trusted = false; - if (RR->topology->isSupernode(peer->address())) { + if (RR->topology->isRoot(peer->identity())) { RR->node->postNewerVersionIfNewer(vMajor,vMinor,vRevision); trusted = true; } @@ -362,10 +362,10 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr &p } break; case Packet::VERB_WHOIS: { - // Right now only supernodes are allowed to send OK(WHOIS) to prevent - // poisoning attacks. Further decentralization will require some other - // kind of trust mechanism. - if (RR->topology->isSupernode(peer->address())) { + /* Right now only root servers are allowed to send OK(WHOIS) to prevent + * poisoning attacks. Further decentralization will require some other + * kind of trust mechanism. */ + if (RR->topology->isRoot(peer->identity())) { const Identity id(*this,ZT_PROTO_VERB_WHOIS__OK__IDX_IDENTITY); if (id.locallyValidate()) RR->sw->doAnythingWaitingForPeer(RR->topology->addPeer(SharedPtr(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(netconfStr.data(),(unsigned int)netconfStr.length()); outp.compress(); + outp.armor(peer->key(),true); 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()); } else { diff --git a/node/InetAddress.hpp b/node/InetAddress.hpp index 5b7251745..16e3f4d52 100644 --- a/node/InetAddress.hpp +++ b/node/InetAddress.hpp @@ -265,6 +265,16 @@ struct InetAddress : public sockaddr_storage */ 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 */ diff --git a/node/Multicaster.cpp b/node/Multicaster.cpp index 7da2b14c3..8a15bac13 100644 --- a/node/Multicaster.cpp +++ b/node/Multicaster.cpp @@ -216,7 +216,7 @@ void Multicaster::send( if ((now - gs.lastExplicitGather) >= ZT_MULTICAST_EXPLICIT_GATHER_DELAY) { gs.lastExplicitGather = now; - SharedPtr sn(RR->topology->getBestSupernode()); + SharedPtr sn(RR->topology->getBestRoot()); if (sn) { 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 if (indexes != idxbuf) 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 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) { Mutex::Lock _l(_groups_m); for(std::map< std::pair,MulticastGroupStatus >::iterator mm(_groups.begin());mm!=_groups.end();) { - for(std::list::iterator tx(mm->second.txQueue.begin());tx!=mm->second.txQueue.end();) { - if ((tx->expired(now))||(tx->atLimit())) - mm->second.txQueue.erase(tx++); - else ++tx; + for(std::vector::iterator tx(mm->second.txQueue.begin());tx!=mm->second.txQueue.end();) { + if ((tx->expired(now))||(tx->atLimit())) { + // erase element (replace by last) + *tx = mm->second.txQueue.back(); + mm->second.txQueue.pop_back(); + } else ++tx; } 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)")); - for(std::list::iterator tx(gs.txQueue.begin());tx!=gs.txQueue.end();) { + for(std::vector::iterator tx(gs.txQueue.begin());tx!=gs.txQueue.end();) { if (tx->atLimit()) { - gs.txQueue.erase(tx++); + // erase element (replace by last) + *tx = gs.txQueue.back(); + gs.txQueue.pop_back(); } else { tx->sendIfNew(RR,member); - if (tx->atLimit()) - gs.txQueue.erase(tx++); - else ++tx; + if (tx->atLimit()) { + // erase element (replace by last) + *tx = gs.txQueue.back(); + gs.txQueue.pop_back(); + } else ++tx; } } } diff --git a/node/Multicaster.hpp b/node/Multicaster.hpp index c6c93b1ff..281222b84 100644 --- a/node/Multicaster.hpp +++ b/node/Multicaster.hpp @@ -70,7 +70,7 @@ private: MulticastGroupStatus() : lastExplicitGather(0) {} uint64_t lastExplicitGather; - std::list txQueue; // pending outbound multicasts + std::vector txQueue; // pending outbound multicasts std::vector members; // members of this group }; diff --git a/node/Network.cpp b/node/Network.cpp index e513f43f9..c072e9785 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -286,18 +286,28 @@ void Network::addMembershipCertificate(const CertificateOfMembership &cert,bool return; } - SharedPtr 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) { - // 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; - } + SharedPtr signer(RR->topology->getPeer(cert.signedBy())); - 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; + if (!signer) { + // 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())) { + 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) { Mutex::Lock _l(_lock); @@ -518,13 +514,13 @@ public: RR(renv), _now(renv->node->now()), _network(nw), - _supernodeAddresses(renv->topology->supernodeAddresses()), + _rootAddresses(renv->topology->rootAddresses()), _allMulticastGroups(nw->_allMulticastGroups()) {} inline void operator()(Topology &t,const SharedPtr &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); for(std::vector::iterator mg(_allMulticastGroups.begin());mg!=_allMulticastGroups.end();++mg) { @@ -551,7 +547,7 @@ private: const RuntimeEnvironment *RR; uint64_t _now; Network *_network; - std::vector
_supernodeAddresses; + std::vector
_rootAddresses; std::vector _allMulticastGroups; }; diff --git a/node/Network.hpp b/node/Network.hpp index 7976d9018..daa4554e6 100644 --- a/node/Network.hpp +++ b/node/Network.hpp @@ -47,7 +47,6 @@ #include "MulticastGroup.hpp" #include "MAC.hpp" #include "Dictionary.hpp" -#include "BandwidthAccount.hpp" #include "Multicaster.hpp" #include "NetworkConfig.hpp" #include "CertificateOfMembership.hpp" @@ -237,15 +236,6 @@ public: _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 * @@ -370,7 +360,6 @@ private: 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,BandwidthAccount > _multicastRateAccounts; std::map _remoteBridgeRoutes; // remote addresses where given MACs are reachable diff --git a/node/NetworkConfig.cpp b/node/NetworkConfig.cpp index 4b9620a6c..8d682947f 100644 --- a/node/NetworkConfig.cpp +++ b/node/NetworkConfig.cpp @@ -32,10 +32,6 @@ 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::createTestNetworkConfig(const Address &self) { SharedPtr nc(new NetworkConfig()); @@ -85,18 +81,6 @@ std::vector NetworkConfig::allowedEtherTypes() const return ets; } -const NetworkConfig::MulticastRate &NetworkConfig::multicastRate(const MulticastGroup &mg) const - throw() -{ - std::map::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) { static const std::string zero("0"); @@ -163,6 +147,13 @@ void NetworkConfig::_fromDictionary(const Dictionary &d) std::sort(_staticIps.begin(),_staticIps.end()); std::unique(_staticIps.begin(),_staticIps.end()); + std::vector gatewaysSplit(Utils::split(d.get(ZT_NETWORKCONFIG_DICT_KEY_GATEWAYS,"").c_str(),",","","")); + for(std::vector::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 activeBridgesSplit(Utils::split(d.get(ZT_NETWORKCONFIG_DICT_KEY_ACTIVE_BRIDGES,"").c_str(),",","","")); for(std::vector::const_iterator a(activeBridgesSplit.begin());a!=activeBridgesSplit.end();++a) { 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::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 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 relaysSplit(Utils::split(d.get(ZT_NETWORKCONFIG_DICT_KEY_RELAYS,"").c_str(),",","","")); for(std::vector::const_iterator r(relaysSplit.begin());r!=relaysSplit.end();++r) { 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 (_description != nc._description) return false; if (_staticIps != nc._staticIps) return false; + if (_gateways != nc._gateways) return false; if (_activeBridges != nc._activeBridges) return false; - if (_multicastRates.size() == nc._multicastRates.size()) { - // 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::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 (_relays != nc._relays) return false; if (_com != nc._com) return false; return true; } diff --git a/node/NetworkConfig.hpp b/node/NetworkConfig.hpp index 89d1aec50..75395fd53 100644 --- a/node/NetworkConfig.hpp +++ b/node/NetworkConfig.hpp @@ -49,24 +49,58 @@ namespace ZeroTier { // These dictionary keys are short so they don't take up much room in // netconf response packets. + +// integer(hex)[,integer(hex),...] #define ZT_NETWORKCONFIG_DICT_KEY_ALLOWED_ETHERNET_TYPES "et" + +// network ID #define ZT_NETWORKCONFIG_DICT_KEY_NETWORK_ID "nwid" + +// integer(hex) #define ZT_NETWORKCONFIG_DICT_KEY_TIMESTAMP "ts" + +// integer(hex) #define ZT_NETWORKCONFIG_DICT_KEY_REVISION "r" + +// address of member #define ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO "id" + +// integer(hex) #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" + +// text #define ZT_NETWORKCONFIG_DICT_KEY_NAME "n" + +// text #define ZT_NETWORKCONFIG_DICT_KEY_DESC "d" + +// IP/bits[,IP/bits,...] #define ZT_NETWORKCONFIG_DICT_KEY_IPV4_STATIC "v4s" + +// IP/bits[,IP/bits,...] #define ZT_NETWORKCONFIG_DICT_KEY_IPV6_STATIC "v6s" + +// serialized CertificateOfMembership #define ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATE_OF_MEMBERSHIP "com" + +// 0/1 #define ZT_NETWORKCONFIG_DICT_KEY_ENABLE_BROADCAST "eb" + +// 0/1 #define ZT_NETWORKCONFIG_DICT_KEY_ALLOW_PASSIVE_BRIDGING "pb" + +// node[,node,...] #define ZT_NETWORKCONFIG_DICT_KEY_ACTIVE_BRIDGES "ab" + +// node;IP/port[,node;IP/port] #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 * @@ -77,27 +111,6 @@ class NetworkConfig friend class SharedPtr; 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 * @@ -139,13 +152,13 @@ public: inline uint64_t revision() const throw() { return _revision; } inline const Address &issuedTo() const throw() { return _issuedTo; } inline unsigned int multicastLimit() const throw() { return _multicastLimit; } - inline const std::map &multicastRates() const throw() { return _multicastRates; } inline bool allowPassiveBridging() const throw() { return _allowPassiveBridging; } inline bool isPublic() const throw() { return (!_private); } inline bool isPrivate() const throw() { return _private; } inline const std::string &name() const throw() { return _name; } inline const std::string &description() const throw() { return _description; } inline const std::vector &staticIps() const throw() { return _staticIps; } + inline const std::vector &gateways() const throw() { return _gateways; } inline const std::vector
&activeBridges() const throw() { return _activeBridges; } inline const std::vector< std::pair > &relays() const throw() { return _relays; } inline const CertificateOfMembership &com() const throw() { return _com; } @@ -160,13 +173,6 @@ public: 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; inline bool operator!=(const NetworkConfig &nc) const { return (!(*this == nc)); } @@ -188,9 +194,9 @@ private: std::string _name; std::string _description; std::vector _staticIps; + std::vector _gateways; std::vector
_activeBridges; std::vector< std::pair > _relays; - std::map _multicastRates; CertificateOfMembership _com; AtomicCounter __refCount; diff --git a/node/Node.cpp b/node/Node.cpp index 9f195a106..850114341 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -133,7 +133,7 @@ Node::Node( if (!rt.size()) rt.fromString(ZT_DEFAULTS.defaultRootTopology); } - RR->topology->setSupernodes(Dictionary(rt.get("supernodes",""))); + RR->topology->setRootServers(Dictionary(rt.get("rootservers",""))); postEvent(ZT1_EVENT_UP); } @@ -141,7 +141,7 @@ Node::Node( Node::~Node() { Mutex::Lock _l(_networks_m); - _networks.clear(); + _networks.clear(); // ensure that networks are destroyed before shutdown delete RR->sa; delete RR->topology; delete RR->antiRec; @@ -189,7 +189,7 @@ public: RR(renv), _now(now), _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); if (p->lastReceive() > lastReceiveFromUpstream) lastReceiveFromUpstream = p->lastReceive(); @@ -219,7 +219,7 @@ private: const RuntimeEnvironment *RR; uint64_t _now; const std::vector< std::pair > &_relays; - std::vector
_supernodes; + std::vector
_rootAddresses; }; 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 > needConfig; { Mutex::Lock _l(_networks_m); - for(std::map< uint64_t,SharedPtr >::const_iterator n(_networks.begin());n!=_networks.end();++n) { + for(std::vector< std::pair< uint64_t,SharedPtr > >::const_iterator n(_networks.begin());n!=_networks.end();++n) { SharedPtr nc(n->second->config2()); if (((now - n->second->lastConfigUpdate()) >= ZT_NETWORK_AUTOCONF_DELAY)||(!nc)) 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); 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) { Mutex::Lock _l(_networks_m); - SharedPtr &nwe = _networks[nwid]; - if (!nwe) - nwe = SharedPtr(new Network(RR,nwid)); + SharedPtr nw = _network(nwid); + if(!nw) + _networks.push_back(std::pair< uint64_t,SharedPtr >(nwid,SharedPtr(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; } ZT1_ResultCode Node::leave(uint64_t nwid) { + std::vector< std::pair< uint64_t,SharedPtr > > newn; Mutex::Lock _l(_networks_m); - std::map< uint64_t,SharedPtr >::iterator nw(_networks.find(nwid)); - if (nw != _networks.end()) { - nw->second->destroy(); - _networks.erase(nw); + for(std::vector< std::pair< uint64_t,SharedPtr > >::const_iterator n(_networks.begin());n!=_networks.end();++n) { + if (n->first != nwid) + newn.push_back(*n); } + _networks.swap(newn); return ZT1_RESULT_OK; } @@ -384,7 +386,7 @@ ZT1_PeerList *Node::peers() const p->versionRev = -1; } 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 paths(pi->second->paths()); Path *bestPath = pi->second->getBestPath(_now); @@ -406,10 +408,10 @@ ZT1_PeerList *Node::peers() const ZT1_VirtualNetworkConfig *Node::networkConfig(uint64_t nwid) const { Mutex::Lock _l(_networks_m); - std::map< uint64_t,SharedPtr >::const_iterator nw(_networks.find(nwid)); - if (nw != _networks.end()) { + SharedPtr nw = _network(nwid); + if(nw) { ZT1_VirtualNetworkConfig *nc = (ZT1_VirtualNetworkConfig *)::malloc(sizeof(ZT1_VirtualNetworkConfig)); - nw->second->externalConfig(nc); + nw->externalConfig(nc); return nc; } return (ZT1_VirtualNetworkConfig *)0; @@ -426,7 +428,7 @@ ZT1_VirtualNetworkList *Node::networks() const nl->networks = (ZT1_VirtualNetworkConfig *)(buf + sizeof(ZT1_VirtualNetworkList)); nl->networkCount = 0; - for(std::map< uint64_t,SharedPtr >::const_iterator n(_networks.begin());n!=_networks.end();++n) + for(std::vector< std::pair< uint64_t,SharedPtr > >::const_iterator n(_networks.begin());n!=_networks.end();++n) n->second->externalConfig(&(nl->networks[nl->networkCount++])); return nl; diff --git a/node/Node.hpp b/node/Node.hpp index 1d9372e46..2d2898b57 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -155,19 +155,19 @@ public: len); } - inline SharedPtr network(uint64_t nwid) + inline SharedPtr network(uint64_t nwid) const { Mutex::Lock _l(_networks_m); - std::map< uint64_t,SharedPtr >::iterator nw(_networks.find(nwid)); - return ((nw == _networks.end()) ? SharedPtr() : nw->second); + return _network(nwid); } inline std::vector< SharedPtr > allNetworks() const { - Mutex::Lock _l(_networks_m); std::vector< SharedPtr > nw; - for(std::map< uint64_t,SharedPtr >::const_iterator n(_networks.begin());n!=_networks.end();++n) - nw.push_back(n->second); + Mutex::Lock _l(_networks_m); + nw.reserve(_networks.size()); + for(std::vector< std::pair< uint64_t, SharedPtr > >::const_iterator i=_networks.begin();i!=_networks.end();++i) + nw.push_back(i->second); return nw; } @@ -208,6 +208,16 @@ public: #endif private: + inline SharedPtr _network(uint64_t nwid) const + { + // assumes _networks_m is locked + for(std::vector< std::pair< uint64_t, SharedPtr > >::const_iterator i=_networks.begin();i!=_networks.end();++i) { + if (i->first == nwid) + return i->second; + } + return SharedPtr(); + } + RuntimeEnvironment _RR; RuntimeEnvironment *RR; @@ -223,7 +233,7 @@ private: //Dictionary _localConfig; // persisted as local.conf //Mutex _localConfig_m; - std::map< uint64_t,SharedPtr > _networks; + std::vector< std::pair< uint64_t, SharedPtr > > _networks; Mutex _networks_m; Mutex _backgroundTasksLock; diff --git a/node/Packet.cpp b/node/Packet.cpp index a81873ffd..f75d1df08 100644 --- a/node/Packet.cpp +++ b/node/Packet.cpp @@ -51,6 +51,7 @@ const char *Packet::verbString(Verb v) case VERB_MULTICAST_GATHER: return "MULTICAST_GATHER"; case VERB_MULTICAST_FRAME: return "MULTICAST_FRAME"; case VERB_SET_EPHEMERAL_KEY: return "SET_EPHEMERAL_KEY"; + case VERB_CMA: return "CMA"; } return "(unknown)"; } diff --git a/node/Packet.hpp b/node/Packet.hpp index 2dfb75e4b..49201b712 100644 --- a/node/Packet.hpp +++ b/node/Packet.hpp @@ -513,8 +513,8 @@ public: * Destination address types and formats (not all of these are used now): * 0 - None -- no destination address data present * 1 - Ethernet address -- format: <[6] Ethernet MAC> - * 4 - 6-byte IPv4 address -- format: <[4] IP>, <[2] port> - * 6 - 18-byte IPv6 address -- format: <[16] IP>, <[2] port> + * 4 - 6-byte IPv4 UDP address/port -- format: <[4] IP>, <[2] port> + * 6 - 18-byte IPv6 UDP address/port -- format: <[16] IP>, <[2] port> * * OK payload: * <[8] timestamp (echoed from original HELLO)> @@ -626,7 +626,7 @@ public: * [... additional tuples of network/address/adi ...] * * 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. */ @@ -770,6 +770,9 @@ public: VERB_MULTICAST_FRAME = 14, /* 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 of this key set> * [... begin PFS key record ...] @@ -791,6 +794,12 @@ public: * the first record with common symmetric cipher, public key type, * 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): * 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> * <[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 }; /** diff --git a/node/Peer.cpp b/node/Peer.cpp index d788d0063..96caa72cf 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -122,16 +122,16 @@ void Peer::received( /* Announce multicast groups of interest to direct peers if they are * 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))) { _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); const std::vector< SharedPtr > networks(RR->node->allNetworks()); for(std::vector< SharedPtr >::const_iterator n(networks.begin());n!=networks.end();++n) { - if ( (isSupernode) || ((*n)->isAllowed(_id.address())) ) { + if ( (isRoot) || ((*n)->isAllowed(_id.address())) ) { const std::vector mgs((*n)->allMulticastGroups()); for(std::vector::const_iterator mg(mgs.begin());mg!=mgs.end();++mg) { if ((outp.size() + 18) > ZT_UDP_DEFAULT_PAYLOAD_MTU) { diff --git a/node/SelfAwareness.cpp b/node/SelfAwareness.cpp index d7c0e5cc4..9f7c41d7d 100644 --- a/node/SelfAwareness.cpp +++ b/node/SelfAwareness.cpp @@ -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 // they are still considered alive so that we will re-establish direct links. - SharedPtr sn(RR->topology->getBestSupernode()); + SharedPtr sn(RR->topology->getBestRoot()); if (sn) { Path *snp = sn->getBestPath(now); if (snp) { diff --git a/node/Switch.cpp b/node/Switch.cpp index 0aa0b664b..236c1e660 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -145,12 +145,6 @@ void Switch::onLocalEthernet(const SharedPtr &network,const MAC &from,c if (fromBridged) 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); 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 * 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 - * by the nearly-simultaneous RENDEZVOUS kickoff from the supernode, but - * given that supernodes are hosted on cloud providers this can in some + * by the nearly-simultaneous RENDEZVOUS kickoff from the relay, but + * given that relay are hosted on cloud providers this can in some * 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 * 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. SharedPtr relayTo = RR->topology->getPeer(destination); if ((!relayTo)||(!relayTo->send(RR,fragment.data(),fragment.size(),RR->node->now()))) { - // Don't know peer or no direct path -- so relay via supernode - relayTo = RR->topology->getBestSupernode(); + // Don't know peer or no direct path -- so relay via root server + relayTo = RR->topology->getBestRoot(); if (relayTo) 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())))) { unite(source,destination,false); } else { - // Don't know peer or no direct path -- so relay via supernode - relayTo = RR->topology->getBestSupernode(&source,1,true); + // Don't know peer or no direct path -- so relay via root server + relayTo = RR->topology->getBestRoot(&source,1,true); if (relayTo) relayTo->send(RR,packet->data(),packet->size(),RR->node->now()); } @@ -712,13 +706,13 @@ void Switch::_handleBeacon(const InetAddress &fromAddr,const Buffer supernode(RR->topology->getBestSupernode(peersAlreadyConsulted,numPeersAlreadyConsulted,false)); - if (supernode) { - Packet outp(supernode->address(),RR->identity.address(),Packet::VERB_WHOIS); + SharedPtr root(RR->topology->getBestRoot(peersAlreadyConsulted,numPeersAlreadyConsulted,false)); + if (root) { + Packet outp(root->address(),RR->identity.address(),Packet::VERB_WHOIS); addr.appendTo(outp); - outp.armor(supernode->key(),true); - if (supernode->send(RR,outp.data(),outp.size(),RR->node->now())) - return supernode->address(); + outp.armor(root->key(),true); + if (root->send(RR,outp.data(),outp.size(),RR->node->now())) + return root->address(); } return Address(); } @@ -752,7 +746,7 @@ bool Switch::_trySend(const Packet &packet,bool encrypt,uint64_t nwid) } if (!relay) - relay = RR->topology->getBestSupernode(); + relay = RR->topology->getBestRoot(); if (!(relay)||(!(viaPath = relay->getBestPath(now)))) return false; diff --git a/node/Topology.cpp b/node/Topology.cpp index 5fcc2e612..2b1cc31fe 100644 --- a/node/Topology.cpp +++ b/node/Topology.cpp @@ -36,7 +36,7 @@ namespace ZeroTier { Topology::Topology(const RuntimeEnvironment *renv) : RR(renv), - _amSupernode(false) + _amRoot(false) { } @@ -44,16 +44,16 @@ Topology::~Topology() { } -void Topology::setSupernodes(const std::map< Identity,std::vector > &sn) +void Topology::setRootServers(const std::map< Identity,std::vector > &sn) { Mutex::Lock _l(_lock); - if (_supernodes == sn) + if (_roots == sn) return; // no change - _supernodes = sn; - _supernodeAddresses.clear(); - _supernodePeers.clear(); + _roots = sn; + _rootAddresses.clear(); + _rootPeers.clear(); const uint64_t now = RR->node->now(); for(std::map< Identity,std::vector >::const_iterator i(sn.begin());i!=sn.end();++i) { @@ -64,17 +64,17 @@ void Topology::setSupernodes(const std::map< Identity,std::vector > for(std::vector::const_iterator j(i->second.begin());j!=i->second.end();++j) p->addPath(Path(*j,true)); 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 > m; 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) a.push_back(InetAddress(udp)); } 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 Topology::addPeer(const SharedPtr &peer) @@ -141,28 +141,28 @@ SharedPtr Topology::getPeer(const Address &zta) return SharedPtr(); } -SharedPtr Topology::getBestSupernode(const Address *avoid,unsigned int avoidCount,bool strictAvoid) +SharedPtr Topology::getBestRoot(const Address *avoid,unsigned int avoidCount,bool strictAvoid) { - SharedPtr bestSupernode; + SharedPtr bestRoot; const uint64_t now = RR->node->now(); Mutex::Lock _l(_lock); - if (_amSupernode) { - /* If I am a supernode, the "best" supernode is the one whose address + if (_amRoot) { + /* 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 * causes packets searching for a route to pretty much literally * circumnavigate the globe rather than bouncing between just two. */ - if (_supernodeAddresses.size() > 1) { // gotta be one other than me for this to work - std::vector
::const_iterator sna(std::find(_supernodeAddresses.begin(),_supernodeAddresses.end(),RR->identity.address())); - if (sna != _supernodeAddresses.end()) { // sanity check -- _amSupernode should've been false in this case + if (_rootAddresses.size() > 1) { // gotta be one other than me for this to work + std::vector
::const_iterator sna(std::find(_rootAddresses.begin(),_rootAddresses.end(),RR->identity.address())); + if (sna != _rootAddresses.end()) { // sanity check -- _amRoot should've been false in this case for(;;) { - if (++sna == _supernodeAddresses.end()) - sna = _supernodeAddresses.begin(); // wrap around at end + if (++sna == _rootAddresses.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 std::map< Address,SharedPtr >::const_iterator p(_activePeers.find(*sna)); if ((p != _activePeers.end())&&(p->second->hasActiveDirectPath(now))) { - bestSupernode = p->second; + bestRoot = p->second; break; } } @@ -170,80 +170,87 @@ SharedPtr Topology::getBestSupernode(const Address *avoid,unsigned int avo } } } 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. */ - unsigned int l,bestSupernodeLatency = 65536; + unsigned int l,bestLatency = 65536; uint64_t lds,ldr; - // First look for a best supernode by comparing latencies, but exclude - // supernodes that have not responded to direct messages in order to + // First look for a best root by comparing latencies, but exclude + // root servers that have not responded to direct messages in order to // try to exclude any that are dead or unreachable. - for(std::vector< SharedPtr >::const_iterator sn(_supernodePeers.begin());sn!=_supernodePeers.end();) { + for(std::vector< SharedPtr >::const_iterator sn(_rootPeers.begin());sn!=_rootPeers.end();) { // Skip explicitly avoided relays for(unsigned int i=0;iaddress()) - goto keep_searching_for_supernodes; + goto keep_searching_for_roots; } // Skip possibly comatose or unreachable relays lds = (*sn)->lastDirectSend(); ldr = (*sn)->lastDirectReceive(); 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)) { l = (*sn)->latency(); - if (bestSupernode) { - if ((l)&&(l < bestSupernodeLatency)) { - bestSupernodeLatency = l; - bestSupernode = *sn; + if (bestRoot) { + if ((l)&&(l < bestLatency)) { + bestLatency = l; + bestRoot = *sn; } } else { if (l) - bestSupernodeLatency = l; - bestSupernode = *sn; + bestLatency = l; + bestRoot = *sn; } } -keep_searching_for_supernodes: +keep_searching_for_roots: ++sn; } - if (bestSupernode) { - bestSupernode->use(now); - return bestSupernode; + if (bestRoot) { + bestRoot->use(now); + return bestRoot; } else if (strictAvoid) return SharedPtr(); // If we have nothing from above, just pick one without avoidance criteria. - for(std::vector< SharedPtr >::const_iterator sn=_supernodePeers.begin();sn!=_supernodePeers.end();++sn) { + for(std::vector< SharedPtr >::const_iterator sn=_rootPeers.begin();sn!=_rootPeers.end();++sn) { if ((*sn)->hasActiveDirectPath(now)) { unsigned int l = (*sn)->latency(); - if (bestSupernode) { - if ((l)&&(l < bestSupernodeLatency)) { - bestSupernodeLatency = l; - bestSupernode = *sn; + if (bestRoot) { + if ((l)&&(l < bestLatency)) { + bestLatency = l; + bestRoot = *sn; } } else { if (l) - bestSupernodeLatency = l; - bestSupernode = *sn; + bestLatency = l; + bestRoot = *sn; } } } } - if (bestSupernode) - bestSupernode->use(now); - return bestSupernode; + if (bestRoot) + bestRoot->use(now); + 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) { Mutex::Lock _l(_lock); for(std::map< Address,SharedPtr >::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++); } else ++p; } diff --git a/node/Topology.hpp b/node/Topology.hpp index 56a9709fc..c878bcc6e 100644 --- a/node/Topology.hpp +++ b/node/Topology.hpp @@ -59,21 +59,19 @@ public: ~Topology(); /** - * Set up supernodes for this network - * - * @param sn Supernodes for this network + * @param sn Root server identities and addresses */ - void setSupernodes(const std::map< Identity,std::vector > &sn); + void setRootServers(const std::map< Identity,std::vector > &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 * 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 @@ -95,65 +93,52 @@ public: SharedPtr getPeer(const Address &zta); /** - * @return Vector of peers that are supernodes + * @return Vector of peers that are root servers */ - inline std::vector< SharedPtr > supernodePeers() const + inline std::vector< SharedPtr > rootPeers() const { Mutex::Lock _l(_lock); - return _supernodePeers; + return _rootPeers; } /** - * @return Number of supernodes - */ - inline unsigned int numSupernodes() const - { - Mutex::Lock _l(_lock); - return (unsigned int)_supernodePeers.size(); - } - - /** - * Get the current favorite supernode + * Get the current favorite root server * - * @return Supernode with lowest latency or NULL if none + * @return Root server with lowest latency or NULL if none */ - inline SharedPtr getBestSupernode() + inline SharedPtr 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 - * try to avoid the listed supernodes, only using them if no others + * This will get the best root server (lowest latency, etc.) but will + * try to avoid the listed root servers, only using them if no others * are available. * * @param avoid 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 - * @return Supernode or NULL if none + * @param strictAvoid If false, consider avoided root servers anyway if no non-avoid root servers are available + * @return Root server or NULL if none available */ - SharedPtr getBestSupernode(const Address *avoid,unsigned int avoidCount,bool strictAvoid); + SharedPtr getBestRoot(const Address *avoid,unsigned int avoidCount,bool strictAvoid); /** - * @param zta ZeroTier address - * @return True if this is a designated supernode + * @param id Identity to check + * @return True if this is a designated root server */ - inline bool isSupernode(const Address &zta) const - throw() - { - Mutex::Lock _l(_lock); - return (std::find(_supernodeAddresses.begin(),_supernodeAddresses.end(),zta) != _supernodeAddresses.end()); - } + bool isRoot(const Identity &id) const + throw(); /** - * @return Vector of supernode addresses + * @return Vector of root server addresses */ - inline std::vector
supernodeAddresses() const + inline std::vector
rootAddresses() const { Mutex::Lock _l(_lock); - return _supernodeAddresses; + return _rootAddresses; } /** @@ -206,13 +191,13 @@ private: const RuntimeEnvironment *RR; std::map< Address,SharedPtr > _activePeers; - std::map< Identity,std::vector > _supernodes; - std::vector< Address > _supernodeAddresses; - std::vector< SharedPtr > _supernodePeers; + std::map< Identity,std::vector > _roots; + std::vector< Address > _rootAddresses; + std::vector< SharedPtr > _rootPeers; Mutex _lock; - bool _amSupernode; + bool _amRoot; }; } // namespace ZeroTier diff --git a/osdep/Phy.hpp b/osdep/Phy.hpp index 23fd2ee24..ec01625ba 100644 --- a/osdep/Phy.hpp +++ b/osdep/Phy.hpp @@ -123,12 +123,13 @@ private: enum PhySocketType { - ZT_PHY_SOCKET_TCP_OUT_PENDING = 0x00, - ZT_PHY_SOCKET_TCP_OUT_CONNECTED = 0x01, - ZT_PHY_SOCKET_TCP_IN = 0x02, - ZT_PHY_SOCKET_TCP_LISTEN = 0x03, - ZT_PHY_SOCKET_RAW = 0x04, - ZT_PHY_SOCKET_UDP = 0x05 + ZT_PHY_SOCKET_CLOSED = 0x00, // socket is closed, will be removed on next poll() + ZT_PHY_SOCKET_TCP_OUT_PENDING = 0x01, + ZT_PHY_SOCKET_TCP_OUT_CONNECTED = 0x02, + ZT_PHY_SOCKET_TCP_IN = 0x03, + ZT_PHY_SOCKET_TCP_LISTEN = 0x04, + ZT_PHY_SOCKET_RAW = 0x05, + ZT_PHY_SOCKET_UDP = 0x06 }; struct PhySocketImpl @@ -205,8 +206,10 @@ public: ~Phy() { - while (!_socks.empty()) - this->close((PhySocket *)&(_socks.front()),true); + for(typename std::list::const_iterator s(_socks.begin());s!=_socks.end();++s) { + if (s->type != ZT_PHY_SOCKET_CLOSED) + this->close((PhySocket *)&(*s),true); + } ZT_PHY_CLOSE_SOCKET(_whackReceiveSocket); ZT_PHY_CLOSE_SOCKET(_whackSendSocket); } @@ -620,11 +623,7 @@ public: #endif } - bool atEnd = false; - for(typename std::list::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 - + for(typename std::list::iterator s(_socks.begin());s!=_socks.end();) { switch (s->type) { case ZT_PHY_SOCKET_TCP_OUT_PENDING: @@ -724,6 +723,10 @@ public: break; } + + if (s->type == ZT_PHY_SOCKET_CLOSED) + _socks.erase(s++); + else ++s; } } @@ -736,6 +739,8 @@ public: if (!sock) return; PhySocketImpl &sws = *(reinterpret_cast(sock)); + if (sws.type == ZT_PHY_SOCKET_CLOSED) + return; FD_CLR(sws.sock,&_readfds); FD_CLR(sws.sock,&_writefds); @@ -765,21 +770,15 @@ public: 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::iterator s(_socks.begin());s!=_socks.end();++s) { - if (reinterpret_cast(&(*s)) == sock) { - _socks.erase(s); - break; - } - } - - if (oldSock >= _nfds) { + if (sws.sock >= _nfds) { long nfds = (long)_whackSendSocket; if ((long)_whackReceiveSocket > nfds) nfds = (long)_whackReceiveSocket; for(typename std::list::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 = nfds; diff --git a/osdep/WindowsEthernetTap.cpp b/osdep/WindowsEthernetTap.cpp index b373d9e27..d477f2e3d 100644 --- a/osdep/WindowsEthernetTap.cpp +++ b/osdep/WindowsEthernetTap.cpp @@ -92,9 +92,6 @@ static const WindowsEthernetTapEnv WINENV; // Only create or delete devices one at a time static Mutex _systemTapInitLock; -// Incrementing this causes everyone currently open to close and reopen -static volatile int _systemTapResetStatus = 0; - } // anonymous namespace WindowsEthernetTap::WindowsEthernetTap( @@ -268,12 +265,6 @@ WindowsEthernetTap::WindowsEthernetTap( } } 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) { @@ -299,7 +290,6 @@ WindowsEthernetTap::WindowsEthernetTap( 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]; const char *nbtmp1 = _netCfgInstanceId.c_str(); @@ -573,191 +563,199 @@ void WindowsEthernetTap::scanMulticastGroups(std::vector &added, void WindowsEthernetTap::threadMain() throw() { - char tapPath[256]; - OVERLAPPED tapOvlRead,tapOvlWrite; + char tapReadBuf[ZT_IF_MTU + 32]; + char tapPath[128]; HANDLE wait4[3]; - char *tapReadBuf = (char *)0; - - /* 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); - } + OVERLAPPED tapOvlRead,tapOvlWrite; Utils::snprintf(tapPath,sizeof(tapPath),"\\\\.\\Global\\%s.tap",_netCfgInstanceId.c_str()); - int prevTapResetStatus = _systemTapResetStatus; - bool throwOneAway = true; // Restart once on startup, because Windows. - bool powerCycle = true; // If true, "power cycle" the device, because Windows. - while (_run) { - if (powerCycle) { - _disableTapDevice(); - Sleep(500); + + try { + while (_run) { _enableTapDevice(); Sleep(500); - } - _tap = CreateFileA(tapPath,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_SYSTEM|FILE_FLAG_OVERLAPPED,NULL); - if (_tap == INVALID_HANDLE_VALUE) { - fprintf(stderr,"Error opening %s -- retrying.\r\n",tapPath); - powerCycle = true; - 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; + _tap = CreateFileA(tapPath,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_SYSTEM|FILE_FLAG_OVERLAPPED,NULL); + if (_tap == INVALID_HANDLE_VALUE) { + _disableTapDevice(); + _enableTapDevice(); + Sleep(1000); + continue; } - 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; + + { + 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)); + 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 - } - memset(&tapOvlRead,0,sizeof(tapOvlRead)); - tapOvlRead.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); - memset(&tapOvlWrite,0,sizeof(tapOvlWrite)); - tapOvlWrite.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); + memset(&tapOvlRead,0,sizeof(tapOvlRead)); + tapOvlRead.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); + memset(&tapOvlWrite,0,sizeof(tapOvlWrite)); + tapOvlWrite.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); - wait4[0] = _injectSemaphore; - wait4[1] = tapOvlRead.hEvent; - wait4[2] = tapOvlWrite.hEvent; // only included if writeInProgress is true + wait4[0] = _injectSemaphore; + wait4[1] = tapOvlRead.hEvent; + wait4[2] = tapOvlWrite.hEvent; // only included if writeInProgress is true - ReadFile(_tap,tapReadBuf,sizeof(tapReadBuf),NULL,&tapOvlRead); - bool writeInProgress = false; - while (_run) { - if ((prevTapResetStatus != _systemTapResetStatus)||(throwOneAway)) { - powerCycle = throwOneAway; - throwOneAway = false; - 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) + ReadFile(_tap,tapReadBuf,sizeof(tapReadBuf),NULL,&tapOvlRead); + bool writeInProgress = false; + ULONGLONG timeOfLastBorkCheck = GetTickCount64(); + while (_run) { + DWORD waitResult = WaitForMultipleObjectsEx(writeInProgress ? 3 : 2,wait4,FALSE,2500,TRUE); + if (!_run) break; // will also break outer while(_run) - if ((r == WAIT_TIMEOUT)||(r == 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 + // Check for issues with adapter and close/reopen if any are detected. This + // check fixes a while boatload of Windows adapter 'coma' issues after + // sleep/wake and when adapters are added/removed. Basically if the tap + // device is borked, whack it. + { + ULONGLONG tc = GetTickCount64(); + if ((tc - timeOfLastBorkCheck) >= 2500) { + timeOfLastBorkCheck = tc; + MIB_IF_TABLE2 *ift = NULL; + if ((GetIfTable2(&ift) == NO_ERROR)&&(ift)) { + bool isBorked = false; + for(ULONG r=0;rNumEntries;++r) { + if (ift->Table[r].InterfaceLuid.Value == _deviceLuid.Value) { + 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) { - if (HasOverlappedIoCompleted(&tapOvlWrite)) { - writeInProgress = false; - _injectPending_m.lock(); - _injectPending.pop(); - } else continue; // still writing, so skip code below and wait - } else _injectPending_m.lock(); + CancelIo(_tap); - if (!_injectPending.empty()) { - WriteFile(_tap,_injectPending.front().first.data,_injectPending.front().second,NULL,&tapOvlWrite); - writeInProgress = true; - } + CloseHandle(tapOvlRead.hEvent); + CloseHandle(tapOvlWrite.hEvent); + CloseHandle(_tap); + _tap = INVALID_HANDLE_VALUE; - _injectPending_m.unlock(); + // We will restart and re-open the tap unless _run == false } - - 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); + } catch ( ... ) {} // catch unexpected exceptions -- this should not happen but would prevent program crash or other weird issues since threads should not throw } void WindowsEthernetTap::destroyAllPersistentTapDevices(const char *pathToHelpers) diff --git a/osdep/WindowsEthernetTap.hpp b/osdep/WindowsEthernetTap.hpp index 670467633..944b53f33 100644 --- a/osdep/WindowsEthernetTap.hpp +++ b/osdep/WindowsEthernetTap.hpp @@ -98,8 +98,8 @@ private: GUID _deviceGuid; NET_LUID _deviceLuid; - std::string _netCfgInstanceId; // NetCfgInstanceId, a GUID - std::string _deviceInstanceId; // DeviceInstanceID, another kind of "instance ID" + std::string _netCfgInstanceId; + std::string _deviceInstanceId; std::vector _multicastGroups; diff --git a/root-topology/README.md b/root-topology/README.md index 2614d3d9d..c9c3a9083 100644 --- a/root-topology/README.md +++ b/root-topology/README.md @@ -2,9 +2,9 @@ This folder contains the source files to compile the signed network root topolog Keys in the root topology dictionary are: - * **supernodes**: contains another Dictionary mapping supernode address to supernode definition - * **##########**: supernode address, contains supernode definition - * **id**: supernode identity (public) in string-serialized format + * **rootservers**: contains another Dictionary mapping rootserver address to rootserver definition + * **##########**: rootserver address, contains rootserver definition + * **id**: rootserver identity (public) in string-serialized format * **udp**: comma-delimited list of ip/port UDP addresses of node * **tcp**: *DEPRECATED* comma-delimited list of ip/port TCP addresses of node * **desc**: human-readable description (optional) diff --git a/root-topology/ZT_DEFAULT_ROOT_TOPOLOGY.c b/root-topology/ZT_DEFAULT_ROOT_TOPOLOGY.c index 1de95c717..96835e058 100644 --- a/root-topology/ZT_DEFAULT_ROOT_TOPOLOGY.c +++ b/root-topology/ZT_DEFAULT_ROOT_TOPOLOGY.c @@ -1,98 +1,90 @@ static unsigned char ZT_DEFAULT_ROOT_TOPOLOGY[] = { - 0x73, 0x75, 0x70, 0x65, 0x72, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x3d, 0x37, 0x65, 0x31, 0x39, 0x38, - 0x37, 0x36, 0x61, 0x62, 0x61, 0x5c, 0x3d, 0x69, 0x64, 0x5c, 0x5c, 0x5c, 0x3d, 0x37, 0x65, 0x31, - 0x39, 0x38, 0x37, 0x36, 0x61, 0x62, 0x61, 0x3a, 0x30, 0x3a, 0x32, 0x61, 0x36, 0x65, 0x32, 0x62, - 0x32, 0x33, 0x31, 0x38, 0x39, 0x33, 0x30, 0x66, 0x36, 0x30, 0x65, 0x62, 0x30, 0x39, 0x37, 0x66, - 0x37, 0x30, 0x64, 0x30, 0x66, 0x34, 0x62, 0x30, 0x32, 0x38, 0x62, 0x32, 0x63, 0x64, 0x36, 0x64, - 0x33, 0x64, 0x30, 0x63, 0x36, 0x33, 0x63, 0x30, 0x31, 0x34, 0x62, 0x39, 0x30, 0x33, 0x39, 0x66, - 0x66, 0x33, 0x35, 0x33, 0x39, 0x30, 0x65, 0x34, 0x31, 0x31, 0x38, 0x31, 0x66, 0x32, 0x31, 0x36, - 0x66, 0x62, 0x32, 0x65, 0x36, 0x66, 0x61, 0x38, 0x64, 0x39, 0x35, 0x63, 0x31, 0x65, 0x65, 0x39, - 0x36, 0x36, 0x37, 0x31, 0x35, 0x36, 0x34, 0x31, 0x31, 0x39, 0x30, 0x35, 0x63, 0x33, 0x64, 0x63, - 0x63, 0x66, 0x65, 0x61, 0x37, 0x38, 0x64, 0x38, 0x63, 0x36, 0x64, 0x66, 0x61, 0x66, 0x62, 0x61, - 0x36, 0x38, 0x38, 0x31, 0x37, 0x30, 0x62, 0x33, 0x66, 0x61, 0x5c, 0x5c, 0x6e, 0x75, 0x64, 0x70, - 0x5c, 0x5c, 0x5c, 0x3d, 0x31, 0x39, 0x38, 0x2e, 0x31, 0x39, 0x39, 0x2e, 0x39, 0x37, 0x2e, 0x32, - 0x32, 0x30, 0x2f, 0x39, 0x39, 0x39, 0x33, 0x5c, 0x5c, 0x6e, 0x74, 0x63, 0x70, 0x5c, 0x5c, 0x5c, - 0x3d, 0x31, 0x39, 0x38, 0x2e, 0x31, 0x39, 0x39, 0x2e, 0x39, 0x37, 0x2e, 0x32, 0x32, 0x30, 0x2f, - 0x34, 0x34, 0x33, 0x5c, 0x5c, 0x6e, 0x64, 0x65, 0x73, 0x63, 0x5c, 0x5c, 0x5c, 0x3d, 0x53, 0x61, - 0x6e, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x69, 0x73, 0x63, 0x6f, 0x2c, 0x20, 0x43, 0x61, 0x6c, - 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x2c, 0x20, 0x55, 0x53, 0x41, 0x5c, 0x5c, 0x6e, 0x64, - 0x6e, 0x73, 0x5c, 0x5c, 0x5c, 0x3d, 0x6e, 0x79, 0x61, 0x72, 0x6c, 0x61, 0x74, 0x68, 0x6f, 0x74, - 0x65, 0x70, 0x2e, 0x7a, 0x65, 0x72, 0x6f, 0x74, 0x69, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x5c, - 0x5c, 0x6e, 0x5c, 0x6e, 0x38, 0x38, 0x34, 0x31, 0x34, 0x30, 0x38, 0x61, 0x32, 0x65, 0x5c, 0x3d, - 0x69, 0x64, 0x5c, 0x5c, 0x5c, 0x3d, 0x38, 0x38, 0x34, 0x31, 0x34, 0x30, 0x38, 0x61, 0x32, 0x65, - 0x3a, 0x30, 0x3a, 0x62, 0x62, 0x31, 0x64, 0x33, 0x31, 0x66, 0x32, 0x63, 0x33, 0x32, 0x33, 0x65, - 0x32, 0x36, 0x34, 0x65, 0x39, 0x65, 0x36, 0x34, 0x31, 0x37, 0x32, 0x63, 0x31, 0x61, 0x37, 0x34, - 0x66, 0x37, 0x37, 0x38, 0x39, 0x39, 0x35, 0x35, 0x35, 0x65, 0x64, 0x31, 0x30, 0x37, 0x35, 0x31, - 0x63, 0x64, 0x35, 0x36, 0x65, 0x38, 0x36, 0x34, 0x30, 0x35, 0x63, 0x64, 0x65, 0x31, 0x31, 0x38, - 0x64, 0x30, 0x32, 0x64, 0x66, 0x66, 0x65, 0x35, 0x35, 0x35, 0x64, 0x34, 0x36, 0x32, 0x63, 0x63, - 0x66, 0x36, 0x61, 0x38, 0x35, 0x62, 0x35, 0x36, 0x33, 0x31, 0x63, 0x31, 0x32, 0x33, 0x35, 0x30, - 0x63, 0x38, 0x64, 0x35, 0x64, 0x63, 0x34, 0x30, 0x39, 0x62, 0x61, 0x31, 0x30, 0x62, 0x39, 0x30, - 0x32, 0x35, 0x64, 0x30, 0x66, 0x34, 0x34, 0x35, 0x63, 0x66, 0x34, 0x34, 0x39, 0x64, 0x39, 0x32, - 0x62, 0x31, 0x63, 0x5c, 0x5c, 0x6e, 0x75, 0x64, 0x70, 0x5c, 0x5c, 0x5c, 0x3d, 0x31, 0x30, 0x37, - 0x2e, 0x31, 0x39, 0x31, 0x2e, 0x34, 0x36, 0x2e, 0x32, 0x31, 0x30, 0x2f, 0x39, 0x39, 0x39, 0x33, - 0x5c, 0x5c, 0x6e, 0x74, 0x63, 0x70, 0x5c, 0x5c, 0x5c, 0x3d, 0x31, 0x30, 0x37, 0x2e, 0x31, 0x39, - 0x31, 0x2e, 0x34, 0x36, 0x2e, 0x32, 0x31, 0x30, 0x2f, 0x34, 0x34, 0x33, 0x5c, 0x5c, 0x6e, 0x64, - 0x65, 0x73, 0x63, 0x5c, 0x5c, 0x5c, 0x3d, 0x50, 0x61, 0x72, 0x69, 0x73, 0x2c, 0x20, 0x46, 0x72, - 0x61, 0x6e, 0x63, 0x65, 0x5c, 0x5c, 0x6e, 0x64, 0x6e, 0x73, 0x5c, 0x5c, 0x5c, 0x3d, 0x73, 0x68, - 0x6f, 0x67, 0x67, 0x6f, 0x74, 0x68, 0x2e, 0x7a, 0x65, 0x72, 0x6f, 0x74, 0x69, 0x65, 0x72, 0x2e, - 0x63, 0x6f, 0x6d, 0x5c, 0x5c, 0x6e, 0x5c, 0x6e, 0x38, 0x61, 0x63, 0x66, 0x30, 0x35, 0x39, 0x66, - 0x65, 0x33, 0x5c, 0x3d, 0x69, 0x64, 0x5c, 0x5c, 0x5c, 0x3d, 0x38, 0x61, 0x63, 0x66, 0x30, 0x35, - 0x39, 0x66, 0x65, 0x33, 0x3a, 0x30, 0x3a, 0x34, 0x38, 0x32, 0x66, 0x36, 0x65, 0x65, 0x35, 0x64, - 0x66, 0x65, 0x39, 0x30, 0x32, 0x33, 0x31, 0x39, 0x62, 0x34, 0x31, 0x39, 0x64, 0x65, 0x35, 0x62, - 0x64, 0x63, 0x37, 0x36, 0x35, 0x32, 0x30, 0x39, 0x63, 0x30, 0x65, 0x63, 0x64, 0x61, 0x33, 0x38, - 0x63, 0x34, 0x64, 0x36, 0x65, 0x34, 0x66, 0x63, 0x66, 0x30, 0x64, 0x33, 0x33, 0x36, 0x35, 0x38, - 0x33, 0x39, 0x38, 0x62, 0x34, 0x35, 0x32, 0x37, 0x64, 0x63, 0x64, 0x32, 0x32, 0x66, 0x39, 0x33, - 0x31, 0x31, 0x32, 0x66, 0x62, 0x39, 0x62, 0x65, 0x66, 0x64, 0x30, 0x32, 0x66, 0x64, 0x37, 0x38, - 0x62, 0x66, 0x37, 0x32, 0x36, 0x31, 0x62, 0x33, 0x33, 0x33, 0x66, 0x63, 0x31, 0x30, 0x35, 0x64, - 0x31, 0x39, 0x32, 0x61, 0x36, 0x32, 0x33, 0x63, 0x61, 0x39, 0x65, 0x35, 0x30, 0x66, 0x63, 0x36, - 0x30, 0x62, 0x33, 0x37, 0x34, 0x61, 0x35, 0x5c, 0x5c, 0x6e, 0x75, 0x64, 0x70, 0x5c, 0x5c, 0x5c, - 0x3d, 0x31, 0x36, 0x32, 0x2e, 0x32, 0x34, 0x33, 0x2e, 0x37, 0x37, 0x2e, 0x31, 0x31, 0x31, 0x2f, - 0x39, 0x39, 0x39, 0x33, 0x5c, 0x5c, 0x6e, 0x74, 0x63, 0x70, 0x5c, 0x5c, 0x5c, 0x3d, 0x31, 0x36, - 0x32, 0x2e, 0x32, 0x34, 0x33, 0x2e, 0x37, 0x37, 0x2e, 0x31, 0x31, 0x31, 0x2f, 0x34, 0x34, 0x33, - 0x5c, 0x5c, 0x6e, 0x64, 0x65, 0x73, 0x63, 0x5c, 0x5c, 0x5c, 0x3d, 0x4e, 0x65, 0x77, 0x20, 0x59, - 0x6f, 0x72, 0x6b, 0x2c, 0x20, 0x4e, 0x65, 0x77, 0x20, 0x59, 0x6f, 0x72, 0x6b, 0x2c, 0x20, 0x55, - 0x53, 0x41, 0x5c, 0x5c, 0x6e, 0x64, 0x6e, 0x73, 0x5c, 0x5c, 0x5c, 0x3d, 0x63, 0x74, 0x68, 0x75, - 0x6c, 0x68, 0x75, 0x2e, 0x7a, 0x65, 0x72, 0x6f, 0x74, 0x69, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, - 0x5c, 0x5c, 0x6e, 0x5c, 0x6e, 0x39, 0x64, 0x32, 0x31, 0x39, 0x30, 0x33, 0x39, 0x66, 0x33, 0x5c, - 0x3d, 0x69, 0x64, 0x5c, 0x5c, 0x5c, 0x3d, 0x39, 0x64, 0x32, 0x31, 0x39, 0x30, 0x33, 0x39, 0x66, - 0x33, 0x3a, 0x30, 0x3a, 0x30, 0x31, 0x66, 0x30, 0x39, 0x32, 0x32, 0x61, 0x39, 0x38, 0x65, 0x33, - 0x62, 0x33, 0x34, 0x65, 0x62, 0x63, 0x62, 0x66, 0x66, 0x33, 0x33, 0x33, 0x32, 0x36, 0x39, 0x64, - 0x63, 0x32, 0x36, 0x35, 0x64, 0x37, 0x61, 0x30, 0x32, 0x30, 0x61, 0x61, 0x62, 0x36, 0x39, 0x64, - 0x37, 0x32, 0x62, 0x65, 0x34, 0x64, 0x34, 0x61, 0x63, 0x63, 0x39, 0x63, 0x38, 0x63, 0x39, 0x32, - 0x39, 0x34, 0x37, 0x38, 0x35, 0x37, 0x37, 0x31, 0x32, 0x35, 0x36, 0x63, 0x64, 0x31, 0x64, 0x39, - 0x34, 0x32, 0x61, 0x39, 0x30, 0x64, 0x31, 0x62, 0x64, 0x31, 0x64, 0x32, 0x64, 0x63, 0x61, 0x33, - 0x65, 0x61, 0x38, 0x34, 0x65, 0x66, 0x37, 0x64, 0x38, 0x35, 0x61, 0x66, 0x65, 0x36, 0x36, 0x31, - 0x31, 0x66, 0x62, 0x34, 0x33, 0x66, 0x66, 0x30, 0x62, 0x37, 0x34, 0x31, 0x32, 0x36, 0x64, 0x39, - 0x30, 0x61, 0x36, 0x65, 0x5c, 0x5c, 0x6e, 0x75, 0x64, 0x70, 0x5c, 0x5c, 0x5c, 0x3d, 0x31, 0x32, - 0x38, 0x2e, 0x31, 0x39, 0x39, 0x2e, 0x31, 0x39, 0x37, 0x2e, 0x32, 0x31, 0x37, 0x2f, 0x39, 0x39, - 0x39, 0x33, 0x5c, 0x5c, 0x6e, 0x74, 0x63, 0x70, 0x5c, 0x5c, 0x5c, 0x3d, 0x31, 0x32, 0x38, 0x2e, - 0x31, 0x39, 0x39, 0x2e, 0x31, 0x39, 0x37, 0x2e, 0x32, 0x31, 0x37, 0x2f, 0x34, 0x34, 0x33, 0x5c, - 0x5c, 0x6e, 0x64, 0x65, 0x73, 0x63, 0x5c, 0x5c, 0x5c, 0x3d, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, - 0x6f, 0x72, 0x65, 0x5c, 0x5c, 0x6e, 0x64, 0x6e, 0x73, 0x5c, 0x5c, 0x5c, 0x3d, 0x6d, 0x69, 0x2d, - 0x67, 0x6f, 0x2e, 0x7a, 0x65, 0x72, 0x6f, 0x74, 0x69, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x5c, - 0x5c, 0x6e, 0x5c, 0x6e, 0x0a, 0x7e, 0x21, 0x65, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x3d, 0x62, - 0x37, 0x34, 0x39, 0x33, 0x66, 0x35, 0x61, 0x34, 0x62, 0x37, 0x39, 0x61, 0x31, 0x64, 0x63, 0x63, - 0x34, 0x32, 0x33, 0x66, 0x64, 0x32, 0x35, 0x64, 0x32, 0x64, 0x38, 0x61, 0x61, 0x38, 0x64, 0x36, - 0x32, 0x39, 0x33, 0x63, 0x34, 0x39, 0x30, 0x61, 0x31, 0x32, 0x63, 0x65, 0x62, 0x36, 0x33, 0x39, - 0x35, 0x34, 0x31, 0x37, 0x64, 0x64, 0x35, 0x38, 0x36, 0x38, 0x63, 0x31, 0x37, 0x62, 0x66, 0x62, - 0x63, 0x65, 0x65, 0x36, 0x38, 0x35, 0x64, 0x65, 0x35, 0x38, 0x30, 0x31, 0x39, 0x64, 0x32, 0x31, - 0x66, 0x39, 0x32, 0x35, 0x37, 0x36, 0x61, 0x37, 0x38, 0x61, 0x34, 0x35, 0x32, 0x33, 0x35, 0x64, - 0x33, 0x34, 0x32, 0x65, 0x66, 0x61, 0x32, 0x61, 0x30, 0x30, 0x61, 0x35, 0x34, 0x34, 0x64, 0x65, - 0x64, 0x33, 0x34, 0x37, 0x36, 0x36, 0x64, 0x64, 0x33, 0x32, 0x64, 0x36, 0x66, 0x30, 0x65, 0x31, - 0x31, 0x38, 0x30, 0x39, 0x31, 0x39, 0x37, 0x66, 0x39, 0x62, 0x61, 0x65, 0x65, 0x64, 0x66, 0x34, - 0x63, 0x36, 0x61, 0x30, 0x65, 0x38, 0x64, 0x32, 0x64, 0x36, 0x35, 0x37, 0x64, 0x32, 0x38, 0x30, - 0x61, 0x35, 0x37, 0x39, 0x66, 0x32, 0x66, 0x32, 0x34, 0x37, 0x38, 0x62, 0x32, 0x66, 0x37, 0x63, - 0x37, 0x61, 0x30, 0x38, 0x30, 0x38, 0x39, 0x61, 0x35, 0x30, 0x31, 0x36, 0x62, 0x35, 0x35, 0x0a, - 0x7e, 0x21, 0x73, 0x69, 0x67, 0x69, 0x64, 0x3d, 0x37, 0x37, 0x37, 0x39, 0x32, 0x62, 0x31, 0x63, - 0x30, 0x32, 0x3a, 0x30, 0x3a, 0x62, 0x35, 0x63, 0x33, 0x36, 0x31, 0x65, 0x38, 0x65, 0x39, 0x63, - 0x32, 0x31, 0x35, 0x34, 0x65, 0x38, 0x32, 0x63, 0x33, 0x65, 0x39, 0x30, 0x32, 0x66, 0x64, 0x66, - 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 + 0x72, 0x6f, 0x6f, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x3d, 0x37, 0x65, 0x31, 0x39, + 0x38, 0x37, 0x36, 0x61, 0x62, 0x61, 0x5c, 0x3d, 0x69, 0x64, 0x5c, 0x5c, 0x5c, 0x3d, 0x37, 0x65, + 0x31, 0x39, 0x38, 0x37, 0x36, 0x61, 0x62, 0x61, 0x3a, 0x30, 0x3a, 0x32, 0x61, 0x36, 0x65, 0x32, + 0x62, 0x32, 0x33, 0x31, 0x38, 0x39, 0x33, 0x30, 0x66, 0x36, 0x30, 0x65, 0x62, 0x30, 0x39, 0x37, + 0x66, 0x37, 0x30, 0x64, 0x30, 0x66, 0x34, 0x62, 0x30, 0x32, 0x38, 0x62, 0x32, 0x63, 0x64, 0x36, + 0x64, 0x33, 0x64, 0x30, 0x63, 0x36, 0x33, 0x63, 0x30, 0x31, 0x34, 0x62, 0x39, 0x30, 0x33, 0x39, + 0x66, 0x66, 0x33, 0x35, 0x33, 0x39, 0x30, 0x65, 0x34, 0x31, 0x31, 0x38, 0x31, 0x66, 0x32, 0x31, + 0x36, 0x66, 0x62, 0x32, 0x65, 0x36, 0x66, 0x61, 0x38, 0x64, 0x39, 0x35, 0x63, 0x31, 0x65, 0x65, + 0x39, 0x36, 0x36, 0x37, 0x31, 0x35, 0x36, 0x34, 0x31, 0x31, 0x39, 0x30, 0x35, 0x63, 0x33, 0x64, + 0x63, 0x63, 0x66, 0x65, 0x61, 0x37, 0x38, 0x64, 0x38, 0x63, 0x36, 0x64, 0x66, 0x61, 0x66, 0x62, + 0x61, 0x36, 0x38, 0x38, 0x31, 0x37, 0x30, 0x62, 0x33, 0x66, 0x61, 0x5c, 0x5c, 0x6e, 0x75, 0x64, + 0x70, 0x5c, 0x5c, 0x5c, 0x3d, 0x31, 0x39, 0x38, 0x2e, 0x31, 0x39, 0x39, 0x2e, 0x39, 0x37, 0x2e, + 0x32, 0x32, 0x30, 0x2f, 0x39, 0x39, 0x39, 0x33, 0x5c, 0x5c, 0x6e, 0x74, 0x63, 0x70, 0x5c, 0x5c, + 0x5c, 0x3d, 0x31, 0x39, 0x38, 0x2e, 0x31, 0x39, 0x39, 0x2e, 0x39, 0x37, 0x2e, 0x32, 0x32, 0x30, + 0x2f, 0x34, 0x34, 0x33, 0x5c, 0x5c, 0x6e, 0x64, 0x65, 0x73, 0x63, 0x5c, 0x5c, 0x5c, 0x3d, 0x53, + 0x61, 0x6e, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x69, 0x73, 0x63, 0x6f, 0x2c, 0x20, 0x43, 0x61, + 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x2c, 0x20, 0x55, 0x53, 0x41, 0x5c, 0x5c, 0x6e, + 0x5c, 0x6e, 0x38, 0x38, 0x34, 0x31, 0x34, 0x30, 0x38, 0x61, 0x32, 0x65, 0x5c, 0x3d, 0x69, 0x64, + 0x5c, 0x5c, 0x5c, 0x3d, 0x38, 0x38, 0x34, 0x31, 0x34, 0x30, 0x38, 0x61, 0x32, 0x65, 0x3a, 0x30, + 0x3a, 0x62, 0x62, 0x31, 0x64, 0x33, 0x31, 0x66, 0x32, 0x63, 0x33, 0x32, 0x33, 0x65, 0x32, 0x36, + 0x34, 0x65, 0x39, 0x65, 0x36, 0x34, 0x31, 0x37, 0x32, 0x63, 0x31, 0x61, 0x37, 0x34, 0x66, 0x37, + 0x37, 0x38, 0x39, 0x39, 0x35, 0x35, 0x35, 0x65, 0x64, 0x31, 0x30, 0x37, 0x35, 0x31, 0x63, 0x64, + 0x35, 0x36, 0x65, 0x38, 0x36, 0x34, 0x30, 0x35, 0x63, 0x64, 0x65, 0x31, 0x31, 0x38, 0x64, 0x30, + 0x32, 0x64, 0x66, 0x66, 0x65, 0x35, 0x35, 0x35, 0x64, 0x34, 0x36, 0x32, 0x63, 0x63, 0x66, 0x36, + 0x61, 0x38, 0x35, 0x62, 0x35, 0x36, 0x33, 0x31, 0x63, 0x31, 0x32, 0x33, 0x35, 0x30, 0x63, 0x38, + 0x64, 0x35, 0x64, 0x63, 0x34, 0x30, 0x39, 0x62, 0x61, 0x31, 0x30, 0x62, 0x39, 0x30, 0x32, 0x35, + 0x64, 0x30, 0x66, 0x34, 0x34, 0x35, 0x63, 0x66, 0x34, 0x34, 0x39, 0x64, 0x39, 0x32, 0x62, 0x31, + 0x63, 0x5c, 0x5c, 0x6e, 0x75, 0x64, 0x70, 0x5c, 0x5c, 0x5c, 0x3d, 0x31, 0x30, 0x37, 0x2e, 0x31, + 0x39, 0x31, 0x2e, 0x34, 0x36, 0x2e, 0x32, 0x31, 0x30, 0x2f, 0x39, 0x39, 0x39, 0x33, 0x5c, 0x5c, + 0x6e, 0x74, 0x63, 0x70, 0x5c, 0x5c, 0x5c, 0x3d, 0x31, 0x30, 0x37, 0x2e, 0x31, 0x39, 0x31, 0x2e, + 0x34, 0x36, 0x2e, 0x32, 0x31, 0x30, 0x2f, 0x34, 0x34, 0x33, 0x5c, 0x5c, 0x6e, 0x64, 0x65, 0x73, + 0x63, 0x5c, 0x5c, 0x5c, 0x3d, 0x50, 0x61, 0x72, 0x69, 0x73, 0x2c, 0x20, 0x46, 0x72, 0x61, 0x6e, + 0x63, 0x65, 0x5c, 0x5c, 0x6e, 0x5c, 0x6e, 0x38, 0x61, 0x63, 0x66, 0x30, 0x35, 0x39, 0x66, 0x65, + 0x33, 0x5c, 0x3d, 0x69, 0x64, 0x5c, 0x5c, 0x5c, 0x3d, 0x38, 0x61, 0x63, 0x66, 0x30, 0x35, 0x39, + 0x66, 0x65, 0x33, 0x3a, 0x30, 0x3a, 0x34, 0x38, 0x32, 0x66, 0x36, 0x65, 0x65, 0x35, 0x64, 0x66, + 0x65, 0x39, 0x30, 0x32, 0x33, 0x31, 0x39, 0x62, 0x34, 0x31, 0x39, 0x64, 0x65, 0x35, 0x62, 0x64, + 0x63, 0x37, 0x36, 0x35, 0x32, 0x30, 0x39, 0x63, 0x30, 0x65, 0x63, 0x64, 0x61, 0x33, 0x38, 0x63, + 0x34, 0x64, 0x36, 0x65, 0x34, 0x66, 0x63, 0x66, 0x30, 0x64, 0x33, 0x33, 0x36, 0x35, 0x38, 0x33, + 0x39, 0x38, 0x62, 0x34, 0x35, 0x32, 0x37, 0x64, 0x63, 0x64, 0x32, 0x32, 0x66, 0x39, 0x33, 0x31, + 0x31, 0x32, 0x66, 0x62, 0x39, 0x62, 0x65, 0x66, 0x64, 0x30, 0x32, 0x66, 0x64, 0x37, 0x38, 0x62, + 0x66, 0x37, 0x32, 0x36, 0x31, 0x62, 0x33, 0x33, 0x33, 0x66, 0x63, 0x31, 0x30, 0x35, 0x64, 0x31, + 0x39, 0x32, 0x61, 0x36, 0x32, 0x33, 0x63, 0x61, 0x39, 0x65, 0x35, 0x30, 0x66, 0x63, 0x36, 0x30, + 0x62, 0x33, 0x37, 0x34, 0x61, 0x35, 0x5c, 0x5c, 0x6e, 0x75, 0x64, 0x70, 0x5c, 0x5c, 0x5c, 0x3d, + 0x31, 0x36, 0x32, 0x2e, 0x32, 0x34, 0x33, 0x2e, 0x37, 0x37, 0x2e, 0x31, 0x31, 0x31, 0x2f, 0x39, + 0x39, 0x39, 0x33, 0x5c, 0x5c, 0x6e, 0x74, 0x63, 0x70, 0x5c, 0x5c, 0x5c, 0x3d, 0x31, 0x36, 0x32, + 0x2e, 0x32, 0x34, 0x33, 0x2e, 0x37, 0x37, 0x2e, 0x31, 0x31, 0x31, 0x2f, 0x34, 0x34, 0x33, 0x5c, + 0x5c, 0x6e, 0x64, 0x65, 0x73, 0x63, 0x5c, 0x5c, 0x5c, 0x3d, 0x4e, 0x65, 0x77, 0x20, 0x59, 0x6f, + 0x72, 0x6b, 0x2c, 0x20, 0x4e, 0x65, 0x77, 0x20, 0x59, 0x6f, 0x72, 0x6b, 0x2c, 0x20, 0x55, 0x53, + 0x41, 0x5c, 0x5c, 0x6e, 0x5c, 0x6e, 0x39, 0x64, 0x32, 0x31, 0x39, 0x30, 0x33, 0x39, 0x66, 0x33, + 0x5c, 0x3d, 0x69, 0x64, 0x5c, 0x5c, 0x5c, 0x3d, 0x39, 0x64, 0x32, 0x31, 0x39, 0x30, 0x33, 0x39, + 0x66, 0x33, 0x3a, 0x30, 0x3a, 0x30, 0x31, 0x66, 0x30, 0x39, 0x32, 0x32, 0x61, 0x39, 0x38, 0x65, + 0x33, 0x62, 0x33, 0x34, 0x65, 0x62, 0x63, 0x62, 0x66, 0x66, 0x33, 0x33, 0x33, 0x32, 0x36, 0x39, + 0x64, 0x63, 0x32, 0x36, 0x35, 0x64, 0x37, 0x61, 0x30, 0x32, 0x30, 0x61, 0x61, 0x62, 0x36, 0x39, + 0x64, 0x37, 0x32, 0x62, 0x65, 0x34, 0x64, 0x34, 0x61, 0x63, 0x63, 0x39, 0x63, 0x38, 0x63, 0x39, + 0x32, 0x39, 0x34, 0x37, 0x38, 0x35, 0x37, 0x37, 0x31, 0x32, 0x35, 0x36, 0x63, 0x64, 0x31, 0x64, + 0x39, 0x34, 0x32, 0x61, 0x39, 0x30, 0x64, 0x31, 0x62, 0x64, 0x31, 0x64, 0x32, 0x64, 0x63, 0x61, + 0x33, 0x65, 0x61, 0x38, 0x34, 0x65, 0x66, 0x37, 0x64, 0x38, 0x35, 0x61, 0x66, 0x65, 0x36, 0x36, + 0x31, 0x31, 0x66, 0x62, 0x34, 0x33, 0x66, 0x66, 0x30, 0x62, 0x37, 0x34, 0x31, 0x32, 0x36, 0x64, + 0x39, 0x30, 0x61, 0x36, 0x65, 0x5c, 0x5c, 0x6e, 0x75, 0x64, 0x70, 0x5c, 0x5c, 0x5c, 0x3d, 0x31, + 0x32, 0x38, 0x2e, 0x31, 0x39, 0x39, 0x2e, 0x31, 0x39, 0x37, 0x2e, 0x32, 0x31, 0x37, 0x2f, 0x39, + 0x39, 0x39, 0x33, 0x5c, 0x5c, 0x6e, 0x74, 0x63, 0x70, 0x5c, 0x5c, 0x5c, 0x3d, 0x31, 0x32, 0x38, + 0x2e, 0x31, 0x39, 0x39, 0x2e, 0x31, 0x39, 0x37, 0x2e, 0x32, 0x31, 0x37, 0x2f, 0x34, 0x34, 0x33, + 0x5c, 0x5c, 0x6e, 0x64, 0x65, 0x73, 0x63, 0x5c, 0x5c, 0x5c, 0x3d, 0x53, 0x69, 0x6e, 0x67, 0x61, + 0x70, 0x6f, 0x72, 0x65, 0x5c, 0x5c, 0x6e, 0x5c, 0x6e, 0x0a, 0x7e, 0x21, 0x65, 0x64, 0x32, 0x35, + 0x35, 0x31, 0x39, 0x3d, 0x38, 0x33, 0x32, 0x62, 0x33, 0x35, 0x64, 0x61, 0x64, 0x64, 0x37, 0x66, + 0x35, 0x36, 0x66, 0x66, 0x33, 0x38, 0x31, 0x66, 0x61, 0x37, 0x32, 0x31, 0x64, 0x65, 0x37, 0x64, + 0x35, 0x62, 0x65, 0x34, 0x63, 0x65, 0x62, 0x66, 0x63, 0x63, 0x63, 0x32, 0x30, 0x30, 0x32, 0x30, + 0x38, 0x33, 0x38, 0x30, 0x64, 0x33, 0x30, 0x38, 0x34, 0x66, 0x36, 0x34, 0x38, 0x65, 0x32, 0x63, + 0x31, 0x61, 0x35, 0x63, 0x66, 0x34, 0x33, 0x65, 0x35, 0x39, 0x66, 0x39, 0x32, 0x61, 0x36, 0x36, + 0x35, 0x64, 0x66, 0x34, 0x64, 0x62, 0x63, 0x62, 0x38, 0x33, 0x37, 0x38, 0x38, 0x66, 0x36, 0x62, + 0x64, 0x36, 0x37, 0x37, 0x66, 0x30, 0x32, 0x62, 0x32, 0x31, 0x30, 0x65, 0x35, 0x30, 0x63, 0x61, + 0x66, 0x65, 0x66, 0x64, 0x32, 0x65, 0x66, 0x31, 0x38, 0x39, 0x62, 0x62, 0x66, 0x34, 0x38, 0x31, + 0x62, 0x64, 0x30, 0x32, 0x63, 0x64, 0x63, 0x39, 0x38, 0x34, 0x35, 0x33, 0x38, 0x37, 0x64, 0x38, + 0x34, 0x39, 0x62, 0x63, 0x35, 0x36, 0x66, 0x39, 0x63, 0x37, 0x32, 0x35, 0x31, 0x65, 0x35, 0x64, + 0x30, 0x65, 0x61, 0x34, 0x34, 0x34, 0x66, 0x66, 0x63, 0x66, 0x38, 0x66, 0x37, 0x32, 0x32, 0x63, + 0x32, 0x66, 0x65, 0x62, 0x38, 0x39, 0x36, 0x30, 0x33, 0x61, 0x30, 0x65, 0x35, 0x62, 0x61, 0x32, + 0x39, 0x35, 0x66, 0x63, 0x0a, 0x7e, 0x21, 0x73, 0x69, 0x67, 0x69, 0x64, 0x3d, 0x37, 0x37, 0x37, + 0x39, 0x32, 0x62, 0x31, 0x63, 0x30, 0x32, 0x3a, 0x30, 0x3a, 0x62, 0x35, 0x63, 0x33, 0x36, 0x31, + 0x65, 0x38, 0x65, 0x39, 0x63, 0x32, 0x31, 0x35, 0x34, 0x65, 0x38, 0x32, 0x63, 0x33, 0x65, 0x39, + 0x30, 0x32, 0x66, 0x64, 0x66, 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, 0x65, 0x30, 0x63, 0x62, 0x62, 0x39, 0x38, 0x64, 0x36, 0x0a }; -#define ZT_DEFAULT_ROOT_TOPOLOGY_LEN 1514 +#define ZT_DEFAULT_ROOT_TOPOLOGY_LEN 1391 diff --git a/root-topology/ZT_DEFAULT_ROOT_TOPOLOGY.dict b/root-topology/ZT_DEFAULT_ROOT_TOPOLOGY.dict index 8aa828f0a..58144758e 100644 --- a/root-topology/ZT_DEFAULT_ROOT_TOPOLOGY.dict +++ b/root-topology/ZT_DEFAULT_ROOT_TOPOLOGY.dict @@ -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 -~!ed25519=b7493f5a4b79a1dcc423fd25d2d8aa8d6293c490a12ceb6395417dd5868c17bfbcee685de58019d21f92576a78a45235d342efa2a00a544ded34766dd32d6f0e11809197f9baeedf4c6a0e8d2d657d280a579f2f2478b2f7c7a08089a5016b55 +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=832b35dadd7f56ff381fa721de7d5be4cebfccc200208380d3084f648e2c1a5cf43e59f92a665df4dbcb83788f6bd677f02b210e50cafefd2ef189bbf481bd02cdc9845387d849bc56f9c7251e5d0ea444ffcf8f722c2feb89603a0e5ba295fc ~!sigid=77792b1c02:0:b5c361e8e9c2154e82c3e902fdfc337468b092a7c4d8dc685c37eb10ee4f3c17cc0bb1d024167e8cb0824d12263428373582da3d0a9a14b36e4546c317e811e6 -~!sigts=14ae42d0314 +~!sigts=14e0cbb98d6 diff --git a/root-topology/mktopology.cpp b/root-topology/mktopology.cpp index 00ada7b76..f0ad5b556 100644 --- a/root-topology/mktopology.cpp +++ b/root-topology/mktopology.cpp @@ -30,21 +30,21 @@ int main(int argc,char **argv) if (OSUtils::readFile("template.dict",buf)) topology.fromString(buf); - // Read all entries in supernodes/ that correspond to supernode entry dictionaries - // and add them to topology under supernodes/ subkey. - Dictionary supernodes; - std::vector supernodeDictionaries(OSUtils::listDirectory("supernodes")); - for(std::vector::const_iterator sn(supernodeDictionaries.begin());sn!=supernodeDictionaries.end();++sn) { + // Read all entries in rootservers/ that correspond to rootserver entry dictionaries + // and add them to topology under rootservers/ subkey. + Dictionary rootservers; + std::vector rootserverDictionaries(OSUtils::listDirectory("rootservers")); + for(std::vector::const_iterator sn(rootserverDictionaries.begin());sn!=rootserverDictionaries.end();++sn) { if (sn->length() == 10) { buf.clear(); - if (!OSUtils::readFile((std::string("supernodes/")+(*sn)).c_str(),buf)) { - std::cerr << "Cannot read supernodes/" << *sn << std::endl; + if (!OSUtils::readFile((std::string("rootservers/")+(*sn)).c_str(),buf)) { + std::cerr << "Cannot read rootservers/" << *sn << std::endl; return 1; } - supernodes[*sn] = buf; + rootservers[*sn] = buf; } } - topology["supernodes"] = supernodes.toString(); + topology["rootservers"] = rootservers.toString(); if ((topologyAuthority)&&(topologyAuthority.hasPrivate())) { // Sign topology with root-topology-authority.secret diff --git a/root-topology/supernodes/7e19876aba b/root-topology/rootservers/7e19876aba similarity index 88% rename from root-topology/supernodes/7e19876aba rename to root-topology/rootservers/7e19876aba index 23c2ad247..6bd8dc429 100644 --- a/root-topology/supernodes/7e19876aba +++ b/root-topology/rootservers/7e19876aba @@ -2,4 +2,3 @@ id=7e19876aba:0:2a6e2b2318930f60eb097f70d0f4b028b2cd6d3d0c63c014b9039ff35390e411 udp=198.199.97.220/9993 tcp=198.199.97.220/443 desc=San Francisco, California, USA -dns=nyarlathotep.zerotier.com diff --git a/root-topology/supernodes/8841408a2e b/root-topology/rootservers/8841408a2e similarity index 89% rename from root-topology/supernodes/8841408a2e rename to root-topology/rootservers/8841408a2e index 09258f4e0..3be3333e4 100644 --- a/root-topology/supernodes/8841408a2e +++ b/root-topology/rootservers/8841408a2e @@ -2,4 +2,3 @@ id=8841408a2e:0:bb1d31f2c323e264e9e64172c1a74f77899555ed10751cd56e86405cde118d02 udp=107.191.46.210/9993 tcp=107.191.46.210/443 desc=Paris, France -dns=shoggoth.zerotier.com diff --git a/root-topology/supernodes/8acf059fe3 b/root-topology/rootservers/8acf059fe3 similarity index 89% rename from root-topology/supernodes/8acf059fe3 rename to root-topology/rootservers/8acf059fe3 index 438e67a32..4a569d95b 100644 --- a/root-topology/supernodes/8acf059fe3 +++ b/root-topology/rootservers/8acf059fe3 @@ -2,4 +2,3 @@ id=8acf059fe3:0:482f6ee5dfe902319b419de5bdc765209c0ecda38c4d6e4fcf0d33658398b452 udp=162.243.77.111/9993 tcp=162.243.77.111/443 desc=New York, New York, USA -dns=cthulhu.zerotier.com diff --git a/root-topology/supernodes/9d219039f3 b/root-topology/rootservers/9d219039f3 similarity index 90% rename from root-topology/supernodes/9d219039f3 rename to root-topology/rootservers/9d219039f3 index 1602f35e4..ec9224336 100644 --- a/root-topology/supernodes/9d219039f3 +++ b/root-topology/rootservers/9d219039f3 @@ -2,4 +2,3 @@ id=9d219039f3:0:01f0922a98e3b34ebcbff333269dc265d7a020aab69d72be4d4acc9c8c929478 udp=128.199.197.217/9993 tcp=128.199.197.217/443 desc=Singapore -dns=mi-go.zerotier.com diff --git a/root-topology/test/README.md b/root-topology/test/README.md index 332f8297f..ae7022437 100644 --- a/root-topology/test/README.md +++ b/root-topology/test/README.md @@ -1,6 +1,6 @@ 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. diff --git a/root-topology/test/create-test-root-topology.sh b/root-topology/test/create-test-root-topology.sh index 86c0577cf..cb6287295 100755 --- a/root-topology/test/create-test-root-topology.sh +++ b/root-topology/test/create-test-root-topology.sh @@ -5,18 +5,18 @@ if [ ! -e ../mktopology ]; then exit 1 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 -mkdir supernodes +rm -rf rootservers +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` 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'` echo $cid $ztaddr $id $ip - echo "id=$id" >supernodes/$ztaddr - echo "udp=$ip/9993" >>supernodes/$ztaddr + echo "id=$id" >rootservers/$ztaddr + echo "udp=$ip/9993" >>rootservers/$ztaddr done echo 'Creating test-root-topology...' diff --git a/service/ControlPlane.cpp b/service/ControlPlane.cpp index 71b3fd3fb..015825867 100644 --- a/service/ControlPlane.cpp +++ b/service/ControlPlane.cpp @@ -211,9 +211,9 @@ static void _jsonAppend(unsigned int depth,std::string &buf,const ZT1_Peer *peer const char *prole = ""; switch(peer->role) { - case ZT1_PEER_ROLE_LEAF: prole = "LEAF"; break; - case ZT1_PEER_ROLE_HUB: prole = "HUB"; break; - case ZT1_PEER_ROLE_SUPERNODE: prole = "SUPERNODE"; break; + case ZT1_PEER_ROLE_LEAF: prole = "LEAF"; break; + case ZT1_PEER_ROLE_RELAY: prole = "RELAY"; break; + case ZT1_PEER_ROLE_ROOT: prole = "ROOT"; break; } Utils::snprintf(json,sizeof(json), @@ -454,7 +454,7 @@ unsigned int ControlPlane::handleRequest( } else { #ifdef ZT_ENABLE_NETWORK_CONTROLLER if (_controller) - _controller->handleControlPlaneHttpGET(std::vector(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType); + scode = _controller->handleControlPlaneHttpGET(std::vector(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType); else scode = 404; #else scode = 404; @@ -490,7 +490,7 @@ unsigned int ControlPlane::handleRequest( } else { #ifdef ZT_ENABLE_NETWORK_CONTROLLER if (_controller) - _controller->handleControlPlaneHttpPOST(std::vector(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType); + scode = _controller->handleControlPlaneHttpPOST(std::vector(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType); else scode = 404; #else scode = 404; @@ -525,7 +525,7 @@ unsigned int ControlPlane::handleRequest( } else { #ifdef ZT_ENABLE_NETWORK_CONTROLLER if (_controller) - _controller->handleControlPlaneHttpDELETE(std::vector(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType); + scode = _controller->handleControlPlaneHttpDELETE(std::vector(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType); else scode = 404; #else scode = 404; diff --git a/service/README.md b/service/README.md index acad97a14..df62ff274 100644 --- a/service/README.md +++ b/service/README.md @@ -106,7 +106,7 @@ Getting /peer returns an array of peer objects for all current peers. See below versionRevintegerRevision of remote if knownno versionstringVersion in major.minor.rev formatno latencyintegerLatency in milliseconds if knownno -rolestringLEAF, HUB, or SUPERNODEno +rolestringLEAF, HUB, or ROOTSERVERno paths[object]Array of path objects (see below)no @@ -184,7 +184,7 @@ Relays, IP assignment pools, and rules are edited via direct POSTs to the networ **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. @@ -204,7 +204,7 @@ Relay objects define network-specific preferred relay nodes. Traffic to peers on * **Note**: at the moment, only rules specifying allowed Ethernet types are used. The database supports a richer rule set, but this is not implemented yet in the client. Other types of rules will have no effect (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." @@ -212,7 +212,7 @@ IP related fields apply only to Ethernet frames of type IPv4 or IPV6. Otherwise
FieldTypeDescription
- + diff --git a/tcp-proxy/tcp-proxy.cpp b/tcp-proxy/tcp-proxy.cpp index f7ba2c2f6..6acf7b423 100644 --- a/tcp-proxy/tcp-proxy.cpp +++ b/tcp-proxy/tcp-proxy.cpp @@ -85,7 +85,7 @@ using namespace ZeroTier; * 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 * 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. * * Older ZT clients that do not send this message get their packets relayed
FieldTypeDescription
ruleIdintegerUser-defined rule ID and sort order
ruleNointegerUser-defined rule ID and sort order
nodeIdstring10-digit hex ZeroTier address of node (a.k.a. "port on switch")
vlanIdintegerEthernet VLAN ID
vlanPcpintegerEthernet VLAN priority code point (PCP) ID