Rename super-clients ---> alias-clients

Signed-off-by: DL6ER <dl6er@dl6er.de>
This commit is contained in:
DL6ER 2020-11-15 08:50:24 +01:00
parent 6f6ae518d2
commit 99a07ba57a
No known key found for this signature in database
GPG Key ID: 9A379E34963EE435
21 changed files with 424 additions and 424 deletions

View File

@ -36,8 +36,8 @@
#include "../version.h"
// enum REGEX
#include "../regex_r.h"
// get_superclient_list()
#include "../database/superclients.h"
// get_aliasclient_list()
#include "../database/aliasclients.h"
#define min(a,b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a < _b ? _a : _b; })
@ -396,8 +396,8 @@ void getTopClients(const char *client_message, const int *sock)
{
// Get client pointer
const clientsData* client = getClient(clientID, true);
// Skip invalid clients and also those managed by super clients
if(client == NULL || (!client->superclient && client->superclient_id >= 0))
// Skip invalid clients and also those managed by alias clients
if(client == NULL || (!client->aliasclient && client->aliasclient_id >= 0))
{
temparray[clientID][0] = -1;
continue;
@ -439,7 +439,7 @@ void getTopClients(const char *client_message, const int *sock)
const int clientID = temparray[i][0];
const int ccount = temparray[i][1];
// clientID -1 means this client is to be skipped (managed by a super-client)
// clientID -1 means this client is to be skipped (managed by a alias-client)
if(clientID < 0)
continue;
@ -805,8 +805,8 @@ void getAllQueries(const char *client_message, const int *sock)
{
// Get client pointer
const clientsData* client = getClient(i, true);
// Skip invalid clients and also those managed by super clients
if(client == NULL || client->superclient_id >= 0)
// Skip invalid clients and also those managed by alias clients
if(client == NULL || client->aliasclient_id >= 0)
continue;
// Try to match the requested string
@ -816,9 +816,9 @@ void getAllQueries(const char *client_message, const int *sock)
{
clientid = i;
// Is this a super-client?
if(client->superclient)
clientid_list = get_superclient_list(i);
// Is this a alias-client?
if(client->aliasclient)
clientid_list = get_aliasclient_list(i);
break;
}
@ -925,7 +925,7 @@ void getAllQueries(const char *client_message, const int *sock)
// Normal clients
if(clientid_list == NULL && query->clientID != clientid)
continue;
// Super-clients (we have to check for all clients managed by this super-client)
// Alias-clients (we have to check for all clients managed by this alias-client)
else if(clientid_list != NULL)
{
bool found = false;
@ -1295,7 +1295,7 @@ void getClientsOverTime(const int *sock)
// Check if this client should be skipped
if(insetupVarsArray(getstr(client->ippos)) ||
insetupVarsArray(getstr(client->namepos)) ||
(!client->superclient && client->superclient_id > -1))
(!client->aliasclient && client->aliasclient_id > -1))
skipclient[clientID] = true;
}
}
@ -1316,8 +1316,8 @@ void getClientsOverTime(const int *sock)
// Get client pointer
const clientsData* client = getClient(clientID, true);
// Skip invalid clients and also those managed by super clients
if(client == NULL || client->superclient_id >= 0)
// Skip invalid clients and also those managed by alias clients
if(client == NULL || client->aliasclient_id >= 0)
continue;
const int thisclient = client->overTime[slot];
@ -1367,7 +1367,7 @@ void getClientNames(const int *sock)
// Check if this client should be skipped
if(insetupVarsArray(getstr(client->ippos)) ||
insetupVarsArray(getstr(client->namepos)) ||
(!client->superclient && client->superclient_id > -1))
(!client->aliasclient && client->aliasclient_id > -1))
skipclient[clientID] = true;
}
}

View File

@ -712,9 +712,9 @@ void read_debuging_settings(FILE *fp)
// defaults to: false
setDebugOption(fp, "DEBUG_CLIENTS", DEBUG_CLIENTS);
// DEBUG_SUPERCLIENTS
// DEBUG_ALIASCLIENTS
// defaults to: false
setDebugOption(fp, "DEBUG_SUPERCLIENTS", DEBUG_SUPERCLIENTS);
setDebugOption(fp, "DEBUG_ALIASCLIENTS", DEBUG_ALIASCLIENTS);
// DEBUG_EVENTS
// defaults to: false
@ -746,7 +746,7 @@ void read_debuging_settings(FILE *fp)
logg("* DEBUG_RESOLVER %s *", (config.debug & DEBUG_RESOLVER)? "YES":"NO ");
logg("* DEBUG_EDNS0 %s *", (config.debug & DEBUG_EDNS0)? "YES":"NO ");
logg("* DEBUG_CLIENTS %s *", (config.debug & DEBUG_CLIENTS)? "YES":"NO ");
logg("* DEBUG_SUPERCLIENTS %s *", (config.debug & DEBUG_SUPERCLIENTS)? "YES":"NO ");
logg("* DEBUG_ALIASCLIENTS %s *", (config.debug & DEBUG_ALIASCLIENTS)? "YES":"NO ");
logg("* DEBUG_EVENTS %s *", (config.debug & DEBUG_EVENTS)? "YES":"NO ");
logg("* DEBUG_HELPER %s *", (config.debug & DEBUG_HELPER)? "YES":"NO ");
logg("*****************************");

View File

@ -35,8 +35,8 @@ set(database_sources
sqlite3.h
sqlite3-ext.c
sqlite3-ext.h
superclients.c
superclients.h
aliasclients.c
aliasclients.h
)
add_library(database OBJECT ${database_sources})

319
src/database/aliasclients.c Normal file
View File

