From 734cbb2f1e5e201d2ce295241d3890f6c4f872bd Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 10 Jun 2016 15:58:35 -0700 Subject: Controller modifications for default route are ready to test. Will require slight changes in ZeroTier Central when it goes live. --- controller/SqliteNetworkController.cpp | 471 ++++++++++++--------------------- 1 file changed, 175 insertions(+), 296 deletions(-) (limited to 'controller/SqliteNetworkController.cpp') diff --git a/controller/SqliteNetworkController.cpp b/controller/SqliteNetworkController.cpp index 75523e09..ff718b3e 100644 --- a/controller/SqliteNetworkController.cpp +++ b/controller/SqliteNetworkController.cpp @@ -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;kku.object.values[k].value->u.array.length;++kk) { - json_value *gateway = j->u.object.values[k].value->u.array.values[kk]; - if ((gateway)&&(gateway->type == json_string)) { - InetAddress gwip(gateway->u.string.ptr); - 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;rku.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); } - } - } - } - */ - } 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;kku.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); + 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,"ipAssignmentPools")) { if (j->u.object.values[k].value->type == json_array) { std::vector< std::pair > 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::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) { - 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[12], - (int)ip[13], - (int)ip[14], - (int)ip[15], - (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; - } - */ - - /* deprecated - responseBody.append("],\n\t\"ipLocalRoutes\": ["); + responseBody.append("],\n\t\"routes\": ["); - 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) { + 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(_sGetLocalRoutes,0); - switch (sqlite3_column_int(_sGetLocalRoutes,2)) { + 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\"", - (firstLocalRoute) ? "\"" : ",\"", - (int)ip[12], - (int)ip[13], - (int)ip[14], - (int)ip[15], - (int)sqlite3_column_int(_sGetLocalRoutes,1)); // netmask bits + 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\"", - (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 + 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); - firstLocalRoute = false; + 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(",\"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(&(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(&(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(&(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(&(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 >::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); + // Check if this IPv4 IP is within a local-to-Ethernet routed network + int routedNetmaskBits = 0; + for(unsigned int rk=0;rk(&(nc.routes[rk].target))->sin_addr.s_addr)); + int targetBits = Utils::ntoh((uint16_t)(reinterpret_cast(&(nc.routes[rk].target))->sin_port)); + if ((ip & (0xffffffff << (32 - targetBits))) == targetIp) { + routedNetmaskBits = targetBits; + break; + } + } + } - haveStaticIpAssignment = true; // break outer loop + // 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; } - } - break; // stop checking routed networks + if (v4s.length()) + v4s.push_back(','); + v4s.append(ips); + + haveStaticIpAssignment = true; + break; + } } } - - if (haveStaticIpAssignment) - break; } } } -- cgit v1.2.3