From de697a1c45e8afbdd32687b9b5d203732ce5e62a Mon Sep 17 00:00:00 2001 From: Kees Bos Date: Thu, 11 Jun 2015 11:35:25 +0200 Subject: [PATCH 1/5] Change schema to enforce foreing keys The foreign keys have 'ON DELETE CASCADE' to simplify the removal of networks etc. (controller code) Some unique constraints are replaced with a multi column primary key. To update an existing database: * install updated binaries * stop service * sqlite3 controller.db .dump | \ egrep '((^PRAGMA)|(^BEGIN)|(^INSERT)|(^COMMIT))' | \ grep -v 'schemaVersion' > data.sql * mv controller.db controller.db.backup * start service * stop service * sqlite3 controller.db < data.sql * start service --- controller/schema.sql | 118 ++++++++++++++++++++-------------------- controller/schema.sql.c | 116 +++++++++++++++++++-------------------- 2 files changed, 115 insertions(+), 119 deletions(-) diff --git a/controller/schema.sql b/controller/schema.sql index b5646ee90..a3a7bb7a5 100644 --- a/controller/schema.sql +++ b/controller/schema.sql @@ -3,53 +3,6 @@ CREATE TABLE Config ( v varchar(1024) NOT NULL ); -CREATE TABLE IpAssignment ( - networkId char(16) NOT NULL, - nodeId char(10) NOT NULL, - ip blob(16) NOT NULL, - ipNetmaskBits integer NOT NULL DEFAULT(0), - ipVersion integer NOT NULL DEFAULT(4) -); - -CREATE INDEX IpAssignment_networkId_ip ON IpAssignment (networkId, ip); - -CREATE INDEX IpAssignment_networkId_nodeId ON IpAssignment (networkId, nodeId); - -CREATE INDEX IpAssignment_networkId ON IpAssignment (networkId); - -CREATE TABLE IpAssignmentPool ( - networkId char(16) NOT NULL, - ipNetwork blob(16) NOT NULL, - ipNetmaskBits integer NOT NULL, - ipVersion integer NOT NULL DEFAULT(4) -); - -CREATE INDEX IpAssignmentPool_networkId ON IpAssignmentPool (networkId); - -CREATE TABLE Member ( - networkId char(16) NOT NULL, - nodeId char(10) NOT NULL, - authorized integer NOT NULL DEFAULT(0), - activeBridge integer NOT NULL DEFAULT(0) -); - -CREATE INDEX Member_networkId ON Member (networkId); - -CREATE INDEX Member_networkId_activeBridge ON Member(networkId, activeBridge); - -CREATE UNIQUE INDEX Member_networkId_nodeId ON Member (networkId, nodeId); - -CREATE TABLE MulticastRate ( - networkId char(16) NOT NULL, - mgMac char(12) NOT NULL, - mgAdi integer NOT NULL DEFAULT(0), - preload integer NOT NULL, - maxBalance integer NOT NULL, - accrual integer NOT NULL -); - -CREATE INDEX MulticastRate_networkId ON MulticastRate (networkId); - CREATE TABLE Network ( id char(16) PRIMARY KEY NOT NULL, name varchar(128) NOT NULL, @@ -63,16 +16,6 @@ CREATE TABLE Network ( revision integer NOT NULL DEFAULT(1) ); -CREATE TABLE Relay ( - networkId char(16) NOT NULL, - nodeId char(10) NOT NULL, - phyAddress varchar(64) NOT NULL -); - -CREATE INDEX Relay_networkId ON Relay (networkId); - -CREATE UNIQUE INDEX Relay_networkId_nodeId ON Relay (networkId, nodeId); - CREATE TABLE Node ( id char(10) PRIMARY KEY NOT NULL, identity varchar(4096) NOT NULL, @@ -81,10 +24,65 @@ CREATE TABLE Node ( firstSeen integer NOT NULL DEFAULT(0) ); +CREATE TABLE IpAssignment ( + networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE, + nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE, + ip blob(16) NOT NULL, + ipNetmaskBits integer NOT NULL DEFAULT(0), + ipVersion integer NOT NULL DEFAULT(4) +); + +CREATE INDEX IpAssignment_networkId_ip ON IpAssignment (networkId, ip); + +CREATE INDEX IpAssignment_networkId_nodeId ON IpAssignment (networkId, nodeId); + +CREATE INDEX IpAssignment_networkId ON IpAssignment (networkId); + +CREATE TABLE IpAssignmentPool ( + networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE, + ipNetwork blob(16) NOT NULL, + ipNetmaskBits integer NOT NULL, + ipVersion integer NOT NULL DEFAULT(4) +); + +CREATE INDEX IpAssignmentPool_networkId ON IpAssignmentPool (networkId); + +CREATE TABLE Member ( + networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE, + nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE, + authorized integer NOT NULL DEFAULT(0), + activeBridge integer NOT NULL DEFAULT(0), + PRIMARY KEY (networkId, nodeId) +); + +CREATE INDEX Member_networkId ON Member (networkId); + +CREATE INDEX Member_networkId_activeBridge ON Member(networkId, activeBridge); + +CREATE TABLE MulticastRate ( + networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE, + mgMac char(12) NOT NULL, + mgAdi integer NOT NULL DEFAULT(0), + preload integer NOT NULL, + maxBalance integer NOT NULL, + accrual integer NOT NULL +); + +CREATE INDEX MulticastRate_networkId ON MulticastRate (networkId); + +CREATE TABLE Relay ( + networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE, + nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE, + phyAddress varchar(64) NOT NULL, + PRIMARY KEY (networkId, nodeId) +); + +CREATE INDEX Relay_networkId ON Relay (networkId); + CREATE TABLE Rule ( - networkId char(16) NOT NULL, + networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE, ruleId integer NOT NULL, - nodeId char(10), + nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE, vlanId integer, vlanPcp integer, etherType integer, @@ -101,4 +99,4 @@ CREATE TABLE Rule ( "action" varchar(4096) NOT NULL DEFAULT('accept') ); -CREATE INDEX Rule_networkId ON Rule (networkId); \ No newline at end of file +CREATE INDEX Rule_networkId ON Rule (networkId); diff --git a/controller/schema.sql.c b/controller/schema.sql.c index 1384b9008..0078eac3a 100644 --- a/controller/schema.sql.c +++ b/controller/schema.sql.c @@ -4,53 +4,6 @@ " v varchar(1024) NOT NULL\n"\ ");\n"\ "\n"\ -"CREATE TABLE IpAssignment (\n"\ -" networkId char(16) NOT NULL,\n"\ -" nodeId char(10) NOT NULL,\n"\ -" ip blob(16) NOT NULL,\n"\ -" ipNetmaskBits integer NOT NULL DEFAULT(0),\n"\ -" ipVersion integer NOT NULL DEFAULT(4)\n"\ -");\n"\ -"\n"\ -"CREATE INDEX IpAssignment_networkId_ip ON IpAssignment (networkId, ip);\n"\ -"\n"\ -"CREATE INDEX IpAssignment_networkId_nodeId ON IpAssignment (networkId, nodeId);\n"\ -"\n"\ -"CREATE INDEX IpAssignment_networkId ON IpAssignment (networkId);\n"\ -"\n"\ -"CREATE TABLE IpAssignmentPool (\n"\ -" networkId char(16) NOT NULL,\n"\ -" ipNetwork blob(16) NOT NULL,\n"\ -" ipNetmaskBits integer NOT NULL,\n"\ -" ipVersion integer NOT NULL DEFAULT(4)\n"\ -");\n"\ -"\n"\ -"CREATE INDEX IpAssignmentPool_networkId ON IpAssignmentPool (networkId);\n"\ -"\n"\ -"CREATE TABLE Member (\n"\ -" networkId char(16) NOT NULL,\n"\ -" nodeId char(10) NOT NULL,\n"\ -" authorized integer NOT NULL DEFAULT(0),\n"\ -" activeBridge integer NOT NULL DEFAULT(0)\n"\ -");\n"\ -"\n"\ -"CREATE INDEX Member_networkId ON Member (networkId);\n"\ -"\n"\ -"CREATE INDEX Member_networkId_activeBridge ON Member(networkId, activeBridge);\n"\ -"\n"\ -"CREATE UNIQUE INDEX Member_networkId_nodeId ON Member (networkId, nodeId);\n"\ -"\n"\ -"CREATE TABLE MulticastRate (\n"\ -" networkId char(16) NOT NULL,\n"\ -" mgMac char(12) NOT NULL,\n"\ -" mgAdi integer NOT NULL DEFAULT(0),\n"\ -" preload integer NOT NULL,\n"\ -" maxBalance integer NOT NULL,\n"\ -" accrual integer NOT NULL\n"\ -");\n"\ -"\n"\ -"CREATE INDEX MulticastRate_networkId ON MulticastRate (networkId);\n"\ -"\n"\ "CREATE TABLE Network (\n"\ " id char(16) PRIMARY KEY NOT NULL,\n"\ " name varchar(128) NOT NULL,\n"\ @@ -64,16 +17,6 @@ " revision integer NOT NULL DEFAULT(1)\n"\ ");\n"\ "\n"\ -"CREATE TABLE Relay (\n"\ -" networkId char(16) NOT NULL,\n"\ -" nodeId char(10) NOT NULL,\n"\ -" phyAddress varchar(64) NOT NULL\n"\ -");\n"\ -"\n"\ -"CREATE INDEX Relay_networkId ON Relay (networkId);\n"\ -"\n"\ -"CREATE UNIQUE INDEX Relay_networkId_nodeId ON Relay (networkId, nodeId);\n"\ -"\n"\ "CREATE TABLE Node (\n"\ " id char(10) PRIMARY KEY NOT NULL,\n"\ " identity varchar(4096) NOT NULL,\n"\ @@ -82,10 +25,65 @@ " firstSeen integer NOT NULL DEFAULT(0)\n"\ ");\n"\ "\n"\ +"CREATE TABLE IpAssignment (\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"\ +" ip blob(16) NOT NULL,\n"\ +" ipNetmaskBits integer NOT NULL DEFAULT(0),\n"\ +" ipVersion integer NOT NULL DEFAULT(4)\n"\ +");\n"\ +"\n"\ +"CREATE INDEX IpAssignment_networkId_ip ON IpAssignment (networkId, ip);\n"\ +"\n"\ +"CREATE INDEX IpAssignment_networkId_nodeId ON IpAssignment (networkId, nodeId);\n"\ +"\n"\ +"CREATE INDEX IpAssignment_networkId ON IpAssignment (networkId);\n"\ +"\n"\ +"CREATE TABLE IpAssignmentPool (\n"\ +" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\ +" ipNetwork blob(16) NOT NULL,\n"\ +" ipNetmaskBits integer NOT NULL,\n"\ +" ipVersion integer NOT NULL DEFAULT(4)\n"\ +");\n"\ +"\n"\ +"CREATE INDEX IpAssignmentPool_networkId ON IpAssignmentPool (networkId);\n"\ +"\n"\ +"CREATE TABLE Member (\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"\ +" authorized integer NOT NULL DEFAULT(0),\n"\ +" activeBridge integer NOT NULL DEFAULT(0),\n"\ +" PRIMARY KEY (networkId, nodeId)\n"\ +");\n"\ +"\n"\ +"CREATE INDEX Member_networkId ON Member (networkId);\n"\ +"\n"\ +"CREATE INDEX Member_networkId_activeBridge ON Member(networkId, activeBridge);\n"\ +"\n"\ +"CREATE TABLE MulticastRate (\n"\ +" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\ +" mgMac char(12) NOT NULL,\n"\ +" mgAdi integer NOT NULL DEFAULT(0),\n"\ +" preload integer NOT NULL,\n"\ +" maxBalance integer NOT NULL,\n"\ +" accrual integer NOT NULL\n"\ +");\n"\ +"\n"\ +"CREATE INDEX MulticastRate_networkId ON MulticastRate (networkId);\n"\ +"\n"\ +"CREATE TABLE Relay (\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"\ +" phyAddress varchar(64) NOT NULL,\n"\ +" PRIMARY KEY (networkId, nodeId)\n"\ +");\n"\ +"\n"\ +"CREATE INDEX Relay_networkId ON Relay (networkId);\n"\ +"\n"\ "CREATE TABLE Rule (\n"\ -" networkId char(16) NOT NULL,\n"\ +" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\ " ruleId integer NOT NULL,\n"\ -" nodeId char(10),\n"\ +" nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE,\n"\ " vlanId integer,\n"\ " vlanPcp integer,\n"\ " etherType integer,\n"\ From 0d0af07ce969c9dd5a416c3b9f466ab0139a57e3 Mon Sep 17 00:00:00 2001 From: Kees Bos Date: Thu, 11 Jun 2015 11:49:13 +0200 Subject: [PATCH 2/5] Get deletion of networks in controller going Multiple statements in a sqlite3_prepare_v2 is not usable. Only the first statement will be executed. Since the schema now uses 'ON DELETE CASCADE', there's only one statement needed. If multiple statements are needed, there should be either multiple sqlite3_prepare_v2 calls be used or the sqlite3_exec function. --- controller/SqliteNetworkController.cpp | 5 ++--- service/ControlPlane.cpp | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/controller/SqliteNetworkController.cpp b/controller/SqliteNetworkController.cpp index a1905221f..6fec64534 100644 --- a/controller/SqliteNetworkController.cpp +++ b/controller/SqliteNetworkController.cpp @@ -179,7 +179,7 @@ SqliteNetworkController::SqliteNetworkController(const char *dbPath) : ||(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,"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) + ||(sqlite3_prepare_v2(_db,"DELETE FROM Network WHERE id = ?;",-1,&_sDeleteNetworkAndRelated,(const char **)0) != SQLITE_OK) ) { //printf("!!! %s\n",sqlite3_errmsg(_db)); sqlite3_close(_db); @@ -1017,8 +1017,7 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpDELETE( } else { sqlite3_reset(_sDeleteNetworkAndRelated); - for(int i=1;i<=7;++i) - sqlite3_bind_text(_sDeleteNetworkAndRelated,i,nwids,16,SQLITE_STATIC); + sqlite3_bind_text(_sDeleteNetworkAndRelated,1,nwids,16,SQLITE_STATIC); return ((sqlite3_step(_sDeleteNetworkAndRelated) == SQLITE_DONE) ? 200 : 500); } diff --git a/service/ControlPlane.cpp b/service/ControlPlane.cpp index 71b3fd3fb..3ff9b7a21 100644 --- a/service/ControlPlane.cpp +++ b/service/ControlPlane.cpp @@ -525,7 +525,7 @@ unsigned int ControlPlane::handleRequest( } else { #ifdef ZT_ENABLE_NETWORK_CONTROLLER if (_controller) - _controller->handleControlPlaneHttpDELETE(std::vector(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType); + scode = _controller->handleControlPlaneHttpDELETE(std::vector(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType); else scode = 404; #else scode = 404; From c2ce018202c626ac25b821a1fe2c27edb7877411 Mon Sep 17 00:00:00 2001 From: Kees Bos Date: Thu, 11 Jun 2015 12:10:25 +0200 Subject: [PATCH 3/5] Return 404 on delete if network doesn't exist (controller) --- controller/SqliteNetworkController.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/controller/SqliteNetworkController.cpp b/controller/SqliteNetworkController.cpp index 6fec64534..f7604b158 100644 --- a/controller/SqliteNetworkController.cpp +++ b/controller/SqliteNetworkController.cpp @@ -993,6 +993,11 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpDELETE( char nwids[24]; Utils::snprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)nwid); + sqlite3_reset(_sGetNetworkById); + sqlite3_bind_text(_sGetNetworkById,1,nwids,16,SQLITE_STATIC); + if (sqlite3_step(_sGetNetworkById) != SQLITE_ROW) + return 404; + if (path.size() >= 3) { if ((path.size() == 4)&&(path[2] == "member")&&(path[3].length() == 10)) { From 7a55c6b388740f2dde67ae69011519147b06f3b6 Mon Sep 17 00:00:00 2001 From: Kees Bos Date: Thu, 11 Jun 2015 12:20:52 +0200 Subject: [PATCH 4/5] Return 404 on delete if network member is missing (controller) --- controller/SqliteNetworkController.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/controller/SqliteNetworkController.cpp b/controller/SqliteNetworkController.cpp index f7604b158..67fe1f9d1 100644 --- a/controller/SqliteNetworkController.cpp +++ b/controller/SqliteNetworkController.cpp @@ -1005,6 +1005,12 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpDELETE( char addrs[24]; Utils::snprintf(addrs,sizeof(addrs),"%.10llx",address); + sqlite3_reset(_sGetMember); + sqlite3_bind_text(_sGetMember,1,nwids,16,SQLITE_STATIC); + sqlite3_bind_text(_sGetMember,2,addrs,10,SQLITE_STATIC); + if (sqlite3_step(_sGetMember) != SQLITE_ROW) + return 404; + sqlite3_reset(_sDeleteIpAllocations); sqlite3_bind_text(_sDeleteIpAllocations,1,nwids,16,SQLITE_STATIC); sqlite3_bind_text(_sDeleteIpAllocations,2,addrs,10,SQLITE_STATIC); From dc50e8ae5b4b8ba194d46e5eba4f5ce4a12bf724 Mon Sep 17 00:00:00 2001 From: Kees Bos Date: Thu, 11 Jun 2015 17:56:54 +0200 Subject: [PATCH 5/5] Add ui to /var/lib/zerotier (linux installer) --- ext/installfiles/linux/buildinstaller.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ext/installfiles/linux/buildinstaller.sh b/ext/installfiles/linux/buildinstaller.sh index 496ba32ce..4f661b8d5 100755 --- a/ext/installfiles/linux/buildinstaller.sh +++ b/ext/installfiles/linux/buildinstaller.sh @@ -49,9 +49,12 @@ case "$system" in echo "Assembling Linux installer for $machine and version $vmajor.$vminor.$revision" - mkdir -p 'build-installer/var/lib/zerotier-one' + mkdir -p 'build-installer/var/lib/zerotier-one/ui' cp -fp 'ext/installfiles/linux/uninstall.sh' 'build-installer/var/lib/zerotier-one' cp -fp 'zerotier-one' 'build-installer/var/lib/zerotier-one' + for f in ui/*.html ui/*.js ui/*.css ui/*.jsx ; do + cp -fp "$f" 'build-installer/var/lib/zerotier-one/ui' + done mkdir -p 'build-installer/tmp' cp -fp 'ext/installfiles/linux/init.d/zerotier-one' 'build-installer/tmp/init.d_zerotier-one' cp -fp 'ext/installfiles/linux/systemd/zerotier-one.service' 'build-installer/tmp/systemd_zerotier-one.service'