Merge branch 'development' into new/http
Signed-off-by: DL6ER <dl6er@dl6er.de>
This commit is contained in:
commit
262f62de2b
|
@ -26,7 +26,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
|
|||
# SQLITE_OMIT_PROGRESS_CALLBACK: The progress handler callback counter must be checked in the inner loop of the bytecode engine. By omitting this interface, a single conditional is removed from the inner loop of the bytecode engine, helping SQL statements to run slightly faster.
|
||||
# SQLITE_DEFAULT_FOREIGN_KEYS=1: This macro determines whether enforcement of foreign key constraints is enabled or disabled by default for new database connections.
|
||||
# SQLITE_DQS=0: This setting disables the double-quoted string literal misfeature.
|
||||
set(SQLITE_DEFINES "-DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_MEMORYDB -DSQLITE_DEFAULT_FOREIGN_KEYS=1 -DSQLITE_DQS=0")
|
||||
set(SQLITE_DEFINES "-DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_DEFAULT_FOREIGN_KEYS=1 -DSQLITE_DQS=0")
|
||||
|
||||
# Code hardening and debugging improvements
|
||||
# -fstack-protector-strong: The program will be resistant to having its stack overflowed
|
||||
|
|
26
src/args.c
26
src/args.c
|
@ -31,6 +31,9 @@
|
|||
// defined in dnsmasq.c
|
||||
extern void print_dnsmasq_version(void);
|
||||
|
||||
// defined in database/shell.c
|
||||
extern int sqlite3_shell_main(int argc, char **argv);
|
||||
|
||||
bool dnsmasq_debug = false;
|
||||
bool daemonmode = true, cli_mode = false;
|
||||
int argc_dnsmasq = 0;
|
||||
|
@ -40,6 +43,11 @@ static inline bool strEndsWith(const char *input, const char *end){
|
|||
return strcmp(input + strlen(input) - strlen(end), end) == 0;
|
||||
}
|
||||
|
||||
static void print_FTL_version(void)
|
||||
{
|
||||
printf("Pi-hole FTL %s %s\n", get_FTL_version(), GIT_DATE);
|
||||
}
|
||||
|
||||
void parse_args(int argc, char* argv[])
|
||||
{
|
||||
bool quiet = false;
|
||||
|
@ -61,6 +69,13 @@ void parse_args(int argc, char* argv[])
|
|||
if(strEndsWith(argv[0], "luac"))
|
||||
exit(run_luac(argc, argv));
|
||||
|
||||
if(strEndsWith(argv[0], "sqlite3"))
|
||||
{
|
||||
if(argc == 1) // No arguments after this one
|
||||
print_FTL_version();
|
||||
exit(sqlite3_shell_main(argc, argv));
|
||||
}
|
||||
|
||||
// start from 1, as argv[0] is the executable name
|
||||
for(int i = 1; i < argc; i++)
|
||||
{
|
||||
|
@ -80,6 +95,16 @@ void parse_args(int argc, char* argv[])
|
|||
exit(luac_main(argc - i, &argv[i]));
|
||||
}
|
||||
|
||||
// Expose embedded SQLite3 engine
|
||||
if(strcmp(argv[i], "sql") == 0 ||
|
||||
strcmp(argv[i], "sqlite3") == 0 ||
|
||||
strcmp(argv[i], "--sqlite3") == 0)
|
||||
{
|
||||
if(argc == i+1) // No arguments after this one
|
||||
print_FTL_version();
|
||||
exit(sqlite3_shell_main(argc - i, &argv[i]));
|
||||
}
|
||||
|
||||
// Implement dnsmasq's test function, no need to prepare the entire FTL
|
||||
// environment (initialize shared memory, lead queries from long-term
|
||||
// database, ...) when the task is a simple (dnsmasq) syntax check
|
||||
|
@ -285,6 +310,7 @@ void parse_args(int argc, char* argv[])
|
|||
printf("\t--luac, luac FTL's lua compiler\n");
|
||||
printf("\tdhcp-discover Discover DHCP servers in the local\n");
|
||||
printf("\t network\n");
|
||||
printf("\tsqlite3 FTL's SQLite3 shell\n");
|
||||
printf("\n\nOnline help: https://github.com/pi-hole/FTL\n");
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
# headers in the build command and thus does not need to be rebuilt when headers
|
||||
# are modified.
|
||||
set(sqlite3_sources
|
||||
shell.c
|
||||
sqlite3.c
|
||||
)
|
||||
|
||||
|
|
|
@ -792,7 +792,7 @@ char* __attribute__ ((malloc)) get_client_names_from_ids(const char *group_ids)
|
|||
}
|
||||
|
||||
// Prepare statements for scanning white- and blacklist as well as gravit for one client
|
||||
bool gravityDB_prepare_client_statements(const int clientID, clientsData *client)
|
||||
bool gravityDB_prepare_client_statements(clientsData *client)
|
||||
{
|
||||
// Return early if gravity database is not available
|
||||
if(!gravityDB_opened && !gravityDB_open())
|
||||
|
@ -825,7 +825,7 @@ bool gravityDB_prepare_client_statements(const int clientID, clientsData *client
|
|||
gravityDB_close();
|
||||
return false;
|
||||
}
|
||||
whitelist_stmt->set(whitelist_stmt, clientID, stmt);
|
||||
whitelist_stmt->set(whitelist_stmt, client->id, stmt);
|
||||
free(querystr);
|
||||
|
||||
// Prepare gravity statement
|
||||
|
@ -839,7 +839,7 @@ bool gravityDB_prepare_client_statements(const int clientID, clientsData *client
|
|||
gravityDB_close();
|
||||
return false;
|
||||
}
|
||||
gravity_stmt->set(gravity_stmt, clientID, stmt);
|
||||
gravity_stmt->set(gravity_stmt, client->id, stmt);
|
||||
free(querystr);
|
||||
|
||||
// Prepare blacklist statement
|
||||
|
@ -853,35 +853,35 @@ bool gravityDB_prepare_client_statements(const int clientID, clientsData *client
|
|||
gravityDB_close();
|
||||
return false;
|
||||
}
|
||||
blacklist_stmt->set(blacklist_stmt, clientID, stmt);
|
||||
blacklist_stmt->set(blacklist_stmt, client->id, stmt);
|
||||
free(querystr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Finalize non-NULL prepared statements and set them to NULL for a given client
|
||||
static inline void gravityDB_finalize_client_statements(const int clientID, clientsData *client)
|
||||
static inline void gravityDB_finalize_client_statements(clientsData *client)
|
||||
{
|
||||
if(config.debug & DEBUG_DATABASE)
|
||||
logg("Finalizing gravity statements for %s", getstr(client->ippos));
|
||||
|
||||
if(whitelist_stmt != NULL &&
|
||||
whitelist_stmt->get(whitelist_stmt, clientID) != NULL)
|
||||
whitelist_stmt->get(whitelist_stmt, client->id) != NULL)
|
||||
{
|
||||
sqlite3_finalize(whitelist_stmt->get(whitelist_stmt, clientID));
|
||||
whitelist_stmt->set(whitelist_stmt, clientID, NULL);
|
||||
sqlite3_finalize(whitelist_stmt->get(whitelist_stmt, client->id));
|
||||
whitelist_stmt->set(whitelist_stmt, client->id, NULL);
|
||||
}
|
||||
if(blacklist_stmt != NULL &&
|
||||
blacklist_stmt->get(blacklist_stmt, clientID) != NULL)
|
||||
blacklist_stmt->get(blacklist_stmt, client->id) != NULL)
|
||||
{
|
||||
sqlite3_finalize(blacklist_stmt->get(blacklist_stmt, clientID));
|
||||
blacklist_stmt->set(blacklist_stmt, clientID, NULL);
|
||||
sqlite3_finalize(blacklist_stmt->get(blacklist_stmt, client->id));
|
||||
blacklist_stmt->set(blacklist_stmt, client->id, NULL);
|
||||
}
|
||||
if(gravity_stmt != NULL &&
|
||||
gravity_stmt->get(gravity_stmt, clientID) != NULL)
|
||||
gravity_stmt->get(gravity_stmt, client->id) != NULL)
|
||||
{
|
||||
sqlite3_finalize(gravity_stmt->get(gravity_stmt, clientID));
|
||||
gravity_stmt->set(gravity_stmt, clientID, NULL);
|
||||
sqlite3_finalize(gravity_stmt->get(gravity_stmt, client->id));
|
||||
gravity_stmt->set(gravity_stmt, client->id, NULL);
|
||||
}
|
||||
|
||||
// Unset group found property to trigger a check next time the
|
||||
|
@ -903,7 +903,7 @@ void gravityDB_close(void)
|
|||
for(int clientID = 0; clientID < counters->clients; clientID++)
|
||||
{
|
||||
clientsData *client = getClient(clientID, true);
|
||||
gravityDB_finalize_client_statements(clientID, client);
|
||||
gravityDB_finalize_client_statements(client);
|
||||
}
|
||||
|
||||
// Free allocated memory for vectors of prepared client statements
|
||||
|
@ -1169,9 +1169,19 @@ static bool domain_in_list(const char *domain, sqlite3_stmt* stmt, const char* l
|
|||
return (result == 1);
|
||||
}
|
||||
|
||||
void gravityDB_reload_groups(clientsData* client)
|
||||
{
|
||||
// Rebuild client table statements (possibly from a different group set)
|
||||
gravityDB_finalize_client_statements(client);
|
||||
gravityDB_prepare_client_statements(client);
|
||||
|
||||
// Reload regex for this client (possibly from a different group set)
|
||||
reload_per_client_regex(client);
|
||||
}
|
||||
|
||||
// Check if this client needs a rechecking of group membership
|
||||
// This client may be identified by something that wasn't there on its first query (hostname, MAC address, interface)
|
||||
static void gravityDB_client_check_again(const int clientID, clientsData* client)
|
||||
static void gravityDB_client_check_again(clientsData* client)
|
||||
{
|
||||
const time_t diff = time(NULL) - client->firstSeen;
|
||||
const unsigned char check_count = client->reread_groups + 1u;
|
||||
|
@ -1182,17 +1192,11 @@ static void gravityDB_client_check_again(const int clientID, clientsData* client
|
|||
logg("Reloading client groups after %u seconds (%u%s check)",
|
||||
(unsigned int)diff, check_count, ord);
|
||||
client->reread_groups++;
|
||||
|
||||
// Rebuild client table statements (possibly from a different group set)
|
||||
gravityDB_finalize_client_statements(clientID, client);
|
||||
gravityDB_prepare_client_statements(clientID, client);
|
||||
|
||||
// Reload regex for this client (possibly from a different group set)
|
||||
reload_per_client_regex(clientID, client);
|
||||
gravityDB_reload_groups(client);
|
||||
}
|
||||
}
|
||||
|
||||
bool in_whitelist(const char *domain, const DNSCacheData *dns_cache, const int clientID, clientsData* client)
|
||||
bool in_whitelist(const char *domain, const DNSCacheData *dns_cache, clientsData* client)
|
||||
{
|
||||
// If list statement is not ready and cannot be initialized (e.g. no
|
||||
// access to the database), we return false to prevent an FTL crash
|
||||
|
@ -1200,14 +1204,14 @@ bool in_whitelist(const char *domain, const DNSCacheData *dns_cache, const int c
|
|||
return false;
|
||||
|
||||
// Check if this client needs a rechecking of group membership
|
||||
gravityDB_client_check_again(clientID, client);
|
||||
gravityDB_client_check_again(client);
|
||||
|
||||
// Get whitelist statement from vector of prepared statements if available
|
||||
sqlite3_stmt *stmt = whitelist_stmt->get(whitelist_stmt, clientID);
|
||||
sqlite3_stmt *stmt = whitelist_stmt->get(whitelist_stmt, client->id);
|
||||
|
||||
// If client statement is not ready and cannot be initialized (e.g. no access to
|
||||
// the database), we return false (not in whitelist) to prevent an FTL crash
|
||||
if(stmt == NULL && !gravityDB_prepare_client_statements(clientID, client))
|
||||
if(stmt == NULL && !gravityDB_prepare_client_statements(client))
|
||||
{
|
||||
logg("ERROR: Gravity database not available, assuming domain is not whitelisted");
|
||||
return false;
|
||||
|
@ -1216,7 +1220,7 @@ bool in_whitelist(const char *domain, const DNSCacheData *dns_cache, const int c
|
|||
// Update statement if has just been initialized
|
||||
if(stmt == NULL)
|
||||
{
|
||||
stmt = whitelist_stmt->get(whitelist_stmt, clientID);
|
||||
stmt = whitelist_stmt->get(whitelist_stmt, client->id);
|
||||
}
|
||||
|
||||
// We have to check both the exact whitelist (using a prepared database statement)
|
||||
|
@ -1226,10 +1230,10 @@ bool in_whitelist(const char *domain, const DNSCacheData *dns_cache, const int c
|
|||
// optimization as the database lookup will most likely hit (a) more domains and (b)
|
||||
// will be faster (given a sufficiently large number of regex whitelisting filters).
|
||||
return domain_in_list(domain, stmt, "whitelist") ||
|
||||
match_regex(domain, dns_cache, clientID, REGEX_WHITELIST, false) != -1;
|
||||
match_regex(domain, dns_cache, client->id, REGEX_WHITELIST, false) != -1;
|
||||
}
|
||||
|
||||
bool in_gravity(const char *domain, const int clientID, clientsData* client)
|
||||
bool in_gravity(const char *domain, clientsData* client)
|
||||
{
|
||||
// If list statement is not ready and cannot be initialized (e.g. no
|
||||
// access to the database), we return false to prevent an FTL crash
|
||||
|
@ -1237,14 +1241,14 @@ bool in_gravity(const char *domain, const int clientID, clientsData* client)
|
|||
return false;
|
||||
|
||||
// Check if this client needs a rechecking of group membership
|
||||
gravityDB_client_check_again(clientID, client);
|
||||
gravityDB_client_check_again(client);
|
||||
|
||||
// Get whitelist statement from vector of prepared statements
|
||||
sqlite3_stmt *stmt = gravity_stmt->get(gravity_stmt, clientID);
|
||||
sqlite3_stmt *stmt = gravity_stmt->get(gravity_stmt, client->id);
|
||||
|
||||
// If client statement is not ready and cannot be initialized (e.g. no access to
|
||||
// the database), we return false (not in gravity list) to prevent an FTL crash
|
||||
if(stmt == NULL && !gravityDB_prepare_client_statements(clientID, client))
|
||||
if(stmt == NULL && !gravityDB_prepare_client_statements(client))
|
||||
{
|
||||
logg("ERROR: Gravity database not available, assuming domain is not gravity blocked");
|
||||
return false;
|
||||
|
@ -1253,13 +1257,13 @@ bool in_gravity(const char *domain, const int clientID, clientsData* client)
|
|||
// Update statement if has just been initialized
|
||||
if(stmt == NULL)
|
||||
{
|
||||
stmt = gravity_stmt->get(gravity_stmt, clientID);
|
||||
stmt = gravity_stmt->get(gravity_stmt, client->id);
|
||||
}
|
||||
|
||||
return domain_in_list(domain, stmt, "gravity");
|
||||
}
|
||||
|
||||
inline bool in_blacklist(const char *domain, const int clientID, clientsData* client)
|
||||
inline bool in_blacklist(const char *domain, clientsData* client)
|
||||
{
|
||||
// If list statement is not ready and cannot be initialized (e.g. no
|
||||
// access to the database), we return false to prevent an FTL crash
|
||||
|
@ -1267,14 +1271,14 @@ inline bool in_blacklist(const char *domain, const int clientID, clientsData* cl
|
|||
return false;
|
||||
|
||||
// Check if this client needs a rechecking of group membership
|
||||
gravityDB_client_check_again(clientID, client);
|
||||
gravityDB_client_check_again(client);
|
||||
|
||||
// Get whitelist statement from vector of prepared statements
|
||||
sqlite3_stmt *stmt = blacklist_stmt->get(blacklist_stmt, clientID);
|
||||
sqlite3_stmt *stmt = blacklist_stmt->get(blacklist_stmt, client->id);
|
||||
|
||||
// If client statement is not ready and cannot be initialized (e.g. no access to
|
||||
// the database), we return false (not in blacklist) to prevent an FTL crash
|
||||
if(stmt == NULL && !gravityDB_prepare_client_statements(clientID, client))
|
||||
if(stmt == NULL && !gravityDB_prepare_client_statements(client))
|
||||
{
|
||||
logg("ERROR: Gravity database not available, assuming domain is not blacklisted");
|
||||
return false;
|
||||
|
@ -1283,7 +1287,7 @@ inline bool in_blacklist(const char *domain, const int clientID, clientsData* cl
|
|||
// Update statement if has just been initialized
|
||||
if(stmt == NULL)
|
||||
{
|
||||
stmt = blacklist_stmt->get(blacklist_stmt, clientID);
|
||||
stmt = blacklist_stmt->get(blacklist_stmt, client->id);
|
||||
}
|
||||
|
||||
return domain_in_list(domain, stmt, "blacklist");
|
||||
|
@ -1301,10 +1305,10 @@ bool in_auditlist(const char *domain)
|
|||
}
|
||||
|
||||
bool gravityDB_get_regex_client_groups(clientsData* client, const unsigned int numregex, const regex_data *regex,
|
||||
const unsigned char type, const char* table, const int clientID)
|
||||
const unsigned char type, const char* table)
|
||||
{
|
||||
if(config.debug & DEBUG_REGEX)
|
||||
logg("Getting regex client groups for client with ID %i", clientID);
|
||||
logg("Getting regex client groups for client with ID %i", client->id);
|
||||
|
||||
char *querystr = NULL;
|
||||
if(!client->found_group && !get_client_groupids(client))
|
||||
|
@ -1341,7 +1345,7 @@ bool gravityDB_get_regex_client_groups(clientsData* client, const unsigned int n
|
|||
// Regular expressions are stored in one array
|
||||
if(type == REGEX_WHITELIST)
|
||||
regexID += get_num_regex(REGEX_BLACKLIST);
|
||||
set_per_client_regex(clientID, regexID, true);
|
||||
set_per_client_regex(client->id, regexID, true);
|
||||
|
||||
if(config.debug & DEBUG_REGEX)
|
||||
logg("Regex %s: Enabling regex with DB ID %i for client %s", regextype[type], result, getstr(client->ippos));
|
||||
|
|
|
@ -38,7 +38,8 @@ typedef struct {
|
|||
void gravityDB_forked(void);
|
||||
void gravityDB_reopen(void);
|
||||
bool gravityDB_open(void);
|
||||
bool gravityDB_prepare_client_statements(const int clientID, clientsData* client);
|
||||
void gravityDB_reload_groups(clientsData* client);
|
||||
bool gravityDB_prepare_client_statements(clientsData* client);
|
||||
void gravityDB_close(void);
|
||||
bool gravityDB_getTable(unsigned char list);
|
||||
const char* gravityDB_getDomain(int *rowid);
|
||||
|
@ -47,12 +48,12 @@ void gravityDB_finalizeTable(void);
|
|||
int gravityDB_count(const enum gravity_tables list);
|
||||
bool in_auditlist(const char *domain);
|
||||
|
||||
bool in_gravity(const char *domain, const int clientID, clientsData* client);
|
||||
bool in_blacklist(const char *domain, const int clientID, clientsData* client);
|
||||
bool in_whitelist(const char *domain, const DNSCacheData *dns_cache, const int clientID, clientsData* client);
|
||||
bool in_gravity(const char *domain, clientsData* client);
|
||||
bool in_blacklist(const char *domain, clientsData* client);
|
||||
bool in_whitelist(const char *domain, const DNSCacheData *dns_cache, clientsData* client);
|
||||
|
||||
bool gravityDB_get_regex_client_groups(clientsData* client, const unsigned int numregex, const regex_data *regex,
|
||||
const unsigned char type, const char* table, const int clientID);
|
||||
const unsigned char type, const char* table);
|
||||
|
||||
bool gravityDB_readTable(const enum gravity_list_type listtype, const char *filter, const char **message);
|
||||
bool gravityDB_readTableGetRow(tablerow *row, const char **message);
|
||||
|
|
|
@ -124,8 +124,17 @@ void DB_save_queries(void)
|
|||
// TIMESTAMP
|
||||
sqlite3_bind_int(stmt, 1, query->timestamp);
|
||||
|
||||
// TYPE (stored incremented by one so A = 1, AAAA = 2, ... for legacy reasons)
|
||||
sqlite3_bind_int(stmt, 2, query->type+1);
|
||||
// TYPE
|
||||
if(query->type != TYPE_OTHER)
|
||||
{
|
||||
// Store mapped type if query->type is not OTHER
|
||||
sqlite3_bind_int(stmt, 2, query->type);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Store query type + offset if query-> type is OTHER
|
||||
sqlite3_bind_int(stmt, 2, query->qtype + 100);
|
||||
}
|
||||
|
||||
// STATUS
|
||||
sqlite3_bind_int(stmt, 3, query->status);
|
||||
|
@ -344,7 +353,9 @@ void DB_read_queries(void)
|
|||
}
|
||||
|
||||
const int type = sqlite3_column_int(stmt, 2);
|
||||
if(type < TYPE_A || type >= TYPE_MAX)
|
||||
const bool mapped_type = type >= TYPE_A && type < TYPE_MAX;
|
||||
const bool offset_type = type > 100 && type < (100 + UINT16_MAX);
|
||||
if(!mapped_type && !offset_type)
|
||||
{
|
||||
logg("FTL_db warn: TYPE should not be %i", type);
|
||||
continue;
|
||||
|
@ -423,7 +434,18 @@ void DB_read_queries(void)
|
|||
queriesData* query = getQuery(queryIndex, false);
|
||||
query->magic = MAGICBYTE;
|
||||
query->timestamp = queryTimeStamp;
|
||||
query->type = type - 1; // The type is stored incremented by one so A = 1, AAAA = 2, ... for legacy reasons
|
||||
if(type < 100)
|
||||
{
|
||||
// Mapped query type
|
||||
query->type = type;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Offset query type
|
||||
query->type = TYPE_OTHER;
|
||||
query->qtype = type - 100;
|
||||
}
|
||||
|
||||
query->status = status;
|
||||
query->domainID = domainID;
|
||||
query->clientID = clientID;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
26557
src/database/sqlite3.c
26557
src/database/sqlite3.c
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -275,6 +275,9 @@ int findClientID(const char *clientIP, const bool count, const bool aliasclient)
|
|||
// Initialize client-specific overTime data
|
||||
memset(client->overTime, 0, sizeof(client->overTime));
|
||||
|
||||
// Store client ID
|
||||
client->id = clientID;
|
||||
|
||||
// Increase counter by one
|
||||
counters->clients++;
|
||||
|
||||
|
@ -287,7 +290,7 @@ int findClientID(const char *clientIP, const bool count, const bool aliasclient)
|
|||
// during history reading get their enabled regexs reloaded
|
||||
// in the initial call to FTL_reload_all_domainlists()
|
||||
if(!startup && !aliasclient)
|
||||
reload_per_client_regex(clientID, client);
|
||||
reload_per_client_regex(client);
|
||||
|
||||
// Check if this client is managed by a alias-client
|
||||
if(!aliasclient)
|
||||
|
|
|
@ -25,16 +25,17 @@ typedef struct {
|
|||
enum privacy_level privacylevel;
|
||||
enum reply_type reply;
|
||||
enum dnssec_status dnssec;
|
||||
time_t timestamp;
|
||||
uint16_t qtype;
|
||||
int domainID;
|
||||
int clientID;
|
||||
int upstreamID;
|
||||
int id; // the ID is a (signed) int in dnsmasq, so no need for a long int here
|
||||
int CNAME_domainID; // only valid if query has a CNAME blocking status
|
||||
unsigned int timeidx;
|
||||
unsigned long response; // saved in units of 1/10 milliseconds (1 = 0.1ms, 2 = 0.2ms, 2500 = 250.0ms, etc.)
|
||||
unsigned long forwardresponse; // saved in units of 1/10 milliseconds (1 = 0.1ms, 2 = 0.2ms, 2500 = 250.0ms, etc.)
|
||||
time_t timestamp;
|
||||
int64_t db;
|
||||
unsigned int timeidx;
|
||||
bool whitelisted;
|
||||
bool complete;
|
||||
} queriesData;
|
||||
|
@ -65,6 +66,7 @@ typedef struct {
|
|||
int blockedcount;
|
||||
int aliasclient_id;
|
||||
int overTime[OVERTIME_SLOTS];
|
||||
unsigned int id;
|
||||
unsigned int numQueriesARP;
|
||||
size_t groupspos;
|
||||
size_t ippos;
|
||||
|
|
|
@ -1966,7 +1966,7 @@ static void check_dns_listeners(time_t now)
|
|||
fcntl(confd, F_SETFL, flags & ~O_NONBLOCK);
|
||||
|
||||
/******* Pi-hole modification *******/
|
||||
FTL_TCP_worker_created(confd, iface->name);
|
||||
FTL_TCP_worker_created(confd, iface != NULL ? iface->name : NULL);
|
||||
/************************************/
|
||||
|
||||
buff = tcp_request(confd, now, &tcp_addr, netmask, auth_dns);
|
||||
|
|
|
@ -91,7 +91,7 @@ static bool check_domain_blocked(const char *domain, const int clientID,
|
|||
// Check domains against exact blacklist
|
||||
// Skipped when the domain is whitelisted
|
||||
bool blockDomain = false;
|
||||
if(in_blacklist(domain, clientID, client))
|
||||
if(in_blacklist(domain, client))
|
||||
{
|
||||
// We block this domain
|
||||
blockDomain = true;
|
||||
|
@ -106,7 +106,7 @@ static bool check_domain_blocked(const char *domain, const int clientID,
|
|||
// Check domains against gravity domains
|
||||
// Skipped when the domain is whitelisted or blocked by exact blacklist
|
||||
if(!query->whitelisted && !blockDomain &&
|
||||
in_gravity(domain, clientID, client))
|
||||
in_gravity(domain, client))
|
||||
{
|
||||
// We block this domain
|
||||
blockDomain = true;
|
||||
|
@ -122,7 +122,7 @@ static bool check_domain_blocked(const char *domain, const int clientID,
|
|||
// Skipped when the domain is whitelisted or blocked by exact blacklist or gravity
|
||||
int regex_idx = 0;
|
||||
if(!query->whitelisted && !blockDomain &&
|
||||
(regex_idx = match_regex(domain, dns_cache, clientID, REGEX_BLACKLIST, false)) > -1)
|
||||
(regex_idx = match_regex(domain, dns_cache, client->id, REGEX_BLACKLIST, false)) > -1)
|
||||
{
|
||||
// We block this domain
|
||||
blockDomain = true;
|
||||
|
@ -281,7 +281,7 @@ static bool _FTL_check_blocking(int queryID, int domainID, int clientID, const c
|
|||
const char *blockedDomain = domainstr;
|
||||
|
||||
// Check whitelist (exact + regex) for match
|
||||
query->whitelisted = in_whitelist(domainstr, dns_cache, clientID, client);
|
||||
query->whitelisted = in_whitelist(domainstr, dns_cache, client);
|
||||
|
||||
bool blockDomain = false;
|
||||
unsigned char new_status = QUERY_UNKNOWN;
|
||||
|
@ -627,6 +627,7 @@ bool _FTL_new_query(const unsigned int flags, const char *name,
|
|||
query->magic = MAGICBYTE;
|
||||
query->timestamp = querytimestamp;
|
||||
query->type = querytype;
|
||||
query->qtype = qtype;
|
||||
query->status = QUERY_UNKNOWN;
|
||||
query->domainID = domainID;
|
||||
query->clientID = clientID;
|
||||
|
@ -677,9 +678,33 @@ bool _FTL_new_query(const unsigned int flags, const char *name,
|
|||
client->lastQuery = querytimestamp;
|
||||
client->numQueriesARP++;
|
||||
|
||||
// Store interface information in client data (if available)
|
||||
if(client->ifacepos == 0u && next_iface != NULL)
|
||||
client->ifacepos = addstr(next_iface);
|
||||
// Preocess interface information of client (if available)
|
||||
if(next_iface != NULL)
|
||||
{
|
||||
if(client->ifacepos == 0u)
|
||||
{
|
||||
// Store in the client data if unknown so far
|
||||
client->ifacepos = addstr(next_iface);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check if this is still the same interface or
|
||||
// if the client moved to another interface
|
||||
// (may require group re-processing)
|
||||
const char *oldiface = getstr(client->ifacepos);
|
||||
if(strcasecmp(oldiface, next_iface) != 0)
|
||||
{
|
||||
if(config.debug & DEBUG_CLIENTS)
|
||||
{
|
||||
const char *clientName = getstr(client->namepos);
|
||||
logg("Client %s (%s) changed interface: %s -> %s",
|
||||
clientIP, clientName, oldiface, next_iface);
|
||||
}
|
||||
|
||||
gravityDB_reload_groups(client);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set client MAC address from EDNS(0) information (if available)
|
||||
if(config.edns0_ecs && edns->mac_set)
|
||||
|
@ -2093,8 +2118,11 @@ void FTL_TCP_worker_created(const int confd, const char *iface_name)
|
|||
inet_ntop(iface_sockaddr.sa.sa_family, &iface_addr, local_ip, ADDRSTRLEN);
|
||||
}
|
||||
|
||||
// Substitute interface name if not available
|
||||
if(iface_name == NULL)
|
||||
iface_name = "N/A (iface is NULL)";
|
||||
// Print log
|
||||
logg("TCP worker forked for client %s on interface %s (%s)", peer_ip, iface_name, local_ip);
|
||||
logg("TCP worker forked for client %s on interface %s with IP %s", peer_ip, iface_name, local_ip);
|
||||
}
|
||||
|
||||
if(main_pid() == getpid())
|
||||
|
|
12
src/regex.c
12
src/regex.c
|
@ -416,25 +416,25 @@ static void free_regex(void)
|
|||
// 1. Allocate additional memory if required
|
||||
// 2. Reset all regex to false for this client
|
||||
// 3. Load regex enabled/disabled state
|
||||
void reload_per_client_regex(const int clientID, clientsData *client)
|
||||
void reload_per_client_regex(clientsData *client)
|
||||
{
|
||||
// Ensure there is enough memory in the shared memory object
|
||||
add_per_client_regex(clientID);
|
||||
add_per_client_regex(client->id);
|
||||
|
||||
// Zero-initialize (or wipe previous) regex
|
||||
reset_per_client_regex(clientID);
|
||||
reset_per_client_regex(client->id);
|
||||
|
||||
// Load regex per-group regex blacklist for this client
|
||||
if(num_regex[REGEX_BLACKLIST] > 0)
|
||||
gravityDB_get_regex_client_groups(client, num_regex[REGEX_BLACKLIST],
|
||||
black_regex, REGEX_BLACKLIST,
|
||||
"vw_regex_blacklist", clientID);
|
||||
"vw_regex_blacklist");
|
||||
|
||||
// Load regex per-group regex whitelist for this client
|
||||
if(num_regex[REGEX_WHITELIST] > 0)
|
||||
gravityDB_get_regex_client_groups(client, num_regex[REGEX_WHITELIST],
|
||||
white_regex, REGEX_WHITELIST,
|
||||
"vw_regex_whitelist", clientID);
|
||||
"vw_regex_whitelist");
|
||||
}
|
||||
|
||||
static void read_regex_table(const enum regex_type regexid)
|
||||
|
@ -557,7 +557,7 @@ void read_regex_from_database(void)
|
|||
if(client == NULL || client->aliasclient)
|
||||
continue;
|
||||
|
||||
reload_per_client_regex(clientID, client);
|
||||
reload_per_client_regex(client);
|
||||
}
|
||||
|
||||
// Print message to FTL's log after reloading regex filters
|
||||
|
|
|
@ -42,7 +42,7 @@ unsigned int get_num_regex(const enum regex_type regexid) __attribute__((pure));
|
|||
int match_regex(const char *input, const DNSCacheData* dns_cache, const int clientID,
|
||||
const enum regex_type regexid, const bool regextest);
|
||||
void allocate_regex_client_enabled(clientsData *client, const int clientID);
|
||||
void reload_per_client_regex(const int clientID, clientsData *client);
|
||||
void reload_per_client_regex(clientsData *client);
|
||||
void read_regex_from_database(void);
|
||||
|
||||
int regex_test(const bool debug_mode, const bool quiet, const char *domainin, const char *regexin);
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include "daemon.h"
|
||||
|
||||
/// The version of shared memory used
|
||||
#define SHARED_MEMORY_VERSION 10
|
||||
#define SHARED_MEMORY_VERSION 11
|
||||
|
||||
/// The name of the shared memory. Use this when connecting to the shared memory.
|
||||
#define SHMEM_PATH "/dev/shm"
|
||||
|
|
|
@ -19,19 +19,21 @@ int FTLfallocate(const int fd, const off_t offset, const off_t len, const char *
|
|||
int ret = 0;
|
||||
do
|
||||
{
|
||||
// Reset errno before trying to write
|
||||
errno = 0;
|
||||
// posix_fallocate directly returns errno and doesn't set the
|
||||
// actual errno system global
|
||||
ret = posix_fallocate(fd, offset, len);
|
||||
}
|
||||
// Try again if the last posix_fallocate() call failed due to an
|
||||
// interruption by an incoming signal
|
||||
while(ret < 0 && errno == EINTR);
|
||||
while(ret == EINTR);
|
||||
|
||||
// Final error checking (may have faild for some other reason then an
|
||||
// EINTR = interrupted system call)
|
||||
if(ret < 0)
|
||||
if(ret > 0)
|
||||
logg("WARN: Could not fallocate() in %s() (%s:%i): %s",
|
||||
func, file, line, strerror(errno));
|
||||
func, file, line, strerror(ret));
|
||||
|
||||
return ret;
|
||||
}
|
||||
// Set errno ourselves as posix_fallocate doesn't do it
|
||||
errno = ret;
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -859,3 +859,9 @@
|
|||
printf "%s\n" "${lines[@]}"
|
||||
[[ "${lines[@]}" == *"EDNS(0) CLIENT SUBNET: Skipped ::1/128 (IPv6 loopback address)"* ]]
|
||||
}
|
||||
|
||||
@test "Embedded SQLite3 shell available and functional" {
|
||||
run bash -c './pihole-FTL sqlite3 -help'
|
||||
printf "%s\n" "${lines[@]}"
|
||||
[[ ${lines[0]} == "Usage: sqlite3 [OPTIONS] FILENAME [SQL]" ]]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue