Gateways support in network controller schema and database (not implemented yet in client) toward GitHub issue #178

This commit is contained in:
Adam Ierymenko 2015-06-13 11:34:31 +02:00
parent 8a9715f183
commit 96a58becf8
6 changed files with 194 additions and 6 deletions

View File

@ -179,7 +179,10 @@ 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,"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,"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 Member WHERE networkId = ? AND nodeId = ?",-1,&_sDeleteMember,(const char **)0) != SQLITE_OK)
||(sqlite3_prepare_v2(_db,"DELETE FROM Network WHERE id = ?;",-1,&_sDeleteNetworkAndRelated,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"DELETE FROM Network WHERE id = ?",-1,&_sDeleteNetwork,(const char **)0) != SQLITE_OK)
||(sqlite3_prepare_v2(_db,"SELECT ip,ipVersion,metric FROM Gateway WHERE networkId = ? ORDER BY metric ASC",-1,&_sGetGateways,(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)
) { ) {
//printf("!!! %s\n",sqlite3_errmsg(_db)); //printf("!!! %s\n",sqlite3_errmsg(_db));
sqlite3_close(_db); sqlite3_close(_db);
@ -222,7 +225,10 @@ SqliteNetworkController::~SqliteNetworkController()
sqlite3_finalize(_sDeleteIpAssignmentPoolsForNetwork); sqlite3_finalize(_sDeleteIpAssignmentPoolsForNetwork);
sqlite3_finalize(_sDeleteRulesForNetwork); sqlite3_finalize(_sDeleteRulesForNetwork);
sqlite3_finalize(_sCreateIpAssignmentPool); sqlite3_finalize(_sCreateIpAssignmentPool);
sqlite3_finalize(_sDeleteNetworkAndRelated); sqlite3_finalize(_sDeleteNetwork);
sqlite3_finalize(_sGetGateways);
sqlite3_finalize(_sDeleteGateways);
sqlite3_finalize(_sCreateGateway);
sqlite3_close(_db); sqlite3_close(_db);
} }
} }
@ -455,6 +461,52 @@ NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(co
netconf[ZT_NETWORKCONFIG_DICT_KEY_RELAYS] = relays; netconf[ZT_NETWORKCONFIG_DICT_KEY_RELAYS] = relays;
} }
{
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
case 4:
Utils::snprintf(tmp,sizeof(tmp),"%s%d.%d.%d.%d/%d",
(gateways.length() > 0) ? "," : "",
(int)ip[0],
(int)ip[1],
(int)ip[2],
(int)ip[3],
(int)sqlite3_column_int(_sGetGateways,2)); // metric
gateways.append(tmp);
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);
break;
}
}
if (gateways.length())
netconf[ZT_NETWORKCONFIG_DICT_KEY_GATEWAYS] = gateways;
}
if ((network.v4AssignMode)&&(!strcmp(network.v4AssignMode,"zt"))) { if ((network.v4AssignMode)&&(!strcmp(network.v4AssignMode,"zt"))) {
std::string v4s; std::string v4s;
@ -808,6 +860,31 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(
sqlite3_step(_sCreateRelay); sqlite3_step(_sCreateRelay);
} }
} }
} else if (!strcmp(j->u.object.values[k].name,"gateways")) {
sqlite3_reset(_sDeleteGateways);
sqlite3_bind_text(_sDeleteGateways,1,nwids,16,SQLITE_STATIC);
sqlite3_step(_sDeleteGateways);
if (j->u.object.values[k].value->type == json_array) {
for(unsigned int kk=0;kk<j->u.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);
int ipVersion = 0;
if (gwip.ss_family == AF_INET)
ipVersion = 4;
else if (gwip.ss_family == AF_INET6)
ipVersion = 6;
if (ipVersion) {
sqlite3_reset(_sCreateGateway);
sqlite3_bind_text(_sCreateGateway,1,nwids,16,SQLITE_STATIC);
sqlite3_bind_blob(_sCreateGateway,2,gwip.rawIpData(),(gwip.ss_family == AF_INET6) ? 16 : 4,SQLITE_STATIC);
sqlite3_bind_int(_sCreateGateway,3,ipVersion);
sqlite3_bind_int(_sCreateGateway,4,(int)gwip.metric());
sqlite3_step(_sCreateGateway);
}
}
}
}
} else if (!strcmp(j->u.object.values[k].name,"ipAssignmentPools")) { } else if (!strcmp(j->u.object.values[k].name,"ipAssignmentPools")) {
if (j->u.object.values[k].value->type == json_array) { if (j->u.object.values[k].value->type == json_array) {
std::set<InetAddress> pools; std::set<InetAddress> pools;
@ -1027,9 +1104,9 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpDELETE(
} else { } else {
sqlite3_reset(_sDeleteNetworkAndRelated); sqlite3_reset(_sDeleteNetwork);
sqlite3_bind_text(_sDeleteNetworkAndRelated,1,nwids,16,SQLITE_STATIC); sqlite3_bind_text(_sDeleteNetwork,1,nwids,16,SQLITE_STATIC);
return ((sqlite3_step(_sDeleteNetworkAndRelated) == SQLITE_DONE) ? 200 : 500); return ((sqlite3_step(_sDeleteNetwork) == SQLITE_DONE) ? 200 : 500);
} }
} // else 404 } // else 404
@ -1212,6 +1289,49 @@ unsigned int SqliteNetworkController::_doCPGet(
responseBody.append(_jsonEscape((const char *)sqlite3_column_text(_sGetRelays,1))); responseBody.append(_jsonEscape((const char *)sqlite3_column_text(_sGetRelays,1)));
responseBody.append("\"}"); responseBody.append("\"}");
} }
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[0],
(int)ip[1],
(int)ip[2],
(int)ip[3],
(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;
}
responseBody.append("],\n\t\"ipAssignmentPools\": ["); responseBody.append("],\n\t\"ipAssignmentPools\": [");
sqlite3_reset(_sGetIpAssignmentPools2); sqlite3_reset(_sGetIpAssignmentPools2);

