Merge branch 'development' into new/http

Signed-off-by: DL6ER <dl6er@dl6er.de>
This commit is contained in:
DL6ER 2021-01-15 19:34:07 +01:00
commit 262f62de2b
No known key found for this signature in database
GPG Key ID: 00135ACBD90B28DD
18 changed files with 37401 additions and 12464 deletions

View File

@ -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

View File

@ -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);
}

View File

@ -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
)

View File

@ -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));

View File

@ -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);

View File

@ -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;

21384
src/database/shell.c Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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)

View File

@ -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;

View File

@ -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);

View File

@ -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())

View File

@ -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

View File

@ -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);

View File

@ -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"

View File

@ -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;
}

View File

@ -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]" ]]
}