@ -0,0 +1,319 @@
/* Pi-hole: A black hole for Internet advertisements
* (c) 2020 Pi-hole, LLC (https://pi-hole.net)
* Network-wide ad blocking via your own hardware.
*
* FTL Engine
* Super client table routines
*
* This file is copyright under the latest version of the EUPL.
* Please see LICENSE file for your rights under this license. */
#include "../FTL.h"
#include "aliasclients.h"
#include "common.h"
// global counters variable
#include "../shmem.h"
// global config variable
#include "../config.h"
// logg()
#include "../log.h"
// calloc()
#include "../memory.h"
// getAliasclientIDfromIP()
#include "network-table.h"
bool create_aliasclients_table(void)
{
// Create aliasclient table in the database
SQL_bool("CREATE TABLE aliasclient (id INTEGER PRIMARY KEY NOT NULL, " \
"name TEXT NOT NULL, " \
"comment TEXT);");
// Add aliasclient_id to network table
SQL_bool("ALTER TABLE network ADD COLUMN aliasclient_id INTEGER;");
// Update database version to 9
if(!db_set_FTL_property(DB_VERSION, 9))
{
logg("create_aliasclients_table(): Failed to update database version!");
return false;
}
return true;
}
// Recompute the alias-client's values
// We shouldn't do this too often as it iterates over all existing clients
static void recompute_aliasclient(const int aliasclientID)
{
clientsData *aliasclient = getClient(aliasclientID, true);
if(config.debug & DEBUG_ALIASCLIENTS)
{
logg("Recomputing alias-client \"%s\" (%s)...",
getstr(aliasclient->namepos), getstr(aliasclient->ippos));
}
// Reset this alias-client
aliasclient->count = 0;
aliasclient->blockedcount = 0;
memset(aliasclient->overTime, 0, sizeof(aliasclient->overTime));
// Loop over all existing clients to find which clients are associated to this one
for(int clientID = 0; clientID < counters->clients; clientID++)
{
// Get pointer to client candidate
const clientsData *client = getClient(clientID, true);
// Skip invalid clients and alias-clients
if(client == NULL || client->aliasclient)
continue;
// Skip clients that are not managed by this aliasclient
if(client->aliasclient_id != aliasclientID)
{
if(config.debug & DEBUG_ALIASCLIENTS)
{
logg("Client \"%s\" (%s) NOT managed by this alias-client, skipping",
getstr(client->namepos), getstr(client->ippos));
}
continue;
}
// Debug logging
if(config.debug & DEBUG_ALIASCLIENTS)
{
logg("Client \"%s\" (%s) IS managed by this alias-client, adding counts",
getstr(client->namepos), getstr(client->ippos));
}
// Add counts of this client to the alias-client
aliasclient->count += client->count;
aliasclient->blockedcount += client->blockedcount;
for(int idx = 0; idx < OVERTIME_SLOTS; idx++)
aliasclient->overTime[idx] += client->overTime[idx];
}
}
// Store hostname of device identified by dbID
bool import_aliasclients(void)
{
sqlite3_stmt *stmt = NULL;
const char querystr[] = "SELECT id,name FROM aliasclient";
int rc = sqlite3_prepare_v2(FTL_db, querystr, -1, &stmt, NULL);
if(rc != SQLITE_OK)
{
logg("import_aliasclients() - SQL error prepare: %s", sqlite3_errstr(rc));
return false;
}
// Loop until no further data is available
int imported = 0;
while((rc = sqlite3_step(stmt)) != SQLITE_DONE)
{
// Check if we ran into an error
if(rc != SQLITE_ROW)
{
logg("import_aliasclients() - SQL error step: %s", sqlite3_errstr(rc));
break;
}
// Get hardware address from database and store it as IP + MAC address of this client
const int aliasclient_id = sqlite3_column_int(stmt, 0);
// Create a new (super-)client
char *aliasclient_str = NULL;
if(asprintf(&aliasclient_str, "aliasclient-%i", aliasclient_id) < 10)
{
logg("Memory error in import_aliasclients()");
return false;
}
// Try to open existing client
const int clientID = findClientID(aliasclient_str, false, true);
clientsData *client = getClient(clientID, true);
client->new = false;
// Reset counter
client->count = 0;
// Store intended name
const char *name = (char*)sqlite3_column_text(stmt, 1);
client->namepos = addstr(name);
// This is a aliasclient
client->aliasclient = true;
client->aliasclient_id = aliasclient_id;
// Debug logging
if(config.debug & DEBUG_ALIASCLIENTS)
{
logg("Added alias-client \"%s\" (%s) with FTL ID %i", name, aliasclient_str, clientID);
}
free(aliasclient_str);
imported++;
}
// Finalize statement
if ((rc = sqlite3_finalize(stmt)) != SQLITE_OK)
{
logg("import_aliasclients() - SQL error finalize: %s", sqlite3_errstr(rc));
return false;
}
logg("Imported %d alias-client%s", imported, (imported != 1) ? "s":"");
return true;
}
static int get_aliasclient_ID(const clientsData *client)
{
// Skip alias-clients themselves
if(client->aliasclient)
return -1;
const char *clientIP = getstr(client->ippos);
if(config.debug & DEBUG_ALIASCLIENTS)
{
logg(" Looking for the alias-client for client %s...",
clientIP);
}
// Get aliasclient ID from database (DB index)
const int aliasclient_DBid = getAliasclientIDfromIP(clientIP);
// Compare DB index for all alias-clients stored in FTL
int aliasclientID = 0;
for(; aliasclientID < counters->clients; aliasclientID++)
{
// Get pointer to alias client candidate
const clientsData *alias_client = getClient(aliasclientID, true);
// Skip clients that are not alias-clients
if(!alias_client->aliasclient)
continue;
// Compare MAC address of the current client to the
// alias client candidate's MAC address
if(alias_client->aliasclient_id == aliasclient_DBid)
{
if(config.debug & DEBUG_ALIASCLIENTS)
{
logg(" -> \"%s\" (%s)",
getstr(alias_client->namepos),
getstr(alias_client->ippos));
}
return aliasclientID;
}
}
if(config.debug & DEBUG_ALIASCLIENTS && aliasclientID == counters->clients)
{
logg(" -> not found");
}
// Not found
return -1;
}
void reset_aliasclient(clientsData *client)
{
// Skip alias-clients themselves
if(client->aliasclient)
return;
// Find corresponding alias-client (if any)
client->aliasclient_id = get_aliasclient_ID(client);
// Skip if there is no responsible alias-client
if(client->aliasclient_id == -1)
return;
// Recompute all values for this alias-client
recompute_aliasclient(client->aliasclient_id);
}
// Return a list of clients linked to the current alias-client
// The first element contains the number of following IDs
int *get_aliasclient_list(const int aliasclientID)
{
int count = 0;
// Loop over all existing clients to count associated clients
for(int clientID = 0; clientID < counters->clients; clientID++)
{
// Get pointer to client candidate
const clientsData *client = getClient(clientID, true);
// Skip invalid clients and those that are not managed by this aliasclient
if(client == NULL || client->aliasclient_id != aliasclientID)
continue;
count++;
}
int *list = calloc(count + 1, sizeof(int));
list[0] = count;
// Loop over all existing clients to fill list of clients
count = 0;
for(int clientID = 0; clientID < counters->clients; clientID++)
{
// Get pointer to client candidate
const clientsData *client = getClient(clientID, true);
// Skip invalid clients and those that are not managed by this aliasclient
if(client == NULL || client->aliasclient_id != aliasclientID)
continue;
list[++count] = clientID;
}
return list;
}
// Reimport alias-clients from database
// Note that this will always only change or add new clients. Alias-clients are
// removed by nulling them before importing new clients
void reimport_aliasclients(void)
{
// Open pihole-FTL.db database file if needed
const bool db_already_open = FTL_DB_avail();
if(!db_already_open && !dbopen())
{
logg("reimport_aliasclients() - Failed to open DB");
return;
}
// Loop over all existing alias-clients and set their counters to zero
for(int clientID = 0; clientID < counters->clients; clientID++)
{
// Get pointer to client candidate
clientsData *client = getClient(clientID, true);
// Skip invalid and non-alias-clients
if(client == NULL || !client->aliasclient)
continue;
// Reset this alias-client
client->count = 0;
client->blockedcount = 0;
memset(client->overTime, 0, sizeof(client->overTime));
}
// Import aliasclients from database table
import_aliasclients();
if(!db_already_open)
dbclose();
// Recompute all alias-clients
for(int clientID = 0; clientID < counters->clients; clientID++)
{
// Get pointer to client candidate
clientsData *client = getClient(clientID, true);
// Skip invalid and alias-clients
if(client == NULL || client->aliasclient)
continue;
reset_aliasclient(client);
}
}

