Logging to NodeHistory, SQL queries.

This commit is contained in:
Adam Ierymenko 2016-02-03 18:10:56 -08:00
parent f8eb6b0067
commit 2e04dc03f2
2 changed files with 89 additions and 52 deletions

View File

@ -69,11 +69,14 @@
// Drop requests for a given peer and network ID that occur more frequently // Drop requests for a given peer and network ID that occur more frequently
// than this (ms). // than this (ms).
#define ZT_NETCONF_MIN_REQUEST_PERIOD 1000 #define ZT_NETCONF_MIN_REQUEST_PERIOD 500
// Delay between backups in milliseconds // Delay between backups in milliseconds
#define ZT_NETCONF_BACKUP_PERIOD 120000 #define ZT_NETCONF_BACKUP_PERIOD 120000
// Number of NodeHistory entries to maintain per node and network (can be changed)
#define ZT_NETCONF_NODE_HISTORY_LENGTH 16
namespace ZeroTier { namespace ZeroTier {
namespace { namespace {
@ -200,6 +203,13 @@ SqliteNetworkController::SqliteNetworkController(Node *node,const char *dbPath,c
||(sqlite3_prepare_v2(_db,"SELECT identity FROM Node WHERE id = ?",-1,&_sGetNodeIdentity,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"SELECT identity FROM Node WHERE id = ?",-1,&_sGetNodeIdentity,(const char **)0) != SQLITE_OK)
||(sqlite3_prepare_v2(_db,"INSERT OR REPLACE INTO Node (id,identity) VALUES (?,?)",-1,&_sCreateOrReplaceNode,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"INSERT OR REPLACE INTO Node (id,identity) VALUES (?,?)",-1,&_sCreateOrReplaceNode,(const char **)0) != SQLITE_OK)
/* NodeHistory */
||(sqlite3_prepare_v2(_db,"SELECT IFNULL(MAX(networkVisitCounter),0) FROM NodeHistory WHERE networkId = ? AND nodeId = ?",-1,&_sGetMaxNodeHistoryNetworkVisitCounter,(const char **)0) != SQLITE_OK)
||(sqlite3_prepare_v2(_db,"INSERT INTO NodeHistory (nodeId,networkId,networkVisitCounter,networkRequestAuthorized,requestTime,networkRequestMetaData,fromAddress) VALUES (?,?,?,?,?,?,?)",-1,&_sAddNodeHistoryEntry,(const char **)0) != SQLITE_OK)
||(sqlite3_prepare_v2(_db,"DELETE FROM NodeHistory WHERE networkId = ? AND nodeId = ? AND networkVisitCounter <= ?",-1,&_sDeleteOldNodeHistoryEntries,(const char **)0) != SQLITE_OK)
||(sqlite3_prepare_v2(_db,"SELECT DISTINCT nodeId FROM NodeHistory WHERE networkId = ? AND requestTime >= ? AND networkRequestAuthorized != 0 ORDER BY nodeId ASC",-1,&_sGetActiveNodesOnNetwork,(const char **)0) != SQLITE_OK)
||(sqlite3_prepare_v2(_db,"SELECT networkVisitCounter,networkRequestAuthorized,requestTime,networkRequestMetaData,fromAddress FROM NodeHistory WHERE networkId = ? AND nodeId = ? ORDER BY requestTime DESC",-1,&_sGetNodeHistory,(const char **)0) != SQLITE_OK)
/* Rule */ /* 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,"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,sourcePort,destPort,vlanId,vlanPcP,etherType,macSource,macDest,ipSource,ipDest,ipTos,ipProtocol,ipSourcePort,ipDestPort,flags,invFlags,\"action\") VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",-1,&_sCreateRule,(const char **)0) != SQLITE_OK)
@ -290,6 +300,11 @@ SqliteNetworkController::~SqliteNetworkController()
sqlite3_finalize(_sCreateMember); sqlite3_finalize(_sCreateMember);
sqlite3_finalize(_sGetNodeIdentity); sqlite3_finalize(_sGetNodeIdentity);
sqlite3_finalize(_sCreateOrReplaceNode); sqlite3_finalize(_sCreateOrReplaceNode);
sqlite3_finalize(_sGetMaxNodeHistoryNetworkVisitCounter);
sqlite3_finalize(_sAddNodeHistoryEntry);
sqlite3_finalize(_sDeleteOldNodeHistoryEntries);
sqlite3_finalize(_sGetActiveNodesOnNetwork);
sqlite3_finalize(_sGetNodeHistory);
sqlite3_finalize(_sGetEtherTypesFromRuleTable); sqlite3_finalize(_sGetEtherTypesFromRuleTable);
sqlite3_finalize(_sGetActiveBridges); sqlite3_finalize(_sGetActiveBridges);
sqlite3_finalize(_sGetIpAssignmentsForNode); sqlite3_finalize(_sGetIpAssignmentsForNode);
@ -1198,46 +1213,36 @@ unsigned int SqliteNetworkController::_doCPGet(
(unsigned int)sqlite3_column_int(_sGetIpAssignmentsForNode2,1) (unsigned int)sqlite3_column_int(_sGetIpAssignmentsForNode2,1)
); );
responseBody.append(firstIp ? "\"" : ",\""); responseBody.append(firstIp ? "\"" : ",\"");
firstIp = false;
responseBody.append(_jsonEscape(ip.toString())); responseBody.append(_jsonEscape(ip.toString()));
responseBody.push_back('"'); responseBody.push_back('"');
firstIp = false;
} }
responseBody.append("],\n\t\"recentLog\": ["); responseBody.append("],\n\t\"recentLog\": [");
/* sqlite3_reset(_sGetNodeHistory);
{ sqlite3_bind_text(_sGetNodeHistory,1,nwids,16,SQLITE_STATIC);
std::map< std::pair<Address,uint64_t>,_LLEntry >::const_iterator lli(_lastLog.find(std::pair<Address,uint64_t>(Address(address),nwid))); sqlite3_bind_text(_sGetNodeHistory,2,addrs,10,SQLITE_STATIC);
if (lli != _lastLog.end()) { bool firstHistory = true;
const _LLEntry &lastLogEntry = lli->second; while (sqlite3_step(_sGetNodeHistory) == SQLITE_ROW) {
uint64_t eptr = lastLogEntry.totalRequests; responseBody.append(firstHistory ? "{" : ",{");
for(int k=0;k<ZT_SQLITENETWORKCONTROLLER_IN_MEMORY_LOG_SIZE;++k) { responseBody.append("\"ts\":");
if (!eptr--) responseBody.append((const char *)sqlite3_column_text(_sGetNodeHistory,2));
break; responseBody.append((sqlite3_column_int(_sGetNodeHistory,1) == 0) ? ",\"authorized\":false,\"version\":" : ",\"authorized\":true,\"metaData\":");
const unsigned long ptr = (unsigned long)eptr % ZT_SQLITENETWORKCONTROLLER_IN_MEMORY_LOG_SIZE; const char *md = (const char *)sqlite3_column_text(_sGetNodeHistory,3);
if (md) {
char tsbuf[64]; responseBody.push_back('"');
Utils::snprintf(tsbuf,sizeof(tsbuf),"%llu",(unsigned long long)lastLogEntry.l[ptr].ts); responseBody.append(_jsonEscape(md));
responseBody.append("\",\"fromAddr\":");
responseBody.append((k == 0) ? "{" : ",{"); } else responseBody.append("null,\"fromAddr\":");
responseBody.append("\"ts\":"); const char *fa = (const char *)sqlite3_column_text(_sGetNodeHistory,4);
responseBody.append(tsbuf); if (fa) {
responseBody.append(lastLogEntry.l[ptr].authorized ? ",\"authorized\":false,\"version\":" : ",\"authorized\":true,\"version\":"); responseBody.push_back('"');
if (lastLogEntry.l[ptr].version[0]) { responseBody.append(_jsonEscape(fa));
responseBody.push_back('"'); responseBody.append("\"}");
responseBody.append(_jsonEscape(lastLogEntry.l[ptr].version)); } else responseBody.append("null}");
responseBody.append("\",\"fromAddr\":"); firstHistory = false;
} else responseBody.append("null,\"fromAddr\":");
if (lastLogEntry.l[ptr].fromAddr) {
responseBody.push_back('"');
responseBody.append(_jsonEscape(lastLogEntry.l[ptr].fromAddr.toString()));
responseBody.append("\"}");
} else responseBody.append("null}");
}
}
} }
*/
responseBody.append("]\n}\n"); responseBody.append("]\n}\n");
responseContentType = "application/json"; responseContentType = "application/json";
@ -1589,12 +1594,12 @@ NetworkController::ResultCode SqliteNetworkController::_doNetworkConfigRequest(c
const uint64_t now = OSUtils::now(); const uint64_t now = OSUtils::now();
// Check rate limit circuit breaker to prevent flooding // Check rate limit circuit breaker to prevent flooding
/* {
_LLEntry &lastLogEntry = _lastLog[std::pair<Address,uint64_t>(identity.address(),nwid)]; uint64_t &lrt = _lastRequestTime[identity.address()];
if ((now - lastLogEntry.lastRequestTime) <= ZT_NETCONF_MIN_REQUEST_PERIOD) if ((now - lrt) <= ZT_NETCONF_MIN_REQUEST_PERIOD)
return NetworkController::NETCONF_QUERY_IGNORE; return NetworkController::NETCONF_QUERY_IGNORE;
lastLogEntry.lastRequestTime = now; lrt = now;
*/ }
NetworkRecord network; NetworkRecord network;
memset(&network,0,sizeof(network)); memset(&network,0,sizeof(network));
@ -1680,21 +1685,45 @@ NetworkController::ResultCode SqliteNetworkController::_doNetworkConfigRequest(c
sqlite3_step(_sIncrementMemberRevisionCounter); sqlite3_step(_sIncrementMemberRevisionCounter);
} }
// Add log entry to in-memory circular log // Update NodeHistory with new log entry and delete expired entries
/*
{ {
const unsigned long ptr = (unsigned long)lastLogEntry.totalRequests % ZT_SQLITENETWORKCONTROLLER_IN_MEMORY_LOG_SIZE; int64_t nextVC = 1;
lastLogEntry.l[ptr].ts = now; sqlite3_reset(_sGetMaxNodeHistoryNetworkVisitCounter);
lastLogEntry.l[ptr].fromAddr = fromAddr; sqlite3_bind_text(_sGetMaxNodeHistoryNetworkVisitCounter,1,network.id,16,SQLITE_STATIC);
if ((clientMajorVersion > 0)||(clientMinorVersion > 0)||(clientRevision > 0)) sqlite3_bind_text(_sGetMaxNodeHistoryNetworkVisitCounter,2,member.nodeId,10,SQLITE_STATIC);
Utils::snprintf(lastLogEntry.l[ptr].version,sizeof(lastLogEntry.l[ptr].version),"%u.%u.%u",clientMajorVersion,clientMinorVersion,clientRevision); if (sqlite3_step(_sGetMaxNodeHistoryNetworkVisitCounter) == SQLITE_ROW) {
else lastLogEntry.l[ptr].version[0] = (char)0; nextVC = (int64_t)sqlite3_column_int64(_sGetMaxNodeHistoryNetworkVisitCounter,0) + 1;
lastLogEntry.l[ptr].authorized = member.authorized; }
++lastLogEntry.totalRequests;
// TODO: push or save these somewhere std::string mdstr(metaData.toString());
if (mdstr.length() > 1024)
mdstr = mdstr.substr(0,1024);
std::string fastr;
if (fromAddr)
fastr = fromAddr.toString();
sqlite3_reset(_sAddNodeHistoryEntry);
sqlite3_bind_text(_sAddNodeHistoryEntry,1,member.nodeId,10,SQLITE_STATIC);
sqlite3_bind_text(_sAddNodeHistoryEntry,2,network.id,16,SQLITE_STATIC);
sqlite3_bind_int64(_sAddNodeHistoryEntry,3,nextVC);
sqlite3_bind_int(_sAddNodeHistoryEntry,4,(member.authorized ? 1 : 0));
sqlite3_bind_int64(_sAddNodeHistoryEntry,5,(long long)now);
sqlite3_bind_text(_sAddNodeHistoryEntry,6,mdstr.c_str(),-1,SQLITE_STATIC);
if (fastr.length() > 0)
sqlite3_bind_text(_sAddNodeHistoryEntry,7,fastr.c_str(),-1,SQLITE_STATIC);
else sqlite3_bind_null(_sAddNodeHistoryEntry,7);
sqlite3_step(_sAddNodeHistoryEntry);
nextVC -= ZT_NETCONF_NODE_HISTORY_LENGTH;
if (nextVC >= 0) {
sqlite3_reset(_sDeleteOldNodeHistoryEntries);
sqlite3_bind_text(_sDeleteOldNodeHistoryEntries,1,network.id,16,SQLITE_STATIC);
sqlite3_bind_text(_sDeleteOldNodeHistoryEntries,2,member.nodeId,10,SQLITE_STATIC);
sqlite3_bind_int64(_sDeleteOldNodeHistoryEntries,3,nextVC);
sqlite3_step(_sDeleteOldNodeHistoryEntries);
}
} }
*/
// Check member authorization // Check member authorization

View File

@ -131,6 +131,9 @@ private:
}; };
std::map< uint64_t,_CircuitTestEntry > _circuitTests; std::map< uint64_t,_CircuitTestEntry > _circuitTests;
// Last request time by address, for rate limitation
std::map< Address,uint64_t > _lastRequestTime;
sqlite3 *_db; sqlite3 *_db;
sqlite3_stmt *_sGetNetworkById; sqlite3_stmt *_sGetNetworkById;
@ -138,6 +141,11 @@ private:
sqlite3_stmt *_sCreateMember; sqlite3_stmt *_sCreateMember;
sqlite3_stmt *_sGetNodeIdentity; sqlite3_stmt *_sGetNodeIdentity;
sqlite3_stmt *_sCreateOrReplaceNode; sqlite3_stmt *_sCreateOrReplaceNode;
sqlite3_stmt *_sGetMaxNodeHistoryNetworkVisitCounter;
sqlite3_stmt *_sAddNodeHistoryEntry;
sqlite3_stmt *_sDeleteOldNodeHistoryEntries;
sqlite3_stmt *_sGetActiveNodesOnNetwork;
sqlite3_stmt *_sGetNodeHistory;
sqlite3_stmt *_sGetEtherTypesFromRuleTable; sqlite3_stmt *_sGetEtherTypesFromRuleTable;
sqlite3_stmt *_sGetActiveBridges; sqlite3_stmt *_sGetActiveBridges;
sqlite3_stmt *_sGetIpAssignmentsForNode; sqlite3_stmt *_sGetIpAssignmentsForNode;