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
// than this (ms).
#define ZT_NETCONF_MIN_REQUEST_PERIOD 1000
#define ZT_NETCONF_MIN_REQUEST_PERIOD 500
// Delay between backups in milliseconds
#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 {
@ -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,"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 */
||(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)
@ -290,6 +300,11 @@ SqliteNetworkController::~SqliteNetworkController()
sqlite3_finalize(_sCreateMember);
sqlite3_finalize(_sGetNodeIdentity);
sqlite3_finalize(_sCreateOrReplaceNode);
sqlite3_finalize(_sGetMaxNodeHistoryNetworkVisitCounter);
sqlite3_finalize(_sAddNodeHistoryEntry);
sqlite3_finalize(_sDeleteOldNodeHistoryEntries);
sqlite3_finalize(_sGetActiveNodesOnNetwork);
sqlite3_finalize(_sGetNodeHistory);
sqlite3_finalize(_sGetEtherTypesFromRuleTable);
sqlite3_finalize(_sGetActiveBridges);
sqlite3_finalize(_sGetIpAssignmentsForNode);
@ -1198,46 +1213,36 @@ unsigned int SqliteNetworkController::_doCPGet(
(unsigned int)sqlite3_column_int(_sGetIpAssignmentsForNode2,1)
);
responseBody.append(firstIp ? "\"" : ",\"");
firstIp = false;
responseBody.append(_jsonEscape(ip.toString()));
responseBody.push_back('"');
firstIp = false;
}
responseBody.append("],\n\t\"recentLog\": [");
/*
{
std::map< std::pair<Address,uint64_t>,_LLEntry >::const_iterator lli(_lastLog.find(std::pair<Address,uint64_t>(Address(address),nwid)));
if (lli != _lastLog.end()) {
const _LLEntry &lastLogEntry = lli->second;
uint64_t eptr = lastLogEntry.totalRequests;
for(int k=0;k<ZT_SQLITENETWORKCONTROLLER_IN_MEMORY_LOG_SIZE;++k) {
if (!eptr--)
break;
const unsigned long ptr = (unsigned long)eptr % ZT_SQLITENETWORKCONTROLLER_IN_MEMORY_LOG_SIZE;
char tsbuf[64];
Utils::snprintf(tsbuf,sizeof(tsbuf),"%llu",(unsigned long long)lastLogEntry.l[ptr].ts);
responseBody.append((k == 0) ? "{" : ",{");
responseBody.append("\"ts\":");
responseBody.append(tsbuf);
responseBody.append(lastLogEntry.l[ptr].authorized ? ",\"authorized\":false,\"version\":" : ",\"authorized\":true,\"version\":");
if (lastLogEntry.l[ptr].version[0]) {
responseBody.push_back('"');
responseBody.append(_jsonEscape(lastLogEntry.l[ptr].version));
responseBody.append("\",\"fromAddr\":");
} 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}");
}
}
sqlite3_reset(_sGetNodeHistory);
sqlite3_bind_text(_sGetNodeHistory,1,nwids,16,SQLITE_STATIC);
sqlite3_bind_text(_sGetNodeHistory,2,addrs,10,SQLITE_STATIC);
bool firstHistory = true;
while (sqlite3_step(_sGetNodeHistory) == SQLITE_ROW) {
responseBody.append(firstHistory ? "{" : ",{");
responseBody.append("\"ts\":");
responseBody.append((const char *)sqlite3_column_text(_sGetNodeHistory,2));
responseBody.append((sqlite3_column_int(_sGetNodeHistory,1) == 0) ? ",\"authorized\":false,\"version\":" : ",\"authorized\":true,\"metaData\":");
const char *md = (const char *)sqlite3_column_text(_sGetNodeHistory,3);
if (md) {
responseBody.push_back('"');
responseBody.append(_jsonEscape(md));
responseBody.append("\",\"fromAddr\":");
} else responseBody.append("null,\"fromAddr\":");
const char *fa = (const char *)sqlite3_column_text(_sGetNodeHistory,4);
if (fa) {
responseBody.push_back('"');
responseBody.append(_jsonEscape(fa));
responseBody.append("\"}");
} else responseBody.append("null}");
firstHistory = false;
}
*/
responseBody.append("]\n}\n");
responseContentType = "application/json";
@ -1589,12 +1594,12 @@ NetworkController::ResultCode SqliteNetworkController::_doNetworkConfigRequest(c
const uint64_t now = OSUtils::now();
// Check rate limit circuit breaker to prevent flooding
/*
_LLEntry &lastLogEntry = _lastLog[std::pair<Address,uint64_t>(identity.address(),nwid)];
if ((now - lastLogEntry.lastRequestTime) <= ZT_NETCONF_MIN_REQUEST_PERIOD)
return NetworkController::NETCONF_QUERY_IGNORE;
lastLogEntry.lastRequestTime = now;
*/
{
uint64_t &lrt = _lastRequestTime[identity.address()];
if ((now - lrt) <= ZT_NETCONF_MIN_REQUEST_PERIOD)
return NetworkController::NETCONF_QUERY_IGNORE;
lrt = now;
}
NetworkRecord network;
memset(&network,0,sizeof(network));
@ -1680,21 +1685,45 @@ NetworkController::ResultCode SqliteNetworkController::_doNetworkConfigRequest(c
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;
lastLogEntry.l[ptr].ts = now;
lastLogEntry.l[ptr].fromAddr = fromAddr;
if ((clientMajorVersion > 0)||(clientMinorVersion > 0)||(clientRevision > 0))
Utils::snprintf(lastLogEntry.l[ptr].version,sizeof(lastLogEntry.l[ptr].version),"%u.%u.%u",clientMajorVersion,clientMinorVersion,clientRevision);
else lastLogEntry.l[ptr].version[0] = (char)0;
lastLogEntry.l[ptr].authorized = member.authorized;
++lastLogEntry.totalRequests;
// TODO: push or save these somewhere
int64_t nextVC = 1;
sqlite3_reset(_sGetMaxNodeHistoryNetworkVisitCounter);
sqlite3_bind_text(_sGetMaxNodeHistoryNetworkVisitCounter,1,network.id,16,SQLITE_STATIC);
sqlite3_bind_text(_sGetMaxNodeHistoryNetworkVisitCounter,2,member.nodeId,10,SQLITE_STATIC);
if (sqlite3_step(_sGetMaxNodeHistoryNetworkVisitCounter) == SQLITE_ROW) {
nextVC = (int64_t)sqlite3_column_int64(_sGetMaxNodeHistoryNetworkVisitCounter,0) + 1;
}
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

View File

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