Controller modifications for default route are ready to test. Will require slight changes in ZeroTier Central when it goes live.

This commit is contained in:
Adam Ierymenko 2016-06-10 15:58:35 -07:00
parent acbe8ad398
commit 734cbb2f1e
4 changed files with 179 additions and 302 deletions

View file

@ -110,6 +110,26 @@ static std::string _jsonEscape(const char *s)
} }
static std::string _jsonEscape(const std::string &s) { return _jsonEscape(s.c_str()); } static std::string _jsonEscape(const std::string &s) { return _jsonEscape(s.c_str()); }
// Converts an InetAddress to a blob and an int for storage in database
static void _ipToBlob(const InetAddress &a,char *ipBlob,int &ipVersion) /* blob[16] */
{
switch(a.ss_family) {
case AF_INET:
if ((a.netmaskBits() > 0)&&(a.netmaskBits() <= 32)) {
memset(ipBlob,0,12);
memcpy(ipBlob + 12,a.rawIpData(),4);
ipVersion = 4;
}
break;
case AF_INET6:
if ((a.netmaskBits() > 0)&&(a.netmaskBits() <= 128)) {
memcpy(ipBlob,a.rawIpData(),16);
ipVersion = 6;
}
break;
}
}
struct MemberRecord { struct MemberRecord {
int64_t rowid; int64_t rowid;
char nodeId[16]; char nodeId[16];
@ -191,23 +211,26 @@ SqliteNetworkController::SqliteNetworkController(Node *node,const char *dbPath,c
} }
if (schemaVersion < 3) { if (schemaVersion < 3) {
// Create Route table to upgrade from version 2 to version 3, also drop obsolete Gateway table (which was never actually used) // Create Route table to upgrade from version 2 to version 3 and migrate old
// data. Also delete obsolete Gateway table that was never actually used.
if (sqlite3_exec(_db, if (sqlite3_exec(_db,
"DROP TABLE Gateway;\n" "DROP TABLE Gateway;\n"
"CREATE TABLE Route (\n" "CREATE TABLE Route (\n"
" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n" " networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"
" target blob(16) NOT NULL,\n" " target blob(16) NOT NULL,\n"
" via blob(16) NOT NULL,\n" " via blob(16),\n"
" targetNetmaskBits integer NOT NULL,\n" " targetNetmaskBits integer NOT NULL,\n"
" ipVersion integer NOT NULL,\n" " ipVersion integer NOT NULL,\n"
" flags integer NOT NULL,\n" " flags integer NOT NULL,\n"
" metric integer NOT NULL\n" " metric integer NOT NULL\n"
");\n" ");\n"
"CREATE INDEX Route_networkId ON Route (networkId);\n" "CREATE INDEX Route_networkId ON Route (networkId);\n"
"INSERT INTO Route SELECT DISTINCT networkId,\"ip\" AS \"target\",NULL AS \"via\",ipNetmaskBits AS targetNetmaskBits,ipVersion,0 AS \"flags\",0 AS \"metric\" FROM IpAssignment WHERE nodeId IS NULL AND \"type\" = 1;\n"
"DELETE FROM IpAssignment WHERE nodeId IS NULL AND \"type\" = 1;\n"
"UPDATE \"Config\" SET \"v\" = 3 WHERE \"k\" = 'schemaVersion';\n" "UPDATE \"Config\" SET \"v\" = 3 WHERE \"k\" = 'schemaVersion';\n"
,0,0,0) != SQLITE_OK) { ,0,0,0) != SQLITE_OK) {
char err[1024]; char err[1024];
Utils::snprintf(err,sizeof(err),"SqliteNetworkController cannot upgrade the database to version 2: %s",sqlite3_errmsg(_db)); Utils::snprintf(err,sizeof(err),"SqliteNetworkController cannot upgrade the database to version 3: %s",sqlite3_errmsg(_db));
sqlite3_close(_db); sqlite3_close(_db);
throw std::runtime_error(err); throw std::runtime_error(err);
} else { } else {
@ -267,11 +290,9 @@ SqliteNetworkController::SqliteNetworkController(Node *node,const char *dbPath,c
/* IpAssignment */ /* IpAssignment */
||(sqlite3_prepare_v2(_db,"SELECT \"type\",ip,ipNetmaskBits FROM IpAssignment WHERE networkId = ? AND (nodeId = ? OR nodeId IS NULL) AND ipVersion = ?",-1,&_sGetIpAssignmentsForNode,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"SELECT \"type\",ip,ipNetmaskBits FROM IpAssignment WHERE networkId = ? AND (nodeId = ? OR nodeId IS NULL) AND ipVersion = ?",-1,&_sGetIpAssignmentsForNode,(const char **)0) != SQLITE_OK)
||(sqlite3_prepare_v2(_db,"SELECT ip,ipNetmaskBits,ipVersion FROM IpAssignment WHERE networkId = ? AND nodeId = ? AND \"type\" = ? ORDER BY ip ASC",-1,&_sGetIpAssignmentsForNode2,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"SELECT ip,ipNetmaskBits,ipVersion FROM IpAssignment WHERE networkId = ? AND nodeId = ? AND \"type\" = ? ORDER BY ip ASC",-1,&_sGetIpAssignmentsForNode2,(const char **)0) != SQLITE_OK)
||(sqlite3_prepare_v2(_db,"SELECT ip,ipNetmaskBits,ipVersion FROM IpAssignment WHERE networkId = ? AND nodeId IS NULL AND \"type\" = ?",-1,&_sGetLocalRoutes,(const char **)0) != SQLITE_OK)
||(sqlite3_prepare_v2(_db,"SELECT 1 FROM IpAssignment WHERE networkId = ? AND ip = ? AND ipVersion = ? AND \"type\" = ?",-1,&_sCheckIfIpIsAllocated,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"SELECT 1 FROM IpAssignment WHERE networkId = ? AND ip = ? AND ipVersion = ? AND \"type\" = ?",-1,&_sCheckIfIpIsAllocated,(const char **)0) != SQLITE_OK)
||(sqlite3_prepare_v2(_db,"INSERT INTO IpAssignment (networkId,nodeId,\"type\",ip,ipNetmaskBits,ipVersion) VALUES (?,?,?,?,?,?)",-1,&_sAllocateIp,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"INSERT INTO IpAssignment (networkId,nodeId,\"type\",ip,ipNetmaskBits,ipVersion) VALUES (?,?,?,?,?,?)",-1,&_sAllocateIp,(const char **)0) != SQLITE_OK)
||(sqlite3_prepare_v2(_db,"DELETE FROM IpAssignment WHERE networkId = ? AND nodeId = ? AND \"type\" = ?",-1,&_sDeleteIpAllocations,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"DELETE FROM IpAssignment WHERE networkId = ? AND nodeId = ? AND \"type\" = ?",-1,&_sDeleteIpAllocations,(const char **)0) != SQLITE_OK)
||(sqlite3_prepare_v2(_db,"DELETE FROM IpAssignment WHERE networkId = ? AND nodeId IS NULL AND \"type\" = ?",-1,&_sDeleteLocalRoutes,(const char **)0) != SQLITE_OK)
/* Relay */ /* Relay */
||(sqlite3_prepare_v2(_db,"SELECT \"address\",\"phyAddress\" FROM Relay WHERE \"networkId\" = ? ORDER BY \"address\" ASC",-1,&_sGetRelays,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"SELECT \"address\",\"phyAddress\" FROM Relay WHERE \"networkId\" = ? ORDER BY \"address\" ASC",-1,&_sGetRelays,(const char **)0) != SQLITE_OK)
@ -291,7 +312,7 @@ SqliteNetworkController::SqliteNetworkController(Node *node,const char *dbPath,c
/* Route */ /* Route */
||(sqlite3_prepare_v2(_db,"INSERT INTO Route (networkId,target,via,targetNetmaskBits,ipVersion,flags,metric) VALUES (?,?,?,?,?,?,?)",-1,&_sCreateRoute,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"INSERT INTO Route (networkId,target,via,targetNetmaskBits,ipVersion,flags,metric) VALUES (?,?,?,?,?,?,?)",-1,&_sCreateRoute,(const char **)0) != SQLITE_OK)
||(sqlite3_prepare_v2(_db,"SELECT target,via,targetNetmaskBits,ipVersion,flags,metric FROM \"Route\" WHERE networkId = ?",-1,&_sGetRoutes,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"SELECT DISTINCT target,via,targetNetmaskBits,ipVersion,flags,metric FROM \"Route\" WHERE networkId = ? ORDER BY ipVersion,target,via",-1,&_sGetRoutes,(const char **)0) != SQLITE_OK)
||(sqlite3_prepare_v2(_db,"DELETE FROM \"Route\" WHERE networkId = ?",-1,&_sDeleteRoutes,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"DELETE FROM \"Route\" WHERE networkId = ?",-1,&_sDeleteRoutes,(const char **)0) != SQLITE_OK)
/* Config */ /* Config */
@ -351,11 +372,9 @@ SqliteNetworkController::~SqliteNetworkController()
sqlite3_finalize(_sGetActiveBridges); sqlite3_finalize(_sGetActiveBridges);
sqlite3_finalize(_sGetIpAssignmentsForNode); sqlite3_finalize(_sGetIpAssignmentsForNode);
sqlite3_finalize(_sGetIpAssignmentPools); sqlite3_finalize(_sGetIpAssignmentPools);
sqlite3_finalize(_sGetLocalRoutes);
sqlite3_finalize(_sCheckIfIpIsAllocated); sqlite3_finalize(_sCheckIfIpIsAllocated);
sqlite3_finalize(_sAllocateIp); sqlite3_finalize(_sAllocateIp);
sqlite3_finalize(_sDeleteIpAllocations); sqlite3_finalize(_sDeleteIpAllocations);
sqlite3_finalize(_sDeleteLocalRoutes);
sqlite3_finalize(_sGetRelays); sqlite3_finalize(_sGetRelays);
sqlite3_finalize(_sListNetworks); sqlite3_finalize(_sListNetworks);
sqlite3_finalize(_sListNetworkMembers); sqlite3_finalize(_sListNetworkMembers);
@ -379,7 +398,7 @@ SqliteNetworkController::~SqliteNetworkController()
sqlite3_finalize(_sDeleteNetwork); sqlite3_finalize(_sDeleteNetwork);
sqlite3_finalize(_sCreateRoute); sqlite3_finalize(_sCreateRoute);
sqlite3_finalize(_sGetRoutes); sqlite3_finalize(_sGetRoutes);
sqlite3_finalize(_sDeleteRoute); sqlite3_finalize(_sDeleteRoutes);
sqlite3_finalize(_sIncrementMemberRevisionCounter); sqlite3_finalize(_sIncrementMemberRevisionCounter);
sqlite3_finalize(_sGetConfig); sqlite3_finalize(_sGetConfig);
sqlite3_finalize(_sSetConfig); sqlite3_finalize(_sSetConfig);
@ -518,21 +537,7 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(
InetAddress a(ipalloc->u.string.ptr); InetAddress a(ipalloc->u.string.ptr);
char ipBlob[16]; char ipBlob[16];
int ipVersion = 0; int ipVersion = 0;
switch(a.ss_family) { _ipToBlob(a,ipBlob,ipVersion);
case AF_INET:
if ((a.netmaskBits() > 0)&&(a.netmaskBits() <= 32)) {
memset(ipBlob,0,12);
memcpy(ipBlob + 12,a.rawIpData(),4);
ipVersion = 4;
}
break;
case AF_INET6:
if ((a.netmaskBits() > 0)&&(a.netmaskBits() <= 128)) {
memcpy(ipBlob,a.rawIpData(),16);
ipVersion = 6;
}
break;
}
if (ipVersion > 0) { if (ipVersion > 0) {
sqlite3_reset(_sAllocateIp); sqlite3_reset(_sAllocateIp);
sqlite3_bind_text(_sAllocateIp,1,nwids,16,SQLITE_STATIC); sqlite3_bind_text(_sAllocateIp,1,nwids,16,SQLITE_STATIC);
@ -767,72 +772,55 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(
sqlite3_step(_sCreateRelay); sqlite3_step(_sCreateRelay);
} }
} }
} else if (!strcmp(j->u.object.values[k].name,"gateways")) { } else if (!strcmp(j->u.object.values[k].name,"routes")) {
/* deprecated sqlite3_reset(_sDeleteRoutes);
sqlite3_reset(_sDeleteGateways); sqlite3_bind_text(_sDeleteRoutes,1,nwids,16,SQLITE_STATIC);
sqlite3_bind_text(_sDeleteGateways,1,nwids,16,SQLITE_STATIC); sqlite3_step(_sDeleteRoutes);
sqlite3_step(_sDeleteGateways);
if (j->u.object.values[k].value->type == json_array) { 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) { 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]; json_value *r = j->u.object.values[k].value->u.array.values[kk];
if ((gateway)&&(gateway->type == json_string)) { if ((r)&&(r->type == json_object)) {
InetAddress gwip(gateway->u.string.ptr); InetAddress r_target,r_via;
sqlite3_reset(_sCreateGateway); int r_flags = 0;
sqlite3_bind_text(_sCreateGateway,1,nwids,16,SQLITE_STATIC); int r_metric = 0;
sqlite3_bind_int(_sCreateGateway,4,(int)gwip.metric()); for(unsigned int rk=0;rk<r->u.object.length;++rk) {
if (gwip.ss_family == AF_INET) { if ((!strcmp(r->u.object.values[rk].name,"target"))&&(r->u.object.values[rk].value->type == json_string))
char ipBlob[16]; r_target = InetAddress(std::string(r->u.object.values[rk].value->u.string.ptr));
memset(ipBlob,0,12); else if ((!strcmp(r->u.object.values[rk].name,"via"))&&(r->u.object.values[rk].value->type == json_string))
memcpy(ipBlob + 12,gwip.rawIpData(),4); r_via = InetAddress(std::string(r->u.object.values[rk].value->u.string.ptr),0);
sqlite3_bind_blob(_sCreateGateway,2,(const void *)ipBlob,16,SQLITE_STATIC); else if ((!strcmp(r->u.object.values[rk].name,"flags"))&&(r->u.object.values[rk].value->type == json_string))
sqlite3_bind_int(_sCreateGateway,3,4); r_flags = (int)(Utils::strToUInt(r->u.object.values[rk].value->u.string.ptr) & 0xffff);
sqlite3_step(_sCreateGateway); else if ((!strcmp(r->u.object.values[rk].name,"metric"))&&(r->u.object.values[rk].value->type == json_string))
} else if (gwip.ss_family == AF_INET6) { r_metric = (int)(Utils::strToUInt(r->u.object.values[rk].value->u.string.ptr) & 0xffff);
sqlite3_bind_blob(_sCreateGateway,2,gwip.rawIpData(),16,SQLITE_STATIC); }
sqlite3_bind_int(_sCreateGateway,3,6); if ((r_target)&&((!r_via)||(r_via.ss_family == r_target.ss_family))) {
sqlite3_step(_sCreateGateway); int r_ipVersion = 0;
char r_targetBlob[16];
char r_viaBlob[16];
_ipToBlob(r_target,r_targetBlob,r_ipVersion);
if (r_ipVersion) {
int r_targetNetmaskBits = r_target.netmaskBits();
if ((r_ipVersion == 4)&&(r_targetNetmaskBits > 32)) r_targetNetmaskBits = 32;
else if ((r_ipVersion == 6)&&(r_targetNetmaskBits > 128)) r_targetNetmaskBits = 128;
sqlite3_reset(_sCreateRoute);
sqlite3_bind_text(_sCreateRoute,1,nwids,16,SQLITE_STATIC);
sqlite3_bind_blob(_sCreateRoute,2,(const void *)r_targetBlob,16,SQLITE_STATIC);
if (r_via) {
_ipToBlob(r_via,r_viaBlob,r_ipVersion);
sqlite3_bind_blob(_sCreateRoute,3,(const void *)r_viaBlob,16,SQLITE_STATIC);
} else {
sqlite3_bind_null(_sCreateRoute,3);
}
sqlite3_bind_int(_sCreateRoute,4,r_targetNetmaskBits);
sqlite3_bind_int(_sCreateRoute,5,r_ipVersion);
sqlite3_bind_int(_sCreateRoute,6,r_flags);
sqlite3_bind_int(_sCreateRoute,7,r_metric);
sqlite3_step(_sCreateRoute);
} }
} }
} }
} }
*/
} else if (!strcmp(j->u.object.values[k].name,"ipLocalRoutes")) {
/* deprecated
sqlite3_reset(_sDeleteLocalRoutes);
sqlite3_bind_text(_sDeleteLocalRoutes,1,nwids,16,SQLITE_STATIC);
sqlite3_bind_int(_sDeleteLocalRoutes,2,(int)ZT_IP_ASSIGNMENT_TYPE_NETWORK);
sqlite3_step(_sDeleteLocalRoutes);
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 *localRoute = j->u.object.values[k].value->u.array.values[kk];
if ((localRoute)&&(localRoute->type == json_string)) {
InetAddress lr(localRoute->u.string.ptr);
if (lr.ss_family == AF_INET) {
char ipBlob[16];
memset(ipBlob,0,12);
memcpy(ipBlob + 12,lr.rawIpData(),4);
sqlite3_reset(_sAllocateIp);
sqlite3_bind_text(_sAllocateIp,1,nwids,16,SQLITE_STATIC);
sqlite3_bind_null(_sAllocateIp,2);
sqlite3_bind_int(_sAllocateIp,3,(int)ZT_IP_ASSIGNMENT_TYPE_NETWORK);
sqlite3_bind_blob(_sAllocateIp,4,(const void *)ipBlob,16,SQLITE_STATIC);
sqlite3_bind_int(_sAllocateIp,5,lr.netmaskBits());
sqlite3_bind_int(_sAllocateIp,6,4);
sqlite3_step(_sAllocateIp);
} else if (lr.ss_family == AF_INET6) {
sqlite3_reset(_sAllocateIp);
sqlite3_bind_text(_sAllocateIp,1,nwids,16,SQLITE_STATIC);
sqlite3_bind_null(_sAllocateIp,2);
sqlite3_bind_int(_sAllocateIp,3,(int)ZT_IP_ASSIGNMENT_TYPE_NETWORK);
sqlite3_bind_blob(_sAllocateIp,4,lr.rawIpData(),16,SQLITE_STATIC);
sqlite3_bind_int(_sAllocateIp,5,lr.netmaskBits());
sqlite3_bind_int(_sAllocateIp,6,6);
sqlite3_step(_sAllocateIp);
} }
}
}
}
*/
} 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::vector< std::pair<InetAddress,InetAddress> > pools; std::vector< std::pair<InetAddress,InetAddress> > pools;
@ -1203,55 +1191,8 @@ unsigned int SqliteNetworkController::_doCPGet(
if (sqlite3_step(_sGetMember2) == SQLITE_ROW) { if (sqlite3_step(_sGetMember2) == SQLITE_ROW) {
const char *memberIdStr = (const char *)sqlite3_column_text(_sGetMember2,3); const char *memberIdStr = (const char *)sqlite3_column_text(_sGetMember2,3);
// If testSingingId is included in the URL or X-ZT1-TestSigningId in the headers
// and if it contains an identity with a secret portion, the resturned JSON
// will contain an extra field called _testConf. This will contain several
// fields that report the result of doNetworkConfigRequest() for this member.
std::string testFields;
/*
{
Identity testOutputSigningId;
std::map<std::string,std::string>::const_iterator sid(urlArgs.find("testSigningId"));
if (sid != urlArgs.end()) {
testOutputSigningId.fromString(sid->second.c_str());
} else {
sid = headers.find("x-zt1-testsigningid");
if (sid != headers.end())
testOutputSigningId.fromString(sid->second.c_str());
}
if ((testOutputSigningId.hasPrivate())&&(memberIdStr)) {
Dictionary testNetconf;
NetworkController::ResultCode rc = this->_doNetworkConfigRequest(
InetAddress(),
testOutputSigningId,
Identity(memberIdStr),
nwid,
NetworkConfigRequestMetaData(), // TODO: allow passing of meta-data for testing
testNetconf);
char rcs[16];
Utils::snprintf(rcs,sizeof(rcs),"%d,\n",(int)rc);
testFields.append("\t\"_test\": {\n");
testFields.append("\t\t\"resultCode\": "); testFields.append(rcs);
testFields.append("\t\t\"result\": \""); testFields.append(_jsonEscape(testNetconf.toString().c_str()).c_str()); testFields.append("\",\n");
testFields.append("\t\t\"resultJson\": {\n");
for(Dictionary::const_iterator i(testNetconf.begin());i!=testNetconf.end();++i) {
if (i != testNetconf.begin())
testFields.append(",\n");
testFields.append("\t\t\t\"");
testFields.append(i->first);
testFields.append("\": \"");
testFields.append(_jsonEscape(i->second.c_str()));
testFields.push_back('"');
}
testFields.append("\n\t\t}\n");
testFields.append("\t},\n");
}
}
*/
Utils::snprintf(json,sizeof(json), Utils::snprintf(json,sizeof(json),
"{\n%s" "{\n"
"\t\"nwid\": \"%s\",\n" "\t\"nwid\": \"%s\",\n"
"\t\"address\": \"%s\",\n" "\t\"address\": \"%s\",\n"
"\t\"controllerInstanceId\": \"%s\",\n" "\t\"controllerInstanceId\": \"%s\",\n"
@ -1261,7 +1202,6 @@ unsigned int SqliteNetworkController::_doCPGet(
"\t\"clock\": %llu,\n" "\t\"clock\": %llu,\n"
"\t\"identity\": \"%s\",\n" "\t\"identity\": \"%s\",\n"
"\t\"ipAssignments\": [", "\t\"ipAssignments\": [",
testFields.c_str(),
nwids, nwids,
addrs, addrs,
_instanceId.c_str(), _instanceId.c_str(),
@ -1456,97 +1396,47 @@ unsigned int SqliteNetworkController::_doCPGet(
responseBody.append("\"}"); responseBody.append("\"}");
} }
/* deprecated responseBody.append("],\n\t\"routes\": [");
responseBody.append("],\n\t\"gateways\": [");
sqlite3_reset(_sGetGateways); sqlite3_reset(_sGetRoutes);
sqlite3_bind_text(_sGetGateways,1,nwids,16,SQLITE_STATIC); sqlite3_bind_text(_sGetRoutes,1,nwids,16,SQLITE_STATIC);
bool firstGateway = true; bool firstRoute = true;
while (sqlite3_step(_sGetGateways) == SQLITE_ROW) { while (sqlite3_step(_sGetRoutes) == SQLITE_ROW) {
responseBody.append(firstRoute ? "\n\t\t" : ",\n\t\t");
firstRoute = false;
responseBody.append("{\"target\":");
char tmp[128]; char tmp[128];
const unsigned char *ip = (const unsigned char *)sqlite3_column_blob(_sGetGateways,0); const unsigned char *ip = (const unsigned char *)sqlite3_column_blob(_sGetRoutes,0);
switch(sqlite3_column_int(_sGetGateways,1)) { // ipVersion switch(sqlite3_column_int(_sGetRoutes,3)) { // ipVersion
case 4: case 4:
Utils::snprintf(tmp,sizeof(tmp),"%s%d.%d.%d.%d/%d\"", Utils::snprintf(tmp,sizeof(tmp),"\"%d.%d.%d.%d/%d\"",(int)ip[12],(int)ip[13],(int)ip[14],(int)ip[15],sqlite3_column_int(_sGetRoutes,2));
(firstGateway) ? "\"" : ",\"",
(int)ip[12],
(int)ip[13],
(int)ip[14],
(int)ip[15],
(int)sqlite3_column_int(_sGetGateways,2)); // metric
break; break;
case 6: 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\"", Utils::snprintf(tmp,sizeof(tmp),"\"%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x/%d\"",(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],sqlite3_column_int(_sGetRoutes,2));
(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; break;
} }
responseBody.append(tmp); responseBody.append(tmp);
firstGateway = false; if (sqlite3_column_type(_sGetRoutes,1) == SQLITE_NULL) {
} responseBody.append(",\"via\":null");
*/ } else {
responseBody.append(",\"via\":");
/* deprecated ip = (const unsigned char *)sqlite3_column_blob(_sGetRoutes,1);
responseBody.append("],\n\t\"ipLocalRoutes\": ["); switch(sqlite3_column_int(_sGetRoutes,3)) { // ipVersion
sqlite3_reset(_sGetLocalRoutes);
sqlite3_bind_text(_sGetLocalRoutes,1,nwids,16,SQLITE_STATIC);
sqlite3_bind_int(_sGetLocalRoutes,2,(int)ZT_IP_ASSIGNMENT_TYPE_NETWORK);
bool firstLocalRoute = true;
while (sqlite3_step(_sGetLocalRoutes) == SQLITE_ROW) {
char tmp[128];
const unsigned char *ip = (const unsigned char *)sqlite3_column_blob(_sGetLocalRoutes,0);
switch (sqlite3_column_int(_sGetLocalRoutes,2)) {
case 4: case 4:
Utils::snprintf(tmp,sizeof(tmp),"%s%d.%d.%d.%d/%d\"", Utils::snprintf(tmp,sizeof(tmp),"\"%d.%d.%d.%d\"",(int)ip[12],(int)ip[13],(int)ip[14],(int)ip[15]);
(firstLocalRoute) ? "\"" : ",\"",
(int)ip[12],
(int)ip[13],
(int)ip[14],
(int)ip[15],
(int)sqlite3_column_int(_sGetLocalRoutes,1)); // netmask bits
break; break;
case 6: 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\"", Utils::snprintf(tmp,sizeof(tmp),"\"%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x\"",(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]);
(firstLocalRoute) ? "\"" : ",\"",
(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(_sGetLocalRoutes,1)); // netmask bits
break; break;
} }
responseBody.append(tmp); responseBody.append(tmp);
firstLocalRoute = false;
} }
*/ responseBody.append(",\"flags\":");
responseBody.append((const char *)sqlite3_column_text(_sGetRoutes,4));
responseBody.append(",\"metric\":");
responseBody.append((const char *)sqlite3_column_text(_sGetRoutes,5));
responseBody.push_back('}');
}
responseBody.append("],\n\t\"ipAssignmentPools\": ["); responseBody.append("],\n\t\"ipAssignmentPools\": [");
@ -1701,7 +1591,7 @@ NetworkController::ResultCode SqliteNetworkController::_doNetworkConfigRequest(c
// Note: we can't reuse prepared statements that return const char * pointers without // Note: we can't reuse prepared statements that return const char * pointers without
// making our own copy in e.g. a std::string first. // making our own copy in e.g. a std::string first.
const bool clientIs104 = (Utils::compareVersion(metaData.majorVersion,metaData.minorVersion,metaData.revision,1,0,4) >= 0); //const bool clientIs104 = (Utils::compareVersion(metaData.majorVersion,metaData.minorVersion,metaData.revision,1,0,4) >= 0);
const uint64_t now = OSUtils::now(); const uint64_t now = OSUtils::now();
// Check rate limit circuit breaker to prevent flooding // Check rate limit circuit breaker to prevent flooding
@ -1978,54 +1868,37 @@ NetworkController::ResultCode SqliteNetworkController::_doNetworkConfigRequest(c
legacy[ZT_NETWORKCONFIG_DICT_KEY_RELAYS] = relays; legacy[ZT_NETWORKCONFIG_DICT_KEY_RELAYS] = relays;
} }
// TODO: this should be routes, going to redo DB sqlite3_reset(_sGetRoutes);
/* sqlite3_bind_text(_sGetRoutes,1,network.id,16,SQLITE_STATIC);
{ while ((sqlite3_step(_sGetRoutes) == SQLITE_ROW)&&(nc.routeCount < ZT_MAX_NETWORK_ROUTES)) {
char tmp[128]; ZT_VirtualNetworkRoute *r = &(nc.routes[nc.routeCount]);
std::string gateways; memset(r,0,sizeof(ZT_VirtualNetworkRoute));
sqlite3_reset(_sGetGateways); switch(sqlite3_column_int(_sGetRoutes,3)) { // ipVersion
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: case 4:
Utils::snprintf(tmp,sizeof(tmp),"%s%d.%d.%d.%d/%d", *(reinterpret_cast<InetAddress *>(&(r->target))) = InetAddress((const void *)((const char *)sqlite3_column_blob(_sGetRoutes,0) + 12),4,(unsigned int)sqlite3_column_int(_sGetRoutes,2));
(gateways.length() > 0) ? "," : "",
(int)ip[12],
(int)ip[13],
(int)ip[14],
(int)ip[15],
(int)sqlite3_column_int(_sGetGateways,2)); // metric
gateways.append(tmp);
break; break;
case 6: 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", *(reinterpret_cast<InetAddress *>(&(r->target))) = InetAddress((const void *)sqlite3_column_blob(_sGetRoutes,0),16,(unsigned int)sqlite3_column_int(_sGetRoutes,2));
(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; break;
default:
continue;
}
if (sqlite3_column_type(_sGetRoutes,1) != SQLITE_NULL) {
switch(sqlite3_column_int(_sGetRoutes,3)) { // ipVersion
case 4:
*(reinterpret_cast<InetAddress *>(&(r->via))) = InetAddress((const void *)((const char *)sqlite3_column_blob(_sGetRoutes,1) + 12),4,0);
break;
case 6:
*(reinterpret_cast<InetAddress *>(&(r->via))) = InetAddress((const void *)sqlite3_column_blob(_sGetRoutes,1),16,0);
break;
default:
continue;
} }
} }
if (gateways.length()) r->flags = (uint16_t)sqlite3_column_int(_sGetRoutes,4);
netconf[ZT_NETWORKCONFIG_DICT_KEY_GATEWAYS] = gateways; r->metric = (uint16_t)sqlite3_column_int(_sGetRoutes,5);
++nc.routeCount;
} }
*/
if ((network.v4AssignMode)&&(!strcmp(network.v4AssignMode,"zt"))) { if ((network.v4AssignMode)&&(!strcmp(network.v4AssignMode,"zt"))) {
std::string v4s; std::string v4s;
@ -2084,10 +1957,21 @@ NetworkController::ResultCode SqliteNetworkController::_doNetworkConfigRequest(c
if ((ip & 0x000000ff) == 0x000000ff) if ((ip & 0x000000ff) == 0x000000ff)
continue; // don't allow addresses that end in .255 continue; // don't allow addresses that end in .255
for(std::vector< std::pair<uint32_t,int> >::const_iterator r(routedNetworks.begin());r!=routedNetworks.end();++r) { // Check if this IPv4 IP is within a local-to-Ethernet routed network
if ((ip & (0xffffffff << (32 - r->second))) == r->first) { int routedNetmaskBits = 0;
// IP is included in a routed network, so check if it's allocated for(unsigned int rk=0;rk<nc.routeCount;++rk) {
if ((!nc.routes[rk].via.ss_family)&&(nc.routes[rk].target.ss_family == AF_INET)) {
uint32_t targetIp = Utils::ntoh((uint32_t)(reinterpret_cast<const struct sockaddr_in *>(&(nc.routes[rk].target))->sin_addr.s_addr));
int targetBits = Utils::ntoh((uint16_t)(reinterpret_cast<const struct sockaddr_in *>(&(nc.routes[rk].target))->sin_port));
if ((ip & (0xffffffff << (32 - targetBits))) == targetIp) {
routedNetmaskBits = targetBits;
break;
}
}
}
// If it's routed, then try to claim and assign it and if successful end loop
if (routedNetmaskBits > 0) {
uint32_t ipBlob[4]; uint32_t ipBlob[4];
ipBlob[0] = 0; ipBlob[1] = 0; ipBlob[2] = 0; ipBlob[3] = Utils::hton(ip); ipBlob[0] = 0; ipBlob[1] = 0; ipBlob[2] = 0; ipBlob[3] = Utils::hton(ip);
@ -2103,11 +1987,11 @@ NetworkController::ResultCode SqliteNetworkController::_doNetworkConfigRequest(c
sqlite3_bind_text(_sAllocateIp,2,member.nodeId,10,SQLITE_STATIC); sqlite3_bind_text(_sAllocateIp,2,member.nodeId,10,SQLITE_STATIC);
sqlite3_bind_int(_sAllocateIp,3,(int)0 /*ZT_IP_ASSIGNMENT_TYPE_ADDRESS*/); sqlite3_bind_int(_sAllocateIp,3,(int)0 /*ZT_IP_ASSIGNMENT_TYPE_ADDRESS*/);
sqlite3_bind_blob(_sAllocateIp,4,(const void *)ipBlob,16,SQLITE_STATIC); sqlite3_bind_blob(_sAllocateIp,4,(const void *)ipBlob,16,SQLITE_STATIC);
sqlite3_bind_int(_sAllocateIp,5,r->second); // IP netmask bits from matching route sqlite3_bind_int(_sAllocateIp,5,routedNetmaskBits); // IP netmask bits from matching route
sqlite3_bind_int(_sAllocateIp,6,4); // 4 == IPv4 sqlite3_bind_int(_sAllocateIp,6,4); // 4 == IPv4
if (sqlite3_step(_sAllocateIp) == SQLITE_DONE) { if (sqlite3_step(_sAllocateIp) == SQLITE_DONE) {
char ips[32]; char ips[32];
Utils::snprintf(ips,sizeof(ips),"%d.%d.%d.%d/%d",(int)((ip >> 24) & 0xff),(int)((ip >> 16) & 0xff),(int)((ip >> 8) & 0xff),(int)(ip & 0xff),r->second); Utils::snprintf(ips,sizeof(ips),"%d.%d.%d.%d/%d",(int)((ip >> 24) & 0xff),(int)((ip >> 16) & 0xff),(int)((ip >> 8) & 0xff),(int)(ip & 0xff),routedNetmaskBits);
if (nc.staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES) { if (nc.staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES) {
InetAddress tmp2(ips); InetAddress tmp2(ips);
@ -2119,19 +2003,14 @@ NetworkController::ResultCode SqliteNetworkController::_doNetworkConfigRequest(c
v4s.push_back(','); v4s.push_back(',');
v4s.append(ips); v4s.append(ips);
haveStaticIpAssignment = true; // break outer loop haveStaticIpAssignment = true;
}
}
break; // stop checking routed networks
}
}
if (haveStaticIpAssignment)
break; break;
} }
} }
} }
}
}
}
if (v4s.length()) if (v4s.length())
legacy[ZT_NETWORKCONFIG_DICT_KEY_IPV4_STATIC] = v4s; legacy[ZT_NETWORKCONFIG_DICT_KEY_IPV4_STATIC] = v4s;

View file

@ -152,11 +152,9 @@ private:
sqlite3_stmt *_sGetActiveBridges; sqlite3_stmt *_sGetActiveBridges;
sqlite3_stmt *_sGetIpAssignmentsForNode; sqlite3_stmt *_sGetIpAssignmentsForNode;
sqlite3_stmt *_sGetIpAssignmentPools; sqlite3_stmt *_sGetIpAssignmentPools;
sqlite3_stmt *_sGetLocalRoutes;
sqlite3_stmt *_sCheckIfIpIsAllocated; sqlite3_stmt *_sCheckIfIpIsAllocated;
sqlite3_stmt *_sAllocateIp; sqlite3_stmt *_sAllocateIp;
sqlite3_stmt *_sDeleteIpAllocations; sqlite3_stmt *_sDeleteIpAllocations;
sqlite3_stmt *_sDeleteLocalRoutes;
sqlite3_stmt *_sGetRelays; sqlite3_stmt *_sGetRelays;
sqlite3_stmt *_sListNetworks; sqlite3_stmt *_sListNetworks;
sqlite3_stmt *_sListNetworkMembers; sqlite3_stmt *_sListNetworkMembers;

View file

@ -88,7 +88,7 @@ CREATE INDEX Member_networkId_memberRevision ON Member(networkId, memberRevision
CREATE TABLE Route ( CREATE TABLE Route (
networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE, networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,
target blob(16) NOT NULL, target blob(16) NOT NULL,
via blob(16) NOT NULL, via blob(16),
targetNetmaskBits integer NOT NULL, targetNetmaskBits integer NOT NULL,
ipVersion integer NOT NULL, ipVersion integer NOT NULL,
flags integer NOT NULL, flags integer NOT NULL,

View file

@ -89,8 +89,8 @@
"CREATE TABLE Route (\n"\ "CREATE TABLE Route (\n"\
" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\ " networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\
" target blob(16) NOT NULL,\n"\ " target blob(16) NOT NULL,\n"\
" via blob(16),\n"\
" targetNetmaskBits integer NOT NULL,\n"\ " targetNetmaskBits integer NOT NULL,\n"\
" via blob(16) NOT NULL,\n"\
" ipVersion integer NOT NULL,\n"\ " ipVersion integer NOT NULL,\n"\
" flags integer NOT NULL,\n"\ " flags integer NOT NULL,\n"\
" metric integer NOT NULL\n"\ " metric integer NOT NULL\n"\