diff --git a/controller/SqliteNetworkController.cpp b/controller/SqliteNetworkController.cpp index eb8e399b2..e9d4f6964 100644 --- a/controller/SqliteNetworkController.cpp +++ b/controller/SqliteNetworkController.cpp @@ -154,7 +154,7 @@ SqliteNetworkController::SqliteNetworkController(const char *dbPath) : ||(sqlite3_prepare_v2(_db,"INSERT INTO Node (id,identity,lastAt,lastSeen,firstSeen) VALUES (?,?,?,?,?)",-1,&_sCreateNode,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"UPDATE Node SET lastAt = ?,lastSeen = ? WHERE id = ?",-1,&_sUpdateNode,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"UPDATE Node SET lastSeen = ? WHERE id = ?",-1,&_sUpdateNode2,(const char **)0) != SQLITE_OK) - ||(sqlite3_prepare_v2(_db,"SELECT etherType FROM Rule WHERE networkId = ? AND \"action\" = 'accept'",-1,&_sGetEtherTypesFromRuleTable,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"SELECT etherType, CASE WHEN nodeId IS NULL THEN 1 ELSE 0 END AS general FROM Rule WHERE networkId = ? AND (nodeId = ? OR nodeId IS NULL) AND \"action\" = 'accept' ORDER BY general, ruleNo",-1,&_sGetEtherTypesFromRuleTable,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"SELECT nodeId FROM Member WHERE networkId = ? AND activeBridge > 0 AND authorized > 0",-1,&_sGetActiveBridges,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"SELECT ip,ipNetmaskBits FROM IpAssignment WHERE networkId = ? AND nodeId = ? AND ipVersion = ?",-1,&_sGetIpAssignmentsForNode,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"SELECT ipNetwork,ipNetmaskBits FROM IpAssignmentPool WHERE networkId = ? AND ipVersion = ?",-1,&_sGetIpAssignmentPools,(const char **)0) != SQLITE_OK) @@ -166,8 +166,8 @@ SqliteNetworkController::SqliteNetworkController(const char *dbPath) : ||(sqlite3_prepare_v2(_db,"SELECT m.nodeId FROM Member AS m WHERE m.networkId = ? ORDER BY m.nodeId ASC",-1,&_sListNetworkMembers,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"SELECT m.authorized,m.activeBridge,n.identity,n.lastAt,n.lastSeen,n.firstSeen FROM Member AS m JOIN Node AS n ON n.id = m.nodeId WHERE m.networkId = ? AND m.nodeId = ?",-1,&_sGetMember2,(const char **)0) != SQLITE_OK) ||(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 ruleNo,nodeId,vlanId,vlanPcp,etherType,macSource,macDest,ipSource,ipDest,ipTos,ipProtocol,ipSourcePort,ipDestPort,\"flags\",invFlags,\"action\" FROM Rule WHERE networkId = ? ORDER BY ruleNo ASC",-1,&_sListRules,(const char **)0) != SQLITE_OK) - ||(sqlite3_prepare_v2(_db,"INSERT INTO Rule (networkId,ruleNo,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,"SELECT ruleNo,nodeId,vlanId,vlanPcp,etherType,macSource,macDest,ipSource,ipDest,ipTos,ipProtocol,ipSourcePort,ipDestPort,\"flags\",invFlags,\"action\" FROM Rule WHERE networkId = ? ORDER BY nodeId, ruleNo ASC",-1,&_sListRules,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"INSERT INTO Rule (networkId,ruleNo,nodeId,vlanId,vlanPcP,etherType,macSource,macDest,ipSource,ipDest,ipTos,ipProtocol,ipSourcePort,ipDestPort,flags,invFlags,\"action\") VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",-1,&_sCreateRule,(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) @@ -381,17 +381,25 @@ NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(co { std::vector allowedEtherTypes; + bool nodeRules = false; + // Add member specific rules or add general rules sqlite3_reset(_sGetEtherTypesFromRuleTable); sqlite3_bind_text(_sGetEtherTypesFromRuleTable,1,network.id,16,SQLITE_STATIC); + sqlite3_bind_text(_sGetEtherTypesFromRuleTable,2,member.nodeId,10,SQLITE_STATIC); while (sqlite3_step(_sGetEtherTypesFromRuleTable) == SQLITE_ROW) { int et = sqlite3_column_int(_sGetEtherTypesFromRuleTable,0); + int isGeneral = sqlite3_column_int(_sGetEtherTypesFromRuleTable,1); + if (!isGeneral) + nodeRules = true; + else if (nodeRules) + break; if ((et >= 0)&&(et <= 0xffff)) allowedEtherTypes.push_back(et); } std::sort(allowedEtherTypes.begin(),allowedEtherTypes.end()); - std::unique(allowedEtherTypes.begin(),allowedEtherTypes.end()); + std::vector::iterator end = std::unique(allowedEtherTypes.begin(),allowedEtherTypes.end()); std::string allowedEtherTypesCsv; - for(std::vector::const_iterator i(allowedEtherTypes.begin());i!=allowedEtherTypes.end();++i) { + for(std::vector::const_iterator i(allowedEtherTypes.begin());i!=end;++i) { if (allowedEtherTypesCsv.length()) allowedEtherTypesCsv.push_back(','); char tmp[16]; @@ -1007,7 +1015,8 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST( if (rule.invFlags) sqlite3_bind_int64(_sCreateRule,16,(int64_t)*rule.invFlags); sqlite3_bind_text(_sCreateRule,17,rule.action,-1,SQLITE_STATIC); - sqlite3_step(_sCreateRule); + if (sqlite3_step(_sCreateRule) != SQLITE_DONE) + return 500; } } } @@ -1348,6 +1357,7 @@ unsigned int SqliteNetworkController::_doCPGet( bool firstRule = true; while (sqlite3_step(_sListRules) == SQLITE_ROW) { responseBody.append(firstRule ? "\n\t{\n" : ",{\n"); + firstRule = false; Utils::snprintf(json,sizeof(json),"\t\t\"ruleNo\": %lld,\n",sqlite3_column_int64(_sListRules,0)); responseBody.append(json); if (sqlite3_column_type(_sListRules,1) != SQLITE_NULL) { diff --git a/controller/schema.sql b/controller/schema.sql index d2261b2af..f5cba3943 100644 --- a/controller/schema.sql +++ b/controller/schema.sql @@ -76,7 +76,7 @@ CREATE INDEX Relay_networkId ON Relay (networkId); CREATE TABLE Rule ( networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE, ruleNo integer NOT NULL, - nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE, + nodeId char(10) REFERENCES Node(id) ON DELETE CASCADE, vlanId integer, vlanPcp integer, etherType integer, @@ -93,4 +93,5 @@ CREATE TABLE Rule ( "action" varchar(4096) NOT NULL DEFAULT('accept') ); -CREATE UNIQUE INDEX Rule_networkId_ruleNo ON Rule (networkId, ruleNo); +CREATE UNIQUE INDEX Rule_networkId_ruleNo ON Rule (networkId, ruleNo) WHERE nodeId IS NULL; +CREATE UNIQUE INDEX Rule_networkId_nodeId_ruleNo ON Rule (networkId, ruleNo, nodeId); diff --git a/controller/schema.sql.c b/controller/schema.sql.c index 1157facc5..c98ac9bdd 100644 --- a/controller/schema.sql.c +++ b/controller/schema.sql.c @@ -77,7 +77,7 @@ "CREATE TABLE Rule (\n"\ " networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\ " ruleNo integer NOT NULL,\n"\ -" nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE,\n"\ +" nodeId char(10) REFERENCES Node(id) ON DELETE CASCADE,\n"\ " vlanId integer,\n"\ " vlanPcp integer,\n"\ " etherType integer,\n"\ @@ -94,5 +94,6 @@ " \"action\" varchar(4096) NOT NULL DEFAULT('accept')\n"\ ");\n"\ "\n"\ -"CREATE UNIQUE INDEX Rule_networkId_ruleNo ON Rule (networkId, ruleNo);\n"\ +"CREATE UNIQUE INDEX Rule_networkId_ruleNo ON Rule (networkId, ruleNo) WHERE nodeId IS NULL;\n"\ +"CREATE UNIQUE INDEX Rule_networkId_nodeId_ruleNo ON Rule (networkId, ruleNo, nodeId);\n"\ ""