View File

@ -123,7 +123,10 @@ private:
sqlite3_stmt *_sDeleteRulesForNetwork; sqlite3_stmt *_sDeleteRulesForNetwork;
sqlite3_stmt *_sCreateIpAssignmentPool; sqlite3_stmt *_sCreateIpAssignmentPool;
sqlite3_stmt *_sDeleteMember; sqlite3_stmt *_sDeleteMember;
sqlite3_stmt *_sDeleteNetworkAndRelated; sqlite3_stmt *_sDeleteNetwork;
sqlite3_stmt *_sGetGateways;
sqlite3_stmt *_sDeleteGateways;
sqlite3_stmt *_sCreateGateway;
Mutex _lock; Mutex _lock;
}; };

View File

@ -24,6 +24,15 @@ CREATE TABLE Node (
firstSeen integer NOT NULL DEFAULT(0) firstSeen integer NOT NULL DEFAULT(0)
); );
CREATE TABLE Gateway (
networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,
ip blob(16) NOT NULL,
ipVersion integer NOT NULL DEFAULT(4),
metric integer NOT NULL DEFAULT(0)
);
CREATE UNIQUE INDEX Gateway_networkId_ip ON Gateway (networkId, ip);
CREATE TABLE IpAssignment ( CREATE TABLE IpAssignment (
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, nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE,

View File

@ -25,6 +25,15 @@
" firstSeen integer NOT NULL DEFAULT(0)\n"\ " firstSeen integer NOT NULL DEFAULT(0)\n"\
");\n"\ ");\n"\
"\n"\ "\n"\
"CREATE TABLE Gateway (\n"\
" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\
" ip blob(16) NOT NULL,\n"\
" ipVersion integer NOT NULL DEFAULT(4),\n"\
" metric integer NOT NULL DEFAULT(0)\n"\
");\n"\
"\n"\
"CREATE UNIQUE INDEX Gateway_networkId_ip ON Gateway (networkId, ip);\n"\
"\n"\
"CREATE TABLE IpAssignment (\n"\ "CREATE TABLE IpAssignment (\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"\ " nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE,\n"\

View File

@ -265,6 +265,16 @@ struct InetAddress : public sockaddr_storage
*/ */
inline unsigned int netmaskBits() const throw() { return port(); } inline unsigned int netmaskBits() const throw() { return port(); }
/**
* Alias for port()
*
* This just aliases port() because for gateways we use this field to
* store the gateway metric.
*
* @return Gateway metric
*/
inline unsigned int metric() const throw() { return port(); }
/** /**
* Construct a full netmask as an InetAddress * Construct a full netmask as an InetAddress
*/ */

View File

@ -49,24 +49,61 @@ namespace ZeroTier {
// These dictionary keys are short so they don't take up much room in // These dictionary keys are short so they don't take up much room in
// netconf response packets. // netconf response packets.
// integer(hex)[,integer(hex),...]
#define ZT_NETWORKCONFIG_DICT_KEY_ALLOWED_ETHERNET_TYPES "et" #define ZT_NETWORKCONFIG_DICT_KEY_ALLOWED_ETHERNET_TYPES "et"
// network ID
#define ZT_NETWORKCONFIG_DICT_KEY_NETWORK_ID "nwid" #define ZT_NETWORKCONFIG_DICT_KEY_NETWORK_ID "nwid"
// integer(hex)
#define ZT_NETWORKCONFIG_DICT_KEY_TIMESTAMP "ts" #define ZT_NETWORKCONFIG_DICT_KEY_TIMESTAMP "ts"
// integer(hex)
#define ZT_NETWORKCONFIG_DICT_KEY_REVISION "r" #define ZT_NETWORKCONFIG_DICT_KEY_REVISION "r"
// address of member
#define ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO "id" #define ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO "id"
// integer(hex)
#define ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT "ml" #define ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT "ml"
// dictionary of one or more of: MAC/ADI=preload,maxbalance,accrual
#define ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_RATES "mr" #define ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_RATES "mr"
// 0/1
#define ZT_NETWORKCONFIG_DICT_KEY_PRIVATE "p" #define ZT_NETWORKCONFIG_DICT_KEY_PRIVATE "p"
// text
#define ZT_NETWORKCONFIG_DICT_KEY_NAME "n" #define ZT_NETWORKCONFIG_DICT_KEY_NAME "n"
// text
#define ZT_NETWORKCONFIG_DICT_KEY_DESC "d" #define ZT_NETWORKCONFIG_DICT_KEY_DESC "d"
// IP/bits[,IP/bits,...]
#define ZT_NETWORKCONFIG_DICT_KEY_IPV4_STATIC "v4s" #define ZT_NETWORKCONFIG_DICT_KEY_IPV4_STATIC "v4s"
// IP/bits[,IP/bits,...]
#define ZT_NETWORKCONFIG_DICT_KEY_IPV6_STATIC "v6s" #define ZT_NETWORKCONFIG_DICT_KEY_IPV6_STATIC "v6s"
// serialized CertificateOfMembership
#define ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATE_OF_MEMBERSHIP "com" #define ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATE_OF_MEMBERSHIP "com"
// 0/1
#define ZT_NETWORKCONFIG_DICT_KEY_ENABLE_BROADCAST "eb" #define ZT_NETWORKCONFIG_DICT_KEY_ENABLE_BROADCAST "eb"
// 0/1
#define ZT_NETWORKCONFIG_DICT_KEY_ALLOW_PASSIVE_BRIDGING "pb" #define ZT_NETWORKCONFIG_DICT_KEY_ALLOW_PASSIVE_BRIDGING "pb"
// node[,node,...]
#define ZT_NETWORKCONFIG_DICT_KEY_ACTIVE_BRIDGES "ab" #define ZT_NETWORKCONFIG_DICT_KEY_ACTIVE_BRIDGES "ab"
// node;IP/port[,node;IP/port]
#define ZT_NETWORKCONFIG_DICT_KEY_RELAYS "rl" #define ZT_NETWORKCONFIG_DICT_KEY_RELAYS "rl"
// IP/metric[,IP/metric,...]
#define ZT_NETWORKCONFIG_DICT_KEY_GATEWAYS "gw"
/** /**
* Network configuration received from network controller nodes * Network configuration received from network controller nodes
* *