Merge branch 'adamierymenko-dev' into android-jni

This commit is contained in:
Grant Limberg 2015-07-20 19:51:58 -07:00
commit d05e8a9772
6 changed files with 89 additions and 39 deletions

View File

@ -184,9 +184,9 @@ SqliteNetworkController::SqliteNetworkController(const char *dbPath) :
||(sqlite3_prepare_v2(_db,"DELETE FROM IpAssignment WHERE networkId = ? AND nodeId IS NULL AND \"type\" = ?",-1,&_sDeleteLocalRoutes,(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 nodeId,phyAddress FROM Relay WHERE networkId = ? ORDER BY nodeId 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)
||(sqlite3_prepare_v2(_db,"DELETE FROM Relay WHERE networkId = ?",-1,&_sDeleteRelaysForNetwork,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"DELETE FROM Relay WHERE networkId = ?",-1,&_sDeleteRelaysForNetwork,(const char **)0) != SQLITE_OK)
||(sqlite3_prepare_v2(_db,"INSERT INTO Relay (networkId,nodeId,phyAddress) VALUES (?,?,?)",-1,&_sCreateRelay,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"INSERT INTO Relay (\"networkId\",\"address\",\"phyAddress\") VALUES (?,?,?)",-1,&_sCreateRelay,(const char **)0) != SQLITE_OK)
/* Member */ /* Member */
||(sqlite3_prepare_v2(_db,"SELECT rowid,authorized,activeBridge FROM Member WHERE networkId = ? AND nodeId = ?",-1,&_sGetMember,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"SELECT rowid,authorized,activeBridge FROM Member WHERE networkId = ? AND nodeId = ?",-1,&_sGetMember,(const char **)0) != SQLITE_OK)
@ -203,11 +203,35 @@ SqliteNetworkController::SqliteNetworkController(const char *dbPath) :
||(sqlite3_prepare_v2(_db,"DELETE FROM Gateway WHERE networkId = ?",-1,&_sDeleteGateways,(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) ||(sqlite3_prepare_v2(_db,"INSERT INTO Gateway (networkId,ip,ipVersion,metric) VALUES (?,?,?,?)",-1,&_sCreateGateway,(const char **)0) != SQLITE_OK)
/* Config */
||(sqlite3_prepare_v2(_db,"SELECT \"v\" FROM \"Config\" WHERE \"k\" = ?",-1,&_sGetConfig,(const char **)0) != SQLITE_OK)
||(sqlite3_prepare_v2(_db,"INSERT INTO \"Config\" (\"k\",\"v\") VALUES (?,?)",-1,&_sSetConfig,(const char **)0) != SQLITE_OK)
) { ) {
//printf("!!! %s\n",sqlite3_errmsg(_db)); //printf("!!! %s\n",sqlite3_errmsg(_db));
sqlite3_close(_db); sqlite3_close(_db);
throw std::runtime_error("SqliteNetworkController unable to initialize one or more prepared statements"); throw std::runtime_error("SqliteNetworkController unable to initialize one or more prepared statements");
} }
/* Generate a 128-bit / 32-character "instance ID" if one isn't already
* defined. Clients can use this to determine if this is the same controller
* database they know and love. */
sqlite3_reset(_sGetConfig);
sqlite3_bind_text(_sGetConfig,1,"instanceId",10,SQLITE_STATIC);
if (sqlite3_step(_sGetConfig) != SQLITE_ROW) {
unsigned char sr[32];
Utils::getSecureRandom(sr,32);
char instanceId[32];
for(unsigned int i=0;i<32;++i)
instanceId[i] = "0123456789abcdef"[(unsigned int)sr[i] & 0xf];
sqlite3_reset(_sSetConfig);
sqlite3_bind_text(_sSetConfig,1,"instanceId",10,SQLITE_STATIC);
sqlite3_bind_text(_sSetConfig,2,instanceId,32,SQLITE_STATIC);
if (sqlite3_step(_sSetConfig) != SQLITE_DONE) {
sqlite3_close(_db);
throw std::runtime_error("SqliteNetworkController unable to read or initialize instanceId");
}
}
} }
SqliteNetworkController::~SqliteNetworkController() SqliteNetworkController::~SqliteNetworkController()
@ -254,6 +278,8 @@ SqliteNetworkController::~SqliteNetworkController()
sqlite3_finalize(_sDeleteGateways); sqlite3_finalize(_sDeleteGateways);
sqlite3_finalize(_sCreateGateway); sqlite3_finalize(_sCreateGateway);
sqlite3_finalize(_sIncrementMemberRevisionCounter); sqlite3_finalize(_sIncrementMemberRevisionCounter);
sqlite3_finalize(_sGetConfig);
sqlite3_finalize(_sSetConfig);
sqlite3_close(_db); sqlite3_close(_db);
} }
} }
@ -363,8 +389,10 @@ NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(co
// If netconf is unchanged from client reported revision, just tell client they're up to date // If netconf is unchanged from client reported revision, just tell client they're up to date
if ((haveRevision > 0)&&(haveRevision == network.revision)) // Temporarily disabled -- old version didn't do this, and we'll go ahead and
return NetworkController::NETCONF_QUERY_OK_BUT_NOT_NEWER; // test more thoroughly before enabling this optimization.
//if ((haveRevision > 0)&&(haveRevision == network.revision))
// return NetworkController::NETCONF_QUERY_OK_BUT_NOT_NEWER;
// Create and sign netconf // Create and sign netconf
@ -387,10 +415,16 @@ NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(co
sqlite3_reset(_sGetEtherTypesFromRuleTable); sqlite3_reset(_sGetEtherTypesFromRuleTable);
sqlite3_bind_text(_sGetEtherTypesFromRuleTable,1,network.id,16,SQLITE_STATIC); sqlite3_bind_text(_sGetEtherTypesFromRuleTable,1,network.id,16,SQLITE_STATIC);
while (sqlite3_step(_sGetEtherTypesFromRuleTable) == SQLITE_ROW) { while (sqlite3_step(_sGetEtherTypesFromRuleTable) == SQLITE_ROW) {
if (sqlite3_column_type(_sGetEtherTypesFromRuleTable,0) == SQLITE_NULL) {
allowedEtherTypes.clear();
allowedEtherTypes.push_back(0); // NULL 'allow' matches ANY
break;
} else {
int et = sqlite3_column_int(_sGetEtherTypesFromRuleTable,0); int et = sqlite3_column_int(_sGetEtherTypesFromRuleTable,0);
if ((et >= 0)&&(et <= 0xffff)) if ((et >= 0)&&(et <= 0xffff))
allowedEtherTypes.push_back(et); allowedEtherTypes.push_back(et);
} }
}
std::sort(allowedEtherTypes.begin(),allowedEtherTypes.end()); std::sort(allowedEtherTypes.begin(),allowedEtherTypes.end());
allowedEtherTypes.erase(std::unique(allowedEtherTypes.begin(),allowedEtherTypes.end()),allowedEtherTypes.end()); allowedEtherTypes.erase(std::unique(allowedEtherTypes.begin(),allowedEtherTypes.end()),allowedEtherTypes.end());
std::string allowedEtherTypesCsv; std::string allowedEtherTypesCsv;
@ -792,16 +826,15 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(
if (!networkExists) { if (!networkExists) {
if (path[1].substr(10) == "______") { if (path[1].substr(10) == "______") {
// A special POST /network/##########______ feature lets users create a network // A special POST /network/##########______ feature lets users create a network
// with an arbitrary unused network ID. // with an arbitrary unused network number at this controller.
nwid = 0; nwid = 0;
uint64_t nwidPrefix = (Utils::hexStrToU64(path[1].substr(0,10).c_str()) << 24) & 0xffffffffff000000ULL; uint64_t nwidPrefix = (Utils::hexStrToU64(path[1].substr(0,10).c_str()) << 24) & 0xffffffffff000000ULL;
uint64_t nwidPostfix = 0; uint64_t nwidPostfix = 0;
Utils::getSecureRandom(&nwidPostfix,sizeof(nwidPostfix)); Utils::getSecureRandom(&nwidPostfix,sizeof(nwidPostfix));
nwidPostfix &= 0xffffffULL;
uint64_t nwidOriginalPostfix = nwidPostfix; uint64_t nwidOriginalPostfix = nwidPostfix;
do { do {
uint64_t tryNwid = nwidPrefix | nwidPostfix; uint64_t tryNwid = nwidPrefix | (nwidPostfix & 0xffffffULL);
if (!nwidPostfix) if (!nwidPostfix)
tryNwid |= 1; tryNwid |= 1;
Utils::snprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)tryNwid); Utils::snprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)tryNwid);
@ -814,7 +847,6 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(
} }
++nwidPostfix; ++nwidPostfix;
nwidPostfix &= 0xffffffULL;
} while (nwidPostfix != nwidOriginalPostfix); } while (nwidPostfix != nwidOriginalPostfix);
// 503 means we have no more free IDs for this prefix. You shouldn't host anywhere // 503 means we have no more free IDs for this prefix. You shouldn't host anywhere
@ -840,12 +872,12 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(
if (!strcmp(j->u.object.values[k].name,"name")) { if (!strcmp(j->u.object.values[k].name,"name")) {
if ((j->u.object.values[k].value->type == json_string)&&(j->u.object.values[k].value->u.string.ptr[0])) { if ((j->u.object.values[k].value->type == json_string)&&(j->u.object.values[k].value->u.string.ptr[0])) {
if (sqlite3_prepare_v2(_db,"UPDATE Network SET name = ? WHERE id = ?",-1,&stmt,(const char **)0) == SQLITE_OK) if (sqlite3_prepare_v2(_db,"UPDATE Network SET \"name\" = ? WHERE id = ?",-1,&stmt,(const char **)0) == SQLITE_OK)
sqlite3_bind_text(stmt,1,j->u.object.values[k].value->u.string.ptr,-1,SQLITE_STATIC); sqlite3_bind_text(stmt,1,j->u.object.values[k].value->u.string.ptr,-1,SQLITE_STATIC);
} }
} else if (!strcmp(j->u.object.values[k].name,"private")) { } else if (!strcmp(j->u.object.values[k].name,"private")) {
if (j->u.object.values[k].value->type == json_boolean) { if (j->u.object.values[k].value->type == json_boolean) {
if (sqlite3_prepare_v2(_db,"UPDATE Network SET private = ? WHERE id = ?",-1,&stmt,(const char **)0) == SQLITE_OK) if (sqlite3_prepare_v2(_db,"UPDATE Network SET \"private\" = ? WHERE id = ?",-1,&stmt,(const char **)0) == SQLITE_OK)
sqlite3_bind_int(stmt,1,(j->u.object.values[k].value->u.boolean == 0) ? 0 : 1); sqlite3_bind_int(stmt,1,(j->u.object.values[k].value->u.boolean == 0) ? 0 : 1);
} }
} else if (!strcmp(j->u.object.values[k].name,"enableBroadcast")) { } else if (!strcmp(j->u.object.values[k].name,"enableBroadcast")) {
@ -899,8 +931,9 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(
for(std::map<Address,InetAddress>::iterator rl(nodeIdToPhyAddress.begin());rl!=nodeIdToPhyAddress.end();++rl) { for(std::map<Address,InetAddress>::iterator rl(nodeIdToPhyAddress.begin());rl!=nodeIdToPhyAddress.end();++rl) {
sqlite3_reset(_sCreateRelay); sqlite3_reset(_sCreateRelay);
sqlite3_bind_text(_sCreateRelay,1,nwids,16,SQLITE_STATIC); sqlite3_bind_text(_sCreateRelay,1,nwids,16,SQLITE_STATIC);
sqlite3_bind_text(_sCreateRelay,2,rl->first.toString().c_str(),-1,SQLITE_STATIC); std::string a(rl->first.toString()),b(rl->second.toString()); // don't destroy strings until sqlite3_step()
sqlite3_bind_text(_sCreateRelay,3,rl->second.toString().c_str(),-1,SQLITE_STATIC); sqlite3_bind_text(_sCreateRelay,2,a.c_str(),-1,SQLITE_STATIC);
sqlite3_bind_text(_sCreateRelay,3,b.c_str(),-1,SQLITE_STATIC);
sqlite3_step(_sCreateRelay); sqlite3_step(_sCreateRelay);
} }
} }
@ -999,13 +1032,12 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(
sqlite3_step(_sDeleteIpAssignmentPoolsForNetwork); sqlite3_step(_sDeleteIpAssignmentPoolsForNetwork);
for(std::vector< std::pair<InetAddress,InetAddress> >::const_iterator p(pools.begin());p!=pools.end();++p) { for(std::vector< std::pair<InetAddress,InetAddress> >::const_iterator p(pools.begin());p!=pools.end();++p) {
char ipBlob1[16],ipBlob2[16];
sqlite3_reset(_sCreateIpAssignmentPool); sqlite3_reset(_sCreateIpAssignmentPool);
sqlite3_bind_text(_sCreateIpAssignmentPool,1,nwids,16,SQLITE_STATIC); sqlite3_bind_text(_sCreateIpAssignmentPool,1,nwids,16,SQLITE_STATIC);
if (p->first.ss_family == AF_INET) { if (p->first.ss_family == AF_INET) {
char ipBlob1[16];
memset(ipBlob1,0,12); memset(ipBlob1,0,12);
memcpy(ipBlob1 + 12,p->first.rawIpData(),4); memcpy(ipBlob1 + 12,p->first.rawIpData(),4);
char ipBlob2[16];
memset(ipBlob2,0,12); memset(ipBlob2,0,12);
memcpy(ipBlob2 + 12,p->second.rawIpData(),4); memcpy(ipBlob2 + 12,p->second.rawIpData(),4);
sqlite3_bind_blob(_sCreateIpAssignmentPool,2,(const void *)ipBlob1,16,SQLITE_STATIC); sqlite3_bind_blob(_sCreateIpAssignmentPool,2,(const void *)ipBlob1,16,SQLITE_STATIC);
@ -1498,15 +1530,28 @@ unsigned int SqliteNetworkController::_doCPGet(
sqlite3_bind_text(_sGetIpAssignmentPools2,1,nwids,16,SQLITE_STATIC); sqlite3_bind_text(_sGetIpAssignmentPools2,1,nwids,16,SQLITE_STATIC);
bool firstIpAssignmentPool = true; bool firstIpAssignmentPool = true;
while (sqlite3_step(_sGetIpAssignmentPools2) == SQLITE_ROW) { while (sqlite3_step(_sGetIpAssignmentPools2) == SQLITE_ROW) {
const char *ipRangeStartB = reinterpret_cast<const char *>(sqlite3_column_blob(_sGetIpAssignmentPools2,0));
const char *ipRangeEndB = reinterpret_cast<const char *>(sqlite3_column_blob(_sGetIpAssignmentPools2,1));
if ((ipRangeStartB)&&(ipRangeEndB)) {
InetAddress ipps,ippe;
int ipVersion = sqlite3_column_int(_sGetIpAssignmentPools2,2);
if (ipVersion == 4) {
ipps.set((const void *)(ipRangeStartB + 12),4,0);
ippe.set((const void *)(ipRangeEndB + 12),4,0);
} else if (ipVersion == 6) {
ipps.set((const void *)ipRangeStartB,16,0);
ippe.set((const void *)ipRangeEndB,16,0);
}
if (ipps) {
responseBody.append(firstIpAssignmentPool ? "\n\t\t" : ",\n\t\t"); responseBody.append(firstIpAssignmentPool ? "\n\t\t" : ",\n\t\t");
firstIpAssignmentPool = false; firstIpAssignmentPool = false;
InetAddress ipps((const void *)sqlite3_column_blob(_sGetIpAssignmentPools2,0),(sqlite3_column_int(_sGetIpAssignmentPools2,2) == 6) ? 16 : 4,0);
InetAddress ippe((const void *)sqlite3_column_blob(_sGetIpAssignmentPools2,1),(sqlite3_column_int(_sGetIpAssignmentPools2,2) == 6) ? 16 : 4,0);
Utils::snprintf(json,sizeof(json),"{\"ipRangeStart\":\"%s\",\"ipRangeEnd\":\"%s\"}", Utils::snprintf(json,sizeof(json),"{\"ipRangeStart\":\"%s\",\"ipRangeEnd\":\"%s\"}",
_jsonEscape(ipps.toIpString()).c_str(), _jsonEscape(ipps.toIpString()).c_str(),
_jsonEscape(ippe.toIpString()).c_str()); _jsonEscape(ippe.toIpString()).c_str());
responseBody.append(json); responseBody.append(json);
} }
}
}
responseBody.append("],\n\t\"rules\": ["); responseBody.append("],\n\t\"rules\": [");
@ -1515,6 +1560,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");
firstRule = false;
Utils::snprintf(json,sizeof(json),"\t\t\"ruleNo\": %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) {
@ -1611,10 +1657,14 @@ unsigned int SqliteNetworkController::_doCPGet(
} else { } else {
// GET /controller returns status and API version if controller is supported // GET /controller returns status and API version if controller is supported
Utils::snprintf(json,sizeof(json),"{\n\t\"controller\": true,\n\t\"apiVersion\": %d,\n\t\"clock\": %llu\n}",ZT_NETCONF_CONTROLLER_API_VERSION,(unsigned long long)OSUtils::now()); sqlite3_reset(_sGetConfig);
sqlite3_bind_text(_sGetConfig,1,"instanceId",10,SQLITE_STATIC);
if (sqlite3_step(_sGetConfig) == SQLITE_ROW) {
Utils::snprintf(json,sizeof(json),"{\n\t\"controller\": true,\n\t\"apiVersion\": %d,\n\t\"clock\": %llu,\n\t\"instanceId\": \"%s\"\n}\n",ZT_NETCONF_CONTROLLER_API_VERSION,(unsigned long long)OSUtils::now(),(const char *)sqlite3_column_text(_sGetConfig,0));
responseBody = json; responseBody = json;
responseContentType = "applicaiton/json"; responseContentType = "applicaiton/json";
return 200; return 200;
} else return 500;
} }
return 404; return 404;

View File

@ -138,6 +138,8 @@ private:
sqlite3_stmt *_sDeleteGateways; sqlite3_stmt *_sDeleteGateways;
sqlite3_stmt *_sCreateGateway; sqlite3_stmt *_sCreateGateway;
sqlite3_stmt *_sIncrementMemberRevisionCounter; sqlite3_stmt *_sIncrementMemberRevisionCounter;
sqlite3_stmt *_sGetConfig;
sqlite3_stmt *_sSetConfig;
Mutex _lock; Mutex _lock;
}; };

View File

@ -67,12 +67,11 @@ CREATE INDEX Member_networkId_memberRevision ON Member(networkId, memberRevision
CREATE TABLE Relay ( CREATE TABLE Relay (
networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE, networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,
nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE, address char(10) NOT NULL,
phyAddress varchar(64) NOT NULL, phyAddress varchar(64) NOT NULL
PRIMARY KEY (networkId, nodeId)
); );
CREATE INDEX Relay_networkId ON Relay (networkId); CREATE UNIQUE INDEX Relay_networkId_address ON Relay (networkId,address);
CREATE TABLE Rule ( CREATE TABLE Rule (
networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE, networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,

View File

@ -68,12 +68,11 @@
"\n"\ "\n"\
"CREATE TABLE Relay (\n"\ "CREATE TABLE Relay (\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"\
" nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE,\n"\ " address char(10) NOT NULL,\n"\
" phyAddress varchar(64) NOT NULL,\n"\ " phyAddress varchar(64) NOT NULL\n"\
" PRIMARY KEY (networkId, nodeId)\n"\
");\n"\ ");\n"\
"\n"\ "\n"\
"CREATE INDEX Relay_networkId ON Relay (networkId);\n"\ "CREATE UNIQUE INDEX Relay_networkId_address ON Relay (networkId,address);\n"\
"\n"\ "\n"\
"CREATE TABLE Rule (\n"\ "CREATE TABLE Rule (\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"\

View File

@ -89,7 +89,7 @@ public:
throw() throw()
{ {
if (ip.isV4()) { if (ip.isV4()) {
// IPv4 wants braodcast MACs, so we shove the V4 address itself into // IPv4 wants broadcast MACs, so we shove the V4 address itself into
// the Multicast Group ADI field. Making V4 ARP work is basically why // the Multicast Group ADI field. Making V4 ARP work is basically why
// ADI was added, as well as handling other things that want mindless // ADI was added, as well as handling other things that want mindless
// Ethernet broadcast to all. // Ethernet broadcast to all.

View File

@ -626,7 +626,7 @@ public:
while (ua) { while (ua) {
InetAddress ip(ua->Address.lpSockaddr); InetAddress ip(ua->Address.lpSockaddr);
ip.setPort(_port); ip.setPort(_port);
_node->addLocalInterfaceAddress(reinterpret_cast<const struct sockaddr_storage *>(&ip),0,ZT1_LOCAL_INTERFACE_ADDRESS_TRUST_NORMAL,0); _node->addLocalInterfaceAddress(reinterpret_cast<const struct sockaddr_storage *>(&ip),0,ZT1_LOCAL_INTERFACE_ADDRESS_TRUST_NORMAL);
ua = ua->Next; ua = ua->Next;
} }
} }