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()); }
// 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 {
int64_t rowid;
char nodeId[16];
@ -191,23 +211,26 @@ SqliteNetworkController::SqliteNetworkController(Node *node,const char *dbPath,c
}
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,
"DROP TABLE Gateway;\n"
"CREATE TABLE Route (\n"
" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"
" target blob(16) NOT NULL,\n"
" via blob(16) NOT NULL,\n"
" via blob(16),\n"
" targetNetmaskBits integer NOT NULL,\n"
" ipVersion integer NOT NULL,\n"
" flags integer NOT NULL,\n"
" metric integer NOT NULL\n"
");\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"
,0,0,0) != SQLITE_OK) {
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);
throw std::runtime_error(err);
} else {
@ -267,11 +290,9 @@ SqliteNetworkController::SqliteNetworkController(Node *node,const char *dbPath,c
/* 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 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,"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 IS NULL AND \"type\" = ?",-1,&_sDeleteLocalRoutes,(const char **)0) != SQLITE_OK)
/* Relay */
||(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 */
||(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)
/* Config */
@ -351,11 +372,9 @@ SqliteNetworkController::~SqliteNetworkController()
sqlite3_finalize(_sGetActiveBridges);
sqlite3_finalize(_sGetIpAssignmentsForNode);
sqlite3_finalize(_sGetIpAssignmentPools);
sqlite3_finalize(_sGetLocalRoutes);
sqlite3_finalize(_sCheckIfIpIsAllocated);
sqlite3_finalize(_sAllocateIp);
sqlite3_finalize(_sDeleteIpAllocations);
sqlite3_finalize(_sDeleteLocalRoutes);
sqlite3_finalize(_sGetRelays);
sqlite3_finalize(_sListNetworks);
sqlite3_finalize(_sListNetworkMembers);
@ -379,7 +398,7 @@ SqliteNetworkController::~SqliteNetworkController()
sqlite3_finalize(_sDeleteNetwork);
sqlite3_finalize(_sCreateRoute);
sqlite3_finalize(_sGetRoutes);
sqlite3_finalize(_sDeleteRoute);
sqlite3_finalize(_sDeleteRoutes);
sqlite3_finalize(_sIncrementMemberRevisionCounter);
sqlite3_finalize(_sGetConfig);
sqlite3_finalize(_sSetConfig);
@ -518,21 +537,7 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(
InetAddress a(ipalloc->u.string.ptr);
char ipBlob[16];
int ipVersion = 0;
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;
}
_ipToBlob(a,ipBlob,ipVersion);
if (ipVersion > 0) {
sqlite3_reset(_sAllocateIp);
sqlite3_bind_text(_sAllocateIp,1,nwids,16,SQLITE_STATIC);
@ -767,72 +772,55 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(
sqlite3_step(_sCreateRelay);
}
}
} else if (!strcmp(j->u.object.values[k].name,"gateways")) {
/* deprecated
sqlite3_reset(_sDeleteGateways);
sqlite3_bind_text(_sDeleteGateways,1,nwids,16,SQLITE_STATIC);
sqlite3_step(_sDeleteGateways);
} else if (!strcmp(j->u.object.values[k].name,"routes")) {
sqlite3_reset(_sDeleteRoutes);
sqlite3_bind_text(_sDeleteRoutes,1,nwids,16,SQLITE_STATIC);
sqlite3_step(_sDeleteRoutes);
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);
sqlite3_reset(_sCreateGateway);
sqlite3_bind_text(_sCreateGateway,1,nwids,16,SQLITE_STATIC);
sqlite3_bind_int(_sCreateGateway,4,(int)gwip.metric());
if (gwip.ss_family == AF_INET) {
char ipBlob[16];
memset(ipBlob,0,12);
memcpy(ipBlob + 12,gwip.rawIpData(),4);
sqlite3_bind_blob(_sCreateGateway,2,(const void *)ipBlob,16,SQLITE_STATIC);
sqlite3_bind_int(_sCreateGateway,3,4);
sqlite3_step(_sCreateGateway);
} else if (gwip.ss_family == AF_INET6) {
sqlite3_bind_blob(_sCreateGateway,2,gwip.rawIpData(),16,SQLITE_STATIC);
sqlite3_bind_int(_sCreateGateway,3,6);
sqlite3_step(_sCreateGateway);
json_value *r = j->u.object.values[k].value->u.array.values[kk];
if ((r)&&(r->type == json_object)) {
InetAddress r_target,r_via;
int r_flags = 0;
int r_metric = 0;
for(unsigned int rk=0;rk<r->u.object.length;++rk) {
if ((!strcmp(r->u.object.values[rk].name,"target"))&&(r->u.object.values[rk].value->type == json_string))
r_target = InetAddress(std::string(r->u.object.values[rk].value->u.string.ptr));
else if ((!strcmp(r->u.object.values[rk].name,"via"))&&(r->u.object.values[rk].value->type == json_string))
r_via = InetAddress(std::string(r->u.object.values[rk].value->u.string.ptr),0);
else if ((!strcmp(r->u.object.values[rk].name,"flags"))&&(r->u.object.values[rk].value->type == json_string))
r_flags = (int)(Utils::strToUInt(r->u.object.values[rk].value->u.string.ptr) & 0xffff);
else if ((!strcmp(r->u.object.values[rk].name,"metric"))&&(r->u.object.values[rk].value->type == json_string))
r_metric = (int)(Utils::strToUInt(r->u.object.values[rk].value->u.string.ptr) & 0xffff);
}
if ((r_target)&&((!r_via)||(r_via.ss_family == r_target.ss_family))) {
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")) {
if (j->u.object.values[k].value->type == json_array) {
std::vector< std::pair<InetAddress,InetAddress> > pools;
@ -1203,55 +1191,8 @@ unsigned int SqliteNetworkController::_doCPGet(
if (sqlite3_step(_sGetMember2) == SQLITE_ROW) {
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),
"{\n%s"
"{\n"
"\t\"nwid\": \"%s\",\n"
"\t\"address\": \"%s\",\n"
"\t\"controllerInstanceId\": \"%s\",\n"
@ -1261,7 +1202,6 @@ unsigned int SqliteNetworkController::_doCPGet(
"\t\"clock\": %llu,\n"
"\t\"identity\": \"%s\",\n"
"\t\"ipAssignments\": [",
testFields.c_str(),
nwids,
addrs,
_instanceId.c_str(),
@ -1456,97 +1396,47 @@ unsigned int SqliteNetworkController::_doCPGet(
responseBody.append("\"}");
}
/* deprecated
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) {
responseBody.append("],\n\t\"routes\": [");
sqlite3_reset(_sGetRoutes);
sqlite3_bind_text(_sGetRoutes,1,nwids,16,SQLITE_STATIC);
bool firstRoute = true;
while (sqlite3_step(_sGetRoutes) == SQLITE_ROW) {
responseBody.append(firstRoute ? "\n\t\t" : ",\n\t\t");
firstRoute = false;
responseBody.append("{\"target\":");
char tmp[128];
const unsigned char *ip = (const unsigned char *)sqlite3_column_blob(_sGetGateways,0);
switch(sqlite3_column_int(_sGetGateways,1)) { // ipVersion
const unsigned char *ip = (const unsigned char *)sqlite3_column_blob(_sGetRoutes,0);
switch(sqlite3_column_int(_sGetRoutes,3)) { // ipVersion
case 4:
Utils::snprintf(tmp,sizeof(tmp),"%s%d.%d.%d.%d/%d\"",
(firstGateway) ? "\"" : ",\"",
(int)ip[12],
(int)ip[13],
(int)ip[14],
(int)ip[15],
(int)sqlite3_column_int(_sGetGateways,2)); // metric
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));
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
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));
break;
}
responseBody.append(tmp);
firstGateway = false;
}
*/
/* deprecated
responseBody.append("],\n\t\"ipLocalRoutes\": [");
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:
Utils::snprintf(tmp,sizeof(tmp),"%s%d.%d.%d.%d/%d\"",
(firstLocalRoute) ? "\"" : ",\"",
(int)ip[12],
(int)ip[13],
(int)ip[14],
(int)ip[15],
(int)sqlite3_column_int(_sGetLocalRoutes,1)); // netmask bits
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\"",
(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;
if (sqlite3_column_type(_sGetRoutes,1) == SQLITE_NULL) {
responseBody.append(",\"via\":null");
} else {
responseBody.append(",\"via\":");
ip = (const unsigned char *)sqlite3_column_blob(_sGetRoutes,1);
switch(sqlite3_column_int(_sGetRoutes,3)) { // ipVersion
case 4:
Utils::snprintf(tmp,sizeof(tmp),"\"%d.%d.%d.%d\"",(int)ip[12],(int)ip[13],(int)ip[14],(int)ip[15]);
break;
case 6:
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]);
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\": [");
@ -1701,7 +1591,7 @@ NetworkController::ResultCode SqliteNetworkController::_doNetworkConfigRequest(c
// Note: we can't reuse prepared statements that return const char * pointers without
// 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();
// Check rate limit circuit breaker to prevent flooding
@ -1978,54 +1868,37 @@ NetworkController::ResultCode SqliteNetworkController::_doNetworkConfigRequest(c
legacy[ZT_NETWORKCONFIG_DICT_KEY_RELAYS] = relays;
}
// TODO: this should be routes, going to redo DB
/*
{
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
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)) {
ZT_VirtualNetworkRoute *r = &(nc.routes[nc.routeCount]);
memset(r,0,sizeof(ZT_VirtualNetworkRoute));
switch(sqlite3_column_int(_sGetRoutes,3)) { // ipVersion
case 4:
*(reinterpret_cast<InetAddress *>(&(r->target))) = InetAddress((const void *)((const char *)sqlite3_column_blob(_sGetRoutes,0) + 12),4,(unsigned int)sqlite3_column_int(_sGetRoutes,2));
break;
case 6:
*(reinterpret_cast<InetAddress *>(&(r->target))) = InetAddress((const void *)sqlite3_column_blob(_sGetRoutes,0),16,(unsigned int)sqlite3_column_int(_sGetRoutes,2));
break;
default:
continue;
}
if (sqlite3_column_type(_sGetRoutes,1) != SQLITE_NULL) {
switch(sqlite3_column_int(_sGetRoutes,3)) { // ipVersion
case 4:
Utils::snprintf(tmp,sizeof(tmp),"%s%d.%d.%d.%d/%d",
(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);
*(reinterpret_cast<InetAddress *>(&(r->via))) = InetAddress((const void *)((const char *)sqlite3_column_blob(_sGetRoutes,1) + 12),4,0);
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);
*(reinterpret_cast<InetAddress *>(&(r->via))) = InetAddress((const void *)sqlite3_column_blob(_sGetRoutes,1),16,0);
break;
default:
continue;
}
}
if (gateways.length())
netconf[ZT_NETWORKCONFIG_DICT_KEY_GATEWAYS] = gateways;
r->flags = (uint16_t)sqlite3_column_int(_sGetRoutes,4);
r->metric = (uint16_t)sqlite3_column_int(_sGetRoutes,5);
++nc.routeCount;
}
*/
if ((network.v4AssignMode)&&(!strcmp(network.v4AssignMode,"zt"))) {
std::string v4s;
@ -2084,51 +1957,57 @@ NetworkController::ResultCode SqliteNetworkController::_doNetworkConfigRequest(c
if ((ip & 0x000000ff) == 0x000000ff)
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) {
if ((ip & (0xffffffff << (32 - r->second))) == r->first) {
// IP is included in a routed network, so check if it's allocated
uint32_t ipBlob[4];
ipBlob[0] = 0; ipBlob[1] = 0; ipBlob[2] = 0; ipBlob[3] = Utils::hton(ip);
sqlite3_reset(_sCheckIfIpIsAllocated);
sqlite3_bind_text(_sCheckIfIpIsAllocated,1,network.id,16,SQLITE_STATIC);
sqlite3_bind_blob(_sCheckIfIpIsAllocated,2,(const void *)ipBlob,16,SQLITE_STATIC);
sqlite3_bind_int(_sCheckIfIpIsAllocated,3,4); // 4 == IPv4
sqlite3_bind_int(_sCheckIfIpIsAllocated,4,(int)0 /*ZT_IP_ASSIGNMENT_TYPE_ADDRESS*/);
if (sqlite3_step(_sCheckIfIpIsAllocated) != SQLITE_ROW) {
// No rows returned, so the IP is available
sqlite3_reset(_sAllocateIp);
sqlite3_bind_text(_sAllocateIp,1,network.id,16,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_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,6,4); // 4 == IPv4
if (sqlite3_step(_sAllocateIp) == SQLITE_DONE) {
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);
if (nc.staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES) {
InetAddress tmp2(ips);
if (tmp2)
nc.staticIps[nc.staticIpCount++] = tmp2;
}
if (v4s.length())
v4s.push_back(',');
v4s.append(ips);
haveStaticIpAssignment = true; // break outer loop
}
// Check if this IPv4 IP is within a local-to-Ethernet routed network
int routedNetmaskBits = 0;
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;
}
break; // stop checking routed networks
}
}
if (haveStaticIpAssignment)
break;
// If it's routed, then try to claim and assign it and if successful end loop
if (routedNetmaskBits > 0) {
uint32_t ipBlob[4];
ipBlob[0] = 0; ipBlob[1] = 0; ipBlob[2] = 0; ipBlob[3] = Utils::hton(ip);
sqlite3_reset(_sCheckIfIpIsAllocated);
sqlite3_bind_text(_sCheckIfIpIsAllocated,1,network.id,16,SQLITE_STATIC);
sqlite3_bind_blob(_sCheckIfIpIsAllocated,2,(const void *)ipBlob,16,SQLITE_STATIC);
sqlite3_bind_int(_sCheckIfIpIsAllocated,3,4); // 4 == IPv4
sqlite3_bind_int(_sCheckIfIpIsAllocated,4,(int)0 /*ZT_IP_ASSIGNMENT_TYPE_ADDRESS*/);
if (sqlite3_step(_sCheckIfIpIsAllocated) != SQLITE_ROW) {
// No rows returned, so the IP is available
sqlite3_reset(_sAllocateIp);
sqlite3_bind_text(_sAllocateIp,1,network.id,16,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_blob(_sAllocateIp,4,(const void *)ipBlob,16,SQLITE_STATIC);
sqlite3_bind_int(_sAllocateIp,5,routedNetmaskBits); // IP netmask bits from matching route
sqlite3_bind_int(_sAllocateIp,6,4); // 4 == IPv4
if (sqlite3_step(_sAllocateIp) == SQLITE_DONE) {
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),routedNetmaskBits);
if (nc.staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES) {
InetAddress tmp2(ips);
if (tmp2)
nc.staticIps[nc.staticIpCount++] = tmp2;
}
if (v4s.length())
v4s.push_back(',');
v4s.append(ips);
haveStaticIpAssignment = true;
break;
}
}
}
}
}
}

View file

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

View file

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

View file

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