More rules engine work: key/value pair matching for microsegmentation.

This commit is contained in:
Adam Ierymenko 2016-07-28 10:58:10 -07:00
parent 1e6e112806
commit 22e44c762b
7 changed files with 92 additions and 92 deletions

View File

@ -66,8 +66,8 @@
// Stored in database as schemaVersion key in Config.
// If not present, database is assumed to be empty and at the current schema version
// and this key/value is added automatically.
#define ZT_NETCONF_SQLITE_SCHEMA_VERSION 4
#define ZT_NETCONF_SQLITE_SCHEMA_VERSION_STR "4"
#define ZT_NETCONF_SQLITE_SCHEMA_VERSION 5
#define ZT_NETCONF_SQLITE_SCHEMA_VERSION_STR "5"
// API version reported via JSON control plane
#define ZT_NETCONF_CONTROLLER_API_VERSION 2
@ -334,6 +334,38 @@ SqliteNetworkController::SqliteNetworkController(Node *node,const char *dbPath,c
}
}
if (schemaVersion < 5) {
// Upgrade old rough draft Rule table to new release format
if (sqlite3_exec(_db,
"DROP INDEX Rule_networkId_ruleNo;\n"
"ALTER TABLE \"Rule\" RENAME TO RuleOld;\n"
"CREATE TABLE Rule (\n"
" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"
" policyId varchar(32),\n"
" ruleNo integer NOT NULL,\n"
" ruleType integer NOT NULL DEFAULT(0),\n"
" \"addr\" blob(16),\n"
" \"int1\" integer,\n"
" \"int2\" integer,\n"
" \"int3\" integer,\n"
" \"int4\" integer\n"
");\n"
"INSERT INTO \"Rule\" SELECT networkId,(ruleNo*2) AS ruleNo,37 AS \"ruleType\",etherType AS \"int1\" FROM RuleOld WHERE RuleOld.etherType IS NOT NULL AND RuleOld.etherType > 0;\n"
"INSERT INTO \"Rule\" SELECT networkId,((ruleNo*2)+1) AS ruleNo,1 AS \"ruleType\" FROM RuleOld;\n"
"DROP TABLE RuleOld;\n"
"CREATE INDEX Rule_networkId_ruleNo ON Rule (networkId, ruleNo);\n"
"CREATE INDEX Rule_networkId_policyId ON Rule (networkId, policyId);\n"
"UPDATE \"Config\" SET \"v\" = 5 WHERE \"k\" = 'schemaVersion';\n"
,0,0,0) != SQLITE_OK) {
char err[1024];
Utils::snprintf(err,sizeof(err),"SqliteNetworkController cannot upgrade the database to version 3: %s",sqlite3_errmsg(_db));
sqlite3_close(_db);
throw std::runtime_error(err);
} else {
schemaVersion = 5;
}
}
if (schemaVersion != ZT_NETCONF_SQLITE_SCHEMA_VERSION) {
sqlite3_close(_db);
throw std::runtime_error("SqliteNetworkController database schema version mismatch");
@ -365,8 +397,7 @@ SqliteNetworkController::SqliteNetworkController(Node *node,const char *dbPath,c
||(sqlite3_prepare_v2(_db,"INSERT OR REPLACE INTO Node (id,identity) VALUES (?,?)",-1,&_sCreateOrReplaceNode,(const char **)0) != SQLITE_OK)
/* Rule */
||(sqlite3_prepare_v2(_db,"SELECT etherType FROM Rule WHERE networkId = ? AND \"action\" = 'accept'",-1,&_sGetEtherTypesFromRuleTable,(const char **)0) != SQLITE_OK)
||(sqlite3_prepare_v2(_db,"INSERT INTO Rule (networkId,ruleNo,nodeId,sourcePort,destPort,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 Rule (networkId,ruleNo,nodeId,ztSource,ztDest,vlanId,vlanPcp,vlanDei,) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",-1,&_sCreateRule,(const char **)0) != SQLITE_OK)
||(sqlite3_prepare_v2(_db,"SELECT ruleNo,nodeId,sourcePort,destPort,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,"DELETE FROM Rule WHERE networkId = ?",-1,&_sDeleteRulesForNetwork,(const char **)0) != SQLITE_OK)
@ -457,7 +488,6 @@ SqliteNetworkController::~SqliteNetworkController()
sqlite3_finalize(_sCreateMember);
sqlite3_finalize(_sGetNodeIdentity);
sqlite3_finalize(_sCreateOrReplaceNode);
sqlite3_finalize(_sGetEtherTypesFromRuleTable);
sqlite3_finalize(_sGetActiveBridges);
sqlite3_finalize(_sGetIpAssignmentsForNode);
sqlite3_finalize(_sGetIpAssignmentPools);

View File

@ -137,7 +137,6 @@ private:
sqlite3_stmt *_sCreateMember;
sqlite3_stmt *_sGetNodeIdentity;
sqlite3_stmt *_sCreateOrReplaceNode;
sqlite3_stmt *_sGetEtherTypesFromRuleTable;
sqlite3_stmt *_sGetActiveBridges;
sqlite3_stmt *_sGetIpAssignmentsForNode;
sqlite3_stmt *_sGetIpAssignmentPools;

View File

@ -96,24 +96,15 @@ CREATE UNIQUE INDEX Relay_networkId_address ON Relay (networkId,address);
CREATE TABLE Rule (
networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,
policyId varchar(32),
ruleNo integer NOT NULL,
nodeId char(10) REFERENCES Node(id),
sourcePort char(10),
destPort char(10),
vlanId integer,
vlanPcp integer,
etherType integer,
macSource char(12),
macDest char(12),
ipSource varchar(64),
ipDest varchar(64),
ipTos integer,
ipProtocol integer,
ipSourcePort integer,
ipDestPort integer,
flags integer,
invFlags integer,
"action" varchar(4096) NOT NULL DEFAULT('accept')
ruleType integer NOT NULL DEFAULT(0),
"addr" blob(16),
"int1" integer,
"int2" integer,
"int3" integer,
"int4" integer
);
CREATE UNIQUE INDEX Rule_networkId_ruleNo ON Rule (networkId, ruleNo);
CREATE INDEX Rule_networkId_ruleNo ON Rule (networkId, ruleNo);
CREATE INDEX Rule_networkId_policyId ON Rule (networkId, policyId);

View File

@ -97,25 +97,16 @@
"\n"\
"CREATE TABLE Rule (\n"\
" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\
" policyId varchar(32),\n"\
" ruleNo integer NOT NULL,\n"\
" nodeId char(10) REFERENCES Node(id),\n"\
" sourcePort char(10),\n"\
" destPort char(10),\n"\
" vlanId integer,\n"\
" vlanPcp integer,\n"\
" etherType integer,\n"\
" macSource char(12),\n"\
" macDest char(12),\n"\
" ipSource varchar(64),\n"\
" ipDest varchar(64),\n"\
" ipTos integer,\n"\
" ipProtocol integer,\n"\
" ipSourcePort integer,\n"\
" ipDestPort integer,\n"\
" flags integer,\n"\
" invFlags integer,\n"\
" \"action\" varchar(4096) NOT NULL DEFAULT('accept')\n"\
" ruleType integer NOT NULL DEFAULT(0),\n"\
" \"addr\" blob(16),\n"\
" \"int1\" integer,\n"\
" \"int2\" integer,\n"\
" \"int3\" integer,\n"\
" \"int4\" integer\n"\
");\n"\
"\n"\
"CREATE UNIQUE INDEX Rule_networkId_ruleNo ON Rule (networkId, ruleNo);\n"\
"CREATE INDEX Rule_networkId_ruleNo ON Rule (networkId, ruleNo);\n"\
"CREATE INDEX Rule_networkId_policyId ON Rule (networkId, policyId);\n"\
""

View File

@ -391,12 +391,15 @@ enum ZT_VirtualNetworkType
/**
* The type of a virtual network rules table entry
*
* These must range from 0 to 127 (0x7f).
* These must range from 0 to 127 (0x7f) because the most significant bit
* is reserved as a NOT flag.
*
* Each rule is composed of one or more MATCHes followed by an ACTION.
*/
enum ZT_VirtualNetworkRuleType
{
// 0 to 31 reserved for actions
/**
* Drop frame
*/
@ -408,16 +411,16 @@ enum ZT_VirtualNetworkRuleType
ZT_NETWORK_RULE_ACTION_ACCEPT = 1,
/**
* Forward a copy of this frame to an observer
* Forward a copy of this frame to an observer (by ZT address)
*/
ZT_NETWORK_RULE_ACTION_TEE = 2,
/**
* Explicitly redirect this frame to another device (ignored if this is the target device)
* Drop and redirect this frame to another node (by ZT address)
*/
ZT_NETWORK_RULE_ACTION_REDIRECT = 3,
// <32 == actions
// 32 to 127 reserved for match criteria
/**
* Source ZeroTier address -- analogous to an Ethernet port ID on a switch

View File

@ -44,9 +44,9 @@
#define ZT_NETWORK_COM_DEFAULT_REVISION_MAX_DELTA (ZT_NETWORK_AUTOCONF_DELAY * 5)
/**
* Maximum number of qualifiers in a COM
* Maximum number of qualifiers allowed in a COM (absolute max: 65535)
*/
#define ZT_NETWORK_COM_MAX_QUALIFIERS 16
#define ZT_NETWORK_COM_MAX_QUALIFIERS 256
namespace ZeroTier {
@ -87,14 +87,15 @@ public:
*/
enum Type
{
COM_UINT64_ED25519 = 1 // tuples of unsigned 64's signed with Ed25519
// tuples of unsigned 64's signed with Ed25519
COM_UINT64_ED25519 = 1
};
/**
* Reserved qualifier IDs
*
* IDs below 65536 should be considered reserved for future global
* assignment here.
* IDs below 1024 are reserved for use as standard IDs. Others are available
* for user-defined use.
*
* Addition of new required fields requires that code in hasRequiredFields
* be updated as well.
@ -126,12 +127,11 @@ public:
};
/**
* Create an empty certificate
* Create an empty certificate of membership
*/
CertificateOfMembership() :
_qualifierCount(0)
CertificateOfMembership()
{
memset(_signature.data,0,_signature.size());
memset(this,0,sizeof(CertificateOfMembership));
}
CertificateOfMembership(const CertificateOfMembership &c)
@ -168,22 +168,6 @@ public:
return *this;
}
#ifdef ZT_SUPPORT_OLD_STYLE_NETCONF
/**
* Create from string-serialized data
*
* @param s String-serialized COM
*/
CertificateOfMembership(const char *s) { fromString(s); }
/**
* Create from string-serialized data
*
* @param s String-serialized COM
*/
CertificateOfMembership(const std::string &s) { fromString(s.c_str()); }
#endif // ZT_SUPPORT_OLD_STYLE_NETCONF
/**
* Create from binary-serialized COM in buffer
*
@ -201,24 +185,6 @@ public:
*/
inline operator bool() const throw() { return (_qualifierCount != 0); }
/**
* Check for presence of all required fields common to all networks
*
* @return True if all required fields are present
*/
inline bool hasRequiredFields() const
{
if (_qualifierCount < 3)
return false;
if (_qualifiers[0].id != COM_RESERVED_ID_REVISION)
return false;
if (_qualifiers[1].id != COM_RESERVED_ID_NETWORK_ID)
return false;
if (_qualifiers[2].id != COM_RESERVED_ID_ISSUED_TO)
return false;
return true;
}
/**
* @return Maximum delta for mandatory revision field or 0 if field missing
*/
@ -279,6 +245,21 @@ public:
void setQualifier(uint64_t id,uint64_t value,uint64_t maxDelta);
inline void setQualifier(ReservedId id,uint64_t value,uint64_t maxDelta) { setQualifier((uint64_t)id,value,maxDelta); }
/**
* Get the value of a qualifier field
*
* @param id Qualifier ID
* @return Value or 0 if not found
*/
inline uint64_t getQualifierValue(uint64_t id)
{
for(unsigned int i=0;i<_qualifierCount;++i) {
if (_qualifiers[i].id == id)
return _qualifiers[i].value;
}
return 0;
}
#ifdef ZT_SUPPORT_OLD_STYLE_NETCONF
/**
* @return String-serialized representation of this certificate

View File

@ -126,12 +126,17 @@ public:
{
memset(&_tid,0,sizeof(_tid));
pthread_attr_init(&_tattr);
#ifdef __LINUX__
pthread_attr_setstacksize(&_tattr,8388608); // for MUSL libc and others, has no effect in normal glibc environments
#endif
// This corrects for systems with abnormally small defaults (musl) and also
// shrinks the stack on systems with large defaults to save a bit of memory.
pthread_attr_setstacksize(&_tattr,524288);
_started = false;
}
~Thread()
{
pthread_attr_destroy(&_tattr);
}
Thread(const Thread &t)
throw()
{