Merge pull request #134 from pi-hole/new/clientsovertime

[WIP] Add clients over time data structure
This commit is contained in:
DL6ER
2017-10-10 19:06:20 +02:00
committed by GitHub
4 changed files with 168 additions and 3 deletions
+3
View File
@@ -169,6 +169,8 @@ typedef struct {
int forwardnum;
int *forwarddata;
int *querytypedata;
int clientnum;
int *clientdata;
} overTimeDataStruct;
typedef struct {
@@ -179,6 +181,7 @@ typedef struct {
int forwardedips;
int forwardednames;
int forwarddata;
int clientdata;
int querytypedata;
} memoryStruct;
+38 -2
View File
@@ -272,6 +272,8 @@ void process_pihole_log(int file)
overTime[timeidx].forwardnum = 0;
overTime[timeidx].forwarddata = NULL;
overTime[timeidx].querytypedata = calloc(2, sizeof(int));
overTime[timeidx].clientnum = 0;
overTime[timeidx].clientdata = NULL;
memory.querytypedata += 2*sizeof(int);
counters.overTime++;
@@ -600,6 +602,27 @@ void process_pihole_log(int file)
break;
}
// Determine if there is enough space for saving the current
// clientID in the overTime data structure, allocate space otherwise
validate_access("overTime", timeidx, true, __LINE__, __FUNCTION__, __FILE__);
if(overTime[timeidx].clientnum <= clientID)
{
// Reallocate more space for clientdata
overTime[timeidx].clientdata = realloc(overTime[timeidx].clientdata, (clientID+1)*sizeof(*overTime[timeidx].clientdata));
// Initialize new data fields with zeroes
for(i = overTime[timeidx].clientnum; i <= clientID; i++)
{
overTime[timeidx].clientdata[i] = 0;
memory.clientdata++;
}
// Update counter
overTime[timeidx].clientnum = clientID + 1;
}
// Update overTime data structure with the new client
validate_access_oTcl(timeidx, clientID, __LINE__, __FUNCTION__, __FILE__);
overTime[timeidx].clientdata[clientID]++;
// Free allocated memory
free(client);
free(domain);
@@ -655,11 +678,13 @@ void process_pihole_log(int file)
overTime[timeidx].forwardnum = 0;
overTime[timeidx].forwarddata = NULL;
overTime[timeidx].querytypedata = calloc(2, sizeof(int));
overTime[timeidx].clientnum = 0;
overTime[timeidx].clientdata = NULL;
memory.querytypedata += 2*sizeof(int);
counters.overTime++;
}
// Determine if there is enough space for saving the current
// forwardID in the overTime data structure -allocate space otherwise
// forwardID in the overTime data structure, allocate space otherwise
validate_access("overTime", timeidx, true, __LINE__, __FUNCTION__, __FILE__);
if(overTime[timeidx].forwardnum <= forwardID)
{
@@ -1041,7 +1066,18 @@ void validate_access_oTfd(int timeidx, int pos, int line, const char * function,
if(pos >= limit || pos < 0)
{
logg("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
logg("FATAL ERROR: Trying to access overTime.forwardata[%i], but maximum is %i", pos, limit);
logg("FATAL ERROR: Trying to access overTime.forwarddata[%i], but maximum is %i", pos, limit);
logg(" found in %s() (line %i) in %s", function, line, file);
}
}
void validate_access_oTcl(int timeidx, int pos, int line, const char * function, const char * file)
{
int limit = overTime[timeidx].clientnum;
if(pos >= limit || pos < 0)
{
logg("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
logg("FATAL ERROR: Trying to access overTime.clientdata[%i], but maximum is %i", pos, limit);
logg(" found in %s() (line %i) in %s", function, line, file);
}
}
+126 -1
View File
@@ -30,6 +30,8 @@ void getClientID(int *sock);
void getQueryTypesOverTime(int *sock);
void getVersion(int *sock);
void getDBstats(int *sock);
void getClientsOverTime(int *sock);
void getClientNames(int *sock);
void process_request(char *client_message, int *sock)
{
@@ -113,6 +115,16 @@ void process_request(char *client_message, int *sock)
processed = true;
getDBstats(sock);
}
else if(command(client_message, ">ClientsoverTime"))
{
processed = true;
getClientsOverTime(sock);
}
else if(command(client_message, ">client-names"))
{
processed = true;
getClientNames(sock);
}
// Test only at the end if we want to quit or kill
// so things can be processed before
@@ -439,7 +451,7 @@ void getTopClients(char *client_message, int *sock)
// Sort temporary array
qsort(temparray, counters.clients, sizeof(int[2]), cmpasc);
// Get domains which the user doesn't want to see
// Get clients which the user doesn't want to see
char * excludeclients = read_setupVarsconf("API_EXCLUDE_CLIENTS");
if(excludeclients != NULL)
{
@@ -1026,3 +1038,116 @@ void getDBstats(int *sock)
if(debugclients)
logg("Sent DB info to client, ID: %i", *sock);
}
void getClientsOverTime(int *sock)
{
char server_message[SOCKETBUFFERLEN];
int i, sendit = -1;
for(i = 0; i < counters.overTime; i++)
{
validate_access("overTime", i, true, __LINE__, __FUNCTION__, __FILE__);
if((overTime[i].total > 0 || overTime[i].blocked > 0))
{
sendit = i;
break;
}
}
if(sendit < 0)
return;
// Get clients which the user doesn't want to see
char * excludeclients = read_setupVarsconf("API_EXCLUDE_CLIENTS");
// Array of clients to be skipped in the output
// if skipclient[i] == true then this client should be hidden from
// returned data. We initialize it with false
bool skipclient[counters.clients];
memset(skipclient, false, counters.clients*sizeof(bool));
if(excludeclients != NULL)
{
getSetupVarsArray(excludeclients);
for(i=0; i < counters.clients; i++)
{
validate_access("clients", i, true, __LINE__, __FUNCTION__, __FILE__);
// Check if this client should be skipped
if(insetupVarsArray(clients[i].ip) || insetupVarsArray(clients[i].name))
{
skipclient[i] = true;
}
}
}
// Main return loop
for(i = sendit; i < counters.overTime; i++)
{
validate_access("overTime", i, true, __LINE__, __FUNCTION__, __FILE__);
sprintf(server_message, "%i", overTime[i].timestamp);
// Loop over forward destinations to generate output to be sent to the client
int j;
for(j = 0; j < counters.clients; j++)
{
int thisclient = 0;
if(skipclient[j])
continue;
if(j < overTime[i].clientnum)
{
// This client entry does already exist at this timestamp
// -> use counter of requests sent to this destination
thisclient = overTime[i].clientdata[j];
}
sprintf(server_message + strlen(server_message), " %i", thisclient);
}
sprintf(server_message + strlen(server_message), "\n");
swrite(server_message, *sock);
}
if(excludeclients != NULL)
clearSetupVarsArray();
}
void getClientNames(int *sock)
{
char server_message[SOCKETBUFFERLEN];
int i;
// Get clients which the user doesn't want to see
char * excludeclients = read_setupVarsconf("API_EXCLUDE_CLIENTS");
// Array of clients to be skipped in the output
// if skipclient[i] == true then this client should be hidden from
// returned data. We initialize it with false
bool skipclient[counters.clients];
memset(skipclient, false, counters.clients*sizeof(bool));
if(excludeclients != NULL)
{
getSetupVarsArray(excludeclients);
for(i=0; i < counters.clients; i++)
{
validate_access("clients", i, true, __LINE__, __FUNCTION__, __FILE__);
// Check if this client should be skipped
}
}
// Loop over clients to generate output to be sent to the client
for(i = 0; i < counters.clients; i++)
{
validate_access("clients", i, true, __LINE__, __FUNCTION__, __FILE__);
if(insetupVarsArray(clients[i].ip) || insetupVarsArray(clients[i].name))
continue;
sprintf(server_message,"%i %i %s %s\n", i, clients[i].count, clients[i].ip, clients[i].name);
swrite(server_message, *sock);
}
if(excludeclients != NULL)
clearSetupVarsArray();
}
+1
View File
@@ -31,6 +31,7 @@ void process_pihole_log(int file);
void *pihole_log_thread(void *val);
void validate_access(const char * name, int pos, bool testmagic, int line, const char * function, const char * file);
void validate_access_oTfd(int timeidx, int pos, int line, const char * function, const char * file);
void validate_access_oTcl(int timeidx, int pos, int line, const char * function, const char * file);
void reresolveHostnames(void);
void pihole_log_flushed(bool message);