View File

@ -3,22 +3,22 @@
* Network-wide ad blocking via your own hardware.
*
* FTL Engine
* pihole-FTL.db -> super-clients tables prototypes
* pihole-FTL.db -> alias-clients tables prototypes
*
* This file is copyright under the latest version of the EUPL.
* Please see LICENSE file for your rights under this license. */
#ifndef SUPERCLIENTS_TABLE_H
#define SUPERCLIENTS_TABLE_H
#ifndef ALIASCLIENTS_TABLE_H
#define ALIASCLIENTS_TABLE_H
// type clientsData
#include "../datastructure.h"
void reset_superclient(clientsData *client);
void reset_aliasclient(clientsData *client);
bool create_superclients_table(void);
bool import_superclients(void);
void reimport_superclients(void);
bool create_aliasclients_table(void);
bool import_aliasclients(void);
void reimport_aliasclients(void);
int *get_superclient_list(const int superclientID);
int *get_aliasclient_list(const int aliasclientID);
#endif //SUPERCLIENTS_TABLE_H
#endif //ALIASCLIENTS_TABLE_H

View File

@ -22,8 +22,8 @@
// file_exists()
#include "../files.h"
#include "sqlite3-ext.h"
// import_superclients()
#include "superclients.h"
// import_aliasclients()
#include "aliasclients.h"
sqlite3 *FTL_db = NULL;
bool DBdeleteoldqueries = false;
@ -399,11 +399,11 @@ void db_init(void)
// Update to version 9 if lower
if(dbversion < 9)
{
// Update to version 9: Add superclients table
// Update to version 9: Add aliasclients table
logg("Updating long-term database to version 9");
if(!create_superclients_table())
if(!create_aliasclients_table())
{
logg("Superclients table not initialized, database not available");
logg("Aliasclients table not initialized, database not available");
dbclose();
return;
}
@ -411,7 +411,7 @@ void db_init(void)
dbversion = db_get_FTL_property(DB_VERSION);
}
import_superclients();
import_aliasclients();
// Close database to prevent having it opened all time
// We already closed the database when we returned earlier

View File

@ -22,8 +22,8 @@
#include "../timers.h"
// global variable killed
#include "../signals.h"
// reimport_superclients()
#include "superclients.h"
// reimport_aliasclients()
#include "aliasclients.h"
// Eventqueue routines
#include "../events.h"
@ -96,10 +96,10 @@ void *DB_thread(void *val)
resolveNetworkTableNames();
}
if(get_and_clear_event(REIMPORT_SUPERCLIENTS))
if(get_and_clear_event(REIMPORT_ALIASCLIENTS))
{
lock_shm();
reimport_superclients();
reimport_aliasclients();
unlock_shm();
}

View File

