mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-06 12:33:44 +02:00
Merge branch 'adamierymenko-dev' into android-jni
This commit is contained in:
commit
c59c74ddda
14 changed files with 548 additions and 323 deletions
|
@ -167,8 +167,8 @@ SqliteNetworkController::SqliteNetworkController(const char *dbPath) :
|
||||||
||(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 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.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 ipNetwork,ipNetmaskBits,ipVersion FROM IpAssignmentPool WHERE networkId = ? ORDER BY ipNetwork ASC",-1,&_sGetIpAssignmentPools2,(const char **)0) != SQLITE_OK)
|
||(sqlite3_prepare_v2(_db,"SELECT ipNetwork,ipNetmaskBits,ipVersion FROM IpAssignmentPool WHERE networkId = ? ORDER BY ipNetwork ASC",-1,&_sGetIpAssignmentPools2,(const char **)0) != SQLITE_OK)
|
||||||
||(sqlite3_prepare_v2(_db,"SELECT ruleId,nodeId,vlanId,vlanPcp,etherType,macSource,macDest,ipSource,ipDest,ipTos,ipProtocol,ipSourcePort,ipDestPort,\"flags\",invFlags,\"action\" FROM Rule WHERE networkId = ? ORDER BY ruleId ASC",-1,&_sListRules,(const char **)0) != SQLITE_OK)
|
||(sqlite3_prepare_v2(_db,"SELECT ruleNo,nodeId,vlanId,vlanPcp,etherType,macSource,macDest,ipSource,ipDest,ipTos,ipProtocol,ipSourcePort,ipDestPort,\"flags\",invFlags,\"action\" FROM Rule WHERE networkId = ? ORDER BY ruleNo ASC",-1,&_sListRules,(const char **)0) != SQLITE_OK)
|
||||||
||(sqlite3_prepare_v2(_db,"INSERT INTO Rule (networkId,ruleId,nodeId,vlanId,vlanPcP,etherType,macSource,macDest,ipSource,ipDest,ipTos,ipProtocol,ipSourcePort,ipDestPort,\"action\") VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",-1,&_sCreateRule,(const char **)0) != SQLITE_OK)
|
||(sqlite3_prepare_v2(_db,"INSERT INTO Rule (networkId,ruleNo,nodeId,vlanId,vlanPcP,etherType,macSource,macDest,ipSource,ipDest,ipTos,ipProtocol,ipSourcePort,ipDestPort,\"action\") VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",-1,&_sCreateRule,(const char **)0) != SQLITE_OK)
|
||||||
||(sqlite3_prepare_v2(_db,"INSERT INTO Network (id,name,creationTime,revision) VALUES (?,?,?,1)",-1,&_sCreateNetwork,(const char **)0) != SQLITE_OK)
|
||(sqlite3_prepare_v2(_db,"INSERT INTO Network (id,name,creationTime,revision) VALUES (?,?,?,1)",-1,&_sCreateNetwork,(const char **)0) != SQLITE_OK)
|
||||||
||(sqlite3_prepare_v2(_db,"SELECT revision FROM Network WHERE id = ?",-1,&_sGetNetworkRevision,(const char **)0) != SQLITE_OK)
|
||(sqlite3_prepare_v2(_db,"SELECT revision FROM Network WHERE id = ?",-1,&_sGetNetworkRevision,(const char **)0) != SQLITE_OK)
|
||||||
||(sqlite3_prepare_v2(_db,"UPDATE Network SET revision = ? WHERE id = ?",-1,&_sSetNetworkRevision,(const char **)0) != SQLITE_OK)
|
||(sqlite3_prepare_v2(_db,"UPDATE Network SET revision = ? WHERE id = ?",-1,&_sSetNetworkRevision,(const char **)0) != SQLITE_OK)
|
||||||
|
@ -179,7 +179,10 @@ SqliteNetworkController::SqliteNetworkController(const char *dbPath) :
|
||||||
||(sqlite3_prepare_v2(_db,"DELETE FROM Rule WHERE networkId = ?",-1,&_sDeleteRulesForNetwork,(const char **)0) != SQLITE_OK)
|
||(sqlite3_prepare_v2(_db,"DELETE FROM Rule WHERE networkId = ?",-1,&_sDeleteRulesForNetwork,(const char **)0) != SQLITE_OK)
|
||||||
||(sqlite3_prepare_v2(_db,"INSERT INTO IpAssignmentPool (networkId,ipNetwork,ipNetmaskBits,ipVersion) VALUES (?,?,?,?)",-1,&_sCreateIpAssignmentPool,(const char **)0) != SQLITE_OK)
|
||(sqlite3_prepare_v2(_db,"INSERT INTO IpAssignmentPool (networkId,ipNetwork,ipNetmaskBits,ipVersion) VALUES (?,?,?,?)",-1,&_sCreateIpAssignmentPool,(const char **)0) != SQLITE_OK)
|
||||||
||(sqlite3_prepare_v2(_db,"DELETE FROM Member WHERE networkId = ? AND nodeId = ?",-1,&_sDeleteMember,(const char **)0) != SQLITE_OK)
|
||(sqlite3_prepare_v2(_db,"DELETE FROM Member WHERE networkId = ? AND nodeId = ?",-1,&_sDeleteMember,(const char **)0) != SQLITE_OK)
|
||||||
||(sqlite3_prepare_v2(_db,"DELETE FROM IpAssignment WHERE networkId = ?; DELETE FROM IpAssignmentPool WHERE networkId = ?; DELETE FROM Member WHERE networkId = ?; DELETE FROM MulticastRate WHERE networkId = ?; DELETE FROM Relay WHERE networkId = ?; DELETE FROM Rule WHERE networkId = ?; DELETE FROM Network WHERE id = ?;",-1,&_sDeleteNetworkAndRelated,(const char **)0) != SQLITE_OK)
|
||(sqlite3_prepare_v2(_db,"DELETE FROM Network WHERE id = ?",-1,&_sDeleteNetwork,(const char **)0) != SQLITE_OK)
|
||||||
|
||(sqlite3_prepare_v2(_db,"SELECT ip,ipVersion,metric FROM Gateway WHERE networkId = ? ORDER BY metric ASC",-1,&_sGetGateways,(const char **)0) != SQLITE_OK)
|
||||||
|
||(sqlite3_prepare_v2(_db,"DELETE FROM Gateway WHERE networkId = ?",-1,&_sDeleteGateways,(const char **)0) != SQLITE_OK)
|
||||||
|
||(sqlite3_prepare_v2(_db,"INSERT INTO Gateway (networkId,ip,ipVersion,metric) VALUES (?,?,?,?)",-1,&_sCreateGateway,(const char **)0) != SQLITE_OK)
|
||||||
) {
|
) {
|
||||||
//printf("!!! %s\n",sqlite3_errmsg(_db));
|
//printf("!!! %s\n",sqlite3_errmsg(_db));
|
||||||
sqlite3_close(_db);
|
sqlite3_close(_db);
|
||||||
|
@ -222,7 +225,10 @@ SqliteNetworkController::~SqliteNetworkController()
|
||||||
sqlite3_finalize(_sDeleteIpAssignmentPoolsForNetwork);
|
sqlite3_finalize(_sDeleteIpAssignmentPoolsForNetwork);
|
||||||
sqlite3_finalize(_sDeleteRulesForNetwork);
|
sqlite3_finalize(_sDeleteRulesForNetwork);
|
||||||
sqlite3_finalize(_sCreateIpAssignmentPool);
|
sqlite3_finalize(_sCreateIpAssignmentPool);
|
||||||
sqlite3_finalize(_sDeleteNetworkAndRelated);
|
sqlite3_finalize(_sDeleteNetwork);
|
||||||
|
sqlite3_finalize(_sGetGateways);
|
||||||
|
sqlite3_finalize(_sDeleteGateways);
|
||||||
|
sqlite3_finalize(_sCreateGateway);
|
||||||
sqlite3_close(_db);
|
sqlite3_close(_db);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -455,6 +461,52 @@ NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(co
|
||||||
netconf[ZT_NETWORKCONFIG_DICT_KEY_RELAYS] = relays;
|
netconf[ZT_NETWORKCONFIG_DICT_KEY_RELAYS] = relays;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
char tmp[128];
|
||||||
|
std::string gateways;
|
||||||
|
sqlite3_reset(_sGetGateways);
|
||||||
|
sqlite3_bind_text(_sGetGateways,1,network.id,16,SQLITE_STATIC);
|
||||||
|
while (sqlite3_step(_sGetGateways) == SQLITE_ROW) {
|
||||||
|
const unsigned char *ip = (const unsigned char *)sqlite3_column_blob(_sGetGateways,0);
|
||||||
|
switch(sqlite3_column_int(_sGetGateways,1)) { // ipVersion
|
||||||
|
case 4:
|
||||||
|
Utils::snprintf(tmp,sizeof(tmp),"%s%d.%d.%d.%d/%d",
|
||||||
|
(gateways.length() > 0) ? "," : "",
|
||||||
|
(int)ip[0],
|
||||||
|
(int)ip[1],
|
||||||
|
(int)ip[2],
|
||||||
|
(int)ip[3],
|
||||||
|
(int)sqlite3_column_int(_sGetGateways,2)); // metric
|
||||||
|
gateways.append(tmp);
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
Utils::snprintf(tmp,sizeof(tmp),"%s%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x/%d",
|
||||||
|
(gateways.length() > 0) ? "," : "",
|
||||||
|
(int)ip[0],
|
||||||
|
(int)ip[1],
|
||||||
|
(int)ip[2],
|
||||||
|
(int)ip[3],
|
||||||
|
(int)ip[4],
|
||||||
|
(int)ip[5],
|
||||||
|
(int)ip[6],
|
||||||
|
(int)ip[7],
|
||||||
|
(int)ip[8],
|
||||||
|
(int)ip[9],
|
||||||
|
(int)ip[10],
|
||||||
|
(int)ip[11],
|
||||||
|
(int)ip[12],
|
||||||
|
(int)ip[13],
|
||||||
|
(int)ip[14],
|
||||||
|
(int)ip[15],
|
||||||
|
(int)sqlite3_column_int(_sGetGateways,2)); // metric
|
||||||
|
gateways.append(tmp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (gateways.length())
|
||||||
|
netconf[ZT_NETWORKCONFIG_DICT_KEY_GATEWAYS] = gateways;
|
||||||
|
}
|
||||||
|
|
||||||
if ((network.v4AssignMode)&&(!strcmp(network.v4AssignMode,"zt"))) {
|
if ((network.v4AssignMode)&&(!strcmp(network.v4AssignMode,"zt"))) {
|
||||||
std::string v4s;
|
std::string v4s;
|
||||||
|
|
||||||
|
@ -808,6 +860,31 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(
|
||||||
sqlite3_step(_sCreateRelay);
|
sqlite3_step(_sCreateRelay);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (!strcmp(j->u.object.values[k].name,"gateways")) {
|
||||||
|
sqlite3_reset(_sDeleteGateways);
|
||||||
|
sqlite3_bind_text(_sDeleteGateways,1,nwids,16,SQLITE_STATIC);
|
||||||
|
sqlite3_step(_sDeleteGateways);
|
||||||
|
if (j->u.object.values[k].value->type == json_array) {
|
||||||
|
for(unsigned int kk=0;kk<j->u.object.values[k].value->u.array.length;++kk) {
|
||||||
|
json_value *gateway = j->u.object.values[k].value->u.array.values[kk];
|
||||||
|
if ((gateway)&&(gateway->type == json_string)) {
|
||||||
|
InetAddress gwip(gateway->u.string.ptr);
|
||||||
|
int ipVersion = 0;
|
||||||
|
if (gwip.ss_family == AF_INET)
|
||||||
|
ipVersion = 4;
|
||||||
|
else if (gwip.ss_family == AF_INET6)
|
||||||
|
ipVersion = 6;
|
||||||
|
if (ipVersion) {
|
||||||
|
sqlite3_reset(_sCreateGateway);
|
||||||
|
sqlite3_bind_text(_sCreateGateway,1,nwids,16,SQLITE_STATIC);
|
||||||
|
sqlite3_bind_blob(_sCreateGateway,2,gwip.rawIpData(),(gwip.ss_family == AF_INET6) ? 16 : 4,SQLITE_STATIC);
|
||||||
|
sqlite3_bind_int(_sCreateGateway,3,ipVersion);
|
||||||
|
sqlite3_bind_int(_sCreateGateway,4,(int)gwip.metric());
|
||||||
|
sqlite3_step(_sCreateGateway);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (!strcmp(j->u.object.values[k].name,"ipAssignmentPools")) {
|
} else if (!strcmp(j->u.object.values[k].name,"ipAssignmentPools")) {
|
||||||
if (j->u.object.values[k].value->type == json_array) {
|
if (j->u.object.values[k].value->type == json_array) {
|
||||||
std::set<InetAddress> pools;
|
std::set<InetAddress> pools;
|
||||||
|
@ -855,7 +932,7 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(
|
||||||
json_value *rj = j->u.object.values[k].value->u.array.values[kk];
|
json_value *rj = j->u.object.values[k].value->u.array.values[kk];
|
||||||
if ((rj)&&(rj->type == json_object)) {
|
if ((rj)&&(rj->type == json_object)) {
|
||||||
struct { // NULL pointers indicate missing or NULL -- wildcards
|
struct { // NULL pointers indicate missing or NULL -- wildcards
|
||||||
const json_int_t *ruleId;
|
const json_int_t *ruleNo;
|
||||||
const char *nodeId;
|
const char *nodeId;
|
||||||
const json_int_t *vlanId;
|
const json_int_t *vlanId;
|
||||||
const json_int_t *vlanPcp;
|
const json_int_t *vlanPcp;
|
||||||
|
@ -875,8 +952,8 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(
|
||||||
memset(&rule,0,sizeof(rule));
|
memset(&rule,0,sizeof(rule));
|
||||||
|
|
||||||
for(unsigned int rk=0;rk<rj->u.object.length;++rk) {
|
for(unsigned int rk=0;rk<rj->u.object.length;++rk) {
|
||||||
if ((!strcmp(rj->u.object.values[rk].name,"ruleId"))&&(rj->u.object.values[rk].value->type == json_integer))
|
if ((!strcmp(rj->u.object.values[rk].name,"ruleNo"))&&(rj->u.object.values[rk].value->type == json_integer))
|
||||||
rule.ruleId = &(rj->u.object.values[rk].value->u.integer);
|
rule.ruleNo = &(rj->u.object.values[rk].value->u.integer);
|
||||||
else if ((!strcmp(rj->u.object.values[rk].name,"nodeId"))&&(rj->u.object.values[rk].value->type == json_string))
|
else if ((!strcmp(rj->u.object.values[rk].name,"nodeId"))&&(rj->u.object.values[rk].value->type == json_string))
|
||||||
rule.nodeId = rj->u.object.values[rk].value->u.string.ptr;
|
rule.nodeId = rj->u.object.values[rk].value->u.string.ptr;
|
||||||
else if ((!strcmp(rj->u.object.values[rk].name,"vlanId"))&&(rj->u.object.values[rk].value->type == json_integer))
|
else if ((!strcmp(rj->u.object.values[rk].name,"vlanId"))&&(rj->u.object.values[rk].value->type == json_integer))
|
||||||
|
@ -909,11 +986,11 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(
|
||||||
rule.action = rj->u.object.values[rk].value->u.string.ptr;
|
rule.action = rj->u.object.values[rk].value->u.string.ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((rule.ruleId)&&(rule.action)&&(rule.action[0])) {
|
if ((rule.ruleNo)&&(rule.action)&&(rule.action[0])) {
|
||||||
char mactmp1[16],mactmp2[16];
|
char mactmp1[16],mactmp2[16];
|
||||||
sqlite3_reset(_sCreateRule);
|
sqlite3_reset(_sCreateRule);
|
||||||
sqlite3_bind_text(_sCreateRule,1,nwids,16,SQLITE_STATIC);
|
sqlite3_bind_text(_sCreateRule,1,nwids,16,SQLITE_STATIC);
|
||||||
sqlite3_bind_int64(_sCreateRule,2,*rule.ruleId);
|
sqlite3_bind_int64(_sCreateRule,2,*rule.ruleNo);
|
||||||
|
|
||||||
// Optional values: null by default
|
// Optional values: null by default
|
||||||
for(int i=3;i<=16;++i)
|
for(int i=3;i<=16;++i)
|
||||||
|
@ -993,6 +1070,11 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpDELETE(
|
||||||
char nwids[24];
|
char nwids[24];
|
||||||
Utils::snprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)nwid);
|
Utils::snprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)nwid);
|
||||||
|
|
||||||
|
sqlite3_reset(_sGetNetworkById);
|
||||||
|
sqlite3_bind_text(_sGetNetworkById,1,nwids,16,SQLITE_STATIC);
|
||||||
|
if (sqlite3_step(_sGetNetworkById) != SQLITE_ROW)
|
||||||
|
return 404;
|
||||||
|
|
||||||
if (path.size() >= 3) {
|
if (path.size() >= 3) {
|
||||||
|
|
||||||
if ((path.size() == 4)&&(path[2] == "member")&&(path[3].length() == 10)) {
|
if ((path.size() == 4)&&(path[2] == "member")&&(path[3].length() == 10)) {
|
||||||
|
@ -1000,6 +1082,12 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpDELETE(
|
||||||
char addrs[24];
|
char addrs[24];
|
||||||
Utils::snprintf(addrs,sizeof(addrs),"%.10llx",address);
|
Utils::snprintf(addrs,sizeof(addrs),"%.10llx",address);
|
||||||
|
|
||||||
|
sqlite3_reset(_sGetMember);
|
||||||
|
sqlite3_bind_text(_sGetMember,1,nwids,16,SQLITE_STATIC);
|
||||||
|
sqlite3_bind_text(_sGetMember,2,addrs,10,SQLITE_STATIC);
|
||||||
|
if (sqlite3_step(_sGetMember) != SQLITE_ROW)
|
||||||
|
return 404;
|
||||||
|
|
||||||
sqlite3_reset(_sDeleteIpAllocations);
|
sqlite3_reset(_sDeleteIpAllocations);
|
||||||
sqlite3_bind_text(_sDeleteIpAllocations,1,nwids,16,SQLITE_STATIC);
|
sqlite3_bind_text(_sDeleteIpAllocations,1,nwids,16,SQLITE_STATIC);
|
||||||
sqlite3_bind_text(_sDeleteIpAllocations,2,addrs,10,SQLITE_STATIC);
|
sqlite3_bind_text(_sDeleteIpAllocations,2,addrs,10,SQLITE_STATIC);
|
||||||
|
@ -1016,10 +1104,9 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpDELETE(
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
sqlite3_reset(_sDeleteNetworkAndRelated);
|
sqlite3_reset(_sDeleteNetwork);
|
||||||
for(int i=1;i<=7;++i)
|
sqlite3_bind_text(_sDeleteNetwork,1,nwids,16,SQLITE_STATIC);
|
||||||
sqlite3_bind_text(_sDeleteNetworkAndRelated,i,nwids,16,SQLITE_STATIC);
|
return ((sqlite3_step(_sDeleteNetwork) == SQLITE_DONE) ? 200 : 500);
|
||||||
return ((sqlite3_step(_sDeleteNetworkAndRelated) == SQLITE_DONE) ? 200 : 500);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
} // else 404
|
} // else 404
|
||||||
|
@ -1202,6 +1289,49 @@ unsigned int SqliteNetworkController::_doCPGet(
|
||||||
responseBody.append(_jsonEscape((const char *)sqlite3_column_text(_sGetRelays,1)));
|
responseBody.append(_jsonEscape((const char *)sqlite3_column_text(_sGetRelays,1)));
|
||||||
responseBody.append("\"}");
|
responseBody.append("\"}");
|
||||||
}
|
}
|
||||||
|
responseBody.append("],\n\t\"gateways\": [");
|
||||||
|
|
||||||
|
sqlite3_reset(_sGetGateways);
|
||||||
|
sqlite3_bind_text(_sGetGateways,1,nwids,16,SQLITE_STATIC);
|
||||||
|
bool firstGateway = true;
|
||||||
|
while (sqlite3_step(_sGetGateways) == SQLITE_ROW) {
|
||||||
|
char tmp[128];
|
||||||
|
const unsigned char *ip = (const unsigned char *)sqlite3_column_blob(_sGetGateways,0);
|
||||||
|
switch(sqlite3_column_int(_sGetGateways,1)) { // ipVersion
|
||||||
|
case 4:
|
||||||
|
Utils::snprintf(tmp,sizeof(tmp),"%s%d.%d.%d.%d/%d\"",
|
||||||
|
(firstGateway) ? "\"" : ",\"",
|
||||||
|
(int)ip[0],
|
||||||
|
(int)ip[1],
|
||||||
|
(int)ip[2],
|
||||||
|
(int)ip[3],
|
||||||
|
(int)sqlite3_column_int(_sGetGateways,2)); // metric
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
Utils::snprintf(tmp,sizeof(tmp),"%s%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x/%d\"",
|
||||||
|
(firstGateway) ? "\"" : ",\"",
|
||||||
|
(int)ip[0],
|
||||||
|
(int)ip[1],
|
||||||
|
(int)ip[2],
|
||||||
|
(int)ip[3],
|
||||||
|
(int)ip[4],
|
||||||
|
(int)ip[5],
|
||||||
|
(int)ip[6],
|
||||||
|
(int)ip[7],
|
||||||
|
(int)ip[8],
|
||||||
|
(int)ip[9],
|
||||||
|
(int)ip[10],
|
||||||
|
(int)ip[11],
|
||||||
|
(int)ip[12],
|
||||||
|
(int)ip[13],
|
||||||
|
(int)ip[14],
|
||||||
|
(int)ip[15],
|
||||||
|
(int)sqlite3_column_int(_sGetGateways,2)); // metric
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
responseBody.append(tmp);
|
||||||
|
firstGateway = false;
|
||||||
|
}
|
||||||
responseBody.append("],\n\t\"ipAssignmentPools\": [");
|
responseBody.append("],\n\t\"ipAssignmentPools\": [");
|
||||||
|
|
||||||
sqlite3_reset(_sGetIpAssignmentPools2);
|
sqlite3_reset(_sGetIpAssignmentPools2);
|
||||||
|
@ -1223,7 +1353,7 @@ unsigned int SqliteNetworkController::_doCPGet(
|
||||||
bool firstRule = true;
|
bool firstRule = true;
|
||||||
while (sqlite3_step(_sListRules) == SQLITE_ROW) {
|
while (sqlite3_step(_sListRules) == SQLITE_ROW) {
|
||||||
responseBody.append(firstRule ? "\n\t{\n" : ",{\n");
|
responseBody.append(firstRule ? "\n\t{\n" : ",{\n");
|
||||||
Utils::snprintf(json,sizeof(json),"\t\t\"ruleId\": %lld,\n",sqlite3_column_int64(_sListRules,0));
|
Utils::snprintf(json,sizeof(json),"\t\t\"ruleNo\": %lld,\n",sqlite3_column_int64(_sListRules,0));
|
||||||
responseBody.append(json);
|
responseBody.append(json);
|
||||||
if (sqlite3_column_type(_sListRules,1) != SQLITE_NULL) {
|
if (sqlite3_column_type(_sListRules,1) != SQLITE_NULL) {
|
||||||
Utils::snprintf(json,sizeof(json),"\t\t\"nodeId\": \"%s\",\n",(const char *)sqlite3_column_text(_sListRules,1));
|
Utils::snprintf(json,sizeof(json),"\t\t\"nodeId\": \"%s\",\n",(const char *)sqlite3_column_text(_sListRules,1));
|
||||||
|
|
|
@ -123,7 +123,10 @@ private:
|
||||||
sqlite3_stmt *_sDeleteRulesForNetwork;
|
sqlite3_stmt *_sDeleteRulesForNetwork;
|
||||||
sqlite3_stmt *_sCreateIpAssignmentPool;
|
sqlite3_stmt *_sCreateIpAssignmentPool;
|
||||||
sqlite3_stmt *_sDeleteMember;
|
sqlite3_stmt *_sDeleteMember;
|
||||||
sqlite3_stmt *_sDeleteNetworkAndRelated;
|
sqlite3_stmt *_sDeleteNetwork;
|
||||||
|
sqlite3_stmt *_sGetGateways;
|
||||||
|
sqlite3_stmt *_sDeleteGateways;
|
||||||
|
sqlite3_stmt *_sCreateGateway;
|
||||||
|
|
||||||
Mutex _lock;
|
Mutex _lock;
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,53 +3,6 @@ CREATE TABLE Config (
|
||||||
v varchar(1024) NOT NULL
|
v varchar(1024) NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE IpAssignment (
|
|
||||||
networkId char(16) NOT NULL,
|
|
||||||
nodeId char(10) NOT NULL,
|
|
||||||
ip blob(16) NOT NULL,
|
|
||||||
ipNetmaskBits integer NOT NULL DEFAULT(0),
|
|
||||||
ipVersion integer NOT NULL DEFAULT(4)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE INDEX IpAssignment_networkId_ip ON IpAssignment (networkId, ip);
|
|
||||||
|
|
||||||
CREATE INDEX IpAssignment_networkId_nodeId ON IpAssignment (networkId, nodeId);
|
|
||||||
|
|
||||||
CREATE INDEX IpAssignment_networkId ON IpAssignment (networkId);
|
|
||||||
|
|
||||||
CREATE TABLE IpAssignmentPool (
|
|
||||||
networkId char(16) NOT NULL,
|
|
||||||
ipNetwork blob(16) NOT NULL,
|
|
||||||
ipNetmaskBits integer NOT NULL,
|
|
||||||
ipVersion integer NOT NULL DEFAULT(4)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE INDEX IpAssignmentPool_networkId ON IpAssignmentPool (networkId);
|
|
||||||
|
|
||||||
CREATE TABLE Member (
|
|
||||||
networkId char(16) NOT NULL,
|
|
||||||
nodeId char(10) NOT NULL,
|
|
||||||
authorized integer NOT NULL DEFAULT(0),
|
|
||||||
activeBridge integer NOT NULL DEFAULT(0)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE INDEX Member_networkId ON Member (networkId);
|
|
||||||
|
|
||||||
CREATE INDEX Member_networkId_activeBridge ON Member(networkId, activeBridge);
|
|
||||||
|
|
||||||
CREATE UNIQUE INDEX Member_networkId_nodeId ON Member (networkId, nodeId);
|
|
||||||
|
|
||||||
CREATE TABLE MulticastRate (
|
|
||||||
networkId char(16) NOT NULL,
|
|
||||||
mgMac char(12) NOT NULL,
|
|
||||||
mgAdi integer NOT NULL DEFAULT(0),
|
|
||||||
preload integer NOT NULL,
|
|
||||||
maxBalance integer NOT NULL,
|
|
||||||
accrual integer NOT NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE INDEX MulticastRate_networkId ON MulticastRate (networkId);
|
|
||||||
|
|
||||||
CREATE TABLE Network (
|
CREATE TABLE Network (
|
||||||
id char(16) PRIMARY KEY NOT NULL,
|
id char(16) PRIMARY KEY NOT NULL,
|
||||||
name varchar(128) NOT NULL,
|
name varchar(128) NOT NULL,
|
||||||
|
@ -63,16 +16,6 @@ CREATE TABLE Network (
|
||||||
revision integer NOT NULL DEFAULT(1)
|
revision integer NOT NULL DEFAULT(1)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE Relay (
|
|
||||||
networkId char(16) NOT NULL,
|
|
||||||
nodeId char(10) NOT NULL,
|
|
||||||
phyAddress varchar(64) NOT NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE INDEX Relay_networkId ON Relay (networkId);
|
|
||||||
|
|
||||||
CREATE UNIQUE INDEX Relay_networkId_nodeId ON Relay (networkId, nodeId);
|
|
||||||
|
|
||||||
CREATE TABLE Node (
|
CREATE TABLE Node (
|
||||||
id char(10) PRIMARY KEY NOT NULL,
|
id char(10) PRIMARY KEY NOT NULL,
|
||||||
identity varchar(4096) NOT NULL,
|
identity varchar(4096) NOT NULL,
|
||||||
|
@ -81,10 +24,70 @@ CREATE TABLE Node (
|
||||||
firstSeen integer NOT NULL DEFAULT(0)
|
firstSeen integer NOT NULL DEFAULT(0)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE TABLE Gateway (
|
||||||
|
networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,
|
||||||
|
ip blob(16) NOT NULL,
|
||||||
|
ipVersion integer NOT NULL DEFAULT(4),
|
||||||
|
metric integer NOT NULL DEFAULT(0)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX Gateway_networkId_ip ON Gateway (networkId, ip);
|
||||||
|
|
||||||
|
CREATE TABLE IpAssignment (
|
||||||
|
networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,
|
||||||
|
nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE,
|
||||||
|
ip blob(16) NOT NULL,
|
||||||
|
ipNetmaskBits integer NOT NULL DEFAULT(0),
|
||||||
|
ipVersion integer NOT NULL DEFAULT(4)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX IpAssignment_networkId_ip ON IpAssignment (networkId, ip);
|
||||||
|
|
||||||
|
CREATE INDEX IpAssignment_networkId_nodeId ON IpAssignment (networkId, nodeId);
|
||||||
|
|
||||||
|
CREATE TABLE IpAssignmentPool (
|
||||||
|
networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,
|
||||||
|
ipNetwork blob(16) NOT NULL,
|
||||||
|
ipNetmaskBits integer NOT NULL,
|
||||||
|
ipVersion integer NOT NULL DEFAULT(4)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IpAssignmentPool_networkId ON IpAssignmentPool (networkId);
|
||||||
|
|
||||||
|
CREATE TABLE Member (
|
||||||
|
networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,
|
||||||
|
nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE,
|
||||||
|
authorized integer NOT NULL DEFAULT(0),
|
||||||
|
activeBridge integer NOT NULL DEFAULT(0),
|
||||||
|
PRIMARY KEY (networkId, nodeId)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX Member_networkId_activeBridge ON Member(networkId, activeBridge);
|
||||||
|
|
||||||
|
CREATE TABLE MulticastRate (
|
||||||
|
networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,
|
||||||
|
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 Relay (
|
||||||
|
networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,
|
||||||
|
nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE,
|
||||||
|
phyAddress varchar(64) NOT NULL,
|
||||||
|
PRIMARY KEY (networkId, nodeId)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX Relay_networkId ON Relay (networkId);
|
||||||
|
|
||||||
CREATE TABLE Rule (
|
CREATE TABLE Rule (
|
||||||
networkId char(16) NOT NULL,
|
networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,
|
||||||
ruleId integer NOT NULL,
|
ruleNo integer NOT NULL,
|
||||||
nodeId char(10),
|
nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE,
|
||||||
vlanId integer,
|
vlanId integer,
|
||||||
vlanPcp integer,
|
vlanPcp integer,
|
||||||
etherType integer,
|
etherType integer,
|
||||||
|
@ -101,4 +104,4 @@ CREATE TABLE Rule (
|
||||||
"action" varchar(4096) NOT NULL DEFAULT('accept')
|
"action" varchar(4096) NOT NULL DEFAULT('accept')
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE INDEX Rule_networkId ON Rule (networkId);
|
CREATE UNIQUE INDEX Rule_networkId_ruleNo ON Rule (networkId, ruleNo);
|
||||||
|
|
|
@ -4,53 +4,6 @@
|
||||||
" v varchar(1024) NOT NULL\n"\
|
" v varchar(1024) NOT NULL\n"\
|
||||||
");\n"\
|
");\n"\
|
||||||
"\n"\
|
"\n"\
|
||||||
"CREATE TABLE IpAssignment (\n"\
|
|
||||||
" networkId char(16) NOT NULL,\n"\
|
|
||||||
" nodeId char(10) NOT NULL,\n"\
|
|
||||||
" ip blob(16) NOT NULL,\n"\
|
|
||||||
" ipNetmaskBits integer NOT NULL DEFAULT(0),\n"\
|
|
||||||
" ipVersion integer NOT NULL DEFAULT(4)\n"\
|
|
||||||
");\n"\
|
|
||||||
"\n"\
|
|
||||||
"CREATE INDEX IpAssignment_networkId_ip ON IpAssignment (networkId, ip);\n"\
|
|
||||||
"\n"\
|
|
||||||
"CREATE INDEX IpAssignment_networkId_nodeId ON IpAssignment (networkId, nodeId);\n"\
|
|
||||||
"\n"\
|
|
||||||
"CREATE INDEX IpAssignment_networkId ON IpAssignment (networkId);\n"\
|
|
||||||
"\n"\
|
|
||||||
"CREATE TABLE IpAssignmentPool (\n"\
|
|
||||||
" networkId char(16) NOT NULL,\n"\
|
|
||||||
" ipNetwork blob(16) NOT NULL,\n"\
|
|
||||||
" ipNetmaskBits integer NOT NULL,\n"\
|
|
||||||
" ipVersion integer NOT NULL DEFAULT(4)\n"\
|
|
||||||
");\n"\
|
|
||||||
"\n"\
|
|
||||||
"CREATE INDEX IpAssignmentPool_networkId ON IpAssignmentPool (networkId);\n"\
|
|
||||||
"\n"\
|
|
||||||
"CREATE TABLE Member (\n"\
|
|
||||||
" networkId char(16) NOT NULL,\n"\
|
|
||||||
" nodeId char(10) NOT NULL,\n"\
|
|
||||||
" authorized integer NOT NULL DEFAULT(0),\n"\
|
|
||||||
" activeBridge integer NOT NULL DEFAULT(0)\n"\
|
|
||||||
");\n"\
|
|
||||||
"\n"\
|
|
||||||
"CREATE INDEX Member_networkId ON Member (networkId);\n"\
|
|
||||||
"\n"\
|
|
||||||
"CREATE INDEX Member_networkId_activeBridge ON Member(networkId, activeBridge);\n"\
|
|
||||||
"\n"\
|
|
||||||
"CREATE UNIQUE INDEX Member_networkId_nodeId ON Member (networkId, nodeId);\n"\
|
|
||||||
"\n"\
|
|
||||||
"CREATE TABLE MulticastRate (\n"\
|
|
||||||
" networkId char(16) NOT NULL,\n"\
|
|
||||||
" mgMac char(12) NOT NULL,\n"\
|
|
||||||
" mgAdi integer NOT NULL DEFAULT(0),\n"\
|
|
||||||
" preload integer NOT NULL,\n"\
|
|
||||||
" maxBalance integer NOT NULL,\n"\
|
|
||||||
" accrual integer NOT NULL\n"\
|
|
||||||
");\n"\
|
|
||||||
"\n"\
|
|
||||||
"CREATE INDEX MulticastRate_networkId ON MulticastRate (networkId);\n"\
|
|
||||||
"\n"\
|
|
||||||
"CREATE TABLE Network (\n"\
|
"CREATE TABLE Network (\n"\
|
||||||
" id char(16) PRIMARY KEY NOT NULL,\n"\
|
" id char(16) PRIMARY KEY NOT NULL,\n"\
|
||||||
" name varchar(128) NOT NULL,\n"\
|
" name varchar(128) NOT NULL,\n"\
|
||||||
|
@ -64,16 +17,6 @@
|
||||||
" revision integer NOT NULL DEFAULT(1)\n"\
|
" revision integer NOT NULL DEFAULT(1)\n"\
|
||||||
");\n"\
|
");\n"\
|
||||||
"\n"\
|
"\n"\
|
||||||
"CREATE TABLE Relay (\n"\
|
|
||||||
" networkId char(16) NOT NULL,\n"\
|
|
||||||
" nodeId char(10) NOT NULL,\n"\
|
|
||||||
" phyAddress varchar(64) NOT NULL\n"\
|
|
||||||
");\n"\
|
|
||||||
"\n"\
|
|
||||||
"CREATE INDEX Relay_networkId ON Relay (networkId);\n"\
|
|
||||||
"\n"\
|
|
||||||
"CREATE UNIQUE INDEX Relay_networkId_nodeId ON Relay (networkId, nodeId);\n"\
|
|
||||||
"\n"\
|
|
||||||
"CREATE TABLE Node (\n"\
|
"CREATE TABLE Node (\n"\
|
||||||
" id char(10) PRIMARY KEY NOT NULL,\n"\
|
" id char(10) PRIMARY KEY NOT NULL,\n"\
|
||||||
" identity varchar(4096) NOT NULL,\n"\
|
" identity varchar(4096) NOT NULL,\n"\
|
||||||
|
@ -82,10 +25,70 @@
|
||||||
" firstSeen integer NOT NULL DEFAULT(0)\n"\
|
" firstSeen integer NOT NULL DEFAULT(0)\n"\
|
||||||
");\n"\
|
");\n"\
|
||||||
"\n"\
|
"\n"\
|
||||||
|
"CREATE TABLE Gateway (\n"\
|
||||||
|
" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\
|
||||||
|
" ip blob(16) NOT NULL,\n"\
|
||||||
|
" ipVersion integer NOT NULL DEFAULT(4),\n"\
|
||||||
|
" metric integer NOT NULL DEFAULT(0)\n"\
|
||||||
|
");\n"\
|
||||||
|
"\n"\
|
||||||
|
"CREATE UNIQUE INDEX Gateway_networkId_ip ON Gateway (networkId, ip);\n"\
|
||||||
|
"\n"\
|
||||||
|
"CREATE TABLE IpAssignment (\n"\
|
||||||
|
" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\
|
||||||
|
" nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE,\n"\
|
||||||
|
" ip blob(16) NOT NULL,\n"\
|
||||||
|
" ipNetmaskBits integer NOT NULL DEFAULT(0),\n"\
|
||||||
|
" ipVersion integer NOT NULL DEFAULT(4)\n"\
|
||||||
|
");\n"\
|
||||||
|
"\n"\
|
||||||
|
"CREATE UNIQUE INDEX IpAssignment_networkId_ip ON IpAssignment (networkId, ip);\n"\
|
||||||
|
"\n"\
|
||||||
|
"CREATE INDEX IpAssignment_networkId_nodeId ON IpAssignment (networkId, nodeId);\n"\
|
||||||
|
"\n"\
|
||||||
|
"CREATE TABLE IpAssignmentPool (\n"\
|
||||||
|
" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\
|
||||||
|
" ipNetwork blob(16) NOT NULL,\n"\
|
||||||
|
" ipNetmaskBits integer NOT NULL,\n"\
|
||||||
|
" ipVersion integer NOT NULL DEFAULT(4)\n"\
|
||||||
|
");\n"\
|
||||||
|
"\n"\
|
||||||
|
"CREATE INDEX IpAssignmentPool_networkId ON IpAssignmentPool (networkId);\n"\
|
||||||
|
"\n"\
|
||||||
|
"CREATE TABLE Member (\n"\
|
||||||
|
" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\
|
||||||
|
" nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE,\n"\
|
||||||
|
" authorized integer NOT NULL DEFAULT(0),\n"\
|
||||||
|
" activeBridge integer NOT NULL DEFAULT(0),\n"\
|
||||||
|
" PRIMARY KEY (networkId, nodeId)\n"\
|
||||||
|
");\n"\
|
||||||
|
"\n"\
|
||||||
|
"CREATE INDEX Member_networkId_activeBridge ON Member(networkId, activeBridge);\n"\
|
||||||
|
"\n"\
|
||||||
|
"CREATE TABLE MulticastRate (\n"\
|
||||||
|
" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\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 Relay (\n"\
|
||||||
|
" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\
|
||||||
|
" nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE,\n"\
|
||||||
|
" phyAddress varchar(64) NOT NULL,\n"\
|
||||||
|
" PRIMARY KEY (networkId, nodeId)\n"\
|
||||||
|
");\n"\
|
||||||
|
"\n"\
|
||||||
|
"CREATE INDEX Relay_networkId ON Relay (networkId);\n"\
|
||||||
|
"\n"\
|
||||||
"CREATE TABLE Rule (\n"\
|
"CREATE TABLE Rule (\n"\
|
||||||
" networkId char(16) NOT NULL,\n"\
|
" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\
|
||||||
" ruleId integer NOT NULL,\n"\
|
" ruleNo integer NOT NULL,\n"\
|
||||||
" nodeId char(10),\n"\
|
" nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE,\n"\
|
||||||
" vlanId integer,\n"\
|
" vlanId integer,\n"\
|
||||||
" vlanPcp integer,\n"\
|
" vlanPcp integer,\n"\
|
||||||
" etherType integer,\n"\
|
" etherType integer,\n"\
|
||||||
|
@ -102,5 +105,5 @@
|
||||||
" \"action\" varchar(4096) NOT NULL DEFAULT('accept')\n"\
|
" \"action\" varchar(4096) NOT NULL DEFAULT('accept')\n"\
|
||||||
");\n"\
|
");\n"\
|
||||||
"\n"\
|
"\n"\
|
||||||
"CREATE INDEX Rule_networkId ON Rule (networkId);\n"\
|
"CREATE UNIQUE INDEX Rule_networkId_ruleNo ON Rule (networkId, ruleNo);\n"\
|
||||||
""
|
""
|
||||||
|
|
|
@ -49,9 +49,12 @@ case "$system" in
|
||||||
|
|
||||||
echo "Assembling Linux installer for $machine and version $vmajor.$vminor.$revision"
|
echo "Assembling Linux installer for $machine and version $vmajor.$vminor.$revision"
|
||||||
|
|
||||||
mkdir -p 'build-installer/var/lib/zerotier-one'
|
mkdir -p 'build-installer/var/lib/zerotier-one/ui'
|
||||||
cp -fp 'ext/installfiles/linux/uninstall.sh' 'build-installer/var/lib/zerotier-one'
|
cp -fp 'ext/installfiles/linux/uninstall.sh' 'build-installer/var/lib/zerotier-one'
|
||||||
cp -fp 'zerotier-one' 'build-installer/var/lib/zerotier-one'
|
cp -fp 'zerotier-one' 'build-installer/var/lib/zerotier-one'
|
||||||
|
for f in ui/*.html ui/*.js ui/*.css ui/*.jsx ; do
|
||||||
|
cp -fp "$f" 'build-installer/var/lib/zerotier-one/ui'
|
||||||
|
done
|
||||||
mkdir -p 'build-installer/tmp'
|
mkdir -p 'build-installer/tmp'
|
||||||
cp -fp 'ext/installfiles/linux/init.d/zerotier-one' 'build-installer/tmp/init.d_zerotier-one'
|
cp -fp 'ext/installfiles/linux/init.d/zerotier-one' 'build-installer/tmp/init.d_zerotier-one'
|
||||||
cp -fp 'ext/installfiles/linux/systemd/zerotier-one.service' 'build-installer/tmp/systemd_zerotier-one.service'
|
cp -fp 'ext/installfiles/linux/systemd/zerotier-one.service' 'build-installer/tmp/systemd_zerotier-one.service'
|
||||||
|
|
|
@ -265,6 +265,16 @@ struct InetAddress : public sockaddr_storage
|
||||||
*/
|
*/
|
||||||
inline unsigned int netmaskBits() const throw() { return port(); }
|
inline unsigned int netmaskBits() const throw() { return port(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for port()
|
||||||
|
*
|
||||||
|
* This just aliases port() because for gateways we use this field to
|
||||||
|
* store the gateway metric.
|
||||||
|
*
|
||||||
|
* @return Gateway metric
|
||||||
|
*/
|
||||||
|
inline unsigned int metric() const throw() { return port(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a full netmask as an InetAddress
|
* Construct a full netmask as an InetAddress
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -163,6 +163,13 @@ void NetworkConfig::_fromDictionary(const Dictionary &d)
|
||||||
std::sort(_staticIps.begin(),_staticIps.end());
|
std::sort(_staticIps.begin(),_staticIps.end());
|
||||||
std::unique(_staticIps.begin(),_staticIps.end());
|
std::unique(_staticIps.begin(),_staticIps.end());
|
||||||
|
|
||||||
|
std::vector<std::string> gatewaysSplit(Utils::split(d.get(ZT_NETWORKCONFIG_DICT_KEY_GATEWAYS,"").c_str(),",","",""));
|
||||||
|
for(std::vector<std::string>::const_iterator gwstr(gatewaysSplit.begin());gwstr!=gatewaysSplit.end();++gwstr) {
|
||||||
|
InetAddress gw(*gwstr);
|
||||||
|
if ((std::find(_gateways.begin(),_gateways.end(),gw) == _gateways.end())&&((gw.ss_family == AF_INET)||(gw.ss_family == AF_INET6)))
|
||||||
|
_gateways.push_back(gw);
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<std::string> activeBridgesSplit(Utils::split(d.get(ZT_NETWORKCONFIG_DICT_KEY_ACTIVE_BRIDGES,"").c_str(),",","",""));
|
std::vector<std::string> activeBridgesSplit(Utils::split(d.get(ZT_NETWORKCONFIG_DICT_KEY_ACTIVE_BRIDGES,"").c_str(),",","",""));
|
||||||
for(std::vector<std::string>::const_iterator a(activeBridgesSplit.begin());a!=activeBridgesSplit.end();++a) {
|
for(std::vector<std::string>::const_iterator a(activeBridgesSplit.begin());a!=activeBridgesSplit.end();++a) {
|
||||||
if (a->length() == ZT_ADDRESS_LENGTH_HEX) { // ignore empty or garbage fields
|
if (a->length() == ZT_ADDRESS_LENGTH_HEX) { // ignore empty or garbage fields
|
||||||
|
@ -211,7 +218,9 @@ bool NetworkConfig::operator==(const NetworkConfig &nc) const
|
||||||
if (_name != nc._name) return false;
|
if (_name != nc._name) return false;
|
||||||
if (_description != nc._description) return false;
|
if (_description != nc._description) return false;
|
||||||
if (_staticIps != nc._staticIps) return false;
|
if (_staticIps != nc._staticIps) return false;
|
||||||
|
if (_gateways != nc._gateways) return false;
|
||||||
if (_activeBridges != nc._activeBridges) return false;
|
if (_activeBridges != nc._activeBridges) return false;
|
||||||
|
if (_relays != nc._relays) return false;
|
||||||
if (_multicastRates.size() == nc._multicastRates.size()) {
|
if (_multicastRates.size() == nc._multicastRates.size()) {
|
||||||
// uclibc++ doesn't seem to implement map<> != map<> correctly, so do
|
// uclibc++ doesn't seem to implement map<> != map<> correctly, so do
|
||||||
// it ourselves. Note that this depends on the maps being sorted.
|
// it ourselves. Note that this depends on the maps being sorted.
|
||||||
|
|
|
@ -49,24 +49,61 @@ namespace ZeroTier {
|
||||||
|
|
||||||
// These dictionary keys are short so they don't take up much room in
|
// These dictionary keys are short so they don't take up much room in
|
||||||
// netconf response packets.
|
// netconf response packets.
|
||||||
|
|
||||||
|
// integer(hex)[,integer(hex),...]
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_ALLOWED_ETHERNET_TYPES "et"
|
#define ZT_NETWORKCONFIG_DICT_KEY_ALLOWED_ETHERNET_TYPES "et"
|
||||||
|
|
||||||
|
// network ID
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_NETWORK_ID "nwid"
|
#define ZT_NETWORKCONFIG_DICT_KEY_NETWORK_ID "nwid"
|
||||||
|
|
||||||
|
// integer(hex)
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_TIMESTAMP "ts"
|
#define ZT_NETWORKCONFIG_DICT_KEY_TIMESTAMP "ts"
|
||||||
|
|
||||||
|
// integer(hex)
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_REVISION "r"
|
#define ZT_NETWORKCONFIG_DICT_KEY_REVISION "r"
|
||||||
|
|
||||||
|
// address of member
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO "id"
|
#define ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO "id"
|
||||||
|
|
||||||
|
// integer(hex)
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT "ml"
|
#define ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT "ml"
|
||||||
|
|
||||||
|
// dictionary of one or more of: MAC/ADI=preload,maxbalance,accrual
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_RATES "mr"
|
#define ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_RATES "mr"
|
||||||
|
|
||||||
|
// 0/1
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_PRIVATE "p"
|
#define ZT_NETWORKCONFIG_DICT_KEY_PRIVATE "p"
|
||||||
|
|
||||||
|
// text
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_NAME "n"
|
#define ZT_NETWORKCONFIG_DICT_KEY_NAME "n"
|
||||||
|
|
||||||
|
// text
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_DESC "d"
|
#define ZT_NETWORKCONFIG_DICT_KEY_DESC "d"
|
||||||
|
|
||||||
|
// IP/bits[,IP/bits,...]
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_IPV4_STATIC "v4s"
|
#define ZT_NETWORKCONFIG_DICT_KEY_IPV4_STATIC "v4s"
|
||||||
|
|
||||||
|
// IP/bits[,IP/bits,...]
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_IPV6_STATIC "v6s"
|
#define ZT_NETWORKCONFIG_DICT_KEY_IPV6_STATIC "v6s"
|
||||||
|
|
||||||
|
// serialized CertificateOfMembership
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATE_OF_MEMBERSHIP "com"
|
#define ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATE_OF_MEMBERSHIP "com"
|
||||||
|
|
||||||
|
// 0/1
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_ENABLE_BROADCAST "eb"
|
#define ZT_NETWORKCONFIG_DICT_KEY_ENABLE_BROADCAST "eb"
|
||||||
|
|
||||||
|
// 0/1
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_ALLOW_PASSIVE_BRIDGING "pb"
|
#define ZT_NETWORKCONFIG_DICT_KEY_ALLOW_PASSIVE_BRIDGING "pb"
|
||||||
|
|
||||||
|
// node[,node,...]
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_ACTIVE_BRIDGES "ab"
|
#define ZT_NETWORKCONFIG_DICT_KEY_ACTIVE_BRIDGES "ab"
|
||||||
|
|
||||||
|
// node;IP/port[,node;IP/port]
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_RELAYS "rl"
|
#define ZT_NETWORKCONFIG_DICT_KEY_RELAYS "rl"
|
||||||
|
|
||||||
|
// IP/metric[,IP/metric,...]
|
||||||
|
#define ZT_NETWORKCONFIG_DICT_KEY_GATEWAYS "gw"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Network configuration received from network controller nodes
|
* Network configuration received from network controller nodes
|
||||||
*
|
*
|
||||||
|
@ -146,6 +183,7 @@ public:
|
||||||
inline const std::string &name() const throw() { return _name; }
|
inline const std::string &name() const throw() { return _name; }
|
||||||
inline const std::string &description() const throw() { return _description; }
|
inline const std::string &description() const throw() { return _description; }
|
||||||
inline const std::vector<InetAddress> &staticIps() const throw() { return _staticIps; }
|
inline const std::vector<InetAddress> &staticIps() const throw() { return _staticIps; }
|
||||||
|
inline const std::vector<InetAddress> &gateways() const throw() { return _gateways; }
|
||||||
inline const std::vector<Address> &activeBridges() const throw() { return _activeBridges; }
|
inline const std::vector<Address> &activeBridges() const throw() { return _activeBridges; }
|
||||||
inline const std::vector< std::pair<Address,InetAddress> > &relays() const throw() { return _relays; }
|
inline const std::vector< std::pair<Address,InetAddress> > &relays() const throw() { return _relays; }
|
||||||
inline const CertificateOfMembership &com() const throw() { return _com; }
|
inline const CertificateOfMembership &com() const throw() { return _com; }
|
||||||
|
@ -188,6 +226,7 @@ private:
|
||||||
std::string _name;
|
std::string _name;
|
||||||
std::string _description;
|
std::string _description;
|
||||||
std::vector<InetAddress> _staticIps;
|
std::vector<InetAddress> _staticIps;
|
||||||
|
std::vector<InetAddress> _gateways;
|
||||||
std::vector<Address> _activeBridges;
|
std::vector<Address> _activeBridges;
|
||||||
std::vector< std::pair<Address,InetAddress> > _relays;
|
std::vector< std::pair<Address,InetAddress> > _relays;
|
||||||
std::map<MulticastGroup,MulticastRate> _multicastRates;
|
std::map<MulticastGroup,MulticastRate> _multicastRates;
|
||||||
|
|
|
@ -51,6 +51,7 @@ const char *Packet::verbString(Verb v)
|
||||||
case VERB_MULTICAST_GATHER: return "MULTICAST_GATHER";
|
case VERB_MULTICAST_GATHER: return "MULTICAST_GATHER";
|
||||||
case VERB_MULTICAST_FRAME: return "MULTICAST_FRAME";
|
case VERB_MULTICAST_FRAME: return "MULTICAST_FRAME";
|
||||||
case VERB_SET_EPHEMERAL_KEY: return "SET_EPHEMERAL_KEY";
|
case VERB_SET_EPHEMERAL_KEY: return "SET_EPHEMERAL_KEY";
|
||||||
|
case VERB_CMA: return "CMA";
|
||||||
}
|
}
|
||||||
return "(unknown)";
|
return "(unknown)";
|
||||||
}
|
}
|
||||||
|
|
|
@ -513,8 +513,8 @@ public:
|
||||||
* Destination address types and formats (not all of these are used now):
|
* Destination address types and formats (not all of these are used now):
|
||||||
* 0 - None -- no destination address data present
|
* 0 - None -- no destination address data present
|
||||||
* 1 - Ethernet address -- format: <[6] Ethernet MAC>
|
* 1 - Ethernet address -- format: <[6] Ethernet MAC>
|
||||||
* 4 - 6-byte IPv4 address -- format: <[4] IP>, <[2] port>
|
* 4 - 6-byte IPv4 UDP address/port -- format: <[4] IP>, <[2] port>
|
||||||
* 6 - 18-byte IPv6 address -- format: <[16] IP>, <[2] port>
|
* 6 - 18-byte IPv6 UDP address/port -- format: <[16] IP>, <[2] port>
|
||||||
*
|
*
|
||||||
* OK payload:
|
* OK payload:
|
||||||
* <[8] timestamp (echoed from original HELLO)>
|
* <[8] timestamp (echoed from original HELLO)>
|
||||||
|
@ -770,6 +770,9 @@ public:
|
||||||
VERB_MULTICAST_FRAME = 14,
|
VERB_MULTICAST_FRAME = 14,
|
||||||
|
|
||||||
/* Ephemeral (PFS) key push:
|
/* Ephemeral (PFS) key push:
|
||||||
|
* <[2] flags (unused and reserved, must be 0)>
|
||||||
|
* <[2] length of padding / extra field section>
|
||||||
|
* <[...] padding / extra field section>
|
||||||
* <[8] 64-bit PFS key set ID sender holds for recipient (0==none)>
|
* <[8] 64-bit PFS key set ID sender holds for recipient (0==none)>
|
||||||
* <[8] 64-bit PFS key set ID of this key set>
|
* <[8] 64-bit PFS key set ID of this key set>
|
||||||
* [... begin PFS key record ...]
|
* [... begin PFS key record ...]
|
||||||
|
@ -791,6 +794,12 @@ public:
|
||||||
* the first record with common symmetric cipher, public key type,
|
* the first record with common symmetric cipher, public key type,
|
||||||
* and relevant flags must be used.
|
* and relevant flags must be used.
|
||||||
*
|
*
|
||||||
|
* The padding section may be filled with an arbitrary amount of random
|
||||||
|
* or empty payload. This may be used as a countermeasure to prevent PFS
|
||||||
|
* key pushes from being recognized by packet size vs. other packets in
|
||||||
|
* the stream. This also provides potential space for additional fields
|
||||||
|
* that might be indicated in the future by flags.
|
||||||
|
*
|
||||||
* Flags (all unspecified flags must be zero):
|
* Flags (all unspecified flags must be zero):
|
||||||
* 0x01 - FIPS mode, only use record if FIPS compliant crypto in use
|
* 0x01 - FIPS mode, only use record if FIPS compliant crypto in use
|
||||||
*
|
*
|
||||||
|
@ -814,7 +823,24 @@ public:
|
||||||
* <[8] PFS key set ID of received key set>
|
* <[8] PFS key set ID of received key set>
|
||||||
* <[1] index in record list of chosen key record>
|
* <[1] index in record list of chosen key record>
|
||||||
*/
|
*/
|
||||||
VERB_SET_EPHEMERAL_KEY = 15
|
VERB_SET_EPHEMERAL_KEY = 15,
|
||||||
|
|
||||||
|
/* "Call me at" -- push of potential endpoints for direct communication:
|
||||||
|
* <[1] flags>
|
||||||
|
* <[2] number of addresses>
|
||||||
|
* <[...] address types and addresses>
|
||||||
|
*
|
||||||
|
* Address types and addresses are of the same format as the destination
|
||||||
|
* address type and address in HELLO.
|
||||||
|
*
|
||||||
|
* The receiver may, upon receiving a CMA push, attempt to establish a
|
||||||
|
* direct link to one or more of the indicated addresses. Senders should
|
||||||
|
* only send CMA pushes to peers that they have some relationship
|
||||||
|
* with such as a shared network membership or a mutual trust.
|
||||||
|
*
|
||||||
|
* OK/ERROR are not generated.
|
||||||
|
*/
|
||||||
|
VERB_CMA = 16
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -92,9 +92,6 @@ static const WindowsEthernetTapEnv WINENV;
|
||||||
// Only create or delete devices one at a time
|
// Only create or delete devices one at a time
|
||||||
static Mutex _systemTapInitLock;
|
static Mutex _systemTapInitLock;
|
||||||
|
|
||||||
// Incrementing this causes everyone currently open to close and reopen
|
|
||||||
static volatile int _systemTapResetStatus = 0;
|
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
WindowsEthernetTap::WindowsEthernetTap(
|
WindowsEthernetTap::WindowsEthernetTap(
|
||||||
|
@ -268,12 +265,6 @@ WindowsEthernetTap::WindowsEthernetTap(
|
||||||
}
|
}
|
||||||
} else break; // no more keys or error occurred
|
} else break; // no more keys or error occurred
|
||||||
}
|
}
|
||||||
|
|
||||||
// When we create a new tap device from scratch, existing taps for
|
|
||||||
// some reason go into 'unplugged' state. This can be fixed by
|
|
||||||
// closing and re-opening them. Incrementing this causes all
|
|
||||||
// existing tap threads to do this.
|
|
||||||
++_systemTapResetStatus;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_netCfgInstanceId.length() > 0) {
|
if (_netCfgInstanceId.length() > 0) {
|
||||||
|
@ -299,7 +290,6 @@ WindowsEthernetTap::WindowsEthernetTap(
|
||||||
throw std::runtime_error("unable to find or create tap adapter");
|
throw std::runtime_error("unable to find or create tap adapter");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert device GUID junk... blech... is there an easier way to do this?
|
|
||||||
{
|
{
|
||||||
char nobraces[128];
|
char nobraces[128];
|
||||||
const char *nbtmp1 = _netCfgInstanceId.c_str();
|
const char *nbtmp1 = _netCfgInstanceId.c_str();
|
||||||
|
@ -573,191 +563,199 @@ void WindowsEthernetTap::scanMulticastGroups(std::vector<MulticastGroup> &added,
|
||||||
void WindowsEthernetTap::threadMain()
|
void WindowsEthernetTap::threadMain()
|
||||||
throw()
|
throw()
|
||||||
{
|
{
|
||||||
char tapPath[256];
|
char tapReadBuf[ZT_IF_MTU + 32];
|
||||||
OVERLAPPED tapOvlRead,tapOvlWrite;
|
char tapPath[128];
|
||||||
HANDLE wait4[3];
|
HANDLE wait4[3];
|
||||||
char *tapReadBuf = (char *)0;
|
OVERLAPPED tapOvlRead,tapOvlWrite;
|
||||||
|
|
||||||
/* No idea why I did this. I did it a long time ago and there was only a
|
|
||||||
* a snarky comment. But I'd never do crap like this without a reason, so
|
|
||||||
* I am leaving it alone with a more descriptive snarky comment. */
|
|
||||||
while (!tapReadBuf) {
|
|
||||||
tapReadBuf = (char *)::malloc(ZT_IF_MTU + 32);
|
|
||||||
if (!tapReadBuf)
|
|
||||||
Sleep(1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
Utils::snprintf(tapPath,sizeof(tapPath),"\\\\.\\Global\\%s.tap",_netCfgInstanceId.c_str());
|
Utils::snprintf(tapPath,sizeof(tapPath),"\\\\.\\Global\\%s.tap",_netCfgInstanceId.c_str());
|
||||||
int prevTapResetStatus = _systemTapResetStatus;
|
|
||||||
bool throwOneAway = true; // Restart once on startup, because Windows.
|
try {
|
||||||
bool powerCycle = true; // If true, "power cycle" the device, because Windows.
|
while (_run) {
|
||||||
while (_run) {
|
|
||||||
if (powerCycle) {
|
|
||||||
_disableTapDevice();
|
|
||||||
Sleep(500);
|
|
||||||
_enableTapDevice();
|
_enableTapDevice();
|
||||||
Sleep(500);
|
Sleep(500);
|
||||||
}
|
|
||||||
|
|
||||||
_tap = CreateFileA(tapPath,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_SYSTEM|FILE_FLAG_OVERLAPPED,NULL);
|
_tap = CreateFileA(tapPath,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_SYSTEM|FILE_FLAG_OVERLAPPED,NULL);
|
||||||
if (_tap == INVALID_HANDLE_VALUE) {
|
if (_tap == INVALID_HANDLE_VALUE) {
|
||||||
fprintf(stderr,"Error opening %s -- retrying.\r\n",tapPath);
|
_disableTapDevice();
|
||||||
powerCycle = true;
|
_enableTapDevice();
|
||||||
continue;
|
Sleep(1000);
|
||||||
}
|
continue;
|
||||||
|
|
||||||
{
|
|
||||||
uint32_t tmpi = 1;
|
|
||||||
DWORD bytesReturned = 0;
|
|
||||||
DeviceIoControl(_tap,TAP_WIN_IOCTL_SET_MEDIA_STATUS,&tmpi,sizeof(tmpi),&tmpi,sizeof(tmpi),&bytesReturned,NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
#ifdef ZT_WINDOWS_CREATE_FAKE_DEFAULT_ROUTE
|
|
||||||
/* This inserts a fake default route and a fake ARP entry, forcing
|
|
||||||
* Windows to detect this as a "real" network and apply proper
|
|
||||||
* firewall rules.
|
|
||||||
*
|
|
||||||
* This hack is completely stupid, but Windows made me do it
|
|
||||||
* by being broken and insane.
|
|
||||||
*
|
|
||||||
* Background: Windows tries to detect its network location by
|
|
||||||
* matching it to the ARP address of the default route. Networks
|
|
||||||
* without default routes are "unidentified networks" and cannot
|
|
||||||
* have their firewall classification changed by the user (easily).
|
|
||||||
*
|
|
||||||
* Yes, you read that right.
|
|
||||||
*
|
|
||||||
* The common workaround is to set *NdisDeviceType to 1, which
|
|
||||||
* totally disables all Windows firewall functionality. This is
|
|
||||||
* the answer you'll find on most forums for things like OpenVPN.
|
|
||||||
*
|
|
||||||
* Yes, you read that right.
|
|
||||||
*
|
|
||||||
* The default route workaround is also known, but for this to
|
|
||||||
* work there must be a known default IP that resolves to a known
|
|
||||||
* ARP address. This works for an OpenVPN tunnel, but not here
|
|
||||||
* because this isn't a tunnel. It's a mesh. There is no "other
|
|
||||||
* end," or any other known always on IP.
|
|
||||||
*
|
|
||||||
* So let's make a fake one and shove it in there along with its
|
|
||||||
* fake static ARP entry. Also makes it instant-on and static.
|
|
||||||
*
|
|
||||||
* We'll have to see what DHCP does with this. In the future we
|
|
||||||
* probably will not want to do this on DHCP-enabled networks, so
|
|
||||||
* when we enable DHCP we will go in and yank this wacko hacko from
|
|
||||||
* the routing table before doing so.
|
|
||||||
*
|
|
||||||
* Like Jesse Pinkman would say: "YEEEEAAH BITCH!" */
|
|
||||||
const uint32_t fakeIp = htonl(0x19fffffe); // 25.255.255.254 -- unrouted IPv4 block
|
|
||||||
for(int i=0;i<8;++i) {
|
|
||||||
MIB_IPNET_ROW2 ipnr;
|
|
||||||
memset(&ipnr,0,sizeof(ipnr));
|
|
||||||
ipnr.Address.si_family = AF_INET;
|
|
||||||
ipnr.Address.Ipv4.sin_addr.s_addr = fakeIp;
|
|
||||||
ipnr.InterfaceLuid.Value = _deviceLuid.Value;
|
|
||||||
ipnr.PhysicalAddress[0] = _mac[0] ^ 0x10; // just make something up that's consistent and not part of this net
|
|
||||||
ipnr.PhysicalAddress[1] = 0x00;
|
|
||||||
ipnr.PhysicalAddress[2] = (UCHAR)((_deviceGuid.Data1 >> 24) & 0xff);
|
|
||||||
ipnr.PhysicalAddress[3] = (UCHAR)((_deviceGuid.Data1 >> 16) & 0xff);
|
|
||||||
ipnr.PhysicalAddress[4] = (UCHAR)((_deviceGuid.Data1 >> 8) & 0xff);
|
|
||||||
ipnr.PhysicalAddress[5] = (UCHAR)(_deviceGuid.Data1 & 0xff);
|
|
||||||
ipnr.PhysicalAddressLength = 6;
|
|
||||||
ipnr.State = NlnsPermanent;
|
|
||||||
ipnr.IsRouter = 1;
|
|
||||||
ipnr.IsUnreachable = 0;
|
|
||||||
ipnr.ReachabilityTime.LastReachable = 0x0fffffff;
|
|
||||||
ipnr.ReachabilityTime.LastUnreachable = 1;
|
|
||||||
DWORD result = CreateIpNetEntry2(&ipnr);
|
|
||||||
if (result != NO_ERROR)
|
|
||||||
Sleep(500);
|
|
||||||
else break;
|
|
||||||
}
|
}
|
||||||
for(int i=0;i<8;++i) {
|
|
||||||
MIB_IPFORWARD_ROW2 nr;
|
{
|
||||||
memset(&nr,0,sizeof(nr));
|
uint32_t tmpi = 1;
|
||||||
InitializeIpForwardEntry(&nr);
|
DWORD bytesReturned = 0;
|
||||||
nr.InterfaceLuid.Value = _deviceLuid.Value;
|
DeviceIoControl(_tap,TAP_WIN_IOCTL_SET_MEDIA_STATUS,&tmpi,sizeof(tmpi),&tmpi,sizeof(tmpi),&bytesReturned,NULL);
|
||||||
nr.DestinationPrefix.Prefix.si_family = AF_INET; // rest is left as 0.0.0.0/0
|
}
|
||||||
nr.NextHop.si_family = AF_INET;
|
|
||||||
nr.NextHop.Ipv4.sin_addr.s_addr = fakeIp;
|
#ifdef ZT_WINDOWS_CREATE_FAKE_DEFAULT_ROUTE
|
||||||
nr.Metric = 9999; // do not use as real default route
|
{
|
||||||
nr.Protocol = MIB_IPPROTO_NETMGMT;
|
/* This inserts a fake default route and a fake ARP entry, forcing
|
||||||
DWORD result = CreateIpForwardEntry2(&nr);
|
* Windows to detect this as a "real" network and apply proper
|
||||||
if (result != NO_ERROR)
|
* firewall rules.
|
||||||
Sleep(500);
|
*
|
||||||
else break;
|
* This hack is completely stupid, but Windows made me do it
|
||||||
|
* by being broken and insane.
|
||||||
|
*
|
||||||
|
* Background: Windows tries to detect its network location by
|
||||||
|
* matching it to the ARP address of the default route. Networks
|
||||||
|
* without default routes are "unidentified networks" and cannot
|
||||||
|
* have their firewall classification changed by the user (easily).
|
||||||
|
*
|
||||||
|
* Yes, you read that right.
|
||||||
|
*
|
||||||
|
* The common workaround is to set *NdisDeviceType to 1, which
|
||||||
|
* totally disables all Windows firewall functionality. This is
|
||||||
|
* the answer you'll find on most forums for things like OpenVPN.
|
||||||
|
*
|
||||||
|
* Yes, you read that right.
|
||||||
|
*
|
||||||
|
* The default route workaround is also known, but for this to
|
||||||
|
* work there must be a known default IP that resolves to a known
|
||||||
|
* ARP address. This works for an OpenVPN tunnel, but not here
|
||||||
|
* because this isn't a tunnel. It's a mesh. There is no "other
|
||||||
|
* end," or any other known always on IP.
|
||||||
|
*
|
||||||
|
* So let's make a fake one and shove it in there along with its
|
||||||
|
* fake static ARP entry. Also makes it instant-on and static.
|
||||||
|
*
|
||||||
|
* We'll have to see what DHCP does with this. In the future we
|
||||||
|
* probably will not want to do this on DHCP-enabled networks, so
|
||||||
|
* when we enable DHCP we will go in and yank this wacko hacko from
|
||||||
|
* the routing table before doing so.
|
||||||
|
*
|
||||||
|
* Like Jesse Pinkman would say: "YEEEEAAH BITCH!" */
|
||||||
|
const uint32_t fakeIp = htonl(0x19fffffe); // 25.255.255.254 -- unrouted IPv4 block
|
||||||
|
for(int i=0;i<8;++i) {
|
||||||
|
MIB_IPNET_ROW2 ipnr;
|
||||||
|
memset(&ipnr,0,sizeof(ipnr));
|
||||||
|
ipnr.Address.si_family = AF_INET;
|
||||||
|
ipnr.Address.Ipv4.sin_addr.s_addr = fakeIp;
|
||||||
|
ipnr.InterfaceLuid.Value = _deviceLuid.Value;
|
||||||
|
ipnr.PhysicalAddress[0] = _mac[0] ^ 0x10; // just make something up that's consistent and not part of this net
|
||||||
|
ipnr.PhysicalAddress[1] = 0x00;
|
||||||
|
ipnr.PhysicalAddress[2] = (UCHAR)((_deviceGuid.Data1 >> 24) & 0xff);
|
||||||
|
ipnr.PhysicalAddress[3] = (UCHAR)((_deviceGuid.Data1 >> 16) & 0xff);
|
||||||
|
ipnr.PhysicalAddress[4] = (UCHAR)((_deviceGuid.Data1 >> 8) & 0xff);
|
||||||
|
ipnr.PhysicalAddress[5] = (UCHAR)(_deviceGuid.Data1 & 0xff);
|
||||||
|
ipnr.PhysicalAddressLength = 6;
|
||||||
|
ipnr.State = NlnsPermanent;
|
||||||
|
ipnr.IsRouter = 1;
|
||||||
|
ipnr.IsUnreachable = 0;
|
||||||
|
ipnr.ReachabilityTime.LastReachable = 0x0fffffff;
|
||||||
|
ipnr.ReachabilityTime.LastUnreachable = 1;
|
||||||
|
DWORD result = CreateIpNetEntry2(&ipnr);
|
||||||
|
if (result != NO_ERROR)
|
||||||
|
Sleep(500);
|
||||||
|
else break;
|
||||||
|
}
|
||||||
|
for(int i=0;i<8;++i) {
|
||||||
|
MIB_IPFORWARD_ROW2 nr;
|
||||||
|
memset(&nr,0,sizeof(nr));
|
||||||
|
InitializeIpForwardEntry(&nr);
|
||||||
|
nr.InterfaceLuid.Value = _deviceLuid.Value;
|
||||||
|
nr.DestinationPrefix.Prefix.si_family = AF_INET; // rest is left as 0.0.0.0/0
|
||||||
|
nr.NextHop.si_family = AF_INET;
|
||||||
|
nr.NextHop.Ipv4.sin_addr.s_addr = fakeIp;
|
||||||
|
nr.Metric = 9999; // do not use as real default route
|
||||||
|
nr.Protocol = MIB_IPPROTO_NETMGMT;
|
||||||
|
DWORD result = CreateIpForwardEntry2(&nr);
|
||||||
|
if (result != NO_ERROR)
|
||||||
|
Sleep(500);
|
||||||
|
else break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
memset(&tapOvlRead,0,sizeof(tapOvlRead));
|
memset(&tapOvlRead,0,sizeof(tapOvlRead));
|
||||||
tapOvlRead.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
tapOvlRead.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
||||||
memset(&tapOvlWrite,0,sizeof(tapOvlWrite));
|
memset(&tapOvlWrite,0,sizeof(tapOvlWrite));
|
||||||
tapOvlWrite.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
tapOvlWrite.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
||||||
|
|
||||||
wait4[0] = _injectSemaphore;
|
wait4[0] = _injectSemaphore;
|
||||||
wait4[1] = tapOvlRead.hEvent;
|
wait4[1] = tapOvlRead.hEvent;
|
||||||
wait4[2] = tapOvlWrite.hEvent; // only included if writeInProgress is true
|
wait4[2] = tapOvlWrite.hEvent; // only included if writeInProgress is true
|
||||||
|
|
||||||
ReadFile(_tap,tapReadBuf,sizeof(tapReadBuf),NULL,&tapOvlRead);
|
ReadFile(_tap,tapReadBuf,sizeof(tapReadBuf),NULL,&tapOvlRead);
|
||||||
bool writeInProgress = false;
|
bool writeInProgress = false;
|
||||||
while (_run) {
|
ULONGLONG timeOfLastBorkCheck = GetTickCount64();
|
||||||
if ((prevTapResetStatus != _systemTapResetStatus)||(throwOneAway)) {
|
while (_run) {
|
||||||
powerCycle = throwOneAway;
|
DWORD waitResult = WaitForMultipleObjectsEx(writeInProgress ? 3 : 2,wait4,FALSE,2500,TRUE);
|
||||||
throwOneAway = false;
|
if (!_run) break; // will also break outer while(_run)
|
||||||
prevTapResetStatus = _systemTapResetStatus;
|
|
||||||
break; // this will cause us to close and reopen the tap
|
|
||||||
}
|
|
||||||
DWORD r = WaitForMultipleObjectsEx(writeInProgress ? 3 : 2,wait4,FALSE,2500,TRUE);
|
|
||||||
if (!_run) break; // will also break outer while(_run)
|
|
||||||
|
|
||||||
if ((r == WAIT_TIMEOUT)||(r == WAIT_FAILED))
|
// Check for issues with adapter and close/reopen if any are detected. This
|
||||||
continue;
|
// check fixes a while boatload of Windows adapter 'coma' issues after
|
||||||
|
// sleep/wake and when adapters are added/removed. Basically if the tap
|
||||||
if (HasOverlappedIoCompleted(&tapOvlRead)) {
|
// device is borked, whack it.
|
||||||
DWORD bytesRead = 0;
|
{
|
||||||
if (GetOverlappedResult(_tap,&tapOvlRead,&bytesRead,FALSE)) {
|
ULONGLONG tc = GetTickCount64();
|
||||||
if ((bytesRead > 14)&&(_enabled)) {
|
if ((tc - timeOfLastBorkCheck) >= 2500) {
|
||||||
MAC to(tapReadBuf,6);
|
timeOfLastBorkCheck = tc;
|
||||||
MAC from(tapReadBuf + 6,6);
|
MIB_IF_TABLE2 *ift = NULL;
|
||||||
unsigned int etherType = ((((unsigned int)tapReadBuf[12]) & 0xff) << 8) | (((unsigned int)tapReadBuf[13]) & 0xff);
|
if ((GetIfTable2(&ift) == NO_ERROR)&&(ift)) {
|
||||||
try {
|
bool isBorked = false;
|
||||||
// TODO: decode vlans
|
for(ULONG r=0;r<ift->NumEntries;++r) {
|
||||||
_handler(_arg,_nwid,from,to,etherType,0,tapReadBuf + 14,bytesRead - 14);
|
if (ift->Table[r].InterfaceLuid.Value == _deviceLuid.Value) {
|
||||||
} catch ( ... ) {} // handlers should not throw
|
if ((ift->Table[r].InterfaceAndOperStatusFlags.NotMediaConnected)||(ift->Table[r].MediaConnectState == MediaConnectStateDisconnected))
|
||||||
|
isBorked = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FreeMibTable(ift);
|
||||||
|
if (isBorked) {
|
||||||
|
// Close and reopen tap device if there's an issue (outer loop)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ReadFile(_tap,tapReadBuf,ZT_IF_MTU + 32,NULL,&tapOvlRead);
|
|
||||||
|
if ((waitResult == WAIT_TIMEOUT)||(waitResult == WAIT_FAILED))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (HasOverlappedIoCompleted(&tapOvlRead)) {
|
||||||
|
DWORD bytesRead = 0;
|
||||||
|
if (GetOverlappedResult(_tap,&tapOvlRead,&bytesRead,FALSE)) {
|
||||||
|
if ((bytesRead > 14)&&(_enabled)) {
|
||||||
|
MAC to(tapReadBuf,6);
|
||||||
|
MAC from(tapReadBuf + 6,6);
|
||||||
|
unsigned int etherType = ((((unsigned int)tapReadBuf[12]) & 0xff) << 8) | (((unsigned int)tapReadBuf[13]) & 0xff);
|
||||||
|
try {
|
||||||
|
// TODO: decode vlans
|
||||||
|
_handler(_arg,_nwid,from,to,etherType,0,tapReadBuf + 14,bytesRead - 14);
|
||||||
|
} catch ( ... ) {} // handlers should not throw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ReadFile(_tap,tapReadBuf,ZT_IF_MTU + 32,NULL,&tapOvlRead);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (writeInProgress) {
|
||||||
|
if (HasOverlappedIoCompleted(&tapOvlWrite)) {
|
||||||
|
writeInProgress = false;
|
||||||
|
_injectPending_m.lock();
|
||||||
|
_injectPending.pop();
|
||||||
|
} else continue; // still writing, so skip code below and wait
|
||||||
|
} else _injectPending_m.lock();
|
||||||
|
|
||||||
|
if (!_injectPending.empty()) {
|
||||||
|
WriteFile(_tap,_injectPending.front().first.data,_injectPending.front().second,NULL,&tapOvlWrite);
|
||||||
|
writeInProgress = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_injectPending_m.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (writeInProgress) {
|
CancelIo(_tap);
|
||||||
if (HasOverlappedIoCompleted(&tapOvlWrite)) {
|
|
||||||
writeInProgress = false;
|
|
||||||
_injectPending_m.lock();
|
|
||||||
_injectPending.pop();
|
|
||||||
} else continue; // still writing, so skip code below and wait
|
|
||||||
} else _injectPending_m.lock();
|
|
||||||
|
|
||||||
if (!_injectPending.empty()) {
|
CloseHandle(tapOvlRead.hEvent);
|
||||||
WriteFile(_tap,_injectPending.front().first.data,_injectPending.front().second,NULL,&tapOvlWrite);
|
CloseHandle(tapOvlWrite.hEvent);
|
||||||
writeInProgress = true;
|
CloseHandle(_tap);
|
||||||
}
|
_tap = INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
_injectPending_m.unlock();
|
// We will restart and re-open the tap unless _run == false
|
||||||
}
|
}
|
||||||
|
} catch ( ... ) {} // catch unexpected exceptions -- this should not happen but would prevent program crash or other weird issues since threads should not throw
|
||||||
CancelIo(_tap);
|
|
||||||
|
|
||||||
CloseHandle(tapOvlRead.hEvent);
|
|
||||||
CloseHandle(tapOvlWrite.hEvent);
|
|
||||||
CloseHandle(_tap);
|
|
||||||
_tap = INVALID_HANDLE_VALUE;
|
|
||||||
|
|
||||||
// We will restart and re-open the tap unless _run == false
|
|
||||||
}
|
|
||||||
|
|
||||||
::free(tapReadBuf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowsEthernetTap::destroyAllPersistentTapDevices(const char *pathToHelpers)
|
void WindowsEthernetTap::destroyAllPersistentTapDevices(const char *pathToHelpers)
|
||||||
|
|
|
@ -98,8 +98,8 @@ private:
|
||||||
|
|
||||||
GUID _deviceGuid;
|
GUID _deviceGuid;
|
||||||
NET_LUID _deviceLuid;
|
NET_LUID _deviceLuid;
|
||||||
std::string _netCfgInstanceId; // NetCfgInstanceId, a GUID
|
std::string _netCfgInstanceId;
|
||||||
std::string _deviceInstanceId; // DeviceInstanceID, another kind of "instance ID"
|
std::string _deviceInstanceId;
|
||||||
|
|
||||||
std::vector<MulticastGroup> _multicastGroups;
|
std::vector<MulticastGroup> _multicastGroups;
|
||||||
|
|
||||||
|
|
|
@ -454,7 +454,7 @@ unsigned int ControlPlane::handleRequest(
|
||||||
} else {
|
} else {
|
||||||
#ifdef ZT_ENABLE_NETWORK_CONTROLLER
|
#ifdef ZT_ENABLE_NETWORK_CONTROLLER
|
||||||
if (_controller)
|
if (_controller)
|
||||||
_controller->handleControlPlaneHttpGET(std::vector<std::string>(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType);
|
scode = _controller->handleControlPlaneHttpGET(std::vector<std::string>(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType);
|
||||||
else scode = 404;
|
else scode = 404;
|
||||||
#else
|
#else
|
||||||
scode = 404;
|
scode = 404;
|
||||||
|
@ -490,7 +490,7 @@ unsigned int ControlPlane::handleRequest(
|
||||||
} else {
|
} else {
|
||||||
#ifdef ZT_ENABLE_NETWORK_CONTROLLER
|
#ifdef ZT_ENABLE_NETWORK_CONTROLLER
|
||||||
if (_controller)
|
if (_controller)
|
||||||
_controller->handleControlPlaneHttpPOST(std::vector<std::string>(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType);
|
scode = _controller->handleControlPlaneHttpPOST(std::vector<std::string>(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType);
|
||||||
else scode = 404;
|
else scode = 404;
|
||||||
#else
|
#else
|
||||||
scode = 404;
|
scode = 404;
|
||||||
|
@ -525,7 +525,7 @@ unsigned int ControlPlane::handleRequest(
|
||||||
} else {
|
} else {
|
||||||
#ifdef ZT_ENABLE_NETWORK_CONTROLLER
|
#ifdef ZT_ENABLE_NETWORK_CONTROLLER
|
||||||
if (_controller)
|
if (_controller)
|
||||||
_controller->handleControlPlaneHttpDELETE(std::vector<std::string>(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType);
|
scode = _controller->handleControlPlaneHttpDELETE(std::vector<std::string>(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType);
|
||||||
else scode = 404;
|
else scode = 404;
|
||||||
#else
|
#else
|
||||||
scode = 404;
|
scode = 404;
|
||||||
|
|
|
@ -204,7 +204,7 @@ Relay objects define network-specific preferred relay nodes. Traffic to peers on
|
||||||
|
|
||||||
* **Note**: at the moment, <u>only rules specifying allowed Ethernet types are used</u>. The database supports a richer rule set, but this is not implemented yet in the client. <u>Other types of rules will have no effect</u> (yet).
|
* **Note**: at the moment, <u>only rules specifying allowed Ethernet types are used</u>. The database supports a richer rule set, but this is not implemented yet in the client. <u>Other types of rules will have no effect</u> (yet).
|
||||||
|
|
||||||
Rules are matched in order of ruleId. If no rules match, the default action is 'drop'. To allow all traffic, create a single rule with all *null* fields and an action of 'accept'.
|
Rules are matched in order of ruleNo. If no rules match, the default action is 'drop'. To allow all traffic, create a single rule with all *null* fields and an action of 'accept'.
|
||||||
|
|
||||||
Rule object fields can be *null*, in which case they are omitted from the object. A null field indicates "no match on this criteria."
|
Rule object fields can be *null*, in which case they are omitted from the object. A null field indicates "no match on this criteria."
|
||||||
|
|
||||||
|
@ -212,7 +212,7 @@ IP related fields apply only to Ethernet frames of type IPv4 or IPV6. Otherwise
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
<tr><td><b>Field</b></td><td><b>Type</b></td><td><b>Description</b></td></tr>
|
<tr><td><b>Field</b></td><td><b>Type</b></td><td><b>Description</b></td></tr>
|
||||||
<tr><td>ruleId</td><td>integer</td><td>User-defined rule ID and sort order</td></tr>
|
<tr><td>ruleNo</td><td>integer</td><td>User-defined rule ID and sort order</td></tr>
|
||||||
<tr><td>nodeId</td><td>string</td><td>10-digit hex ZeroTier address of node (a.k.a. "port on switch")</td></tr>
|
<tr><td>nodeId</td><td>string</td><td>10-digit hex ZeroTier address of node (a.k.a. "port on switch")</td></tr>
|
||||||
<tr><td>vlanId</td><td>integer</td><td>Ethernet VLAN ID</td></tr>
|
<tr><td>vlanId</td><td>integer</td><td>Ethernet VLAN ID</td></tr>
|
||||||
<tr><td>vlanPcp</td><td>integer</td><td>Ethernet VLAN priority code point (PCP) ID</td></tr>
|
<tr><td>vlanPcp</td><td>integer</td><td>Ethernet VLAN priority code point (PCP) ID</td></tr>
|
||||||
|
|
Loading…
Add table
Reference in a new issue