|
@@ -169,20 +169,19 @@ SqliteNetworkController::SqliteNetworkController(const char *dbPath) :
|
|
|
||(sqlite3_prepare_v2(_db,"SELECT ipNetwork,ipNetmaskBits,ipVersion FROM IpAssignmentPool WHERE networkId = ? ORDER BY ipNetwork ASC",-1,&_sGetIpAssignmentPools2,(const char **)0) != SQLITE_OK)
|
|
|
||(sqlite3_prepare_v2(_db,"SELECT ruleId,nodeId,vlanId,vlanPcp,etherType,macSource,macDest,ipSource,ipDest,ipTos,ipProtocol,ipSourcePort,ipDestPort,\"action\" FROM Rule WHERE networkId = ? ORDER BY ruleId ASC",-1,&_sListRules,(const char **)0) != SQLITE_OK)
|
|
|
||(sqlite3_prepare_v2(_db,"INSERT INTO Rule (networkId,ruleId,nodeId,vlanId,vlanPcP,etherType,macSource,macDest,ipSource,ipDest,ipTos,ipProtocol,ipSourcePort,ipDestPort,\"action\") VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",-1,&_sCreateRule,(const char **)0) != SQLITE_OK)
|
|
|
- ||(sqlite3_prepare_v2(_db,"INSERT INTO Network (networkId,name,creationTime,revision) VALUES (?,?,?,1)",-1,&_sCreateNetwork,(const char **)0) != SQLITE_OK)
|
|
|
- ||(sqlite3_prepare_v2(_db,"UPDATE Network SET ? = ? WHERE networkId = ?",-1,&_sUpdateNetworkField,(const char **)0) != SQLITE_OK)
|
|
|
+ ||(sqlite3_prepare_v2(_db,"INSERT INTO Network (id,name,creationTime,revision) VALUES (?,?,?,1)",-1,&_sCreateNetwork,(const char **)0) != SQLITE_OK)
|
|
|
||(sqlite3_prepare_v2(_db,"SELECT revision FROM Network WHERE id = ?",-1,&_sGetNetworkRevision,(const char **)0) != SQLITE_OK)
|
|
|
||(sqlite3_prepare_v2(_db,"UPDATE Network SET revision = ? WHERE id = ?",-1,&_sSetNetworkRevision,(const char **)0) != SQLITE_OK)
|
|
|
- ||(sqlite3_prepare_v2(_db,"SELECT ip,ipNetmaskBits,ipVersion FROM IpAssignment WHERE networkId = ? AND nodeId = ?",-1,&_sGetIpAssignmentsForNode2,(const char **)0) != SQLITE_OK)
|
|
|
+ ||(sqlite3_prepare_v2(_db,"SELECT ip,ipNetmaskBits,ipVersion FROM IpAssignment WHERE networkId = ? AND nodeId = ? ORDER BY ip ASC",-1,&_sGetIpAssignmentsForNode2,(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,"DELETE FROM IpAssignmentPool WHERE networkId = ?",-1,&_sDeleteIpAssignmentPoolsForNetwork,(const char **)0) != SQLITE_OK)
|
|
|
||(sqlite3_prepare_v2(_db,"DELETE FROM Rule WHERE networkId = ?",-1,&_sDeleteRulesForNetwork,(const char **)0) != SQLITE_OK)
|
|
|
||(sqlite3_prepare_v2(_db,"INSERT INTO IpAssignmentPool (networkId,ipNetwork,ipNetmaskBits,ipVersion) VALUES (?,?,?,?)",-1,&_sCreateIpAssignmentPool,(const char **)0) != SQLITE_OK)
|
|
|
- ||(sqlite3_prepare_v2(_db,"UPDATE Member SET ? = ? WHERE rowid = ?",-1,&_sUpdateMemberField,(const char **)0) != SQLITE_OK)
|
|
|
||(sqlite3_prepare_v2(_db,"DELETE FROM Member WHERE networkId = ? AND nodeId = ?",-1,&_sDeleteMember,(const char **)0) != SQLITE_OK)
|
|
|
||(sqlite3_prepare_v2(_db,"DELETE FROM IpAssignment WHERE networkId = ?; DELETE FROM IpAssignmentPool WHERE networkId = ?; DELETE FROM Member WHERE networkId = ?; DELETE FROM MulticastRate WHERE networkId = ?; DELETE FROM Relay WHERE networkId = ?; DELETE FROM Rule WHERE networkId = ?; DELETE FROM Network WHERE id = ?;",-1,&_sDeleteNetworkAndRelated,(const char **)0) != SQLITE_OK)
|
|
|
) {
|
|
|
+ //printf("!!! %s\n",sqlite3_errmsg(_db));
|
|
|
sqlite3_close(_db);
|
|
|
throw std::runtime_error("SqliteNetworkController unable to initialize one or more prepared statements");
|
|
|
}
|
|
@@ -215,7 +214,6 @@ SqliteNetworkController::~SqliteNetworkController()
|
|
|
sqlite3_finalize(_sListRules);
|
|
|
sqlite3_finalize(_sCreateRule);
|
|
|
sqlite3_finalize(_sCreateNetwork);
|
|
|
- sqlite3_finalize(_sUpdateNetworkField);
|
|
|
sqlite3_finalize(_sGetNetworkRevision);
|
|
|
sqlite3_finalize(_sSetNetworkRevision);
|
|
|
sqlite3_finalize(_sGetIpAssignmentsForNode2);
|
|
@@ -224,7 +222,6 @@ SqliteNetworkController::~SqliteNetworkController()
|
|
|
sqlite3_finalize(_sDeleteIpAssignmentPoolsForNetwork);
|
|
|
sqlite3_finalize(_sDeleteRulesForNetwork);
|
|
|
sqlite3_finalize(_sCreateIpAssignmentPool);
|
|
|
- sqlite3_finalize(_sUpdateMemberField);
|
|
|
sqlite3_finalize(_sDeleteNetworkAndRelated);
|
|
|
sqlite3_close(_db);
|
|
|
}
|
|
@@ -562,282 +559,8 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpGET(
|
|
|
std::string &responseBody,
|
|
|
std::string &responseContentType)
|
|
|
{
|
|
|
- char json[16384];
|
|
|
-
|
|
|
- if (path.empty())
|
|
|
- return 404;
|
|
|
Mutex::Lock _l(_lock);
|
|
|
-
|
|
|
- if (path[0] == "network") {
|
|
|
-
|
|
|
- if ((path.size() >= 2)&&(path[1].length() == 16)) {
|
|
|
- uint64_t nwid = Utils::hexStrToU64(path[1].c_str());
|
|
|
- char nwids[24];
|
|
|
- Utils::snprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)nwid);
|
|
|
-
|
|
|
- if (path.size() >= 3) {
|
|
|
- if ((path.size() == 4)&&(path[2] == "member")&&(path[3].length() == 10)) {
|
|
|
- uint64_t address = Utils::hexStrToU64(path[3].c_str());
|
|
|
- char addrs[24];
|
|
|
- Utils::snprintf(addrs,sizeof(addrs),"%.10llx",address);
|
|
|
-
|
|
|
- sqlite3_reset(_sGetMember2);
|
|
|
- sqlite3_bind_text(_sGetMember2,1,nwids,16,SQLITE_STATIC);
|
|
|
- sqlite3_bind_text(_sGetMember2,2,addrs,10,SQLITE_STATIC);
|
|
|
- if (sqlite3_step(_sGetMember2) == SQLITE_ROW) {
|
|
|
- Utils::snprintf(json,sizeof(json),
|
|
|
- "{\n"
|
|
|
- "\tnwid: \"%s\",\n"
|
|
|
- "\taddress: \"%s\",\n"
|
|
|
- "\tauthorized: %s,\n"
|
|
|
- "\tactiveBridge: %s,\n"
|
|
|
- "\tlastAt: \"%s\",\n"
|
|
|
- "\tlastSeen: %llu,\n"
|
|
|
- "\tfirstSeen: %llu,\n"
|
|
|
- "\tidentity: \"%s\",\n"
|
|
|
- "\tipAssignments: [",
|
|
|
- nwids,
|
|
|
- addrs,
|
|
|
- (sqlite3_column_int(_sGetMember2,0) > 0) ? "true" : "false",
|
|
|
- (sqlite3_column_int(_sGetMember2,1) > 0) ? "true" : "false",
|
|
|
- _jsonEscape((const char *)sqlite3_column_text(_sGetMember2,3)).c_str(),
|
|
|
- (unsigned long long)sqlite3_column_int64(_sGetMember2,4),
|
|
|
- (unsigned long long)sqlite3_column_int64(_sGetMember2,5),
|
|
|
- _jsonEscape((const char *)sqlite3_column_text(_sGetMember2,2)).c_str());
|
|
|
- responseBody = json;
|
|
|
-
|
|
|
- sqlite3_reset(_sGetIpAssignmentsForNode2);
|
|
|
- sqlite3_bind_text(_sGetIpAssignmentsForNode2,1,nwids,16,SQLITE_STATIC);
|
|
|
- sqlite3_bind_text(_sGetIpAssignmentsForNode2,2,addrs,10,SQLITE_STATIC);
|
|
|
- bool firstIp = true;
|
|
|
- while (sqlite3_step(_sGetIpAssignmentPools2) == SQLITE_ROW) {
|
|
|
- InetAddress ip((const void *)sqlite3_column_blob(_sGetIpAssignmentsForNode2,0),(sqlite3_column_int(_sGetIpAssignmentsForNode2,2) == 6) ? 16 : 4,(unsigned int)sqlite3_column_int(_sGetIpAssignmentPools2,1));
|
|
|
- responseBody.append(firstIp ? "\"" : ",\"");
|
|
|
- firstIp = false;
|
|
|
- responseBody.append(_jsonEscape(ip.toString()));
|
|
|
- responseBody.push_back('"');
|
|
|
- }
|
|
|
-
|
|
|
- responseBody.append("]");
|
|
|
-
|
|
|
- /* It's possible to get the actual netconf dictionary by including these
|
|
|
- * three URL arguments. The member identity must be the string
|
|
|
- * serialized identity of this member, and the signing identity must be
|
|
|
- * the full secret identity of this network controller. The have revision
|
|
|
- * is optional but would designate the revision our hypothetical client
|
|
|
- * already has.
|
|
|
- *
|
|
|
- * This is primarily for testing and is not used in production. It makes
|
|
|
- * it easy to test the entire network controller via its JSON API.
|
|
|
- *
|
|
|
- * If these arguments are included, three more object fields are returned:
|
|
|
- * 'netconf', 'netconfResult', and 'netconfResultMessage'. These are all
|
|
|
- * string fields and contain the actual netconf dictionary, the query
|
|
|
- * result code, and any verbose message e.g. an error description. */
|
|
|
- std::map<std::string,std::string>::const_iterator memids(urlArgs.find("memberIdentity"));
|
|
|
- std::map<std::string,std::string>::const_iterator sigids(urlArgs.find("signingIdentity"));
|
|
|
- std::map<std::string,std::string>::const_iterator hrs(urlArgs.find("haveRevision"));
|
|
|
- if ((memids != urlArgs.end())&&(sigids != urlArgs.end())) {
|
|
|
- Dictionary netconf;
|
|
|
- Identity memid,sigid;
|
|
|
- try {
|
|
|
- if (memid.fromString(memids->second)&&sigid.fromString(sigids->second)&&sigid.hasPrivate()) {
|
|
|
- uint64_t hr = 0;
|
|
|
- if (hrs != urlArgs.end())
|
|
|
- hr = Utils::strToU64(hrs->second.c_str());
|
|
|
- const char *result = "";
|
|
|
- switch(this->doNetworkConfigRequest(InetAddress(),sigid,memid,nwid,Dictionary(),hr,netconf)) {
|
|
|
- case NetworkController::NETCONF_QUERY_OK: result = "OK"; break;
|
|
|
- case NetworkController::NETCONF_QUERY_OK_BUT_NOT_NEWER: result = "OK_BUT_NOT_NEWER"; break;
|
|
|
- case NetworkController::NETCONF_QUERY_OBJECT_NOT_FOUND: result = "OBJECT_NOT_FOUND"; break;
|
|
|
- case NetworkController::NETCONF_QUERY_ACCESS_DENIED: result = "ACCESS_DENIED"; break;
|
|
|
- case NetworkController::NETCONF_QUERY_INTERNAL_SERVER_ERROR: result = "INTERNAL_SERVER_ERROR"; break;
|
|
|
- default: result = "(unrecognized result code)"; break;
|
|
|
- }
|
|
|
- responseBody.append(",\n\tnetconf: \"");
|
|
|
- responseBody.append(_jsonEscape(netconf.toString().c_str()));
|
|
|
- responseBody.append("\",\n\tnetconfResult: \"");
|
|
|
- responseBody.append(result);
|
|
|
- responseBody.append("\",\n\tnetconfResultMessage: \"");
|
|
|
- responseBody.append(_jsonEscape(netconf["error"].c_str()));
|
|
|
- responseBody.append("\"");
|
|
|
- } else {
|
|
|
- responseBody.append(",\n\tnetconf: \"\",\n\tnetconfResult: \"INTERNAL_SERVER_ERROR\",\n\tnetconfResultMessage: \"invalid member or signing identity\"");
|
|
|
- }
|
|
|
- } catch ( ... ) {
|
|
|
- responseBody.append(",\n\tnetconf: \"\",\n\tnetconfResult: \"INTERNAL_SERVER_ERROR\",\n\tnetconfResultMessage: \"unexpected exception\"");
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- responseBody.append("\n}\n");
|
|
|
-
|
|
|
- responseContentType = "application/json";
|
|
|
- return 200;
|
|
|
- } // else 404
|
|
|
- } // else 404
|
|
|
- } else {
|
|
|
- // get network info
|
|
|
- sqlite3_reset(_sGetNetworkById);
|
|
|
- sqlite3_bind_text(_sGetNetworkById,1,nwids,16,SQLITE_STATIC);
|
|
|
- if (sqlite3_step(_sGetNetworkById) == SQLITE_ROW) {
|
|
|
- Utils::snprintf(json,sizeof(json),
|
|
|
- "{\n"
|
|
|
- "\tnwid: \"%s\",\n"
|
|
|
- "\tname: \"%s\",\n"
|
|
|
- "\tprivate: %s,\n"
|
|
|
- "\tenableBroadcast: %s,\n"
|
|
|
- "\tallowPassiveBridging: %s,\n"
|
|
|
- "\tv4AssignMode: \"%s\",\n"
|
|
|
- "\tv6AssignMode: \"%s\",\n"
|
|
|
- "\tmulticastLimit: %d,\n"
|
|
|
- "\tcreationTime: %llu,\n",
|
|
|
- "\trevision: %llu,\n"
|
|
|
- "\amembers: [",
|
|
|
- nwids,
|
|
|
- _jsonEscape((const char *)sqlite3_column_text(_sGetNetworkById,0)).c_str(),
|
|
|
- (sqlite3_column_int(_sGetNetworkById,1) > 0) ? "true" : "false",
|
|
|
- (sqlite3_column_int(_sGetNetworkById,2) > 0) ? "true" : "false",
|
|
|
- (sqlite3_column_int(_sGetNetworkById,3) > 0) ? "true" : "false",
|
|
|
- _jsonEscape((const char *)sqlite3_column_text(_sGetNetworkById,4)).c_str(),
|
|
|
- _jsonEscape((const char *)sqlite3_column_text(_sGetNetworkById,5)).c_str(),
|
|
|
- sqlite3_column_int(_sGetNetworkById,6),
|
|
|
- (unsigned long long)sqlite3_column_int64(_sGetNetworkById,7),
|
|
|
- (unsigned long long)sqlite3_column_int64(_sGetNetworkById,8));
|
|
|
- responseBody = json;
|
|
|
-
|
|
|
- sqlite3_reset(_sListNetworkMembers);
|
|
|
- sqlite3_bind_text(_sListNetworkMembers,1,nwids,16,SQLITE_STATIC);
|
|
|
- bool firstMember = true;
|
|
|
- while (sqlite3_step(_sListNetworkMembers) == SQLITE_ROW) {
|
|
|
- if (!firstMember)
|
|
|
- responseBody.push_back(',');
|
|
|
- responseBody.push_back('"');
|
|
|
- responseBody.append((const char *)sqlite3_column_text(_sListNetworkMembers,0));
|
|
|
- responseBody.push_back('"');
|
|
|
- firstMember = false;
|
|
|
- }
|
|
|
- responseBody.append("],\n\trelays: [");
|
|
|
-
|
|
|
- sqlite3_reset(_sGetRelays);
|
|
|
- sqlite3_bind_text(_sGetRelays,1,nwids,16,SQLITE_STATIC);
|
|
|
- bool firstRelay = true;
|
|
|
- while (sqlite3_step(_sGetRelays) == SQLITE_ROW) {
|
|
|
- responseBody.append(firstRelay ? "\n\t\t" : ",\n\t\t");
|
|
|
- firstRelay = false;
|
|
|
- responseBody.append("{address:\"");
|
|
|
- responseBody.append((const char *)sqlite3_column_text(_sGetRelays,0));
|
|
|
- responseBody.append("\",phyAddress:\"");
|
|
|
- responseBody.append(_jsonEscape((const char *)sqlite3_column_text(_sGetRelays,1)));
|
|
|
- responseBody.append("\"}");
|
|
|
- }
|
|
|
- responseBody.append("],\n\tipAssignmentPools: [");
|
|
|
-
|
|
|
- sqlite3_reset(_sGetIpAssignmentPools2);
|
|
|
- sqlite3_bind_text(_sGetIpAssignmentPools2,1,nwids,16,SQLITE_STATIC);
|
|
|
- bool firstIpAssignmentPool = true;
|
|
|
- while (sqlite3_step(_sGetIpAssignmentPools2) == SQLITE_ROW) {
|
|
|
- responseBody.append(firstIpAssignmentPool ? "\n\t\t" : ",\n\t\t");
|
|
|
- firstIpAssignmentPool = false;
|
|
|
- InetAddress ipp((const void *)sqlite3_column_blob(_sGetIpAssignmentPools2,0),(sqlite3_column_int(_sGetIpAssignmentPools2,2) == 6) ? 16 : 4,(unsigned int)sqlite3_column_int(_sGetIpAssignmentPools2,1));
|
|
|
- Utils::snprintf(json,sizeof(json),"{network:\"%s\",netmaskBits:%u}",
|
|
|
- _jsonEscape(ipp.toIpString()).c_str(),
|
|
|
- ipp.netmaskBits());
|
|
|
- responseBody.append(json);
|
|
|
- }
|
|
|
- responseBody.append("],\n\trules: [");
|
|
|
-
|
|
|
- sqlite3_reset(_sListRules);
|
|
|
- sqlite3_bind_text(_sListRules,1,nwids,16,SQLITE_STATIC);
|
|
|
- bool firstRule = true;
|
|
|
- while (sqlite3_step(_sListRules) == SQLITE_ROW) {
|
|
|
- responseBody.append(firstRule ? "\n\t{\n" : ",{\n");
|
|
|
- Utils::snprintf(json,sizeof(json),"\t\truleId: %lld,\n",sqlite3_column_int64(_sListRules,0));
|
|
|
- responseBody.append(json);
|
|
|
- if (sqlite3_column_type(_sListRules,1) != SQLITE_NULL) {
|
|
|
- Utils::snprintf(json,sizeof(json),"\t\tnodeId: \"%s\",\n",(const char *)sqlite3_column_text(_sListRules,1));
|
|
|
- responseBody.append(json);
|
|
|
- }
|
|
|
- if (sqlite3_column_type(_sListRules,2) != SQLITE_NULL) {
|
|
|
- Utils::snprintf(json,sizeof(json),"\t\tvlanId: %d,\n",sqlite3_column_int(_sListRules,2));
|
|
|
- responseBody.append(json);
|
|
|
- }
|
|
|
- if (sqlite3_column_type(_sListRules,3) != SQLITE_NULL) {
|
|
|
- Utils::snprintf(json,sizeof(json),"\t\tvlanPcp: %d,\n",sqlite3_column_int(_sListRules,3));
|
|
|
- responseBody.append(json);
|
|
|
- }
|
|
|
- if (sqlite3_column_type(_sListRules,4) != SQLITE_NULL) {
|
|
|
- Utils::snprintf(json,sizeof(json),"\t\tetherType: %d,\n",sqlite3_column_int(_sListRules,4));
|
|
|
- responseBody.append(json);
|
|
|
- }
|
|
|
- if (sqlite3_column_type(_sListRules,5) != SQLITE_NULL) {
|
|
|
- Utils::snprintf(json,sizeof(json),"\t\tmacSource: \"%s\",\n",MAC((const char *)sqlite3_column_text(_sListRules,5)).toString().c_str());
|
|
|
- responseBody.append(json);
|
|
|
- }
|
|
|
- if (sqlite3_column_type(_sListRules,6) != SQLITE_NULL) {
|
|
|
- Utils::snprintf(json,sizeof(json),"\t\tmacDest: \"%s\",\n",MAC((const char *)sqlite3_column_text(_sListRules,6)).toString().c_str());
|
|
|
- responseBody.append(json);
|
|
|
- }
|
|
|
- if (sqlite3_column_type(_sListRules,7) != SQLITE_NULL) {
|
|
|
- Utils::snprintf(json,sizeof(json),"\t\tipSource: \"%s\",\n",_jsonEscape((const char *)sqlite3_column_text(_sListRules,7)).c_str());
|
|
|
- responseBody.append(json);
|
|
|
- }
|
|
|
- if (sqlite3_column_type(_sListRules,8) != SQLITE_NULL) {
|
|
|
- Utils::snprintf(json,sizeof(json),"\t\tipDest: \"%s\",\n",_jsonEscape((const char *)sqlite3_column_text(_sListRules,8)).c_str());
|
|
|
- responseBody.append(json);
|
|
|
- }
|
|
|
- if (sqlite3_column_type(_sListRules,9) != SQLITE_NULL) {
|
|
|
- Utils::snprintf(json,sizeof(json),"\t\tipTos: %d,\n",sqlite3_column_int(_sListRules,9));
|
|
|
- responseBody.append(json);
|
|
|
- }
|
|
|
- if (sqlite3_column_type(_sListRules,10) != SQLITE_NULL) {
|
|
|
- Utils::snprintf(json,sizeof(json),"\t\tipProtocol: %d,\n",sqlite3_column_int(_sListRules,10));
|
|
|
- responseBody.append(json);
|
|
|
- }
|
|
|
- if (sqlite3_column_type(_sListRules,11) != SQLITE_NULL) {
|
|
|
- Utils::snprintf(json,sizeof(json),"\t\tipSourcePort: %d,\n",sqlite3_column_int(_sListRules,11));
|
|
|
- responseBody.append(json);
|
|
|
- }
|
|
|
- if (sqlite3_column_type(_sListRules,12) != SQLITE_NULL) {
|
|
|
- Utils::snprintf(json,sizeof(json),"\t\tipDestPort: %d,\n",sqlite3_column_int(_sListRules,12));
|
|
|
- responseBody.append(json);
|
|
|
- }
|
|
|
- responseBody.append("\t\taction: \"");
|
|
|
- responseBody.append(_jsonEscape((const char *)sqlite3_column_text(_sListRules,13)));
|
|
|
- responseBody.append("\"\n\t}");
|
|
|
- }
|
|
|
-
|
|
|
- responseBody.append("]\n}\n");
|
|
|
- responseContentType = "application/json";
|
|
|
- return 200;
|
|
|
- } // else 404
|
|
|
- }
|
|
|
- } else if (path.size() == 1) {
|
|
|
- // list networks
|
|
|
- sqlite3_reset(_sListNetworks);
|
|
|
- responseContentType = "application/json";
|
|
|
- responseBody = "[";
|
|
|
- bool first = true;
|
|
|
- while (sqlite3_step(_sListNetworks) == SQLITE_ROW) {
|
|
|
- if (first) {
|
|
|
- first = false;
|
|
|
- responseBody.push_back('"');
|
|
|
- } else responseBody.append(",\"");
|
|
|
- responseBody.append((const char *)sqlite3_column_text(_sListNetworks,0));
|
|
|
- responseBody.push_back('"');
|
|
|
- }
|
|
|
- responseBody.push_back(']');
|
|
|
- return 200;
|
|
|
- } // else 404
|
|
|
-
|
|
|
- } else {
|
|
|
- // GET /controller returns status and API version if controller is supported
|
|
|
- Utils::snprintf(json,sizeof(json),"{\n\tcontroller: true,\n\tapiVersion: %d\n\tclock: %llu\n}",ZT_NETCONF_CONTROLLER_API_VERSION,(unsigned long long)OSUtils::now());
|
|
|
- responseBody = json;
|
|
|
- responseContentType = "applicaiton/json";
|
|
|
- return 200;
|
|
|
- }
|
|
|
-
|
|
|
- return 404;
|
|
|
+ return _doCPGet(path,urlArgs,headers,body,responseBody,responseContentType);
|
|
|
}
|
|
|
|
|
|
unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(
|
|
@@ -902,20 +625,25 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(
|
|
|
if (j) {
|
|
|
if (j->type == json_object) {
|
|
|
for(unsigned int k=0;k<j->u.object.length;++k) {
|
|
|
- sqlite3_reset(_sUpdateMemberField);
|
|
|
- sqlite3_bind_int64(_sUpdateMemberField,3,memberRowId);
|
|
|
|
|
|
if (!strcmp(j->u.object.values[k].name,"authorized")) {
|
|
|
if (j->u.object.values[k].value->type == json_boolean) {
|
|
|
- sqlite3_bind_text(_sUpdateMemberField,1,"authorized",-1,SQLITE_STATIC);
|
|
|
- sqlite3_bind_int(_sUpdateMemberField,2,(j->u.object.values[k].value->u.boolean == 0) ? 0 : 1);
|
|
|
- sqlite3_step(_sUpdateMemberField);
|
|
|
+ sqlite3_stmt *stmt = (sqlite3_stmt *)0;
|
|
|
+ if (sqlite3_prepare_v2(_db,"UPDATE Member SET authorized = ? WHERE rowid = ?",-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_int64(stmt,2,memberRowId);
|
|
|
+ sqlite3_step(stmt);
|
|
|
+ sqlite3_finalize(stmt);
|
|
|
}
|
|
|
} else if (!strcmp(j->u.object.values[k].name,"activeBridge")) {
|
|
|
if (j->u.object.values[k].value->type == json_boolean) {
|
|
|
- sqlite3_bind_text(_sUpdateMemberField,1,"activeBridge",-1,SQLITE_STATIC);
|
|
|
- sqlite3_bind_int(_sUpdateMemberField,2,(j->u.object.values[k].value->u.boolean == 0) ? 0 : 1);
|
|
|
- sqlite3_step(_sUpdateMemberField);
|
|
|
+ sqlite3_stmt *stmt = (sqlite3_stmt *)0;
|
|
|
+ if (sqlite3_prepare_v2(_db,"UPDATE Member SET activeBridge = ? WHERE rowid = ?",-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_int64(stmt,2,memberRowId);
|
|
|
+ sqlite3_step(stmt);
|
|
|
+ sqlite3_finalize(stmt);
|
|
|
+ }
|
|
|
}
|
|
|
} else if (!strcmp(j->u.object.values[k].name,"ipAssignments")) {
|
|
|
if (j->u.object.values[k].value->type == json_array) {
|
|
@@ -957,12 +685,13 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
}
|
|
|
}
|
|
|
json_value_free(j);
|
|
|
}
|
|
|
|
|
|
- return handleControlPlaneHttpGET(path,urlArgs,headers,body,responseBody,responseContentType);
|
|
|
+ return _doCPGet(path,urlArgs,headers,body,responseBody,responseContentType);
|
|
|
} // else 404
|
|
|
|
|
|
} else {
|
|
@@ -980,50 +709,42 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(
|
|
|
if (j) {
|
|
|
if (j->type == json_object) {
|
|
|
for(unsigned int k=0;k<j->u.object.length;++k) {
|
|
|
- sqlite3_reset(_sUpdateNetworkField);
|
|
|
- sqlite3_bind_text(_sUpdateNetworkField,3,nwids,16,SQLITE_STATIC);
|
|
|
+ sqlite3_stmt *stmt = (sqlite3_stmt *)0;
|
|
|
|
|
|
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])) {
|
|
|
- sqlite3_bind_text(_sUpdateNetworkField,1,"name",-1,SQLITE_STATIC);
|
|
|
- sqlite3_bind_text(_sUpdateNetworkField,2,j->u.object.values[k].value->u.string.ptr,-1,SQLITE_STATIC);
|
|
|
- sqlite3_step(_sUpdateNetworkField);
|
|
|
+ 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);
|
|
|
}
|
|
|
} else if (!strcmp(j->u.object.values[k].name,"private")) {
|
|
|
if (j->u.object.values[k].value->type == json_boolean) {
|
|
|
- sqlite3_bind_text(_sUpdateNetworkField,1,"private",-1,SQLITE_STATIC);
|
|
|
- sqlite3_bind_int(_sUpdateNetworkField,2,(j->u.object.values[k].value->u.boolean == 0) ? 0 : 1);
|
|
|
- sqlite3_step(_sUpdateNetworkField);
|
|
|
+ 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);
|
|
|
}
|
|
|
} else if (!strcmp(j->u.object.values[k].name,"enableBroadcast")) {
|
|
|
if (j->u.object.values[k].value->type == json_boolean) {
|
|
|
- sqlite3_bind_text(_sUpdateNetworkField,1,"enableBroadcast",-1,SQLITE_STATIC);
|
|
|
- sqlite3_bind_int(_sUpdateNetworkField,2,(j->u.object.values[k].value->u.boolean == 0) ? 0 : 1);
|
|
|
- sqlite3_step(_sUpdateNetworkField);
|
|
|
+ if (sqlite3_prepare_v2(_db,"UPDATE Network SET enableBroadcast = ? 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);
|
|
|
}
|
|
|
} else if (!strcmp(j->u.object.values[k].name,"allowPassiveBridging")) {
|
|
|
if (j->u.object.values[k].value->type == json_boolean) {
|
|
|
- sqlite3_bind_text(_sUpdateNetworkField,1,"allowPassiveBridging",-1,SQLITE_STATIC);
|
|
|
- sqlite3_bind_int(_sUpdateNetworkField,2,(j->u.object.values[k].value->u.boolean == 0) ? 0 : 1);
|
|
|
- sqlite3_step(_sUpdateNetworkField);
|
|
|
+ if (sqlite3_prepare_v2(_db,"UPDATE Network SET allowPassiveBridging = ? 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);
|
|
|
}
|
|
|
} else if (!strcmp(j->u.object.values[k].name,"v4AssignMode")) {
|
|
|
if (j->u.object.values[k].value->type == json_string) {
|
|
|
- sqlite3_bind_text(_sUpdateNetworkField,1,"v4AssignMode",-1,SQLITE_STATIC);
|
|
|
- sqlite3_bind_text(_sUpdateNetworkField,2,j->u.object.values[k].value->u.string.ptr,-1,SQLITE_STATIC);
|
|
|
- sqlite3_step(_sUpdateNetworkField);
|
|
|
+ if (sqlite3_prepare_v2(_db,"UPDATE Network SET v4AssignMode = ? 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);
|
|
|
}
|
|
|
} else if (!strcmp(j->u.object.values[k].name,"v6AssignMode")) {
|
|
|
if (j->u.object.values[k].value->type == json_string) {
|
|
|
- sqlite3_bind_text(_sUpdateNetworkField,1,"v6AssignMode",-1,SQLITE_STATIC);
|
|
|
- sqlite3_bind_text(_sUpdateNetworkField,2,j->u.object.values[k].value->u.string.ptr,-1,SQLITE_STATIC);
|
|
|
- sqlite3_step(_sUpdateNetworkField);
|
|
|
+ if (sqlite3_prepare_v2(_db,"UPDATE Network SET v6AssignMode = ? 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);
|
|
|
}
|
|
|
} else if (!strcmp(j->u.object.values[k].name,"multicastLimit")) {
|
|
|
if (j->u.object.values[k].value->type == json_integer) {
|
|
|
- sqlite3_bind_text(_sUpdateNetworkField,1,"multicastLimit",-1,SQLITE_STATIC);
|
|
|
- sqlite3_bind_int(_sUpdateNetworkField,2,(int)j->u.object.values[k].value->u.integer);
|
|
|
- sqlite3_step(_sUpdateNetworkField);
|
|
|
+ if (sqlite3_prepare_v2(_db,"UPDATE Network SET multicastLimit = ? WHERE id = ?",-1,&stmt,(const char **)0) == SQLITE_OK)
|
|
|
+ sqlite3_bind_int(stmt,1,(int)j->u.object.values[k].value->u.integer);
|
|
|
}
|
|
|
} else if (!strcmp(j->u.object.values[k].name,"relays")) {
|
|
|
if (j->u.object.values[k].value->type == json_array) {
|
|
@@ -1185,6 +906,12 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ if (stmt) {
|
|
|
+ sqlite3_bind_text(stmt,2,nwids,16,SQLITE_STATIC);
|
|
|
+ sqlite3_step(stmt);
|
|
|
+ sqlite3_finalize(stmt);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
json_value_free(j);
|
|
@@ -1195,7 +922,7 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(
|
|
|
sqlite3_bind_text(_sSetNetworkRevision,2,nwids,16,SQLITE_STATIC);
|
|
|
sqlite3_step(_sSetNetworkRevision);
|
|
|
|
|
|
- return handleControlPlaneHttpGET(path,urlArgs,headers,body,responseBody,responseContentType);
|
|
|
+ return _doCPGet(path,urlArgs,headers,body,responseBody,responseContentType);
|
|
|
}
|
|
|
|
|
|
} // else 404
|
|
@@ -1260,4 +987,287 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpDELETE(
|
|
|
return 404;
|
|
|
}
|
|
|
|
|
|
+unsigned int SqliteNetworkController::_doCPGet(
|
|
|
+ const std::vector<std::string> &path,
|
|
|
+ const std::map<std::string,std::string> &urlArgs,
|
|
|
+ const std::map<std::string,std::string> &headers,
|
|
|
+ const std::string &body,
|
|
|
+ std::string &responseBody,
|
|
|
+ std::string &responseContentType)
|
|
|
+{
|
|
|
+ // Assumes _lock is locked
|
|
|
+ char json[16384];
|
|
|
+
|
|
|
+ if ((path.size() > 0)&&(path[0] == "network")) {
|
|
|
+
|
|
|
+ if ((path.size() >= 2)&&(path[1].length() == 16)) {
|
|
|
+ uint64_t nwid = Utils::hexStrToU64(path[1].c_str());
|
|
|
+ char nwids[24];
|
|
|
+ Utils::snprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)nwid);
|
|
|
+
|
|
|
+ if (path.size() >= 3) {
|
|
|
+ if ((path.size() == 4)&&(path[2] == "member")&&(path[3].length() == 10)) {
|
|
|
+ uint64_t address = Utils::hexStrToU64(path[3].c_str());
|
|
|
+ char addrs[24];
|
|
|
+ Utils::snprintf(addrs,sizeof(addrs),"%.10llx",address);
|
|
|
+
|
|
|
+ sqlite3_reset(_sGetMember2);
|
|
|
+ sqlite3_bind_text(_sGetMember2,1,nwids,16,SQLITE_STATIC);
|
|
|
+ sqlite3_bind_text(_sGetMember2,2,addrs,10,SQLITE_STATIC);
|
|
|
+ if (sqlite3_step(_sGetMember2) == SQLITE_ROW) {
|
|
|
+ Utils::snprintf(json,sizeof(json),
|
|
|
+ "{\n"
|
|
|
+ "\t\"nwid\": \"%s\",\n"
|
|
|
+ "\t\"address\": \"%s\",\n"
|
|
|
+ "\t\"authorized\": %s,\n"
|
|
|
+ "\t\"activeBridge\": %s,\n"
|
|
|
+ "\t\"lastAt\": \"%s\",\n"
|
|
|
+ "\t\"lastSeen\": %llu,\n"
|
|
|
+ "\t\"firstSeen\": %llu,\n"
|
|
|
+ "\t\"identity\": \"%s\",\n"
|
|
|
+ "\t\"ipAssignments\": [",
|
|
|
+ nwids,
|
|
|
+ addrs,
|
|
|
+ (sqlite3_column_int(_sGetMember2,0) > 0) ? "true" : "false",
|
|
|
+ (sqlite3_column_int(_sGetMember2,1) > 0) ? "true" : "false",
|
|
|
+ _jsonEscape((const char *)sqlite3_column_text(_sGetMember2,3)).c_str(),
|
|
|
+ (unsigned long long)sqlite3_column_int64(_sGetMember2,4),
|
|
|
+ (unsigned long long)sqlite3_column_int64(_sGetMember2,5),
|
|
|
+ _jsonEscape((const char *)sqlite3_column_text(_sGetMember2,2)).c_str());
|
|
|
+ responseBody = json;
|
|
|
+
|
|
|
+ sqlite3_reset(_sGetIpAssignmentsForNode2);
|
|
|
+ sqlite3_bind_text(_sGetIpAssignmentsForNode2,1,nwids,16,SQLITE_STATIC);
|
|
|
+ sqlite3_bind_text(_sGetIpAssignmentsForNode2,2,addrs,10,SQLITE_STATIC);
|
|
|
+ bool firstIp = true;
|
|
|
+ while (sqlite3_step(_sGetIpAssignmentPools2) == SQLITE_ROW) {
|
|
|
+ InetAddress ip((const void *)sqlite3_column_blob(_sGetIpAssignmentsForNode2,0),(sqlite3_column_int(_sGetIpAssignmentsForNode2,2) == 6) ? 16 : 4,(unsigned int)sqlite3_column_int(_sGetIpAssignmentPools2,1));
|
|
|
+ responseBody.append(firstIp ? "\"" : ",\"");
|
|
|
+ firstIp = false;
|
|
|
+ responseBody.append(_jsonEscape(ip.toString()));
|
|
|
+ responseBody.push_back('"');
|
|
|
+ }
|
|
|
+
|
|
|
+ responseBody.append("]");
|
|
|
+
|
|
|
+ /* It's possible to get the actual netconf dictionary by including these
|
|
|
+ * three URL arguments. The member identity must be the string
|
|
|
+ * serialized identity of this member, and the signing identity must be
|
|
|
+ * the full secret identity of this network controller. The have revision
|
|
|
+ * is optional but would designate the revision our hypothetical client
|
|
|
+ * already has.
|
|
|
+ *
|
|
|
+ * This is primarily for testing and is not used in production. It makes
|
|
|
+ * it easy to test the entire network controller via its JSON API.
|
|
|
+ *
|
|
|
+ * If these arguments are included, three more object fields are returned:
|
|
|
+ * 'netconf', 'netconfResult', and 'netconfResultMessage'. These are all
|
|
|
+ * string fields and contain the actual netconf dictionary, the query
|
|
|
+ * result code, and any verbose message e.g. an error description. */
|
|
|
+ std::map<std::string,std::string>::const_iterator memids(urlArgs.find("memberIdentity"));
|
|
|
+ std::map<std::string,std::string>::const_iterator sigids(urlArgs.find("signingIdentity"));
|
|
|
+ std::map<std::string,std::string>::const_iterator hrs(urlArgs.find("haveRevision"));
|
|
|
+ if ((memids != urlArgs.end())&&(sigids != urlArgs.end())) {
|
|
|
+ Dictionary netconf;
|
|
|
+ Identity memid,sigid;
|
|
|
+ try {
|
|
|
+ if (memid.fromString(memids->second)&&sigid.fromString(sigids->second)&&sigid.hasPrivate()) {
|
|
|
+ uint64_t hr = 0;
|
|
|
+ if (hrs != urlArgs.end())
|
|
|
+ hr = Utils::strToU64(hrs->second.c_str());
|
|
|
+ const char *result = "";
|
|
|
+ switch(this->doNetworkConfigRequest(InetAddress(),sigid,memid,nwid,Dictionary(),hr,netconf)) {
|
|
|
+ case NetworkController::NETCONF_QUERY_OK: result = "OK"; break;
|
|
|
+ case NetworkController::NETCONF_QUERY_OK_BUT_NOT_NEWER: result = "OK_BUT_NOT_NEWER"; break;
|
|
|
+ case NetworkController::NETCONF_QUERY_OBJECT_NOT_FOUND: result = "OBJECT_NOT_FOUND"; break;
|
|
|
+ case NetworkController::NETCONF_QUERY_ACCESS_DENIED: result = "ACCESS_DENIED"; break;
|
|
|
+ case NetworkController::NETCONF_QUERY_INTERNAL_SERVER_ERROR: result = "INTERNAL_SERVER_ERROR"; break;
|
|
|
+ default: result = "(unrecognized result code)"; break;
|
|
|
+ }
|
|
|
+ responseBody.append(",\n\t\"netconf\": \"");
|
|
|
+ responseBody.append(_jsonEscape(netconf.toString().c_str()));
|
|
|
+ responseBody.append("\",\n\t\"netconfResult\": \"");
|
|
|
+ responseBody.append(result);
|
|
|
+ responseBody.append("\",\n\t\"netconfResultMessage\": \"");
|
|
|
+ responseBody.append(_jsonEscape(netconf["error"].c_str()));
|
|
|
+ responseBody.append("\"");
|
|
|
+ } else {
|
|
|
+ responseBody.append(",\n\t\"netconf\": \"\",\n\t\"netconfResult\": \"INTERNAL_SERVER_ERROR\",\n\t\"netconfResultMessage\": \"invalid member or signing identity\"");
|
|
|
+ }
|
|
|
+ } catch ( ... ) {
|
|
|
+ responseBody.append(",\n\t\"netconf\": \"\",\n\t\"netconfResult\": \"INTERNAL_SERVER_ERROR\",\n\t\"netconfResultMessage\": \"unexpected exception\"");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ responseBody.append("\n}\n");
|
|
|
+
|
|
|
+ responseContentType = "application/json";
|
|
|
+ return 200;
|
|
|
+ } // else 404
|
|
|
+ } // else 404
|
|
|
+ } else {
|
|
|
+ // get network info
|
|
|
+ sqlite3_reset(_sGetNetworkById);
|
|
|
+ sqlite3_bind_text(_sGetNetworkById,1,nwids,16,SQLITE_STATIC);
|
|
|
+ if (sqlite3_step(_sGetNetworkById) == SQLITE_ROW) {
|
|
|
+ Utils::snprintf(json,sizeof(json),
|
|
|
+ "{\n"
|
|
|
+ "\t\"nwid\": \"%s\",\n"
|
|
|
+ "\t\"name\": \"%s\",\n"
|
|
|
+ "\t\"private\": %s,\n"
|
|
|
+ "\t\"enableBroadcast\": %s,\n"
|
|
|
+ "\t\"allowPassiveBridging\": %s,\n"
|
|
|
+ "\t\"v4AssignMode\": \"%s\",\n"
|
|
|
+ "\t\"v6AssignMode\": \"%s\",\n"
|
|
|
+ "\t\"multicastLimit\": %d,\n"
|
|
|
+ "\t\"creationTime\": %llu,\n"
|
|
|
+ "\t\"revision\": %llu,\n"
|
|
|
+ "\t\"members\": [",
|
|
|
+ nwids,
|
|
|
+ _jsonEscape((const char *)sqlite3_column_text(_sGetNetworkById,0)).c_str(),
|
|
|
+ (sqlite3_column_int(_sGetNetworkById,1) > 0) ? "true" : "false",
|
|
|
+ (sqlite3_column_int(_sGetNetworkById,2) > 0) ? "true" : "false",
|
|
|
+ (sqlite3_column_int(_sGetNetworkById,3) > 0) ? "true" : "false",
|
|
|
+ _jsonEscape((const char *)sqlite3_column_text(_sGetNetworkById,4)).c_str(),
|
|
|
+ _jsonEscape((const char *)sqlite3_column_text(_sGetNetworkById,5)).c_str(),
|
|
|
+ sqlite3_column_int(_sGetNetworkById,6),
|
|
|
+ (unsigned long long)sqlite3_column_int64(_sGetNetworkById,7),
|
|
|
+ (unsigned long long)sqlite3_column_int64(_sGetNetworkById,8));
|
|
|
+ responseBody = json;
|
|
|
+
|
|
|
+ sqlite3_reset(_sListNetworkMembers);
|
|
|
+ sqlite3_bind_text(_sListNetworkMembers,1,nwids,16,SQLITE_STATIC);
|
|
|
+ bool firstMember = true;
|
|
|
+ while (sqlite3_step(_sListNetworkMembers) == SQLITE_ROW) {
|
|
|
+ if (!firstMember)
|
|
|
+ responseBody.push_back(',');
|
|
|
+ responseBody.push_back('"');
|
|
|
+ responseBody.append((const char *)sqlite3_column_text(_sListNetworkMembers,0));
|
|
|
+ responseBody.push_back('"');
|
|
|
+ firstMember = false;
|
|
|
+ }
|
|
|
+ responseBody.append("],\n\t\"relays\": [");
|
|
|
+
|
|
|
+ sqlite3_reset(_sGetRelays);
|
|
|
+ sqlite3_bind_text(_sGetRelays,1,nwids,16,SQLITE_STATIC);
|
|
|
+ bool firstRelay = true;
|
|
|
+ while (sqlite3_step(_sGetRelays) == SQLITE_ROW) {
|
|
|
+ responseBody.append(firstRelay ? "\n\t\t" : ",\n\t\t");
|
|
|
+ firstRelay = false;
|
|
|
+ responseBody.append("{\"address\":\"");
|
|
|
+ responseBody.append((const char *)sqlite3_column_text(_sGetRelays,0));
|
|
|
+ responseBody.append("\",\"phyAddress\":\"");
|
|
|
+ responseBody.append(_jsonEscape((const char *)sqlite3_column_text(_sGetRelays,1)));
|
|
|
+ responseBody.append("\"}");
|
|
|
+ }
|
|
|
+ responseBody.append("],\n\t\"ipAssignmentPools\": [");
|
|
|
+
|
|
|
+ sqlite3_reset(_sGetIpAssignmentPools2);
|
|
|
+ sqlite3_bind_text(_sGetIpAssignmentPools2,1,nwids,16,SQLITE_STATIC);
|
|
|
+ bool firstIpAssignmentPool = true;
|
|
|
+ while (sqlite3_step(_sGetIpAssignmentPools2) == SQLITE_ROW) {
|
|
|
+ responseBody.append(firstIpAssignmentPool ? "\n\t\t" : ",\n\t\t");
|
|
|
+ firstIpAssignmentPool = false;
|
|
|
+ InetAddress ipp((const void *)sqlite3_column_blob(_sGetIpAssignmentPools2,0),(sqlite3_column_int(_sGetIpAssignmentPools2,2) == 6) ? 16 : 4,(unsigned int)sqlite3_column_int(_sGetIpAssignmentPools2,1));
|
|
|
+ Utils::snprintf(json,sizeof(json),"{\"network\":\"%s\",\"netmaskBits\":%u}",
|
|
|
+ _jsonEscape(ipp.toIpString()).c_str(),
|
|
|
+ ipp.netmaskBits());
|
|
|
+ responseBody.append(json);
|
|
|
+ }
|
|
|
+ responseBody.append("],\n\t\"rules\": [");
|
|
|
+
|
|
|
+ sqlite3_reset(_sListRules);
|
|
|
+ sqlite3_bind_text(_sListRules,1,nwids,16,SQLITE_STATIC);
|
|
|
+ bool firstRule = true;
|
|
|
+ while (sqlite3_step(_sListRules) == SQLITE_ROW) {
|
|
|
+ responseBody.append(firstRule ? "\n\t{\n" : ",{\n");
|
|
|
+ Utils::snprintf(json,sizeof(json),"\t\t\"ruleId\": %lld,\n",sqlite3_column_int64(_sListRules,0));
|
|
|
+ responseBody.append(json);
|
|
|
+ if (sqlite3_column_type(_sListRules,1) != SQLITE_NULL) {
|
|
|
+ Utils::snprintf(json,sizeof(json),"\t\t\"nodeId\": \"%s\",\n",(const char *)sqlite3_column_text(_sListRules,1));
|
|
|
+ responseBody.append(json);
|
|
|
+ }
|
|
|
+ if (sqlite3_column_type(_sListRules,2) != SQLITE_NULL) {
|
|
|
+ Utils::snprintf(json,sizeof(json),"\t\t\"vlanId\": %d,\n",sqlite3_column_int(_sListRules,2));
|
|
|
+ responseBody.append(json);
|
|
|
+ }
|
|
|
+ if (sqlite3_column_type(_sListRules,3) != SQLITE_NULL) {
|
|
|
+ Utils::snprintf(json,sizeof(json),"\t\t\"vlanPcp\": %d,\n",sqlite3_column_int(_sListRules,3));
|
|
|
+ responseBody.append(json);
|
|
|
+ }
|
|
|
+ if (sqlite3_column_type(_sListRules,4) != SQLITE_NULL) {
|
|
|
+ Utils::snprintf(json,sizeof(json),"\t\t\"etherType\": %d,\n",sqlite3_column_int(_sListRules,4));
|
|
|
+ responseBody.append(json);
|
|
|
+ }
|
|
|
+ if (sqlite3_column_type(_sListRules,5) != SQLITE_NULL) {
|
|
|
+ Utils::snprintf(json,sizeof(json),"\t\t\"macSource\": \"%s\",\n",MAC((const char *)sqlite3_column_text(_sListRules,5)).toString().c_str());
|
|
|
+ responseBody.append(json);
|
|
|
+ }
|
|
|
+ if (sqlite3_column_type(_sListRules,6) != SQLITE_NULL) {
|
|
|
+ Utils::snprintf(json,sizeof(json),"\t\t\"macDest\": \"%s\",\n",MAC((const char *)sqlite3_column_text(_sListRules,6)).toString().c_str());
|
|
|
+ responseBody.append(json);
|
|
|
+ }
|
|
|
+ if (sqlite3_column_type(_sListRules,7) != SQLITE_NULL) {
|
|
|
+ Utils::snprintf(json,sizeof(json),"\t\t\"ipSource\": \"%s\",\n",_jsonEscape((const char *)sqlite3_column_text(_sListRules,7)).c_str());
|
|
|
+ responseBody.append(json);
|
|
|
+ }
|
|
|
+ if (sqlite3_column_type(_sListRules,8) != SQLITE_NULL) {
|
|
|
+ Utils::snprintf(json,sizeof(json),"\t\t\"ipDest\": \"%s\",\n",_jsonEscape((const char *)sqlite3_column_text(_sListRules,8)).c_str());
|
|
|
+ responseBody.append(json);
|
|
|
+ }
|
|
|
+ if (sqlite3_column_type(_sListRules,9) != SQLITE_NULL) {
|
|
|
+ Utils::snprintf(json,sizeof(json),"\t\t\"ipTos\": %d,\n",sqlite3_column_int(_sListRules,9));
|
|
|
+ responseBody.append(json);
|
|
|
+ }
|
|
|
+ if (sqlite3_column_type(_sListRules,10) != SQLITE_NULL) {
|
|
|
+ Utils::snprintf(json,sizeof(json),"\t\t\"ipProtocol\": %d,\n",sqlite3_column_int(_sListRules,10));
|
|
|
+ responseBody.append(json);
|
|
|
+ }
|
|
|
+ if (sqlite3_column_type(_sListRules,11) != SQLITE_NULL) {
|
|
|
+ Utils::snprintf(json,sizeof(json),"\t\t\"ipSourcePort\": %d,\n",sqlite3_column_int(_sListRules,11));
|
|
|
+ responseBody.append(json);
|
|
|
+ }
|
|
|
+ if (sqlite3_column_type(_sListRules,12) != SQLITE_NULL) {
|
|
|
+ Utils::snprintf(json,sizeof(json),"\t\t\"ipDestPort\": %d,\n",sqlite3_column_int(_sListRules,12));
|
|
|
+ responseBody.append(json);
|
|
|
+ }
|
|
|
+ responseBody.append("\t\t\"action\": \"");
|
|
|
+ responseBody.append(_jsonEscape((const char *)sqlite3_column_text(_sListRules,13)));
|
|
|
+ responseBody.append("\"\n\t}");
|
|
|
+ }
|
|
|
+
|
|
|
+ responseBody.append("]\n}\n");
|
|
|
+ responseContentType = "application/json";
|
|
|
+ return 200;
|
|
|
+ } // else 404
|
|
|
+ }
|
|
|
+ } else if (path.size() == 1) {
|
|
|
+ // list networks
|
|
|
+ sqlite3_reset(_sListNetworks);
|
|
|
+ responseContentType = "application/json";
|
|
|
+ responseBody = "[";
|
|
|
+ bool first = true;
|
|
|
+ while (sqlite3_step(_sListNetworks) == SQLITE_ROW) {
|
|
|
+ if (first) {
|
|
|
+ first = false;
|
|
|
+ responseBody.push_back('"');
|
|
|
+ } else responseBody.append(",\"");
|
|
|
+ responseBody.append((const char *)sqlite3_column_text(_sListNetworks,0));
|
|
|
+ responseBody.push_back('"');
|
|
|
+ }
|
|
|
+ responseBody.push_back(']');
|
|
|
+ return 200;
|
|
|
+ } // else 404
|
|
|
+
|
|
|
+ } else {
|
|
|
+ // 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());
|
|
|
+ responseBody = json;
|
|
|
+ responseContentType = "applicaiton/json";
|
|
|
+ return 200;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 404;
|
|
|
+}
|
|
|
+
|
|
|
} // namespace ZeroTier
|