@ -27,8 +27,8 @@
#include "network-table.h"
// struct DNSCacheData
#include "../datastructure.h"
// reset_superclient()
#include "superclients.h"
// reset_aliasclient()
#include "aliasclients.h"
// Prefix of interface names in the client table
#define INTERFACE_SEP ":"

View File

@ -691,8 +691,8 @@ static bool add_FTL_clients_to_network_table(enum arp_status *client_status, tim
continue;
}
// Silently skip super-clients - they do not really exist
if(client->superclient)
// Silently skip alias-clients - they do not really exist
if(client->aliasclient)
continue;
// Get hostname and IP address of this client
@ -1624,14 +1624,14 @@ char *__attribute__((malloc)) getMACfromIP(const char *ipaddr)
return hwaddr;
}
// Get superclient ID of device identified by IP address (if available)
int getSuperclientIDfromIP(const char *ipaddr)
// Get aliasclient ID of device identified by IP address (if available)
int getAliasclientIDfromIP(const char *ipaddr)
{
// Open pihole-FTL.db database file if needed
const bool db_already_open = FTL_DB_avail();
if(!db_already_open && !dbopen())
{
logg("getSuperclientIDfromIP(\"%s\") - Failed to open DB", ipaddr);
logg("getAliasclientIDfromIP(\"%s\") - Failed to open DB", ipaddr);
return -1;
}
@ -1639,14 +1639,14 @@ int getSuperclientIDfromIP(const char *ipaddr)
// We request the most recent IP entry in case there an IP appears
// multiple times in the network_addresses table
sqlite3_stmt *stmt = NULL;
const char *querystr = "SELECT superclient_id FROM network WHERE id = "
const char *querystr = "SELECT aliasclient_id FROM network WHERE id = "
"(SELECT network_id FROM network_addresses "
"WHERE ip = ? "
"AND superclient_id IS NOT NULL "
"AND aliasclient_id IS NOT NULL "
"GROUP BY ip HAVING max(lastSeen));";
int rc = sqlite3_prepare_v2(FTL_db, querystr, -1, &stmt, NULL);
if( rc != SQLITE_OK ){
logg("getSuperclientIDfromIP(\"%s\") - SQL error prepare: %s",
logg("getAliasclientIDfromIP(\"%s\") - SQL error prepare: %s",
ipaddr, sqlite3_errstr(rc));
if(!db_already_open)
dbclose();
@ -1656,7 +1656,7 @@ int getSuperclientIDfromIP(const char *ipaddr)
// Bind ipaddr to prepared statement
if((rc = sqlite3_bind_text(stmt, 1, ipaddr, -1, SQLITE_STATIC)) != SQLITE_OK)
{
logg("getSuperclientIDfromIP(\"%s\"): Failed to bind ip: %s",
logg("getAliasclientIDfromIP(\"%s\"): Failed to bind ip: %s",
ipaddr, sqlite3_errstr(rc));
sqlite3_reset(stmt);
sqlite3_finalize(stmt);
@ -1665,17 +1665,17 @@ int getSuperclientIDfromIP(const char *ipaddr)
return -1;
}
int superclient_id = -1;
int aliasclient_id = -1;
rc = sqlite3_step(stmt);
if(rc == SQLITE_ROW)
{
// Database record found
superclient_id = sqlite3_column_int(stmt, 0);
aliasclient_id = sqlite3_column_int(stmt, 0);
}
if(config.debug & DEBUG_SUPERCLIENTS)
logg(" Superclient ID %s -> %i%s", ipaddr, superclient_id,
(superclient_id == -1) ? " (NOT FOUND)" : "");
if(config.debug & DEBUG_ALIASCLIENTS)
logg(" Aliasclient ID %s -> %i%s", ipaddr, aliasclient_id,
(aliasclient_id == -1) ? " (NOT FOUND)" : "");
// Finalize statement and close database handle
sqlite3_reset(stmt);
@ -1683,7 +1683,7 @@ int getSuperclientIDfromIP(const char *ipaddr)
if(!db_already_open)
dbclose();
return superclient_id;
return aliasclient_id;
}
// Get host name of device identified by IP address

View File

@ -18,7 +18,7 @@ void updateMACVendorRecords(void);
bool unify_hwaddr(void);
char* getDatabaseHostname(const char* ipaddr) __attribute__((malloc));
char* __attribute__((malloc)) getMACfromIP(const char* ipaddr);
int getSuperclientIDfromIP(const char *ipaddr);
int getAliasclientIDfromIP(const char *ipaddr);
char* __attribute__((malloc)) getNameFromIP(const char* ipaddr);
char* __attribute__((malloc)) getIfaceFromIP(const char* ipaddr);
void resolveNetworkTableNames(void);

View File

@ -1,319 +0,0 @@
/* Pi-hole: A black hole for Internet advertisements
* (c) 2020 Pi-hole, LLC (https://pi-hole.net)
* Network-wide ad blocking via your own hardware.
*
* FTL Engine
* Super client table routines
*
* This file is copyright under the latest version of the EUPL.
* Please see LICENSE file for your rights under this license. */
#include "../FTL.h"
#include "superclients.h"
#include "common.h"
// global counters variable
#include "../shmem.h"
// global config variable
#include "../config.h"
// logg()
#include "../log.h"
// calloc()
#include "../memory.h"
// getSuperclientIDfromIP()
#include "network-table.h"
bool create_superclients_table(void)
{
// Create superclient table in the database
SQL_bool("CREATE TABLE superclient (id INTEGER PRIMARY KEY NOT NULL, " \
"name TEXT NOT NULL, " \
"comment TEXT);");
// Add superclient_id to network table
SQL_bool("ALTER TABLE network ADD COLUMN superclient_id INTEGER;");
// Update database version to 9
if(!db_set_FTL_property(DB_VERSION, 9))
{
logg("create_superclients_table(): Failed to update database version!");
return false;
}
return true;
}
// Recompute the super-client's values
// We shouldn't do this too often as it iterates over all existing clients
static void recompute_superclient(const int superclientID)
{
clientsData *superclient = getClient(superclientID, true);
if(config.debug & DEBUG_SUPERCLIENTS)
{
logg("Recomputing super-client \"%s\" (%s)...",
getstr(superclient->namepos), getstr(superclient->ippos));
}
// Reset this super-client
superclient->count = 0;
superclient->blockedcount = 0;
memset(superclient->overTime, 0, sizeof(superclient->overTime));
// Loop over all existing clients to find which clients are associated to this one
for(int clientID = 0; clientID < counters->clients; clientID++)
{
// Get pointer to client candidate
const clientsData *client = getClient(clientID, true);
// Skip invalid clients and super-clients
if(client == NULL || client->superclient)
continue;
// Skip clients that are not managed by this superclient
if(client->superclient_id != superclientID)
{
if(config.debug & DEBUG_SUPERCLIENTS)
{
logg("Client \"%s\" (%s) NOT managed by this super-client, skipping",
getstr(client->namepos), getstr(client->ippos));
}
continue;
}
// Debug logging
if(config.debug & DEBUG_SUPERCLIENTS)
{
logg("Client \"%s\" (%s) IS managed by this super-client, adding counts",
getstr(client->namepos), getstr(client->ippos));
}
// Add counts of this client to the super-client
superclient->count += client->count;
superclient->blockedcount += client->blockedcount;
for(int idx = 0; idx < OVERTIME_SLOTS; idx++)
superclient->overTime[idx] += client->overTime[idx];
}
}
// Store hostname of device identified by dbID
bool import_superclients(void)
{
sqlite3_stmt *stmt = NULL;
const char querystr[] = "SELECT id,name FROM superclient";
int rc = sqlite3_prepare_v2(FTL_db, querystr, -1, &stmt, NULL);
if(rc != SQLITE_OK)
{
logg("import_superclients() - SQL error prepare: %s", sqlite3_errstr(rc));
return false;
}
// Loop until no further data is available
int imported = 0;
while((rc = sqlite3_step(stmt)) != SQLITE_DONE)
{
// Check if we ran into an error
if(rc != SQLITE_ROW)
{
logg("import_superclients() - SQL error step: %s", sqlite3_errstr(rc));
break;
}
// Get hardware address from database and store it as IP + MAC address of this client
const int superclient_id = sqlite3_column_int(stmt, 0);
// Create a new (super-)client
char *superclient_str = NULL;
if(asprintf(&superclient_str, "superclient-%i", superclient_id) < 10)
{
logg("Memory error in import_superclients()");
return false;
}
// Try to open existing client
const int clientID = findClientID(superclient_str, false, true);
clientsData *client = getClient(clientID, true);
client->new = false;
// Reset counter
client->count = 0;
// Store intended name
const char *name = (char*)sqlite3_column_text(stmt, 1);
client->namepos = addstr(name);
// This is a superclient
client->superclient = true;
client->superclient_id = superclient_id;
// Debug logging
if(config.debug & DEBUG_SUPERCLIENTS)
{
logg("Added super-client \"%s\" (%s) with FTL ID %i", name, superclient_str, clientID);
}
free(superclient_str);
imported++;
}
// Finalize statement
if ((rc = sqlite3_finalize(stmt)) != SQLITE_OK)
{
logg("import_superclients() - SQL error finalize: %s", sqlite3_errstr(rc));
return false;
}
logg("Imported %d super-client%s", imported, (imported != 1) ? "s":"");
return true;
}
static int get_superclient_ID(const clientsData *client)
{
// Skip super-clients themselves
if(client->superclient)
return -1;
const char *clientIP = getstr(client->ippos);
if(config.debug & DEBUG_SUPERCLIENTS)
{
logg(" Looking for the super-client for client %s...",
clientIP);
}
// Get superclient ID from database (DB index)
const int superclient_DBid = getSuperclientIDfromIP(clientIP);
// Compare DB index for all super-clients stored in FTL
int superclientID = 0;
for(; superclientID < counters->clients; superclientID++)
{
// Get pointer to super client candidate
const clientsData *super_client = getClient(superclientID, true);
// Skip clients that are not super-clients
if(!super_client->superclient)
continue;
// Compare MAC address of the current client to the
// super client candidate's MAC address
if(super_client->superclient_id == superclient_DBid)
{
if(config.debug & DEBUG_SUPERCLIENTS)
{
logg(" -> \"%s\" (%s)",
getstr(super_client->namepos),
getstr(super_client->ippos));
}
return superclientID;
}
}
if(config.debug & DEBUG_SUPERCLIENTS && superclientID == counters->clients)
{
logg(" -> not found");
}
// Not found
return -1;
}
void reset_superclient(clientsData *client)
{
// Skip super-clients themselves
if(client->superclient)
return;
// Find corresponding super-client (if any)
client->superclient_id = get_superclient_ID(client);
// Skip if there is no responsible super-client
if(client->superclient_id == -1)
return;
// Recompute all values for this super-client
recompute_superclient(client->superclient_id);
}
// Return a list of clients linked to the current super-client
// The first element contains the number of following IDs
int *get_superclient_list(const int superclientID)
{
int count = 0;
// Loop over all existing clients to count associated clients
for(int clientID = 0; clientID < counters->clients; clientID++)
{
// Get pointer to client candidate
const clientsData *client = getClient(clientID, true);
// Skip invalid clients and those that are not managed by this superclient
if(client == NULL || client->superclient_id != superclientID)
continue;
count++;
}
int *list = calloc(count + 1, sizeof(int));
list[0] = count;
// Loop over all existing clients to fill list of clients
count = 0;
for(int clientID = 0; clientID < counters->clients; clientID++)
{
// Get pointer to client candidate
const clientsData *client = getClient(clientID, true);
// Skip invalid clients and those that are not managed by this superclient
if(client == NULL || client->superclient_id != superclientID)
continue;
list[++count] = clientID;
}
return list;
}
// Reimport super-clients from database
// Note that this will always only change or add new clients. Super-clients are
// removed by nulling them before importing new clients
void reimport_superclients(void)
{
// Open pihole-FTL.db database file if needed
const bool db_already_open = FTL_DB_avail();
if(!db_already_open && !dbopen())
{
logg("reimport_superclients() - Failed to open DB");
return;
}
// Loop over all existing super-clients and set their counters to zero
for(int clientID = 0; clientID < counters->clients; clientID++)
{
// Get pointer to client candidate
clientsData *client = getClient(clientID, true);
// Skip invalid and non-super-clients
if(client == NULL || !client->superclient)
continue;
// Reset this super-client
client->count = 0;
client->blockedcount = 0;
memset(client->overTime, 0, sizeof(client->overTime));
}
// Import superclients from database table
import_superclients();
if(!db_already_open)
dbclose();
// Recompute all super-clients
for(int clientID = 0; clientID < counters->clients; clientID++)
{
// Get pointer to client candidate
clientsData *client = getClient(clientID, true);
// Skip invalid and super-clients
if(client == NULL || client->superclient)
continue;
reset_superclient(client);
}
}

View File

@ -21,8 +21,8 @@
#include "database/message-table.h"
// bool startup
#include "main.h"
// reset_superclient()
#include "database/superclients.h"
// reset_aliasclient()
#include "database/aliasclients.h"
// piholeFTLDB_reopen()
#include "database/common.h"
@ -183,7 +183,7 @@ int findDomainID(const char *domainString, const bool count)
return domainID;
}
int findClientID(const char *clientIP, const bool count, const bool superclient)
int findClientID(const char *clientIP, const bool count, const bool aliasclient)
{
// Compare content of client against known client IP addresses
for(int clientID=0; clientID < counters->clients; clientID++)
@ -203,14 +203,14 @@ int findClientID(const char *clientIP, const bool count, const bool superclient)
if(strcmp(getstr(client->ippos), clientIP) == 0)
{
// Add one if count == true (do not add one, e.g., during ARP table processing)
if(count && !superclient) change_clientcount(client, 1, 0, -1, 0);
if(count && !aliasclient) change_clientcount(client, 1, 0, -1, 0);
return clientID;
}
}
// Return -1 (= not found) if count is false because we do not want to create a new client here
// Proceed if we are looking for a super-client because we want to create a new record
if(!count && !superclient)
// Proceed if we are looking for a alias-client because we want to create a new record
if(!count && !aliasclient)
return -1;
// If we did not return until here, then this client is definitely new
@ -231,7 +231,7 @@ int findClientID(const char *clientIP, const bool count, const bool superclient)
// Set magic byte
client->magic = MAGICBYTE;
// Set its counter to 1
client->count = (count && !superclient)? 1 : 0;
client->count = (count && !aliasclient)? 1 : 0;
// Initialize blocked count to zero
client->blockedcount = 0;
// Store client IP - no need to check for NULL here as it doesn't harm
@ -258,9 +258,9 @@ int findClientID(const char *clientIP, const bool count, const bool superclient)
// Set all MAC address bytes to zero
client->hwlen = -1;
memset(client->hwaddr, 0, sizeof(client->hwaddr));
// This may be a super-client, the ID is set elsewhere
client->superclient = superclient;
client->superclient_id = -1;
// This may be a alias-client, the ID is set elsewhere
client->aliasclient = aliasclient;
client->aliasclient_id = -1;
// Initialize client-specific overTime data
memset(client->overTime, 0, sizeof(client->overTime));
@ -276,12 +276,12 @@ int findClientID(const char *clientIP, const bool count, const bool superclient)
// database may not be available. All clients initialized
// during history reading get their enabled regexs reloaded
// in the initial call to FTL_reload_all_domainlists()
if(!startup && !superclient)
if(!startup && !aliasclient)
reload_per_client_regex(clientID, client);
// Check if this client is managed by a super-client
if(!superclient)
reset_superclient(client);
// Check if this client is managed by a alias-client
if(!aliasclient)
reset_aliasclient(client);
return clientID;
}
@ -293,20 +293,20 @@ void change_clientcount(clientsData *client, int total, int blocked, int overTim
if(overTimeIdx > -1 && overTimeIdx < OVERTIME_SLOTS)
client->overTime[overTimeIdx] += overTimeMod;
// Also add counts to the conencted super-client (if any)
if(client->superclient)
// Also add counts to the conencted alias-client (if any)
if(client->aliasclient)
{
logg("WARN: Should not add to super-client directly (client \"%s\" (%s))!",
logg("WARN: Should not add to alias-client directly (client \"%s\" (%s))!",
getstr(client->namepos), getstr(client->ippos));
return;
}
if(client->superclient_id > -1)
if(client->aliasclient_id > -1)
{
clientsData *superclient = getClient(client->superclient_id, true);
superclient->count += total;
superclient->blockedcount += blocked;
clientsData *aliasclient = getClient(client->aliasclient_id, true);
aliasclient->count += total;
aliasclient->blockedcount += blocked;
if(overTimeIdx > -1 && overTimeIdx < OVERTIME_SLOTS)
superclient->overTime[overTimeIdx] += overTimeMod;
aliasclient->overTime[overTimeIdx] += overTimeMod;
}
}

View File

@ -56,10 +56,10 @@ typedef struct {
unsigned char hwaddr[16]; // See DHCP_CHADDR_MAX in dnsmasq/dhcp-protocol.h
bool new;
bool found_group;
bool superclient;
bool aliasclient;
int count;
int blockedcount;
int superclient_id;
int aliasclient_id;
int overTime[OVERTIME_SLOTS];
unsigned int numQueriesARP;
size_t groupspos;
@ -91,7 +91,7 @@ void strtolower(char *str);
int findQueryID(const int id);
int findUpstreamID(const char * upstream, const in_port_t port, const bool count);
int findDomainID(const char *domain, const bool count);
int findClientID(const char *client, const bool count, const bool superclient);
int findClientID(const char *client, const bool count, const bool aliasclient);
int findCacheID(int domainID, int clientID, enum query_types query_type);
bool isValidIPv4(const char *addr);
bool isValidIPv6(const char *addr);

View File

@ -136,7 +136,7 @@ enum debug_flags {
DEBUG_RESOLVER = (1 << 15), /* 00000000 00000000 10000000 00000000 */
DEBUG_EDNS0 = (1 << 16), /* 00000000 00000001 00000000 00000000 */
DEBUG_CLIENTS = (1 << 17), /* 00000000 00000010 00000000 00000000 */
DEBUG_SUPERCLIENTS = (1 << 18), /* 00000000 00000100 00000000 00000000 */
DEBUG_ALIASCLIENTS = (1 << 18), /* 00000000 00000100 00000000 00000000 */
DEBUG_EVENTS = (1 << 19), /* 00000000 00001000 00000000 00000000 */
DEBUG_HELPER = (1 << 20), /* 00000000 00010000 00000000 00000000 */
} __attribute__ ((packed));
@ -145,7 +145,7 @@ enum events {
RELOAD_GRAVITY,
RELOAD_PRIVACY_LEVEL,
RERESOLVE_HOSTNAMES,
REIMPORT_SUPERCLIENTS,
REIMPORT_ALIASCLIENTS,
PARSE_NEIGHBOR_CACHE,
RERESOLVE_DATABASE_NAMES,
EVENTS_MAX

View File

@ -92,8 +92,8 @@ static const char *eventtext(const enum events event)
return "RELOAD_PRIVACY_LEVEL";
case RERESOLVE_HOSTNAMES:
return "RERESOLVE_HOSTNAMES";
case REIMPORT_SUPERCLIENTS:
return "REIMPORT_SUPERCLIENTS";
case REIMPORT_ALIASCLIENTS:
return "REIMPORT_ALIASCLIENTS";
case PARSE_NEIGHBOR_CACHE:
return "PARSE_NEIGHBOR_CACHE";
case RERESOLVE_DATABASE_NAMES:

View File

@ -466,8 +466,8 @@ void read_regex_from_database(void)
{
// Get client pointer
clientsData *client = getClient(clientID, true);
// Skip invalid and super-clients
if(client == NULL || client->superclient)
// Skip invalid and alias-clients
if(client == NULL || client->aliasclient)
continue;
reload_per_client_regex(clientID, client);

View File

@ -362,8 +362,8 @@ static void resolveClients(const bool onlynew)
continue;
}
// Skip super-clients
if(client->superclient)
// Skip alias-clients
if(client->aliasclient)
{
unlock_shm();
continue;

View File

@ -278,8 +278,8 @@ static void SIGRT_handler(int signum, siginfo_t *si, void *unused)
}
else if(rtsig == 3)
{
// Reimport super-clients from database
set_event(REIMPORT_SUPERCLIENTS);
// Reimport alias-clients from database
set_event(REIMPORT_ALIASCLIENTS);
}
else if(rtsig == 4)
{

View File

@ -15,7 +15,7 @@ void handle_realtime_signals(void);
pid_t main_pid(void);
extern volatile sig_atomic_t killed;
extern volatile sig_atomic_t want_to_reimport_superclients;
extern volatile sig_atomic_t want_to_reimport_aliasclients;
extern volatile sig_atomic_t want_to_reload_lists;
#endif //SIGNALS_H

View File

@ -9,7 +9,7 @@ CREATE TABLE counters (id INTEGER PRIMARY KEY NOT NULL, value INTEGER NOT NULL);
INSERT INTO counters VALUES(0,21);
INSERT INTO counters VALUES(1,6);
CREATE TABLE message (id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp INTEGER NOT NULL, type TEXT NOT NULL, message TEXT NOT NULL, blob1 BLOB, blob2 BLOB, blob3 BLOB, blob4 BLOB, blob5 BLOB);
CREATE TABLE IF NOT EXISTS "network" (id INTEGER PRIMARY KEY NOT NULL, hwaddr TEXT UNIQUE NOT NULL, interface TEXT NOT NULL, firstSeen INTEGER NOT NULL, lastQuery INTEGER NOT NULL, numQueries INTEGER NOT NULL, macVendor TEXT, superclient_id INTEGER);
CREATE TABLE IF NOT EXISTS "network" (id INTEGER PRIMARY KEY NOT NULL, hwaddr TEXT UNIQUE NOT NULL, interface TEXT NOT NULL, firstSeen INTEGER NOT NULL, lastQuery INTEGER NOT NULL, numQueries INTEGER NOT NULL, macVendor TEXT, aliasclient_id INTEGER);
CREATE TABLE IF NOT EXISTS "network_addresses" (network_id INTEGER NOT NULL, ip TEXT UNIQUE NOT NULL, lastSeen INTEGER NOT NULL DEFAULT (cast(strftime('%s', 'now') as int)), name TEXT, nameUpdated INTEGER, FOREIGN KEY(network_id) REFERENCES network(id));
CREATE INDEX idx_queries_timestamps ON queries (timestamp);
@ -17,10 +17,10 @@ INSERT INTO "network" (id, hwaddr, interface, firstSeen, lastQuery, numQueries)
INSERT INTO "network_addresses" (network_id, ip) VALUES (0, '127.0.0.4');
INSERT INTO "network_addresses" (network_id, ip) VALUES (0, '127.0.0.5');
INSERT INTO "network" (id, hwaddr, interface, firstSeen, lastQuery, numQueries, superclient_id) VALUES (1, '00:11:22:33:44:55', 'enp0s123', 0, 0, 0, 0);
INSERT INTO "network" (id, hwaddr, interface, firstSeen, lastQuery, numQueries, aliasclient_id) VALUES (1, '00:11:22:33:44:55', 'enp0s123', 0, 0, 0, 0);
INSERT INTO "network_addresses" (network_id, ip) VALUES (1, '127.0.0.6');
CREATE TABLE superclient (id INTEGER PRIMARY KEY NOT NULL, name TEXT NOT NULL, comment TEXT);
INSERT INTO superclient (id, name) VALUES (0, 'some-superclient');
CREATE TABLE aliasclient (id INTEGER PRIMARY KEY NOT NULL, name TEXT NOT NULL, comment TEXT);
INSERT INTO aliasclient (id, name) VALUES (0, 'some-aliasclient');
COMMIT;
COMMIT;

View File

@ -293,7 +293,7 @@
[[ ${lines[1]} == "0 15 127.0.0.1 "* ]]
[[ ${lines[2]} == "1 4 127.0.0.3 "* ]]
[[ ${lines[3]} == "2 3 127.0.0.2 "* ]]
[[ ${lines[4]} == "3 1 superclient-0 some-superclient" ]]
[[ ${lines[4]} == "3 1 aliasclient-0 some-aliasclient" ]]
[[ ${lines[5]} == "4 1 127.0.0.4 "* ]]
[[ ${lines[6]} == "5 1 127.0.0.5 "* ]]
[[ ${lines[7]} == "" ]]
@ -450,10 +450,10 @@
[[ "${lines[@]}" == *"CREATE TABLE queries (id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp INTEGER NOT NULL, type INTEGER NOT NULL, status INTEGER NOT NULL, domain TEXT NOT NULL, client TEXT NOT NULL, forward TEXT, additional_info TEXT);"* ]]
[[ "${lines[@]}" == *"CREATE TABLE ftl (id INTEGER PRIMARY KEY NOT NULL, value BLOB NOT NULL);"* ]]
[[ "${lines[@]}" == *"CREATE TABLE counters (id INTEGER PRIMARY KEY NOT NULL, value INTEGER NOT NULL);"* ]]
[[ "${lines[@]}" == *"CREATE TABLE IF NOT EXISTS \"network\" (id INTEGER PRIMARY KEY NOT NULL, hwaddr TEXT UNIQUE NOT NULL, interface TEXT NOT NULL, firstSeen INTEGER NOT NULL, lastQuery INTEGER NOT NULL, numQueries INTEGER NOT NULL, macVendor TEXT, superclient_id INTEGER);"* ]]
[[ "${lines[@]}" == *"CREATE TABLE IF NOT EXISTS \"network\" (id INTEGER PRIMARY KEY NOT NULL, hwaddr TEXT UNIQUE NOT NULL, interface TEXT NOT NULL, firstSeen INTEGER NOT NULL, lastQuery INTEGER NOT NULL, numQueries INTEGER NOT NULL, macVendor TEXT, aliasclient_id INTEGER);"* ]]
[[ "${lines[@]}" == *"CREATE TABLE IF NOT EXISTS \"network_addresses\" (network_id INTEGER NOT NULL, ip TEXT UNIQUE NOT NULL, lastSeen INTEGER NOT NULL DEFAULT (cast(strftime('%s', 'now') as int)), name TEXT, nameUpdated INTEGER, FOREIGN KEY(network_id) REFERENCES network(id));"* ]]
[[ "${lines[@]}" == *"CREATE INDEX idx_queries_timestamps ON queries (timestamp);"* ]]
[[ "${lines[@]}" == *"CREATE TABLE superclient (id INTEGER PRIMARY KEY NOT NULL, name TEXT NOT NULL, comment TEXT);"* ]]
[[ "${lines[@]}" == *"CREATE TABLE aliasclient (id INTEGER PRIMARY KEY NOT NULL, name TEXT NOT NULL, comment TEXT);"* ]]
# Depending on the version of sqlite3, ftl can be enquoted or not...
[[ "${lines[@]}" == *"INSERT INTO"?*"ftl"?*"VALUES(0,9);"* ]]
}
@ -963,14 +963,14 @@
[[ "${lines[@]}" == *"**** new UDP query[A] query \"localhost\" from lo:fe80::b167:af1e:968b:dead "* ]]
}
@test "Super-client is imported and used for configured client" {
run bash -c 'grep -c "Added super-client \"some-superclient\" (superclient-0) with FTL ID 0" /var/log/pihole-FTL.log'
@test "alias-client is imported and used for configured client" {
run bash -c 'grep -c "Added alias-client \"some-aliasclient\" (aliasclient-0) with FTL ID 0" /var/log/pihole-FTL.log'
printf "Added: %s\n" "${lines[@]}"
[[ ${lines[0]} == "1" ]]
run bash -c 'grep -c "Superclient ID 127.0.0.6 -> 0" /var/log/pihole-FTL.log'
run bash -c 'grep -c "Aliasclient ID 127.0.0.6 -> 0" /var/log/pihole-FTL.log'
printf "Found ID: %s\n" "${lines[@]}"
[[ ${lines[0]} == "1" ]]
run bash -c 'grep -c "Client .* (127.0.0.6) IS managed by this super-client, adding counts" /var/log/pihole-FTL.log'
run bash -c 'grep -c "Client .* (127.0.0.6) IS managed by this alias-client, adding counts" /var/log/pihole-FTL.log'
printf "Adding counts: %s\n" "${lines[@]}"
[[ ${lines[0]} == "1" ]]
}