Merge branch 'development' into new/super-clients
Signed-off-by: DL6ER <dl6er@dl6er.de>
This commit is contained in:
commit
6f6ae518d2
|
@ -3,52 +3,76 @@ version: 2
|
|||
.job_steps: &job_steps
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: "Setup"
|
||||
command: |
|
||||
if [[ $CIRCLE_JOB == *"qemu"* ]] ; then sudo docker run --rm --privileged multiarch/qemu-user-static:register --reset ; fi
|
||||
- run:
|
||||
name: "Build"
|
||||
no_output_timeout: 30m
|
||||
command: |
|
||||
BRANCH=$([ -z "$CIRCLE_TAG" ] && echo "$CIRCLE_BRANCH" || echo "master")
|
||||
[[ $CIRCLE_JOB == *"qemu"* ]] && DOCKERIFNEEDED="docker run --rm -v $(pwd):/workspace -w /workspace pihole/ftl-build:arm-qemu "
|
||||
$DOCKERIFNEEDED bash .circleci/build-CI.sh "${STATIC}" "${BRANCH}" "${CIRCLE_TAG}" "${CIRCLE_JOB}"
|
||||
bash .circleci/build-CI.sh "${STATIC}" "${BRANCH}" "${CIRCLE_TAG}" "${CIRCLE_JOB}"
|
||||
- run:
|
||||
name: "Binary checks"
|
||||
command: bash test/arch_test.sh
|
||||
- run:
|
||||
name: "Upload"
|
||||
name: "Compute checksum"
|
||||
command: |
|
||||
mv pihole-FTL "${BIN_NAME}"
|
||||
sha1sum pihole-FTL-* > ${BIN_NAME}.sha1
|
||||
- run:
|
||||
name: "Upload binary to binary bucket"
|
||||
command: |
|
||||
[ -z "${CIRCLE_PR_USERNAME}" ] || exit 0
|
||||
DIR="${CIRCLE_TAG:-${CIRCLE_BRANCH}}"
|
||||
mv pihole-FTL "${BIN_NAME}"
|
||||
sha1sum pihole-FTL-* > ${BIN_NAME}.sha1
|
||||
mkdir -p ~/.ssh/
|
||||
ssh-keyscan -H $SSH_HOST >> ~/.ssh/known_hosts
|
||||
sftp -b - $SSH_USER@$SSH_HOST <<< "-mkdir ${DIR}
|
||||
put ${BIN_NAME}* ${DIR}"
|
||||
mv "${BIN_NAME}" pihole-FTL
|
||||
sftp -b - $SSH_USER@$SSH_HOST <<< "-mkdir html/${DIR}
|
||||
put ${BIN_NAME}* html/${DIR}"
|
||||
- run:
|
||||
name: "Verify uploaded binary"
|
||||
command: |
|
||||
[ -z "${CIRCLE_PR_USERNAME}" ] || exit 0
|
||||
DIR="${CIRCLE_TAG:-${CIRCLE_BRANCH}}"
|
||||
mkdir download
|
||||
cd download
|
||||
wget "https://ftl.pi-hole.net/${DIR}/${BIN_NAME}"
|
||||
wget "https://ftl.pi-hole.net/${DIR}/${BIN_NAME}.sha1"
|
||||
sha1sum -c "${BIN_NAME}.sha1"
|
||||
cd ..
|
||||
- run:
|
||||
name: "Test"
|
||||
command: |
|
||||
mv "${BIN_NAME}" pihole-FTL
|
||||
test/run.sh
|
||||
|
||||
.docker_template: &docker_template
|
||||
docker:
|
||||
- image: pihole/ftl-build:v1.3-$CIRCLE_JOB
|
||||
- image: pihole/ftl-build:v1.7-$CIRCLE_JOB
|
||||
<<: *job_steps
|
||||
|
||||
jobs:
|
||||
arm:
|
||||
armv4t:
|
||||
<<: *docker_template
|
||||
environment:
|
||||
BIN_NAME: "pihole-FTL-arm-linux-gnueabi"
|
||||
BIN_NAME: "pihole-FTL-armv4-linux-gnueabi"
|
||||
|
||||
armhf:
|
||||
armv5te:
|
||||
<<: *docker_template
|
||||
environment:
|
||||
BIN_NAME: "pihole-FTL-arm-linux-gnueabihf"
|
||||
BIN_NAME: "pihole-FTL-armv5-linux-gnueabi"
|
||||
|
||||
armv6hf:
|
||||
<<: *docker_template
|
||||
environment:
|
||||
BIN_NAME: "pihole-FTL-armv6-linux-gnueabihf"
|
||||
|
||||
armv7hf:
|
||||
<<: *docker_template
|
||||
environment:
|
||||
BIN_NAME: "pihole-FTL-armv7-linux-gnueabihf"
|
||||
|
||||
armv8a:
|
||||
<<: *docker_template
|
||||
environment:
|
||||
BIN_NAME: "pihole-FTL-armv8-linux-gnueabihf"
|
||||
|
||||
aarch64:
|
||||
<<: *docker_template
|
||||
|
@ -70,26 +94,27 @@ jobs:
|
|||
environment:
|
||||
BIN_NAME: "pihole-FTL-linux-x86_32"
|
||||
|
||||
arm-qemu:
|
||||
machine:
|
||||
enabled: true
|
||||
environment:
|
||||
BIN_NAME: "pihole-FTL-armel-native"
|
||||
<<: *job_steps
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
build:
|
||||
jobs:
|
||||
- arm:
|
||||
- armv4t:
|
||||
filters:
|
||||
tags:
|
||||
only: /^v.*/
|
||||
- arm-qemu:
|
||||
- armv5te:
|
||||
filters:
|
||||
tags:
|
||||
only: /^v.*/
|
||||
- armhf:
|
||||
- armv6hf:
|
||||
filters:
|
||||
tags:
|
||||
only: /^v.*/
|
||||
- armv7hf:
|
||||
filters:
|
||||
tags:
|
||||
only: /^v.*/
|
||||
- armv8a:
|
||||
filters:
|
||||
tags:
|
||||
only: /^v.*/
|
||||
|
|
|
@ -199,7 +199,7 @@ find_program(SETCAP setcap)
|
|||
install(TARGETS pihole-FTL
|
||||
RUNTIME DESTINATION bin
|
||||
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
|
||||
install(CODE "execute_process(COMMAND ${SETCAP} CAP_NET_BIND_SERVICE,CAP_NET_RAW,CAP_NET_ADMIN+eip \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/bin/pihole-FTL)")
|
||||
install(CODE "execute_process(COMMAND ${SETCAP} CAP_NET_BIND_SERVICE,CAP_NET_RAW,CAP_NET_ADMIN,CAP_SYS_NICE+eip \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/bin/pihole-FTL)")
|
||||
|
||||
add_subdirectory(api)
|
||||
add_subdirectory(database)
|
||||
|
|
|
@ -125,6 +125,10 @@
|
|||
#define calloc(numer_of_elements, element_size) FTLcalloc(numer_of_elements, element_size, __FILE__, __FUNCTION__, __LINE__)
|
||||
#define realloc(ptr, new_size) FTLrealloc(ptr, new_size, __FILE__, __FUNCTION__, __LINE__)
|
||||
|
||||
// Preprocessor help functions
|
||||
#define str(x) # x
|
||||
#define xstr(x) str(x)
|
||||
|
||||
extern pthread_t telnet_listenthreadv4;
|
||||
extern pthread_t telnet_listenthreadv6;
|
||||
extern pthread_t socket_listenthread;
|
||||
|
|
|
@ -525,6 +525,7 @@ void getUpstreamDestinations(const char *client_message, const int *sock)
|
|||
{
|
||||
float percentage = 0.0f;
|
||||
const char* ip, *name;
|
||||
in_port_t upstream_port = 0;
|
||||
|
||||
if(i == -2)
|
||||
{
|
||||
|
@ -548,7 +549,7 @@ void getUpstreamDestinations(const char *client_message, const int *sock)
|
|||
}
|
||||
else
|
||||
{
|
||||
// Regular forward destionation
|
||||
// Regular upstream destination
|
||||
// Get sorted indices
|
||||
int upstreamID;
|
||||
if(sort)
|
||||
|
@ -556,18 +557,22 @@ void getUpstreamDestinations(const char *client_message, const int *sock)
|
|||
else
|
||||
upstreamID = i;
|
||||
|
||||
// Get forward pointer
|
||||
const upstreamsData* forward = getUpstream(upstreamID, true);
|
||||
if(forward == NULL)
|
||||
// Get upstream pointer
|
||||
const upstreamsData* upstream = getUpstream(upstreamID, true);
|
||||
if(upstream == NULL)
|
||||
continue;
|
||||
|
||||
// Get IP and host name of forward destination if available
|
||||
ip = getstr(forward->ippos);
|
||||
name = getstr(forward->namepos);
|
||||
// Get IP and host name of upstream destination if available
|
||||
ip = getstr(upstream->ippos);
|
||||
if(upstream->namepos != 0)
|
||||
name = getstr(upstream->namepos);
|
||||
else
|
||||
name = getstr(upstream->ippos);
|
||||
upstream_port = upstream->port;
|
||||
|
||||
// Get percentage
|
||||
if(totalqueries > 0)
|
||||
percentage = 1e2f * forward->count / totalqueries;
|
||||
percentage = 1e2f * upstream->count / totalqueries;
|
||||
}
|
||||
|
||||
// Send data:
|
||||
|
@ -576,7 +581,11 @@ void getUpstreamDestinations(const char *client_message, const int *sock)
|
|||
if(percentage > 0.0f || i < 0)
|
||||
{
|
||||
if(istelnet[*sock])
|
||||
ssend(*sock, "%i %.2f %s %s\n", i, percentage, ip, name);
|
||||
if(upstream_port != 0)
|
||||
ssend(*sock, "%i %.2f %s#%u %s#%u\n", i, percentage,
|
||||
ip, upstream_port, name, upstream_port);
|
||||
else
|
||||
ssend(*sock, "%i %.2f %s %s\n", i, percentage, ip, name);
|
||||
else
|
||||
{
|
||||
if(!pack_str32(*sock, name) || !pack_str32(*sock, ip))
|
||||
|
@ -706,6 +715,15 @@ void getAllQueries(const char *client_message, const int *sock)
|
|||
forwarddestid = -2;
|
||||
else
|
||||
{
|
||||
// Extract address/name and port
|
||||
char serv_addr[INET6_ADDRSTRLEN] = { 0 };
|
||||
unsigned int serv_port = 53;
|
||||
// We limit the number of bytes written into the serv_addr buffer
|
||||
// to prevent buffer overflows. If there is no port available in
|
||||
// the database, we skip extracting them and use the default port
|
||||
sscanf(forwarddest, "%"xstr(INET6_ADDRSTRLEN)"[^#]#%u", serv_addr, &serv_port);
|
||||
serv_addr[INET6_ADDRSTRLEN-1] = '\0';
|
||||
|
||||
// Iterate through all known forward destinations
|
||||
forwarddestid = -3;
|
||||
for(int i = 0; i < counters->upstreams; i++)
|
||||
|
@ -717,9 +735,9 @@ void getAllQueries(const char *client_message, const int *sock)
|
|||
|
||||
// Try to match the requested string against their IP addresses and
|
||||
// (if available) their host names
|
||||
if(strcmp(getstr(forward->ippos), forwarddest) == 0 ||
|
||||
if((strcmp(getstr(forward->ippos), serv_addr) == 0 ||
|
||||
(forward->namepos != 0 &&
|
||||
strcmp(getstr(forward->namepos), forwarddest) == 0))
|
||||
strcmp(getstr(forward->namepos), serv_addr) == 0)) && forward->port == serv_port)
|
||||
{
|
||||
forwarddestid = i;
|
||||
break;
|
||||
|
@ -979,9 +997,28 @@ void getAllQueries(const char *client_message, const int *sock)
|
|||
regex_idx = dns_cache->black_regex_idx;
|
||||
}
|
||||
|
||||
// Get IP of upstream destination, if applicable
|
||||
in_port_t upstream_port = 0;
|
||||
const char *upstream_name = "N/A";
|
||||
if(query->status == QUERY_FORWARDED)
|
||||
{
|
||||
const upstreamsData *upstream = getUpstream(query->upstreamID, true);
|
||||
if(upstream != NULL)
|
||||
{
|
||||
if(upstream->namepos != 0)
|
||||
// Get upstream destination name if possible
|
||||
upstream_name = getstr(upstream->namepos);
|
||||
else
|
||||
// If we have no name, get the IP address
|
||||
upstream_name = getstr(upstream->ippos);
|
||||
|
||||
upstream_port = upstream->port;
|
||||
}
|
||||
}
|
||||
|
||||
if(istelnet[*sock])
|
||||
{
|
||||
ssend(*sock,"%lli %s %s %s %i %i %i %lu %s %i",
|
||||
ssend(*sock,"%lli %s %s %s %i %i %i %lu %s %i %s",
|
||||
(long long)query->timestamp,
|
||||
qtype,
|
||||
domain,
|
||||
|
@ -991,7 +1028,11 @@ void getAllQueries(const char *client_message, const int *sock)
|
|||
query->reply,
|
||||
delay,
|
||||
CNAME_domain,
|
||||
regex_idx);
|
||||
regex_idx,
|
||||
upstream_name);
|
||||
if(upstream_port != 0)
|
||||
ssend(*sock, "#%u", upstream_port);
|
||||
|
||||
if(config.debug & DEBUG_API)
|
||||
ssend(*sock, " %i", queryID);
|
||||
ssend(*sock, "\n");
|
||||
|
|
|
@ -720,6 +720,10 @@ void read_debuging_settings(FILE *fp)
|
|||
// defaults to: false
|
||||
setDebugOption(fp, "DEBUG_EVENTS", DEBUG_EVENTS);
|
||||
|
||||
// DEBUG_HELPER
|
||||
// defaults to: false
|
||||
setDebugOption(fp, "DEBUG_HELPER", DEBUG_HELPER);
|
||||
|
||||
if(config.debug)
|
||||
{
|
||||
logg("*****************************");
|
||||
|
@ -744,6 +748,7 @@ void read_debuging_settings(FILE *fp)
|
|||
logg("* DEBUG_CLIENTS %s *", (config.debug & DEBUG_CLIENTS)? "YES":"NO ");
|
||||
logg("* DEBUG_SUPERCLIENTS %s *", (config.debug & DEBUG_SUPERCLIENTS)? "YES":"NO ");
|
||||
logg("* DEBUG_EVENTS %s *", (config.debug & DEBUG_EVENTS)? "YES":"NO ");
|
||||
logg("* DEBUG_HELPER %s *", (config.debug & DEBUG_HELPER)? "YES":"NO ");
|
||||
logg("*****************************");
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ typedef struct {
|
|||
bool ignore_localhost;
|
||||
bool analyze_only_A_AAAA;
|
||||
bool DBimport;
|
||||
bool DBexport;
|
||||
bool parse_arp_cache;
|
||||
bool cname_inspection;
|
||||
bool block_esni;
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include "superclients.h"
|
||||
|
||||
sqlite3 *FTL_db = NULL;
|
||||
bool database = true;
|
||||
bool DBdeleteoldqueries = false;
|
||||
long int lastdbindex = 0;
|
||||
static bool db_avail = false;
|
||||
|
@ -40,31 +39,29 @@ __attribute__ ((pure)) bool FTL_DB_avail(void)
|
|||
|
||||
void dbclose(void)
|
||||
{
|
||||
// Mark database as being closed
|
||||
db_avail = false;
|
||||
|
||||
if(config.debug & DEBUG_LOCKS)
|
||||
logg("Unlocking FTL database");
|
||||
|
||||
// Only try to close an existing database connection
|
||||
int rc = SQLITE_OK;
|
||||
if( FTL_db != NULL )
|
||||
{
|
||||
rc = sqlite3_close(FTL_db);
|
||||
if((rc = sqlite3_close(FTL_db)) != SQLITE_OK)
|
||||
logg("Encountered error while trying to close database: %s", sqlite3_errstr(rc));
|
||||
|
||||
FTL_db = NULL;
|
||||
}
|
||||
|
||||
db_avail = false;
|
||||
|
||||
// Report any error
|
||||
if( rc != SQLITE_OK )
|
||||
{
|
||||
logg("Encountered error while trying to close database: %s", sqlite3_errstr(rc));
|
||||
database = false;
|
||||
}
|
||||
|
||||
if(config.debug & DEBUG_LOCKS)
|
||||
logg("Unlocking database");
|
||||
else if(config.debug & DEBUG_LOCKS)
|
||||
logg("Unlocking FTL database: already NULL");
|
||||
|
||||
// Unlock mutex on the database
|
||||
pthread_mutex_unlock(&dblock);
|
||||
|
||||
if(config.debug & DEBUG_LOCKS)
|
||||
logg("Unlocking database: Success");
|
||||
logg("Unlocking FTL database: Success");
|
||||
}
|
||||
|
||||
bool dbopen(void)
|
||||
|
@ -73,25 +70,28 @@ bool dbopen(void)
|
|||
if(FTL_db != NULL && db_avail)
|
||||
{
|
||||
if(config.debug & DEBUG_LOCKS)
|
||||
logg("Not locking database (already open)");
|
||||
logg("Not locking FTL database (already open)");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Do not open database if it is not to be used
|
||||
if(!use_database())
|
||||
return false;
|
||||
|
||||
if(config.debug & DEBUG_LOCKS)
|
||||
logg("Locking database");
|
||||
logg("Locking FTL database");
|
||||
|
||||
// Lock mutex on the database
|
||||
pthread_mutex_lock(&dblock);
|
||||
|
||||
if(config.debug & DEBUG_LOCKS)
|
||||
logg("Locking database: Success");
|
||||
logg("Locking FTL database: Success");
|
||||
|
||||
// Try to open database
|
||||
int rc = sqlite3_open_v2(FTLfiles.FTL_db, &FTL_db, SQLITE_OPEN_READWRITE, NULL);
|
||||
if( rc != SQLITE_OK )
|
||||
{
|
||||
logg("Encountered error while trying to open database: %s", sqlite3_errstr(rc));
|
||||
database = false;
|
||||
pthread_mutex_unlock(&dblock);
|
||||
return false;
|
||||
}
|
||||
|
@ -102,7 +102,6 @@ bool dbopen(void)
|
|||
{
|
||||
logg("Encountered error while trying to set busy timeout (%d ms) on database: %s",
|
||||
DATABASE_BUSY_TIMEOUT, sqlite3_errstr(rc));
|
||||
database = false;
|
||||
dbclose();
|
||||
return false;
|
||||
}
|
||||
|
@ -112,6 +111,13 @@ bool dbopen(void)
|
|||
return true;
|
||||
}
|
||||
|
||||
// (Re-)Open pihole-FTL database connection
|
||||
void piholeFTLDB_reopen(void)
|
||||
{
|
||||
dbclose();
|
||||
dbopen();
|
||||
}
|
||||
|
||||
int dbquery(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
@ -127,7 +133,7 @@ int dbquery(const char *format, ...)
|
|||
|
||||
// Log generated SQL string when dbquery() is called
|
||||
// although the database connection is not available
|
||||
if(FTL_db == NULL && !dbopen())
|
||||
if(!FTL_DB_avail())
|
||||
{
|
||||
logg("dbquery(\"%s\") called but database is not available!", query);
|
||||
sqlite3_free(query);
|
||||
|
@ -166,19 +172,19 @@ static bool create_counter_table(void)
|
|||
|
||||
// ID 0 = total queries
|
||||
if(!db_set_counter(DB_TOTALQUERIES, 0))
|
||||
{ dbclose(); return false; }
|
||||
return false;
|
||||
|
||||
// ID 1 = total blocked queries
|
||||
if(!db_set_counter(DB_BLOCKEDQUERIES, 0))
|
||||
{ dbclose(); return false; }
|
||||
return false;
|
||||
|
||||
// Time stamp of creation of the counters database
|
||||
if(!db_set_FTL_property(DB_FIRSTCOUNTERTIMESTAMP, time(NULL)))
|
||||
{ dbclose(); return false; }
|
||||
return false;
|
||||
|
||||
// Update database version to 2
|
||||
if(!db_set_FTL_property(DB_VERSION, 2))
|
||||
{ dbclose(); return false; }
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -191,6 +197,10 @@ static bool db_create(void)
|
|||
logg("Encountered error while trying to create database in rw-mode: %s", sqlite3_errstr(rc));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Mark database as being available so dbquery() doesn't error out
|
||||
db_avail = true;
|
||||
|
||||
// Create Queries table in the database
|
||||
SQL_bool("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 );");
|
||||
|
||||
|
@ -210,7 +220,7 @@ static bool db_create(void)
|
|||
return false;
|
||||
|
||||
// Done initializing the database
|
||||
// Close database handle
|
||||
// Close database handle, it will be reopened in db_init()
|
||||
dbclose();
|
||||
|
||||
// Explicitly set permissions to 0644
|
||||
|
@ -240,9 +250,6 @@ void db_init(void)
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Lock database thread
|
||||
pthread_mutex_lock(&dblock);
|
||||
|
||||
// Initialize SQLite3 logging callback
|
||||
// This ensures SQLite3 errors and warnings are logged to pihole-FTL.log
|
||||
// We use this to possibly catch even more errors in places we do not
|
||||
|
@ -260,18 +267,12 @@ void db_init(void)
|
|||
{
|
||||
logg("Creation of database failed, database is not available");
|
||||
pthread_mutex_unlock(&dblock);
|
||||
database = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Try to open the database connection
|
||||
rc = sqlite3_open_v2(FTLfiles.FTL_db, &FTL_db, SQLITE_OPEN_READWRITE, NULL);
|
||||
if( rc != SQLITE_OK ){
|
||||
logg("Cannot initialize (open) long-term database: %s", sqlite3_errstr(rc));
|
||||
database = false;
|
||||
return;
|
||||
}
|
||||
// Open database
|
||||
dbopen();
|
||||
|
||||
db_avail = true;
|
||||
|
||||
|
@ -281,8 +282,6 @@ void db_init(void)
|
|||
{
|
||||
logg("Database not available, please ensure the database is unlocked when starting pihole-FTL !");
|
||||
dbclose();
|
||||
|
||||
database = false;
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
@ -300,8 +299,6 @@ void db_init(void)
|
|||
{
|
||||
logg("Counter table not initialized, database not available");
|
||||
dbclose();
|
||||
|
||||
database = false;
|
||||
return;
|
||||
}
|
||||
// Get updated version
|
||||
|
@ -317,8 +314,6 @@ void db_init(void)
|
|||
{
|
||||
logg("Network table not initialized, database not available");
|
||||
dbclose();
|
||||
|
||||
database = false;
|
||||
return;
|
||||
}
|
||||
// Get updated version
|
||||
|
@ -334,8 +329,6 @@ void db_init(void)
|
|||
{
|
||||
logg("Unable to unify clients in network table, database not available");
|
||||
dbclose();
|
||||
|
||||
database = false;
|
||||
return;
|
||||
}
|
||||
// Get updated version
|
||||
|
@ -351,8 +344,6 @@ void db_init(void)
|
|||
{
|
||||
logg("Network-addresses table not initialized, database not available");
|
||||
dbclose();
|
||||
|
||||
database = false;
|
||||
return;
|
||||
}
|
||||
// Get updated version
|
||||
|
@ -368,8 +359,6 @@ void db_init(void)
|
|||
{
|
||||
logg("Message table not initialized, database not available");
|
||||
dbclose();
|
||||
|
||||
database = false;
|
||||
return;
|
||||
}
|
||||
// Get updated version
|
||||
|
@ -386,8 +375,6 @@ void db_init(void)
|
|||
{
|
||||
logg("Column additional_info not initialized, database not available");
|
||||
dbclose();
|
||||
|
||||
database = false;
|
||||
return;
|
||||
}
|
||||
// Get updated version
|
||||
|
@ -403,8 +390,6 @@ void db_init(void)
|
|||
{
|
||||
logg("Network addresses table not initialized, database not available");
|
||||
dbclose();
|
||||
|
||||
database = false;
|
||||
return;
|
||||
}
|
||||
// Get updated version
|
||||
|
@ -420,8 +405,6 @@ void db_init(void)
|
|||
{
|
||||
logg("Superclients table not initialized, database not available");
|
||||
dbclose();
|
||||
|
||||
database = false;
|
||||
return;
|
||||
}
|
||||
// Get updated version
|
||||
|
@ -439,16 +422,20 @@ void db_init(void)
|
|||
if(!use_database())
|
||||
{
|
||||
logg("Not using the long-term database for storing queries");
|
||||
database = false;
|
||||
config.DBexport = false;
|
||||
return;
|
||||
}
|
||||
config.DBexport = true;
|
||||
|
||||
// Close database here, we have to reopen it later (after forking)
|
||||
dbclose();
|
||||
|
||||
logg("Database successfully initialized");
|
||||
}
|
||||
|
||||
int db_get_FTL_property(const enum ftl_table_props ID)
|
||||
{
|
||||
if(!database || FTL_db == NULL)
|
||||
if(!FTL_DB_avail())
|
||||
{
|
||||
logg("db_get_FTL_property(%u) called but database is not available!", ID);
|
||||
return DB_FAILED;
|
||||
|
@ -471,7 +458,7 @@ int db_get_FTL_property(const enum ftl_table_props ID)
|
|||
|
||||
bool db_set_FTL_property(const enum ftl_table_props ID, const int value)
|
||||
{
|
||||
if(!database || FTL_db == NULL)
|
||||
if(!FTL_DB_avail())
|
||||
{
|
||||
logg("db_set_FTL_property(%u, %i) called but database is not available!", ID, value);
|
||||
return false;
|
||||
|
@ -481,31 +468,48 @@ bool db_set_FTL_property(const enum ftl_table_props ID, const int value)
|
|||
|
||||
bool db_set_counter(const enum counters_table_props ID, const int value)
|
||||
{
|
||||
if(!database || FTL_db == NULL)
|
||||
if(!FTL_DB_avail())
|
||||
{
|
||||
logg("db_set_counter(%u, %i) called but database is not available!", ID, value);
|
||||
return false;
|
||||
}
|
||||
return dbquery("INSERT OR REPLACE INTO counters (id, value) VALUES ( %u, %i );", ID, value) == SQLITE_OK;
|
||||
|
||||
if(dbquery("INSERT OR REPLACE INTO counters (id, value) VALUES ( %u, %i );", ID, value) != SQLITE_OK)
|
||||
{
|
||||
dbclose();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool db_update_counters(const int total, const int blocked)
|
||||
{
|
||||
if(!database || FTL_db == NULL)
|
||||
if(!FTL_DB_avail())
|
||||
{
|
||||
logg("db_update_counters(%i, %i) called but database is not available!", total, blocked);
|
||||
dbclose();
|
||||
return false;
|
||||
}
|
||||
|
||||
if(dbquery("UPDATE counters SET value = value + %i WHERE id = %i;", total, DB_TOTALQUERIES) != SQLITE_OK)
|
||||
{
|
||||
dbclose();
|
||||
return false;
|
||||
}
|
||||
|
||||
if(dbquery("UPDATE counters SET value = value + %i WHERE id = %i;", blocked, DB_BLOCKEDQUERIES) != SQLITE_OK)
|
||||
{
|
||||
dbclose();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int db_query_int(const char* querystr)
|
||||
{
|
||||
if(!database || FTL_db == NULL)
|
||||
if(!FTL_DB_avail())
|
||||
{
|
||||
logg("db_query_int(\"%s\") called but database is not available!", querystr);
|
||||
return DB_FAILED;
|
||||
|
@ -521,10 +525,8 @@ int db_query_int(const char* querystr)
|
|||
if( rc != SQLITE_OK )
|
||||
{
|
||||
if( rc != SQLITE_BUSY )
|
||||
{
|
||||
logg("Encountered prepare error in db_query_int(\"%s\"): %s", querystr, sqlite3_errstr(rc));
|
||||
database = false;
|
||||
}
|
||||
|
||||
return DB_FAILED;
|
||||
}
|
||||
|
||||
|
@ -562,7 +564,7 @@ int db_query_int(const char* querystr)
|
|||
|
||||
long int get_max_query_ID(void)
|
||||
{
|
||||
if(!database || FTL_db == NULL)
|
||||
if(!FTL_DB_avail())
|
||||
{
|
||||
logg("get_max_query_ID() called but database is not available!");
|
||||
return DB_FAILED;
|
||||
|
@ -581,9 +583,10 @@ long int get_max_query_ID(void)
|
|||
if( rc != SQLITE_BUSY )
|
||||
{
|
||||
logg("Encountered prepare error in get_max_query_ID(): %s", sqlite3_errstr(rc));
|
||||
database = false;
|
||||
dbclose();
|
||||
}
|
||||
dbclose();
|
||||
|
||||
// Return okay if the database is busy
|
||||
return DB_FAILED;
|
||||
}
|
||||
|
||||
|
@ -591,7 +594,6 @@ long int get_max_query_ID(void)
|
|||
if( rc != SQLITE_ROW )
|
||||
{
|
||||
logg("Encountered step error in get_max_query_ID(): %s", sqlite3_errstr(rc));
|
||||
database = false;
|
||||
dbclose();
|
||||
return DB_FAILED;
|
||||
}
|
||||
|
@ -608,7 +610,7 @@ long int get_max_query_ID(void)
|
|||
// Returns ID of the most recent successful INSERT.
|
||||
long get_lastID(void)
|
||||
{
|
||||
if(!database || FTL_db == NULL)
|
||||
if(!FTL_DB_avail())
|
||||
{
|
||||
logg("get_lastID() called but database is not available!");
|
||||
return DB_FAILED;
|
||||
|
|
|
@ -35,6 +35,7 @@ int dbquery(const char *format, ...);
|
|||
bool FTL_DB_avail(void) __attribute__ ((pure));
|
||||
bool dbopen(void);
|
||||
void dbclose(void);
|
||||
void piholeFTLDB_reopen(void);
|
||||
int db_query_int(const char*);
|
||||
long get_lastID(void);
|
||||
void SQLite3LogCallback(void *pArg, int iErrCode, const char *zMsg);
|
||||
|
@ -45,7 +46,6 @@ const char *get_sqlite3_version(void);
|
|||
bool use_database(void) __attribute__ ((pure));
|
||||
|
||||
extern sqlite3 *FTL_db;
|
||||
extern bool database;
|
||||
extern long int lastdbindex;
|
||||
extern bool DBdeleteoldqueries;
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ void *DB_thread(void *val)
|
|||
|
||||
while(!killed)
|
||||
{
|
||||
if(database)
|
||||
if(FTL_DB_avail())
|
||||
{
|
||||
time_t now = time(NULL);
|
||||
if(now - lastDBsave >= config.DBinterval)
|
||||
|
@ -52,15 +52,13 @@ void *DB_thread(void *val)
|
|||
// Update lastDBsave timer
|
||||
lastDBsave = time(NULL) - time(NULL)%config.DBinterval;
|
||||
|
||||
// Lock FTL's data structures, since it is
|
||||
// likely that they will be changed here
|
||||
lock_shm();
|
||||
|
||||
// Save data to database
|
||||
DB_save_queries();
|
||||
|
||||
// Release data lock
|
||||
unlock_shm();
|
||||
if(config.DBexport)
|
||||
{
|
||||
lock_shm();
|
||||
DB_save_queries();
|
||||
unlock_shm();
|
||||
}
|
||||
|
||||
// Check if GC should be done on the database
|
||||
if(DBdeleteoldqueries)
|
||||
|
@ -79,6 +77,9 @@ void *DB_thread(void *val)
|
|||
// database is not updated very often)
|
||||
if(now % 2592000L == 0)
|
||||
updateMACVendorRecords();
|
||||
|
||||
if(get_and_clear_event(PARSE_NEIGHBOR_CACHE))
|
||||
parse_neighbor_cache();
|
||||
}
|
||||
|
||||
// Process database related event queue elements
|
||||
|
@ -88,8 +89,12 @@ void *DB_thread(void *val)
|
|||
if(get_and_clear_event(RELOAD_PRIVACY_LEVEL))
|
||||
get_privacy_level(NULL);
|
||||
|
||||
if(get_and_clear_event(PARSE_NEIGHBOR_CACHE))
|
||||
parse_neighbor_cache();
|
||||
if(get_and_clear_event(RERESOLVE_DATABASE_NAMES))
|
||||
{
|
||||
// Try to resolve host names from clients in the network table
|
||||
// which have empty/undefined host names
|
||||
resolveNetworkTableNames();
|
||||
}
|
||||
|
||||
if(get_and_clear_event(REIMPORT_SUPERCLIENTS))
|
||||
{
|
||||
|
|
|
@ -72,28 +72,18 @@ bool create_message_table(void)
|
|||
// Flush message table
|
||||
bool flush_message_table(void)
|
||||
{
|
||||
// Open database connection
|
||||
dbopen();
|
||||
|
||||
// Flush message table
|
||||
SQL_bool("DELETE FROM message;");
|
||||
|
||||
// Close database connection
|
||||
dbclose();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool add_message(enum message_type type, const char *message,
|
||||
const int count,...)
|
||||
{
|
||||
bool opened_database = false;
|
||||
// Open database connection (if not already open)
|
||||
if(!FTL_DB_avail())
|
||||
{
|
||||
if(!dbopen())
|
||||
return false;
|
||||
opened_database = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ensure there are no duplicates when adding host name messages
|
||||
|
@ -105,8 +95,7 @@ static bool add_message(enum message_type type, const char *message,
|
|||
if( rc != SQLITE_OK ){
|
||||
logg("add_message(type=%u, message=%s) - SQL error prepare DELETE: %s",
|
||||
type, message, sqlite3_errstr(rc));
|
||||
if(opened_database)
|
||||
dbclose();
|
||||
dbclose();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -117,8 +106,7 @@ static bool add_message(enum message_type type, const char *message,
|
|||
type, message, sqlite3_errstr(rc));
|
||||
sqlite3_reset(stmt);
|
||||
sqlite3_finalize(stmt);
|
||||
if(opened_database)
|
||||
dbclose();
|
||||
dbclose();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -129,8 +117,7 @@ static bool add_message(enum message_type type, const char *message,
|
|||
type, message, sqlite3_errstr(rc));
|
||||
sqlite3_reset(stmt);
|
||||
sqlite3_finalize(stmt);
|
||||
if(opened_database)
|
||||
dbclose();
|
||||
dbclose();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -139,8 +126,7 @@ static bool add_message(enum message_type type, const char *message,
|
|||
{
|
||||
logg("add_message(type=%u, message=%s) - SQL error step DELETE: %s",
|
||||
type, message, sqlite3_errstr(rc));
|
||||
if(opened_database)
|
||||
dbclose();
|
||||
dbclose();
|
||||
return false;
|
||||
}
|
||||
sqlite3_clear_bindings(stmt);
|
||||
|
@ -157,8 +143,7 @@ static bool add_message(enum message_type type, const char *message,
|
|||
{
|
||||
logg("add_message(type=%u, message=%s) - SQL error prepare: %s",
|
||||
type, message, sqlite3_errstr(rc));
|
||||
if(opened_database)
|
||||
dbclose();
|
||||
dbclose();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -169,8 +154,7 @@ static bool add_message(enum message_type type, const char *message,
|
|||
type, message, sqlite3_errstr(rc));
|
||||
sqlite3_reset(stmt);
|
||||
sqlite3_finalize(stmt);
|
||||
if(opened_database)
|
||||
dbclose();
|
||||
dbclose();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -181,8 +165,7 @@ static bool add_message(enum message_type type, const char *message,
|
|||
type, message, sqlite3_errstr(rc));
|
||||
sqlite3_reset(stmt);
|
||||
sqlite3_finalize(stmt);
|
||||
if(opened_database)
|
||||
dbclose();
|
||||
dbclose();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -214,8 +197,7 @@ static bool add_message(enum message_type type, const char *message,
|
|||
type, message, 3 + j, datatype, sqlite3_errstr(rc));
|
||||
sqlite3_reset(stmt);
|
||||
sqlite3_finalize(stmt);
|
||||
if(opened_database)
|
||||
dbclose();
|
||||
dbclose();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -230,15 +212,10 @@ static bool add_message(enum message_type type, const char *message,
|
|||
if(rc != SQLITE_DONE)
|
||||
{
|
||||
logg("Encountered error while trying to store message in long-term database: %s", sqlite3_errstr(rc));
|
||||
if(opened_database)
|
||||
dbclose();
|
||||
dbclose();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Close database connection (if we opened it)
|
||||
if(opened_database)
|
||||
dbclose();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -842,19 +842,15 @@ static bool add_FTL_clients_to_network_table(enum arp_status *client_status, tim
|
|||
{
|
||||
const char *text;
|
||||
if( rc == SQLITE_BUSY )
|
||||
{
|
||||
text = "WARNING";
|
||||
}
|
||||
else
|
||||
{
|
||||
text = "ERROR";
|
||||
// We shall not use the database any longer
|
||||
database = false;
|
||||
dbclose();
|
||||
}
|
||||
|
||||
logg("%s: Storing devices in network table failed: %s", text, sqlite3_errstr(rc));
|
||||
unlock_shm();
|
||||
dbclose();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1054,9 +1050,9 @@ static bool add_local_interfaces_to_network_table(time_t now, unsigned int *addi
|
|||
void parse_neighbor_cache(void)
|
||||
{
|
||||
// Open database file
|
||||
if(!dbopen())
|
||||
if(!FTL_DB_avail())
|
||||
{
|
||||
logg("parse_neighbor_cache() - Failed to open DB");
|
||||
logg("parse_neighbor_cache() - Database is not available");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1088,19 +1084,15 @@ void parse_neighbor_cache(void)
|
|||
{
|
||||
const char *text;
|
||||
if( rc == SQLITE_BUSY )
|
||||
{
|
||||
text = "WARNING";
|
||||
}
|
||||
else
|
||||
{
|
||||
text = "ERROR";
|
||||
// We shall not use the database any longer
|
||||
database = false;
|
||||
dbclose();
|
||||
}
|
||||
|
||||
// dbquery() above already logs the reson for why the query failed
|
||||
logg("%s: Storing devices in network table (\"%s\") failed", text, sql);
|
||||
dbclose();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1331,26 +1323,20 @@ void parse_neighbor_cache(void)
|
|||
if((rc = dbquery("END TRANSACTION")) != SQLITE_OK) {
|
||||
const char *text;
|
||||
if( rc == SQLITE_BUSY )
|
||||
{
|
||||
text = "WARNING";
|
||||
}
|
||||
else
|
||||
{
|
||||
text = "ERROR";
|
||||
// We shall not use the database any longer
|
||||
database = false;
|
||||
dbclose();
|
||||
}
|
||||
|
||||
logg("%s: Storing devices in network table failed: %s", text, sqlite3_errstr(rc));
|
||||
unlock_shm();
|
||||
dbclose();
|
||||
|
||||
// Return okay if the database is busy
|
||||
return;
|
||||
}
|
||||
|
||||
// Close database connection
|
||||
// We opened the connection in this function
|
||||
dbclose();
|
||||
|
||||
unlock_shm();
|
||||
|
||||
// Debug logging
|
||||
|
@ -1483,7 +1469,7 @@ static char *getMACVendor(const char *hwaddr)
|
|||
hwaddr, hwaddrshort, sqlite3_errstr(rc));
|
||||
sqlite3_reset(stmt);
|
||||
sqlite3_finalize(stmt);
|
||||
dbclose();
|
||||
sqlite3_close(macvendor_db);
|
||||
return strdup("");
|
||||
}
|
||||
|
||||
|
@ -1525,11 +1511,9 @@ void updateMACVendorRecords(void)
|
|||
return;
|
||||
}
|
||||
|
||||
// Open pihole-FTL.db database file if needed
|
||||
const bool db_already_open = FTL_DB_avail();
|
||||
if(!db_already_open && !dbopen())
|
||||
if(!FTL_DB_avail())
|
||||
{
|
||||
logg("updateMACVendorRecords() - Failed to open DB");
|
||||
logg("updateMACVendorRecords() - Database not available");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1538,8 +1522,6 @@ void updateMACVendorRecords(void)
|
|||
int rc = sqlite3_prepare_v2(FTL_db, selectstr, -1, &stmt, NULL);
|
||||
if( rc != SQLITE_OK ){
|
||||
logg("updateMACVendorRecords() - SQL error prepare \"%s\": %s", selectstr, sqlite3_errstr(rc));
|
||||
if(!db_already_open)
|
||||
dbclose();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1584,18 +1566,14 @@ void updateMACVendorRecords(void)
|
|||
}
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
if(!db_already_open)
|
||||
dbclose();
|
||||
}
|
||||
|
||||
// Get hardware address of device identified by IP address
|
||||
char *__attribute__((malloc)) getMACfromIP(const char *ipaddr)
|
||||
{
|
||||
// Open pihole-FTL.db database file if needed
|
||||
const bool db_already_open = FTL_DB_avail();
|
||||
if(!db_already_open && !dbopen())
|
||||
if(!FTL_DB_avail())
|
||||
{
|
||||
logg("getMACfromIP(\"%s\") - Failed to open DB", ipaddr);
|
||||
logg("getMACfromIP(\"%s\") - Database not available", ipaddr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1610,8 +1588,6 @@ char *__attribute__((malloc)) getMACfromIP(const char *ipaddr)
|
|||
if( rc != SQLITE_OK ){
|
||||
logg("getMACfromIP(\"%s\") - SQL error prepare: %s",
|
||||
ipaddr, sqlite3_errstr(rc));
|
||||
if(!db_already_open)
|
||||
dbclose();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1622,8 +1598,6 @@ char *__attribute__((malloc)) getMACfromIP(const char *ipaddr)
|
|||
ipaddr, sqlite3_errstr(rc));
|
||||
sqlite3_reset(stmt);
|
||||
sqlite3_finalize(stmt);
|
||||
if(!db_already_open)
|
||||
dbclose();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1646,8 +1620,6 @@ char *__attribute__((malloc)) getMACfromIP(const char *ipaddr)
|
|||
// Finalize statement and close database handle
|
||||
sqlite3_reset(stmt);
|
||||
sqlite3_finalize(stmt);
|
||||
if(!db_already_open)
|
||||
dbclose();
|
||||
|
||||
return hwaddr;
|
||||
}
|
||||
|
@ -1717,11 +1689,9 @@ int getSuperclientIDfromIP(const char *ipaddr)
|
|||
// Get host name of device identified by IP address
|
||||
char *__attribute__((malloc)) getNameFromIP(const char *ipaddr)
|
||||
{
|
||||
// Open pihole-FTL.db database file if needed
|
||||
const bool db_already_open = FTL_DB_avail();
|
||||
if(!db_already_open && !dbopen())
|
||||
if(!FTL_DB_avail())
|
||||
{
|
||||
logg("getNameFromIP(\"%s\") - Failed to open DB", ipaddr);
|
||||
logg("getNameFromIP(\"%s\") - Database not available", ipaddr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1732,8 +1702,6 @@ char *__attribute__((malloc)) getNameFromIP(const char *ipaddr)
|
|||
if( rc != SQLITE_OK ){
|
||||
logg("getNameFromIP(\"%s\") - SQL error prepare: %s",
|
||||
ipaddr, sqlite3_errstr(rc));
|
||||
if(!db_already_open)
|
||||
dbclose();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1744,8 +1712,6 @@ char *__attribute__((malloc)) getNameFromIP(const char *ipaddr)
|
|||
ipaddr, sqlite3_errstr(rc));
|
||||
sqlite3_reset(stmt);
|
||||
sqlite3_finalize(stmt);
|
||||
if(!db_already_open)
|
||||
dbclose();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1770,12 +1736,7 @@ char *__attribute__((malloc)) getNameFromIP(const char *ipaddr)
|
|||
|
||||
// Return here if we found the name
|
||||
if(name != NULL)
|
||||
{
|
||||
if(!db_already_open)
|
||||
dbclose();
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
// Nothing found for the exact IP address
|
||||
// Check for a host name associated with the same device (but another IP address)
|
||||
|
@ -1788,8 +1749,6 @@ char *__attribute__((malloc)) getNameFromIP(const char *ipaddr)
|
|||
if( rc != SQLITE_OK ){
|
||||
logg("getNameFromIP(\"%s\") - SQL error prepare: %s",
|
||||
ipaddr, sqlite3_errstr(rc));
|
||||
if(!db_already_open)
|
||||
dbclose();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1800,8 +1759,6 @@ char *__attribute__((malloc)) getNameFromIP(const char *ipaddr)
|
|||
ipaddr, sqlite3_errstr(rc));
|
||||
sqlite3_reset(stmt);
|
||||
sqlite3_finalize(stmt);
|
||||
if(!db_already_open)
|
||||
dbclose();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1825,8 +1782,6 @@ char *__attribute__((malloc)) getNameFromIP(const char *ipaddr)
|
|||
// Finalize statement and close database handle
|
||||
sqlite3_reset(stmt);
|
||||
sqlite3_finalize(stmt);
|
||||
if(!db_already_open)
|
||||
dbclose();
|
||||
|
||||
return name;
|
||||
}
|
||||
|
@ -1834,11 +1789,9 @@ char *__attribute__((malloc)) getNameFromIP(const char *ipaddr)
|
|||
// Get interface of device identified by IP address
|
||||
char *__attribute__((malloc)) getIfaceFromIP(const char *ipaddr)
|
||||
{
|
||||
// Open pihole-FTL.db database file if needed
|
||||
const bool db_already_open = FTL_DB_avail();
|
||||
if(!db_already_open && !dbopen())
|
||||
if(!FTL_DB_avail())
|
||||
{
|
||||
logg("getIfaceFromIP(\"%s\") - Failed to open DB", ipaddr);
|
||||
logg("getIfaceFromIP(\"%s\") - Database not available", ipaddr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1854,8 +1807,6 @@ char *__attribute__((malloc)) getIfaceFromIP(const char *ipaddr)
|
|||
if( rc != SQLITE_OK ){
|
||||
logg("getIfaceFromIP(\"%s\") - SQL error prepare: %s",
|
||||
ipaddr, sqlite3_errstr(rc));
|
||||
if(!db_already_open)
|
||||
dbclose();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1872,8 +1823,6 @@ char *__attribute__((malloc)) getIfaceFromIP(const char *ipaddr)
|
|||
ipaddr, sqlite3_errstr(rc));
|
||||
sqlite3_reset(stmt);
|
||||
sqlite3_finalize(stmt);
|
||||
if(!db_already_open)
|
||||
dbclose();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1896,8 +1845,6 @@ char *__attribute__((malloc)) getIfaceFromIP(const char *ipaddr)
|
|||
// Finalize statement and close database handle
|
||||
sqlite3_reset(stmt);
|
||||
sqlite3_finalize(stmt);
|
||||
if(!db_already_open)
|
||||
dbclose();
|
||||
|
||||
return iface;
|
||||
}
|
||||
|
@ -1905,11 +1852,9 @@ char *__attribute__((malloc)) getIfaceFromIP(const char *ipaddr)
|
|||
// Resolve unknown names of recently seen IP addresses in network table
|
||||
void resolveNetworkTableNames(void)
|
||||
{
|
||||
// Open pihole-FTL.db database file if needed
|
||||
const bool db_already_open = FTL_DB_avail();
|
||||
if(!db_already_open && !dbopen())
|
||||
if(!FTL_DB_avail())
|
||||
{
|
||||
logg("resolveNetworkTableNames() - Failed to open DB");
|
||||
logg("resolveNetworkTableNames() - Database not available");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1929,8 +1874,7 @@ void resolveNetworkTableNames(void)
|
|||
|
||||
// dbquery() above already logs the reson for why the query failed
|
||||
logg("%s: Trying to resolve unknown network table host names (\"%s\") failed", text, sql);
|
||||
if(!db_already_open)
|
||||
dbclose();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1946,12 +1890,9 @@ void resolveNetworkTableNames(void)
|
|||
logg("resolveNetworkTableNames() - SQL error prepare: %s",
|
||||
sqlite3_errstr(rc));
|
||||
sqlite3_finalize(table_stmt);
|
||||
if(!db_already_open)
|
||||
dbclose();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Get data
|
||||
while((rc = sqlite3_step(table_stmt)) == SQLITE_ROW)
|
||||
{
|
||||
|
@ -2027,8 +1968,6 @@ void resolveNetworkTableNames(void)
|
|||
logg("resolveNetworkTableNames() - SQL error step: %s",
|
||||
sqlite3_errstr(rc));
|
||||
sqlite3_finalize(table_stmt);
|
||||
if(!db_already_open)
|
||||
dbclose();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2036,6 +1975,4 @@ void resolveNetworkTableNames(void)
|
|||
sqlite3_finalize(table_stmt);
|
||||
|
||||
dbquery("COMMIT");
|
||||
if(!db_already_open)
|
||||
dbclose();
|
||||
}
|
||||
|
|
|
@ -25,14 +25,15 @@
|
|||
#include "../config.h"
|
||||
// getstr()
|
||||
#include "../shmem.h"
|
||||
// free()
|
||||
#include "../memory.h"
|
||||
|
||||
static bool saving_failed_before = false;
|
||||
|
||||
int get_number_of_queries_in_DB(void)
|
||||
{
|
||||
// This routine is used by the API routines.
|
||||
// We need to handle opening/closing of the database herein.
|
||||
if(!dbopen())
|
||||
if(!FTL_DB_avail())
|
||||
{
|
||||
return DB_FAILED;
|
||||
}
|
||||
|
@ -40,9 +41,6 @@ int get_number_of_queries_in_DB(void)
|
|||
// Count number of rows using the index timestamp is faster than select(*)
|
||||
int result = db_query_int("SELECT COUNT(timestamp) FROM queries");
|
||||
|
||||
// Close pihole-FTL.db database connection
|
||||
dbclose();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -52,13 +50,6 @@ void DB_save_queries(void)
|
|||
if(config.debug & DEBUG_DATABASE)
|
||||
timer_start(DATABASE_WRITE_TIMER);
|
||||
|
||||
// Open database
|
||||
if(!dbopen())
|
||||
{
|
||||
logg("Failed to open long-term database when trying to store queries");
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int saved = 0;
|
||||
bool error = false;
|
||||
sqlite3_stmt* stmt = NULL;
|
||||
|
@ -68,18 +59,14 @@ void DB_save_queries(void)
|
|||
{
|
||||
const char *text;
|
||||
if( rc == SQLITE_BUSY )
|
||||
{
|
||||
text = "WARNING";
|
||||
}
|
||||
else
|
||||
{
|
||||
text = "ERROR";
|
||||
// We shall not use the database any longer
|
||||
database = false;
|
||||
dbclose();
|
||||
}
|
||||
|
||||
logg("%s: Storing queries in long-term database failed: %s", text, sqlite3_errstr(rc));
|
||||
dbclose();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -96,15 +83,13 @@ void DB_save_queries(void)
|
|||
{
|
||||
text = "ERROR";
|
||||
spaces = " ";
|
||||
// We shall not use the database any longer
|
||||
database = false;
|
||||
dbclose();
|
||||
}
|
||||
|
||||
// dbquery() above already logs the reson for why the query failed
|
||||
logg("%s: Storing queries in long-term database failed: %s\n", text, sqlite3_errstr(rc));
|
||||
logg("%s Keeping queries in memory for later new attempt", spaces);
|
||||
saving_failed_before = true;
|
||||
dbclose();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -160,7 +145,14 @@ void DB_save_queries(void)
|
|||
{
|
||||
// Get forward pointer
|
||||
const upstreamsData* upstream = getUpstream(query->upstreamID, true);
|
||||
sqlite3_bind_text(stmt, 6, getstr(upstream->ippos), -1, SQLITE_STATIC);
|
||||
char *buffer = NULL;
|
||||
if(asprintf(&buffer, "%s#%u", getstr(upstream->ippos), upstream->port) > 0)
|
||||
sqlite3_bind_text(stmt, 6, buffer, -1, SQLITE_TRANSIENT);
|
||||
else
|
||||
sqlite3_bind_null(stmt, 6);
|
||||
|
||||
if(buffer != NULL)
|
||||
free(buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -237,11 +229,8 @@ void DB_save_queries(void)
|
|||
saving_failed_before = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
database = false;
|
||||
}
|
||||
dbclose();
|
||||
|
||||
dbclose();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -257,11 +246,8 @@ void DB_save_queries(void)
|
|||
saving_failed_before = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
database = false;
|
||||
}
|
||||
dbclose();
|
||||
|
||||
dbclose();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -274,9 +260,6 @@ void DB_save_queries(void)
|
|||
db_update_counters(total, blocked);
|
||||
}
|
||||
|
||||
// Close database
|
||||
dbclose();
|
||||
|
||||
if(config.debug & DEBUG_DATABASE || saving_failed_before)
|
||||
{
|
||||
logg("Notice: Queries stored in long-term database: %u (took %.1f ms, last SQLite ID %li)", saved, timer_elapsed_msec(DATABASE_WRITE_TIMER), lastID);
|
||||
|
@ -291,9 +274,8 @@ void DB_save_queries(void)
|
|||
void delete_old_queries_in_DB(void)
|
||||
{
|
||||
// Open database
|
||||
if(!dbopen())
|
||||
if(!FTL_DB_avail())
|
||||
{
|
||||
logg("Failed to open long-term database when trying to delete old queries");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -311,20 +293,14 @@ void delete_old_queries_in_DB(void)
|
|||
// Print final message only if there is a difference
|
||||
if((config.debug & DEBUG_DATABASE) || affected)
|
||||
logg("Notice: Database size is %.2f MB, deleted %i rows", 1e-6*get_FTL_db_filesize(), affected);
|
||||
|
||||
// Close database
|
||||
dbclose();
|
||||
}
|
||||
|
||||
// Get most recent 24 hours data from long-term database
|
||||
void DB_read_queries(void)
|
||||
{
|
||||
// Open database file
|
||||
// Open database
|
||||
if(!dbopen())
|
||||
{
|
||||
logg("Failed to open long-term database when trying to read queries");
|
||||
return;
|
||||
}
|
||||
|
||||
// Prepare request
|
||||
// Get time stamp 24 hours in the past
|
||||
|
@ -422,7 +398,16 @@ void DB_read_queries(void)
|
|||
(long long)queryTimeStamp);
|
||||
continue;
|
||||
}
|
||||
upstreamID = findUpstreamID(upstream, true);
|
||||
|
||||
// Get IP address and port of upstream destination
|
||||
char serv_addr[INET6_ADDRSTRLEN] = { 0 };
|
||||
unsigned int serv_port = 53;
|
||||
// We limit the number of bytes written into the serv_addr buffer
|
||||
// to prevent buffer overflows. If there is no port available in
|
||||
// the database, we skip extracting them and use the default port
|
||||
sscanf(upstream, "%"xstr(INET6_ADDRSTRLEN)"[^#]#%u", serv_addr, &serv_port);
|
||||
serv_addr[INET6_ADDRSTRLEN-1] = '\0';
|
||||
upstreamID = findUpstreamID(serv_addr, (in_port_t)serv_port, true);
|
||||
}
|
||||
|
||||
// Obtain IDs only after filtering which queries we want to keep
|
||||
|
@ -559,5 +544,7 @@ void DB_read_queries(void)
|
|||
|
||||
// Finalize SQLite3 statement
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
// Close database here, we have to reopen it later (after forking)
|
||||
dbclose();
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include "main.h"
|
||||
// reset_superclient()
|
||||
#include "database/superclients.h"
|
||||
// piholeFTLDB_reopen()
|
||||
#include "database/common.h"
|
||||
|
||||
const char *querytypes[TYPE_MAX] = {"UNKNOWN", "A", "AAAA", "ANY", "SRV", "SOA", "PTR", "TXT",
|
||||
"NAPTR", "MX", "DS", "RRSIG", "DNSKEY", "NS", "OTHER"};
|
||||
|
@ -63,7 +65,7 @@ int findQueryID(const int id)
|
|||
return -1;
|
||||
}
|
||||
|
||||
int findUpstreamID(const char * upstreamString, const bool count)
|
||||
int findUpstreamID(const char * upstreamString, const in_port_t port, const bool count)
|
||||
{
|
||||
// Go through already knows upstream servers and see if we used one of those
|
||||
for(int upstreamID=0; upstreamID < counters->upstreams; upstreamID++)
|
||||
|
@ -75,7 +77,7 @@ int findUpstreamID(const char * upstreamString, const bool count)
|
|||
if(upstream == NULL)
|
||||
continue;
|
||||
|
||||
if(strcmp(getstr(upstream->ippos), upstreamString) == 0)
|
||||
if(strcmp(getstr(upstream->ippos), upstreamString) == 0 && upstream->port == port)
|
||||
{
|
||||
if(count)
|
||||
{
|
||||
|
@ -88,7 +90,7 @@ int findUpstreamID(const char * upstreamString, const bool count)
|
|||
// This upstream server is not known
|
||||
// Store ID
|
||||
const int upstreamID = counters->upstreams;
|
||||
logg("New upstream server: %s (%i/%u)", upstreamString, upstreamID, counters->upstreams_MAX);
|
||||
logg("New upstream server: %s:%u (%i/%u)", upstreamString, port, upstreamID, counters->upstreams_MAX);
|
||||
|
||||
// Check struct size
|
||||
memory_check(UPSTREAMS);
|
||||
|
@ -119,6 +121,8 @@ int findUpstreamID(const char * upstreamString, const bool count)
|
|||
upstream->namepos = 0; // 0 -> string with length zero
|
||||
// This is a new upstream server
|
||||
upstream->lastQuery = time(NULL);
|
||||
// Store port
|
||||
upstream->port = port;
|
||||
// Increase counter by one
|
||||
counters->upstreams++;
|
||||
|
||||
|
@ -461,6 +465,11 @@ void FTL_reset_per_client_domain_data(void)
|
|||
|
||||
void FTL_reload_all_domainlists(void)
|
||||
{
|
||||
lock_shm();
|
||||
|
||||
// (Re-)open FTL database connection
|
||||
piholeFTLDB_reopen();
|
||||
|
||||
// Flush messages stored in the long-term database
|
||||
flush_message_table();
|
||||
|
||||
|
@ -477,4 +486,6 @@ void FTL_reload_all_domainlists(void)
|
|||
// Reset FTL's internal DNS cache storing whether a specific domain
|
||||
// has already been validated for a specific user
|
||||
FTL_reset_per_client_domain_data();
|
||||
|
||||
unlock_shm();
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ typedef struct {
|
|||
typedef struct {
|
||||
unsigned char magic;
|
||||
bool new;
|
||||
in_addr_t port;
|
||||
int count;
|
||||
int failed;
|
||||
size_t ippos;
|
||||
|
@ -88,7 +89,7 @@ typedef struct {
|
|||
|
||||
void strtolower(char *str);
|
||||
int findQueryID(const int id);
|
||||
int findUpstreamID(const char * upstream, const bool count);
|
||||
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 findCacheID(int domainID, int clientID, enum query_types query_type);
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
#include "FTL.h"
|
||||
#include "dhcp-discover.h"
|
||||
// logg()
|
||||
// logg(), format_time()
|
||||
#include "log.h"
|
||||
// read_FTLconf()
|
||||
#include "config.h"
|
||||
|
@ -226,27 +226,6 @@ static bool send_dhcp_discover(const int sock, const uint32_t xid, const char *i
|
|||
return bytes > 0;
|
||||
}
|
||||
|
||||
static void nice_time(char *buffer, unsigned long seconds)
|
||||
{
|
||||
unsigned int days = seconds / (60 * 60 * 24);
|
||||
seconds -= days * (60 * 60 * 24);
|
||||
unsigned int hours = seconds / (60 * 60);
|
||||
seconds -= hours * (60 * 60);
|
||||
unsigned int minutes = seconds / 60;
|
||||
seconds %= 60;
|
||||
|
||||
buffer[0] = ' ';
|
||||
buffer[1] = '\0';
|
||||
if(days > 0)
|
||||
sprintf(buffer + strlen(buffer), "%ud ", days);
|
||||
if(hours > 0)
|
||||
sprintf(buffer + strlen(buffer), "%uh ", hours);
|
||||
if(minutes > 0)
|
||||
sprintf(buffer + strlen(buffer), "%um ", minutes);
|
||||
if(seconds > 0)
|
||||
sprintf(buffer + strlen(buffer), "%lus ", seconds);
|
||||
}
|
||||
|
||||
// adds a DHCP OFFER to list in memory
|
||||
static void print_dhcp_offer(struct in_addr source, dhcp_packet *offer_packet)
|
||||
{
|
||||
|
@ -360,7 +339,7 @@ static void print_dhcp_offer(struct in_addr source, dhcp_packet *offer_packet)
|
|||
else
|
||||
{
|
||||
char buffer[32] = { 0 };
|
||||
nice_time(buffer, lease_time);
|
||||
format_time(buffer, lease_time, 0.0);
|
||||
logg("%s(%lu seconds)", buffer, (unsigned long)lease_time);
|
||||
}
|
||||
}
|
||||
|
@ -414,7 +393,7 @@ static void print_dhcp_offer(struct in_addr source, dhcp_packet *offer_packet)
|
|||
else
|
||||
{
|
||||
char buffer[32] = { 0 };
|
||||
nice_time(buffer, renewal_time);
|
||||
format_time(buffer, renewal_time, 0.0);
|
||||
logg("%s(%lu seconds)", buffer, (unsigned long)renewal_time);
|
||||
}
|
||||
}
|
||||
|
@ -429,7 +408,7 @@ static void print_dhcp_offer(struct in_addr source, dhcp_packet *offer_packet)
|
|||
else
|
||||
{
|
||||
char buffer[32] = { 0 };
|
||||
nice_time(buffer, rebinding_time);
|
||||
format_time(buffer, rebinding_time, 0.0);
|
||||
logg("%s(%lu seconds)", buffer, (unsigned long)rebinding_time);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1782,6 +1782,11 @@ static void check_dns_listeners(time_t now)
|
|||
|
||||
for (listener = daemon->listeners; listener; listener = listener->next)
|
||||
{
|
||||
|
||||
/******************** Pi-hole modification *******************/
|
||||
FTL_next_iface(listener->iface ? listener->iface->name : NULL);
|
||||
/*************************************************************/
|
||||
|
||||
if (listener->fd != -1 && poll_check(listener->fd, POLLIN))
|
||||
receive_query(listener, now);
|
||||
|
||||
|
|
|
@ -311,6 +311,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
|||
else
|
||||
log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, "retry", (union all_addr *)&forward->sentto->addr.in6.sin6_addr, "dnssec");
|
||||
|
||||
FTL_forwarding_retried(forward->sentto, forward->log_id, daemon->log_id, true);
|
||||
|
||||
if (forward->sentto->sfd)
|
||||
fd = forward->sentto->sfd->fd;
|
||||
|
@ -347,7 +348,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
|||
start = daemon->servers; /* at end of list, recycle */
|
||||
header->id = htons(forward->new_id);
|
||||
|
||||
FTL_forwarding_failed(forward->sentto);
|
||||
FTL_forwarding_retried(forward->sentto, forward->log_id, daemon->log_id, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -546,14 +547,14 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
|||
log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff,
|
||||
(union all_addr *)&start->addr.in.sin_addr, NULL);
|
||||
FTL_forwarded(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff,
|
||||
(union all_addr *)&start->addr.in.sin_addr, daemon->log_display_id);
|
||||
start, daemon->log_display_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff,
|
||||
(union all_addr *)&start->addr.in6.sin6_addr, NULL);
|
||||
FTL_forwarded(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff,
|
||||
(union all_addr *)&start->addr.in6.sin6_addr, daemon->log_display_id);
|
||||
start, daemon->log_display_id);
|
||||
}
|
||||
start->queries++;
|
||||
forwarded = 1;
|
||||
|
@ -2178,14 +2179,14 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||
log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff,
|
||||
(union all_addr *)&last_server->addr.in.sin_addr, NULL);
|
||||
FTL_forwarded(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff,
|
||||
(union all_addr *)&last_server->addr.in.sin_addr, daemon->log_display_id);
|
||||
last_server, daemon->log_display_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff,
|
||||
(union all_addr *)&last_server->addr.in6.sin6_addr, NULL);
|
||||
FTL_forwarded(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff,
|
||||
(union all_addr *)&last_server->addr.in6.sin6_addr, daemon->log_display_id);
|
||||
last_server, daemon->log_display_id);
|
||||
}
|
||||
|
||||
#ifdef HAVE_DNSSEC
|
||||
|
|
|
@ -241,6 +241,9 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
|||
else
|
||||
continue;
|
||||
|
||||
/************************** Pi-hole modification **************************/
|
||||
FTL_log_helper(1, action_str);
|
||||
/**************************************************************************/
|
||||
|
||||
/* stringify MAC into dhcp_buff */
|
||||
p = daemon->dhcp_buff;
|
||||
|
@ -640,6 +643,12 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
|||
fcntl(event_fd, F_SETFD, i | FD_CLOEXEC);
|
||||
close(pipefd[0]);
|
||||
|
||||
/**************************** Pi-hole modification ****************************/
|
||||
FTL_log_helper(5, daemon->lease_change_command, action_str,
|
||||
(is6 && data.action != ACTION_ARP) ? daemon->packet : daemon->dhcp_buff,
|
||||
daemon->addrbuff, hostname);
|
||||
/******************************************************************************/
|
||||
|
||||
p = strrchr(daemon->lease_change_command, '/');
|
||||
if (err == 0)
|
||||
{
|
||||
|
@ -650,6 +659,9 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
|||
err = errno;
|
||||
}
|
||||
/* failed, send event so the main process logs the problem */
|
||||
/**************************** Pi-hole modification ****************************/
|
||||
FTL_log_helper(2, daemon->lease_change_command, strerror(err));
|
||||
/******************************************************************************/
|
||||
send_event(event_fd, EVENT_EXEC_ERR, err, NULL);
|
||||
_exit(0);
|
||||
}
|
||||
|
|
|
@ -70,8 +70,18 @@ const char flagnames[][12] = {"F_IMMORTAL ", "F_NAMEP ", "F_REVERSE ", "F_FORWAR
|
|||
// Store interface the next query will come from for later usage
|
||||
void FTL_next_iface(const char *newiface)
|
||||
{
|
||||
strncpy(next_iface, newiface, sizeof(next_iface)-1);
|
||||
next_iface[sizeof(next_iface)-1] = '\0';
|
||||
if(newiface != NULL)
|
||||
{
|
||||
// Copy interface name if available
|
||||
strncpy(next_iface, newiface, sizeof(next_iface)-1);
|
||||
next_iface[sizeof(next_iface)-1] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use dummy when interface record is not available
|
||||
next_iface[0] = '-';
|
||||
next_iface[1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
static bool check_domain_blocked(const char *domain, const int clientID,
|
||||
|
@ -535,7 +545,11 @@ bool _FTL_new_query(const unsigned int flags, const char *name,
|
|||
char *domainString = strdup(name);
|
||||
strtolower(domainString);
|
||||
|
||||
// Get client IP address (can be overwritten by EDNS(0) client subnet (ECS) data)
|
||||
// Get client IP address
|
||||
// The requestor's IP address can be rewritten using EDNS(0) client
|
||||
// subnet (ECS) data), however, we do not rewrite the IPs ::1 and
|
||||
// 127.0.0.1 to avoid queries originating from localhost of the
|
||||
// *distant* machine as queries coming from the *local* machine
|
||||
const sa_family_t family = (flags & F_IPV4) ? AF_INET : AF_INET6;
|
||||
char clientIP[ADDRSTRLEN] = { 0 };
|
||||
if(config.edns0_ecs && edns->client_set)
|
||||
|
@ -751,7 +765,7 @@ void _FTL_get_blocking_metadata(union all_addr **addrp, unsigned int *flags, con
|
|||
}
|
||||
}
|
||||
|
||||
void _FTL_forwarded(const unsigned int flags, const char *name, const union all_addr *addr, const int id,
|
||||
void _FTL_forwarded(const unsigned int flags, const char *name, const struct server *serv, const int id,
|
||||
const char* file, const int line)
|
||||
{
|
||||
// Save that this query got forwarded to an upstream server
|
||||
|
@ -759,19 +773,33 @@ void _FTL_forwarded(const unsigned int flags, const char *name, const union all_
|
|||
// Lock shared memory
|
||||
lock_shm();
|
||||
|
||||
// Get forward destination IP address
|
||||
// Get forward destination IP address and port
|
||||
in_port_t upstreamPort = 53;
|
||||
char dest[ADDRSTRLEN];
|
||||
// If addr == NULL, we will only duplicate an empty string instead of uninitialized memory
|
||||
dest[0] = '\0';
|
||||
if(addr != NULL)
|
||||
inet_ntop((flags & F_IPV4) ? AF_INET : AF_INET6, addr, dest, ADDRSTRLEN);
|
||||
if(serv != NULL)
|
||||
{
|
||||
if(serv->addr.sa.sa_family == AF_INET)
|
||||
{
|
||||
inet_ntop(AF_INET, &serv->addr.in.sin_addr, dest, ADDRSTRLEN);
|
||||
upstreamPort = ntohs(serv->addr.in.sin_port);
|
||||
}
|
||||
else
|
||||
{
|
||||
inet_ntop(AF_INET6, &serv->addr.in6.sin6_addr, dest, ADDRSTRLEN);
|
||||
upstreamPort = ntohs(serv->addr.in6.sin6_port);
|
||||
}
|
||||
}
|
||||
|
||||
// Convert upstreamIP to lower case
|
||||
char *upstreamIP = strdup(dest);
|
||||
strtolower(upstreamIP);
|
||||
|
||||
// Debug logging
|
||||
if(config.debug & DEBUG_QUERIES) logg("**** forwarded %s to %s (ID %i, %s:%i)", name, upstreamIP, id, file, line);
|
||||
if(config.debug & DEBUG_QUERIES)
|
||||
logg("**** forwarded %s to %s#%u (ID %i, %s:%i)",
|
||||
name, upstreamIP, upstreamPort, id, file, line);
|
||||
|
||||
// Save status and upstreamID in corresponding query identified by dnsmasq's ID
|
||||
const int queryID = findQueryID(id);
|
||||
|
@ -803,7 +831,7 @@ void _FTL_forwarded(const unsigned int flags, const char *name, const union all_
|
|||
|
||||
// Get ID of upstream destination, create new upstream record
|
||||
// if not found in current data structure
|
||||
const int upstreamID = findUpstreamID(upstreamIP, true);
|
||||
const int upstreamID = findUpstreamID(upstreamIP, upstreamPort, true);
|
||||
query->upstreamID = upstreamID;
|
||||
|
||||
// Get time index for this query
|
||||
|
@ -873,6 +901,9 @@ void FTL_dnsmasq_reload(void)
|
|||
|
||||
logg("Reloading DNS cache");
|
||||
|
||||
// (Re-)open FTL database connection
|
||||
piholeFTLDB_reopen();
|
||||
|
||||
// Request reload the privacy level
|
||||
set_event(RELOAD_PRIVACY_LEVEL);
|
||||
|
||||
|
@ -1718,7 +1749,7 @@ void FTL_fork_and_bind_sockets(struct passwd *ent_pw)
|
|||
}
|
||||
|
||||
// Start database thread if database is used
|
||||
if(database && pthread_create( &DBthread, &attr, DB_thread, NULL ) != 0)
|
||||
if(pthread_create( &DBthread, &attr, DB_thread, NULL ) != 0)
|
||||
{
|
||||
logg("Unable to open database thread. Exiting...");
|
||||
exit(EXIT_FAILURE);
|
||||
|
@ -1742,15 +1773,34 @@ void FTL_fork_and_bind_sockets(struct passwd *ent_pw)
|
|||
|
||||
// Chown files if FTL started as user root but a dnsmasq config
|
||||
// option states to run as a different user/group (e.g. "nobody")
|
||||
if(ent_pw != NULL && getuid() == 0)
|
||||
if(getuid() == 0)
|
||||
{
|
||||
if(chown(FTLfiles.log, ent_pw->pw_uid, ent_pw->pw_gid) == -1)
|
||||
logg("Setting ownership (%i:%i) of %s failed: %s (%i)",
|
||||
ent_pw->pw_uid, ent_pw->pw_gid, FTLfiles.log, strerror(errno), errno);
|
||||
if(database && chown(FTLfiles.FTL_db, ent_pw->pw_uid, ent_pw->pw_gid) == -1)
|
||||
logg("Setting ownership (%i:%i) of %s failed: %s (%i)",
|
||||
ent_pw->pw_uid, ent_pw->pw_gid, FTLfiles.FTL_db, strerror(errno), errno);
|
||||
chown_all_shmem(ent_pw);
|
||||
if(ent_pw != NULL)
|
||||
{
|
||||
logg("INFO: FTL is going to drop from root to user %s (UID %d)",
|
||||
ent_pw->pw_name, (int)ent_pw->pw_uid);
|
||||
if(chown(FTLfiles.log, ent_pw->pw_uid, ent_pw->pw_gid) == -1)
|
||||
logg("Setting ownership (%i:%i) of %s failed: %s (%i)",
|
||||
ent_pw->pw_uid, ent_pw->pw_gid, FTLfiles.log, strerror(errno), errno);
|
||||
if(chown(FTLfiles.FTL_db, ent_pw->pw_uid, ent_pw->pw_gid) == -1)
|
||||
logg("Setting ownership (%i:%i) of %s failed: %s (%i)",
|
||||
ent_pw->pw_uid, ent_pw->pw_gid, FTLfiles.FTL_db, strerror(errno), errno);
|
||||
chown_all_shmem(ent_pw);
|
||||
}
|
||||
else
|
||||
{
|
||||
logg("INFO: FTL is running as root");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uid_t uid;
|
||||
struct passwd *current_user;
|
||||
if ((current_user = getpwuid(uid = geteuid())) != NULL)
|
||||
logg("INFO: FTL is running as user %s (UID %d)",
|
||||
current_user->pw_name, (int)current_user->pw_uid);
|
||||
else
|
||||
logg("INFO: Failed to obtain information about FTL user");
|
||||
}
|
||||
|
||||
// Obtain DNS port from dnsmasq daemon
|
||||
|
@ -1775,7 +1825,7 @@ void getCacheInformation(const int *sock)
|
|||
// looked up for the longest time is evicted.
|
||||
}
|
||||
|
||||
void _FTL_forwarding_failed(const struct server *server, const char* file, const int line)
|
||||
void FTL_forwarding_retried(const struct server *serv, const int oldID, const int newID, const bool dnssec)
|
||||
{
|
||||
// Forwarding to upstream server failed
|
||||
|
||||
|
@ -1784,20 +1834,35 @@ void _FTL_forwarding_failed(const struct server *server, const char* file, const
|
|||
|
||||
// Try to obtain destination IP address if available
|
||||
char dest[ADDRSTRLEN];
|
||||
if(server->addr.sa.sa_family == AF_INET)
|
||||
inet_ntop(AF_INET, &server->addr.in.sin_addr, dest, ADDRSTRLEN);
|
||||
else
|
||||
inet_ntop(AF_INET6, &server->addr.in6.sin6_addr, dest, ADDRSTRLEN);
|
||||
in_port_t upstreamPort = 53;
|
||||
dest[0] = '\0';
|
||||
if(serv != NULL)
|
||||
{
|
||||
if(serv->addr.sa.sa_family == AF_INET)
|
||||
{
|
||||
inet_ntop(AF_INET, &serv->addr.in.sin_addr, dest, ADDRSTRLEN);
|
||||
upstreamPort = ntohs(serv->addr.in.sin_port);
|
||||
}
|
||||
else
|
||||
{
|
||||
inet_ntop(AF_INET6, &serv->addr.in6.sin6_addr, dest, ADDRSTRLEN);
|
||||
upstreamPort = ntohs(serv->addr.in6.sin6_port);
|
||||
}
|
||||
}
|
||||
|
||||
// Convert upstream to lower case
|
||||
char *upstreamIP = strdup(dest);
|
||||
strtolower(upstreamIP);
|
||||
|
||||
// Get upstream ID
|
||||
const int upstreamID = findUpstreamID(upstreamIP, false);
|
||||
const int upstreamID = findUpstreamID(upstreamIP, upstreamPort, false);
|
||||
|
||||
// Possible debugging information
|
||||
if(config.debug & DEBUG_QUERIES) logg("**** forwarding to %s (ID %i, %s:%i) FAILED", dest, upstreamID, file, line);
|
||||
if(config.debug & DEBUG_QUERIES)
|
||||
{
|
||||
logg("**** RETRIED query %i as %i to %s (ID %i)",
|
||||
oldID, newID, dest, upstreamID);
|
||||
}
|
||||
|
||||
// Get upstream pointer
|
||||
upstreamsData* upstream = getUpstream(upstreamID, true);
|
||||
|
@ -1806,6 +1871,36 @@ void _FTL_forwarding_failed(const struct server *server, const char* file, const
|
|||
if(upstream != NULL)
|
||||
upstream->failed++;
|
||||
|
||||
// Search for corresponding query identified by ID
|
||||
// Retried DNSSEC queries are ignored, we have to flag themselves (newID)
|
||||
// Retried normal queries take over, we have to flat the original query (oldID)
|
||||
const int queryID = findQueryID(dnssec ? newID : oldID);
|
||||
if(queryID >= 0)
|
||||
{
|
||||
// Get query pointer
|
||||
queriesData* query = getQuery(queryID, true);
|
||||
|
||||
// Set retried status
|
||||
if(query != NULL)
|
||||
{
|
||||
if(dnssec)
|
||||
{
|
||||
// There is point in retrying the query when
|
||||
// we've already got an answer to this query,
|
||||
// but we're awaiting keys for DNSSEC
|
||||
// validation. We're retrying the DNSSEC query
|
||||
// instead
|
||||
query->status = QUERY_RETRIED_DNSSEC;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Normal query retry due to answer not arriving
|
||||
// soon enough at the requestor
|
||||
query->status = QUERY_RETRIED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up and unlock shared memory
|
||||
free(upstreamIP);
|
||||
unlock_shm();
|
||||
|
|
|
@ -24,8 +24,8 @@ void FTL_next_iface(const char *newiface);
|
|||
#define FTL_new_query(flags, name, blockingreason, addr, types, qtype, id, edns, proto) _FTL_new_query(flags, name, blockingreason, addr, types, qtype, id, edns, proto, __FILE__, __LINE__)
|
||||
bool _FTL_new_query(const unsigned int flags, const char *name, const char** blockingreason, const union all_addr *addr, const char *types, const unsigned short qtype, const int id, const struct edns_data *edns, enum protocol proto, const char* file, const int line);
|
||||
|
||||
#define FTL_forwarded(flags, name, addr, id) _FTL_forwarded(flags, name, addr, id, __FILE__, __LINE__)
|
||||
void _FTL_forwarded(const unsigned int flags, const char *name, const union all_addr *addr, const int id, const char* file, const int line);
|
||||
#define FTL_forwarded(flags, name, serv, id) _FTL_forwarded(flags, name, serv, id, __FILE__, __LINE__)
|
||||
void _FTL_forwarded(const unsigned int flags, const char *name, const struct server *serv, const int id, const char* file, const int line);
|
||||
|
||||
#define FTL_reply(flags, name, addr, id) _FTL_reply(flags, name, addr, id, __FILE__, __LINE__)
|
||||
void _FTL_reply(const unsigned int flags, const char *name, const union all_addr *addr, const int id, const char* file, const int line);
|
||||
|
@ -39,8 +39,7 @@ void _FTL_dnssec(const int status, const int id, const char* file, const int lin
|
|||
#define FTL_header_analysis(header4, rcode, id) _FTL_header_analysis(header4, rcode, id, __FILE__, __LINE__)
|
||||
void _FTL_header_analysis(const unsigned char header4, const unsigned int rcode, const int id, const char* file, const int line);
|
||||
|
||||
#define FTL_forwarding_failed(server) _FTL_forwarding_failed(server, __FILE__, __LINE__)
|
||||
void _FTL_forwarding_failed(const struct server *server, const char* file, const int line);
|
||||
void FTL_forwarding_retried(const struct server *server, const int oldID, const int newID, const bool dnssec);
|
||||
|
||||
#define FTL_upstream_error(rcode, id) _FTL_upstream_error(rcode, id, __FILE__, __LINE__)
|
||||
void _FTL_upstream_error(const unsigned int rcode, const int id, const char* file, const int line);
|
||||
|
|
67
src/edns0.c
67
src/edns0.c
|
@ -176,34 +176,34 @@ void FTL_parse_pseudoheaders(struct dns_header *header, size_t n, union mysockad
|
|||
if (code == EDNS0_ECS && config.edns0_ecs)
|
||||
{
|
||||
// EDNS(0) CLIENT SUBNET
|
||||
// RFC 7871 Client Subnet in DNS Queries 6. Option Format
|
||||
// This protocol uses an EDNS0 [RFC6891] option to include client
|
||||
// address information in DNS messages. The option is structured as
|
||||
// follows:
|
||||
//
|
||||
// +0 (MSB) +1 (LSB)
|
||||
// +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
// 0: | OPTION-CODE |
|
||||
// +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
// 2: | OPTION-LENGTH |
|
||||
// +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
// 4: | FAMILY |
|
||||
// +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
// RFC 7871 Client Subnet in DNS Queries 6. Option Format
|
||||
// This protocol uses an EDNS0 [RFC6891] option to include client
|
||||
// address information in DNS messages. The option is structured as
|
||||
// follows:
|
||||
//
|
||||
// +0 (MSB) +1 (LSB)
|
||||
// +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
// 0: | OPTION-CODE |
|
||||
// +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
// 2: | OPTION-LENGTH |
|
||||
// +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
// 4: | FAMILY |
|
||||
// +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
short family;
|
||||
GETSHORT(family, p);
|
||||
// +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
// 6: | SOURCE PREFIX-LENGTH | SCOPE PREFIX-LENGTH |
|
||||
// +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
// +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
// 6: | SOURCE PREFIX-LENGTH | SCOPE PREFIX-LENGTH |
|
||||
// +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
unsigned char source_netmask = *p++;
|
||||
p++; // We are not interested in the scope prefix-length. It MUST be 0 in queries
|
||||
// +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
// 8: | ADDRESS... /
|
||||
// +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
// +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
// 8: | ADDRESS... /
|
||||
// +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
union all_addr addr = {{ 0 }};
|
||||
if(family == 1 && optlen > 4) // IPv4
|
||||
memcpy(&addr.addr4.s_addr, p, optlen - 4);
|
||||
else if(family == 2 && optlen > 4) // IPv6
|
||||
memcpy(addr.addr6.s6_addr, p, optlen - 4);
|
||||
if(family == 1 && optlen == 4 + sizeof(addr.addr4.s_addr)) // IPv4
|
||||
memcpy(&addr.addr4.s_addr, p, sizeof(addr.addr4.s_addr));
|
||||
else if(family == 2 && optlen == 4 + sizeof(addr.addr6.s6_addr)) // IPv6
|
||||
memcpy(addr.addr6.s6_addr, p, sizeof(addr.addr6.s6_addr));
|
||||
else
|
||||
continue;
|
||||
|
||||
|
@ -213,18 +213,31 @@ void FTL_parse_pseudoheaders(struct dns_header *header, size_t n, union mysockad
|
|||
char ipaddr[ADDRSTRLEN] = { 0 };
|
||||
inet_ntop(family == 1 ? AF_INET : AF_INET6, &addr.addr4.s_addr, ipaddr, sizeof(ipaddr));
|
||||
|
||||
if(config.debug & DEBUG_EDNS0)
|
||||
logg("EDNS(0) CLIENT SUBNET: %s/%u", ipaddr, source_netmask);
|
||||
|
||||
// Only use /32 (IPv4) and /128 (IPv6) addresses
|
||||
if(!(family == 1 && source_netmask == 32) &&
|
||||
!(family == 2 && source_netmask == 128))
|
||||
continue;
|
||||
|
||||
// Copy data to edns struct
|
||||
edns->client_set = true;
|
||||
strncpy(edns->client, ipaddr, ADDRSTRLEN);
|
||||
edns->client[ADDRSTRLEN-1] = '\0';
|
||||
|
||||
// Only set the address as useful when it is not the
|
||||
// loopback address of the distant machine (127.0.0.0/8 or ::1)
|
||||
if((family == 1 && (ntohl(addr.addr4.s_addr) & 0xFF000000) == 0x7F000000) ||
|
||||
(family == 2 && IN6_IS_ADDR_LOOPBACK(&addr.addr6)))
|
||||
{
|
||||
if(config.debug & DEBUG_EDNS0)
|
||||
logg("EDNS(0) CLIENT SUBNET: Skipped %s/%u (IPv%u loopback address)",
|
||||
ipaddr, source_netmask, family == 1 ? 4 : 6);
|
||||
}
|
||||
else
|
||||
{
|
||||
edns->client_set = true;
|
||||
if(config.debug & DEBUG_EDNS0)
|
||||
logg("EDNS(0) CLIENT SUBNET: %s/%u - OK (IPv%u)",
|
||||
ipaddr, source_netmask, family == 1 ? 4 : 6);
|
||||
}
|
||||
}
|
||||
else if(code == EDNS0_COOKIE && optlen == 8)
|
||||
{
|
||||
|
|
|
@ -40,6 +40,8 @@ enum query_status {
|
|||
QUERY_GRAVITY_CNAME,
|
||||
QUERY_REGEX_CNAME,
|
||||
QUERY_BLACKLIST_CNAME,
|
||||
QUERY_RETRIED,
|
||||
QUERY_RETRIED_DNSSEC,
|
||||
QUERY_STATUS_MAX
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
@ -136,6 +138,7 @@ enum debug_flags {
|
|||
DEBUG_CLIENTS = (1 << 17), /* 00000000 00000010 00000000 00000000 */
|
||||
DEBUG_SUPERCLIENTS = (1 << 18), /* 00000000 00000100 00000000 00000000 */
|
||||
DEBUG_EVENTS = (1 << 19), /* 00000000 00001000 00000000 00000000 */
|
||||
DEBUG_HELPER = (1 << 20), /* 00000000 00010000 00000000 00000000 */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
enum events {
|
||||
|
@ -144,7 +147,8 @@ enum events {
|
|||
RERESOLVE_HOSTNAMES,
|
||||
REIMPORT_SUPERCLIENTS,
|
||||
PARSE_NEIGHBOR_CACHE,
|
||||
RERESOLVE_DATABASE_NAMES,
|
||||
EVENTS_MAX
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#endif // ENUMS_H
|
||||
#endif // ENUMS_H
|
||||
|
|
|
@ -96,8 +96,10 @@ static const char *eventtext(const enum events event)
|
|||
return "REIMPORT_SUPERCLIENTS";
|
||||
case PARSE_NEIGHBOR_CACHE:
|
||||
return "PARSE_NEIGHBOR_CACHE";
|
||||
case RERESOLVE_DATABASE_NAMES:
|
||||
return "RERESOLVE_DATABASE_NAMES";
|
||||
case EVENTS_MAX: // fall through
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
4
src/gc.c
4
src/gc.c
|
@ -100,7 +100,9 @@ void *GC_thread(void *val)
|
|||
// Unknown (?)
|
||||
counters->unknown--;
|
||||
break;
|
||||
case QUERY_FORWARDED:
|
||||
case QUERY_FORWARDED: // (fall through)
|
||||
case QUERY_RETRIED: // (fall through)
|
||||
case QUERY_RETRIED_DNSSEC:
|
||||
// Forwarded to an upstream DNS server
|
||||
// Adjust counters
|
||||
counters->forwarded--;
|
||||
|
|
70
src/log.c
70
src/log.c
|
@ -166,6 +166,44 @@ void _FTL_log(const bool newline, const char *format, ...)
|
|||
pthread_mutex_unlock(&lock);
|
||||
}
|
||||
|
||||
// Log helper activity (may be script or lua)
|
||||
void FTL_log_helper(const unsigned char n, ...)
|
||||
{
|
||||
// Only log helper debug messages if enabled
|
||||
if(!(config.debug & DEBUG_HELPER))
|
||||
return;
|
||||
|
||||
// Extract all variable arguments
|
||||
va_list args;
|
||||
char *arg[n];
|
||||
va_start(args, n);
|
||||
for(unsigned char i = 0; i < n; i++)
|
||||
arg[i] = strdup(va_arg(args, char*));
|
||||
va_end(args);
|
||||
|
||||
// Select appropriate logging format
|
||||
switch (n)
|
||||
{
|
||||
case 1:
|
||||
logg("Script: Starting helper for action \"%s\"", arg[0]);
|
||||
break;
|
||||
case 2:
|
||||
logg("Script: FAILED to execute \"%s\": %s", arg[0], arg[1]);
|
||||
break;
|
||||
case 5:
|
||||
logg("Script: Executing \"%s\" with arguments: \"%s %s %s %s\"",
|
||||
arg[0], arg[1], arg[2], arg[3], arg[4]);
|
||||
break;
|
||||
default:
|
||||
logg("ERROR: Unsupported number of arguments passed to FTL_log_helper(): %u", n);
|
||||
break;
|
||||
}
|
||||
|
||||
// Free allocated memory
|
||||
for(unsigned char i = 0; i < n; i++)
|
||||
free(arg[i]);
|
||||
}
|
||||
|
||||
void format_memory_size(char * const prefix, const unsigned long long int bytes,
|
||||
double * const formated)
|
||||
{
|
||||
|
@ -183,6 +221,38 @@ void format_memory_size(char * const prefix, const unsigned long long int bytes,
|
|||
strcpy(prefix, prefixes[i]);
|
||||
}
|
||||
|
||||
// Human-readable time
|
||||
void format_time(char buffer[42], unsigned long seconds, double milliseconds)
|
||||
{
|
||||
unsigned long umilliseconds = 0;
|
||||
if(milliseconds > 0)
|
||||
{
|
||||
seconds = milliseconds / 1000;
|
||||
umilliseconds = (unsigned long)milliseconds % 1000;
|
||||
}
|
||||
const unsigned int days = seconds / (60 * 60 * 24);
|
||||
seconds -= days * (60 * 60 * 24);
|
||||
const unsigned int hours = seconds / (60 * 60);
|
||||
seconds -= hours * (60 * 60);
|
||||
const unsigned int minutes = seconds / 60;
|
||||
seconds %= 60;
|
||||
|
||||
buffer[0] = ' ';
|
||||
buffer[1] = '\0';
|
||||
if(days > 0)
|
||||
sprintf(buffer + strlen(buffer), "%ud ", days);
|
||||
if(hours > 0)
|
||||
sprintf(buffer + strlen(buffer), "%uh ", hours);
|
||||
if(minutes > 0)
|
||||
sprintf(buffer + strlen(buffer), "%um ", minutes);
|
||||
if(seconds > 0)
|
||||
sprintf(buffer + strlen(buffer), "%lus ", seconds);
|
||||
|
||||
// Only append milliseconds when the timer value is less than 10 seconds
|
||||
if((days + hours + minutes) == 0 && seconds < 10 && umilliseconds > 0)
|
||||
sprintf(buffer + strlen(buffer), "%lums ", umilliseconds);
|
||||
}
|
||||
|
||||
void log_counter_info(void)
|
||||
{
|
||||
logg(" -> Total DNS queries: %i", counters->queries);
|
||||
|
|
|
@ -18,6 +18,7 @@ void open_FTL_log(const bool test);
|
|||
void log_counter_info(void);
|
||||
void format_memory_size(char * const prefix, unsigned long long int bytes,
|
||||
double * const formated);
|
||||
void format_time(char buffer[42], unsigned long seconds, double milliseconds);
|
||||
const char *get_FTL_version(void) __attribute__ ((malloc));
|
||||
void log_FTL_version(bool crashreport);
|
||||
void get_timestr(char * const timestring, const time_t timein);
|
||||
|
@ -29,5 +30,6 @@ const char *get_ordinal_suffix(unsigned int number) __attribute__ ((const));
|
|||
#define logg_sameline(format, ...) _FTL_log(false, format, ## __VA_ARGS__)
|
||||
void _FTL_log(const bool newline, const char* format, ...) __attribute__ ((format (gnu_printf, 2, 3)));
|
||||
void log_ctrl(bool vlog, bool vstdout);
|
||||
void FTL_log_helper(const unsigned char n, ...);
|
||||
|
||||
#endif //LOG_H
|
||||
|
|
11
src/main.c
11
src/main.c
|
@ -80,7 +80,7 @@ int main (int argc, char* argv[])
|
|||
db_init();
|
||||
|
||||
// Try to import queries from long-term database if available
|
||||
if(database && config.DBimport)
|
||||
if(config.DBimport)
|
||||
DB_read_queries();
|
||||
|
||||
log_counter_info();
|
||||
|
@ -107,8 +107,8 @@ int main (int argc, char* argv[])
|
|||
if(ipv6telnet) pthread_cancel(telnet_listenthreadv6);
|
||||
pthread_cancel(socket_listenthread);
|
||||
|
||||
// Save new queries to database
|
||||
if(database)
|
||||
// Save new queries to database (if database is used)
|
||||
if(use_database())
|
||||
{
|
||||
DB_save_queries();
|
||||
logg("Finished final database update");
|
||||
|
@ -132,6 +132,9 @@ int main (int argc, char* argv[])
|
|||
|
||||
//Remove PID file
|
||||
removepid();
|
||||
logg("########## FTL terminated after %e s! ##########", 1e-3*timer_elapsed_msec(EXIT_TIMER));
|
||||
|
||||
char buffer[42] = { 0 };
|
||||
format_time(buffer, 0, timer_elapsed_msec(EXIT_TIMER));
|
||||
logg("########## FTL terminated after%s! ##########", buffer);
|
||||
return exit_code;
|
||||
}
|
||||
|
|
|
@ -340,6 +340,10 @@ static void free_regex(void)
|
|||
}
|
||||
}
|
||||
|
||||
// This function does three things:
|
||||
// 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)
|
||||
{
|
||||
// Ensure there is enough memory in the shared memory object
|
||||
|
@ -455,8 +459,9 @@ void read_regex_from_database(void)
|
|||
// Read and compile regex whitelist
|
||||
read_regex_table(REGEX_WHITELIST);
|
||||
|
||||
// Load per-client regex data, not all of the regex read and compiled
|
||||
// above will also be used by all clients
|
||||
// Loop over all clients and ensure we have enough space and load
|
||||
// per-client regex data, not all of the regex read and compiled above
|
||||
// will also be used by all clients
|
||||
for(int clientID = 0; clientID < counters->clients; clientID++)
|
||||
{
|
||||
// Get client pointer
|
||||
|
|
|
@ -531,7 +531,10 @@ void *DNSclient_thread(void *val)
|
|||
|
||||
// Run every hour to update possibly changed client host names
|
||||
if(resolver_ready && (time(NULL) % RERESOLVE_INTERVAL == 0))
|
||||
set_event(RERESOLVE_HOSTNAMES);
|
||||
{
|
||||
set_event(RERESOLVE_HOSTNAMES); // done below
|
||||
set_event(RERESOLVE_DATABASE_NAMES); // done in database thread
|
||||
}
|
||||
|
||||
// Process resolver related event queue elements
|
||||
if(get_and_clear_event(RERESOLVE_HOSTNAMES))
|
||||
|
@ -540,9 +543,6 @@ void *DNSclient_thread(void *val)
|
|||
resolveClients(false);
|
||||
// Try to resolve all upstream destination host names (onlynew=false)
|
||||
resolveUpstreams(false);
|
||||
// Try to resolve host names from clients in the network table
|
||||
// which have empty/undefined host names
|
||||
resolveNetworkTableNames();
|
||||
// Prevent immediate re-run of this routine
|
||||
sleepms(500);
|
||||
}
|
||||
|
|
81
src/shmem.c
81
src/shmem.c
|
@ -181,7 +181,7 @@ size_t addstr(const char *str)
|
|||
|
||||
// Reserve additional memory if necessary
|
||||
if(shmSettings->next_str_pos + len > shm_strings.size &&
|
||||
!realloc_shm(&shm_strings, shm_strings.size + pagesize, true))
|
||||
!realloc_shm(&shm_strings, shm_strings.size + pagesize, sizeof(char), true))
|
||||
return 0;
|
||||
|
||||
// Store new string buffer size in corresponding counters entry
|
||||
|
@ -236,22 +236,22 @@ static pthread_mutex_t create_mutex(void) {
|
|||
static void remap_shm(void)
|
||||
{
|
||||
// Remap shared object pointers which might have changed
|
||||
realloc_shm(&shm_queries, counters->queries_MAX*sizeof(queriesData), false);
|
||||
realloc_shm(&shm_queries, counters->queries_MAX, sizeof(queriesData), false);
|
||||
queries = (queriesData*)shm_queries.ptr;
|
||||
|
||||
realloc_shm(&shm_domains, counters->domains_MAX*sizeof(domainsData), false);
|
||||
realloc_shm(&shm_domains, counters->domains_MAX, sizeof(domainsData), false);
|
||||
domains = (domainsData*)shm_domains.ptr;
|
||||
|
||||
realloc_shm(&shm_clients, counters->clients_MAX*sizeof(clientsData), false);
|
||||
realloc_shm(&shm_clients, counters->clients_MAX, sizeof(clientsData), false);
|
||||
clients = (clientsData*)shm_clients.ptr;
|
||||
|
||||
realloc_shm(&shm_upstreams, counters->upstreams_MAX*sizeof(upstreamsData), false);
|
||||
realloc_shm(&shm_upstreams, counters->upstreams_MAX, sizeof(upstreamsData), false);
|
||||
upstreams = (upstreamsData*)shm_upstreams.ptr;
|
||||
|
||||
realloc_shm(&shm_dns_cache, counters->dns_cache_MAX*sizeof(DNSCacheData), false);
|
||||
realloc_shm(&shm_dns_cache, counters->dns_cache_MAX, sizeof(DNSCacheData), false);
|
||||
dns_cache = (DNSCacheData*)shm_dns_cache.ptr;
|
||||
|
||||
realloc_shm(&shm_strings, counters->strings_MAX, false);
|
||||
realloc_shm(&shm_strings, counters->strings_MAX, sizeof(char), false);
|
||||
// strings are not exposed by a global pointer
|
||||
|
||||
// Update local counter to reflect that we absorbed this change
|
||||
|
@ -441,14 +441,15 @@ SharedMemory create_shm(const char *name, const size_t size)
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Resize shared memory file
|
||||
ret = ftruncate(fd, size);
|
||||
|
||||
// Check for `ftruncate` error
|
||||
if(ret == -1)
|
||||
// Allocate shared memory object to specified size
|
||||
// Using fallocate() will ensure that there's actually space for
|
||||
// this file. Otherwise we end up with a sparse file that can give
|
||||
// SIGBUS if we run out of space while writing to it.
|
||||
ret = fallocate(fd, 0, 0U, size);
|
||||
if(ret != 0)
|
||||
{
|
||||
logg("FATAL: create_shm(): ftruncate(%i, %zu): Failed to resize shared memory object \"%s\": %s",
|
||||
fd, size, sharedMemory.name, strerror(errno));
|
||||
logg("FATAL: create_shm(): Failed to resize \"%s\" (%i) to %zu: %s (%i)",
|
||||
sharedMemory.name, fd, size, strerror(errno), ret);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
@ -515,8 +516,8 @@ void *enlarge_shmem_struct(const char type)
|
|||
return 0;
|
||||
}
|
||||
|
||||
// Reallocate enough space for 4096 instances of requested object
|
||||
realloc_shm(sharedMemory, sharedMemory->size + allocation_step*sizeofobj, true);
|
||||
// Reallocate enough space for requested object
|
||||
realloc_shm(sharedMemory, sharedMemory->size/sizeofobj + allocation_step, sizeofobj, true);
|
||||
|
||||
// Add allocated memory to corresponding counter
|
||||
*counter += allocation_step;
|
||||
|
@ -524,8 +525,10 @@ void *enlarge_shmem_struct(const char type)
|
|||
return sharedMemory->ptr;
|
||||
}
|
||||
|
||||
bool realloc_shm(SharedMemory *sharedMemory, const size_t size, const bool resize)
|
||||
bool realloc_shm(SharedMemory *sharedMemory, const size_t size1, const size_t size2, const bool resize)
|
||||
{
|
||||
// Absolute target size
|
||||
const size_t size = size1 * size2;
|
||||
// Check if we can skip this routine as nothing is to be done
|
||||
// when an object is not to be resized and its size didn't
|
||||
// change elsewhere
|
||||
|
@ -535,14 +538,15 @@ bool realloc_shm(SharedMemory *sharedMemory, const size_t size, const bool resiz
|
|||
// Log that we are doing something here
|
||||
char df[64] = { 0 };
|
||||
const int percentage = get_dev_shm_usage(df);
|
||||
|
||||
// Log output
|
||||
if(resize)
|
||||
{
|
||||
logg("Resizing \"%s\" from %zu to %zu (%s)", sharedMemory->name, sharedMemory->size, size, df);
|
||||
}
|
||||
logg("Resizing \"%s\" from %zu to (%zu * %zu) == %zu (%s)",
|
||||
sharedMemory->name, sharedMemory->size, size1, size2, size, df);
|
||||
else
|
||||
{
|
||||
logg("Remapping \"%s\" from %zu to %zu", sharedMemory->name, sharedMemory->size, size);
|
||||
}
|
||||
logg("Remapping \"%s\" from %zu to (%zu * %zu) == %zu",
|
||||
sharedMemory->name, sharedMemory->size, size1, size2, size);
|
||||
|
||||
if(percentage > SHMEM_WARN_LIMIT)
|
||||
logg("WARNING: More than %u%% of "SHMEM_PATH" is used", SHMEM_WARN_LIMIT);
|
||||
|
||||
|
@ -561,16 +565,20 @@ bool realloc_shm(SharedMemory *sharedMemory, const size_t size, const bool resiz
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Truncate shared memory object to specified size
|
||||
const int result = ftruncate(fd, size);
|
||||
if(result == -1) {
|
||||
logg("FATAL: realloc_shm(): ftruncate(%i, %zu): Failed to resize \"%s\": %s",
|
||||
fd, size, sharedMemory->name, strerror(errno));
|
||||
// Allocate shared memory object to specified size
|
||||
// Using fallocate() will ensure that there's actually space for
|
||||
// this file. Otherwise we end up with a sparse file that can give
|
||||
// SIGBUS if we run out of space while writing to it.
|
||||
const int ret = fallocate(fd, 0, 0U, size);
|
||||
if(ret != 0)
|
||||
{
|
||||
logg("FATAL: realloc_shm(): Failed to resize \"%s\" (%i) to %zu: %s (%i)",
|
||||
sharedMemory->name, fd, size, strerror(errno), ret);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Close shared memory object file descriptor as it is no longer
|
||||
// needed after having called ftruncate()
|
||||
// needed after having called fallocate()
|
||||
close(fd);
|
||||
|
||||
// Update shm counters to indicate that at least one shared memory object changed
|
||||
|
@ -758,7 +766,7 @@ void add_per_client_regex(unsigned int clientID)
|
|||
counters->num_regex[REGEX_WHITELIST];
|
||||
const size_t size = counters->clients * num_regex_tot;
|
||||
if(size > shm_per_client_regex.size &&
|
||||
realloc_shm(&shm_per_client_regex, size, true))
|
||||
realloc_shm(&shm_per_client_regex, counters->clients, num_regex_tot, true))
|
||||
{
|
||||
reset_per_client_regex(clientID);
|
||||
}
|
||||
|
@ -769,11 +777,12 @@ bool get_per_client_regex(const int clientID, const int regexID)
|
|||
const unsigned int num_regex_tot = counters->num_regex[REGEX_BLACKLIST] +
|
||||
counters->num_regex[REGEX_WHITELIST];
|
||||
const unsigned int id = clientID * num_regex_tot + regexID;
|
||||
const unsigned int maxval = counters->clients * num_regex_tot;
|
||||
const size_t maxval = shm_per_client_regex.size / sizeof(bool);
|
||||
if(id > maxval)
|
||||
{
|
||||
logg("ERROR: get_per_client_regex(%d,%d): Out of bounds (%d > %d * %d == %d)!",
|
||||
clientID, regexID, id, counters->clients-1, num_regex_tot, maxval);
|
||||
logg("ERROR: get_per_client_regex(%d, %d): Out of bounds (%d > %d * %d, shm_per_client_regex.size = %zd)!",
|
||||
clientID, regexID,
|
||||
id, counters->clients, num_regex_tot, maxval);
|
||||
return false;
|
||||
}
|
||||
return ((bool*) shm_per_client_regex.ptr)[id];
|
||||
|
@ -784,12 +793,12 @@ void set_per_client_regex(const int clientID, const int regexID, const bool valu
|
|||
const unsigned int num_regex_tot = counters->num_regex[REGEX_BLACKLIST] +
|
||||
counters->num_regex[REGEX_WHITELIST];
|
||||
const unsigned int id = clientID * num_regex_tot + regexID;
|
||||
const unsigned int maxval = counters->clients * num_regex_tot;
|
||||
const size_t maxval = shm_per_client_regex.size / sizeof(bool);
|
||||
if(id > maxval)
|
||||
{
|
||||
logg("ERROR: set_per_client_regex(%d,%d,%s): Out of bounds (%d > %d * %d == %d)!",
|
||||
logg("ERROR: set_per_client_regex(%d, %d, %s): Out of bounds (%d > %d * %d, shm_per_client_regex.size = %zd)!",
|
||||
clientID, regexID, value ? "true" : "false",
|
||||
id, counters->clients-1, num_regex_tot, maxval);
|
||||
id, counters->clients, num_regex_tot, maxval);
|
||||
return;
|
||||
}
|
||||
((bool*) shm_per_client_regex.ptr)[id] = value;
|
||||
|
|
|
@ -69,10 +69,11 @@ SharedMemory create_shm(const char *name, const size_t size);
|
|||
/// Reallocate shared memory
|
||||
///
|
||||
/// \param sharedMemory the shared memory struct
|
||||
/// \param size the new size
|
||||
/// \param size1 the new size (factor 1)
|
||||
/// \param size2 the new size (factor 2)
|
||||
/// \param resize whether the object should be resized or only remapped
|
||||
/// \return if reallocation was successful
|
||||
bool realloc_shm(SharedMemory *sharedMemory, const size_t size, const bool resize);
|
||||
bool realloc_shm(SharedMemory *sharedMemory, const size_t size1, const size_t size2, const bool resize);
|
||||
|
||||
/// Disconnect from shared memory. If there are no other connections to shared memory, it will be deleted.
|
||||
///
|
||||
|
|
22
src/timers.c
22
src/timers.c
|
@ -22,7 +22,7 @@ void timer_start(const enum timers i)
|
|||
logg("Code error: Timer %i not defined in timer_start().", i);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t0[i]);
|
||||
clock_gettime(CLOCK_REALTIME, &t0[i]);
|
||||
}
|
||||
|
||||
static struct timespec diff(struct timespec start, struct timespec end)
|
||||
|
@ -31,7 +31,7 @@ static struct timespec diff(struct timespec start, struct timespec end)
|
|||
if(end.tv_nsec-start.tv_nsec < 0L)
|
||||
{
|
||||
diff.tv_sec = end.tv_sec - start.tv_sec - 1; // subtract one second here...
|
||||
diff.tv_nsec = 1000000000 + end.tv_nsec - start.tv_nsec; // ...we have to add it here
|
||||
diff.tv_nsec = end.tv_nsec - start.tv_nsec + 1000000000L; // ...we have to add it here
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -49,27 +49,11 @@ double timer_elapsed_msec(const enum timers i)
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
struct timespec t1, td;
|
||||
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t1);
|
||||
clock_gettime(CLOCK_REALTIME, &t1);
|
||||
td = diff(t0[i], t1);
|
||||
return td.tv_sec * 1e3 + td.tv_nsec * 1e-6;
|
||||
}
|
||||
|
||||
unsigned long timer_elapsed_usec(const enum timers i)
|
||||
{
|
||||
struct timespec t1, td;
|
||||
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t1);
|
||||
td = diff(t0[i], t1);
|
||||
return td.tv_sec * 1000000L + td.tv_nsec / 1000;
|
||||
}
|
||||
|
||||
unsigned long long timer_elapsed_nsec(const enum timers i)
|
||||
{
|
||||
struct timespec t1, td;
|
||||
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t1);
|
||||
td = diff(t0[i], t1);
|
||||
return td.tv_sec * 1000000000LL + td.tv_nsec;
|
||||
}
|
||||
|
||||
void sleepms(const int milliseconds)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
|
|
@ -25,8 +25,6 @@ enum timers {
|
|||
|
||||
void timer_start(const enum timers i);
|
||||
double timer_elapsed_msec(const enum timers i);
|
||||
unsigned long timer_elapsed_usec(const enum timers i);
|
||||
unsigned long long timer_elapsed_nsec(const enum timers i);
|
||||
void sleepms(const int milliseconds);
|
||||
|
||||
#endif //TIMERS_H
|
||||
|
|
|
@ -64,31 +64,59 @@ check_file() {
|
|||
echo "Binary classification checks: OK (${1})"
|
||||
}
|
||||
|
||||
check_static() {
|
||||
if readelf -l ./pihole-FTL | grep -q INTERP; then
|
||||
echo "Not a static executable, depends on dynamic interpreter"
|
||||
ldd ./pihole-FTL
|
||||
exit 1
|
||||
fi
|
||||
echo "Static executable check: OK"
|
||||
}
|
||||
|
||||
if [[ "${CIRCLE_JOB}" == "x86_64" ]]; then
|
||||
|
||||
check_machine "ELF64" "Advanced Micro Devices X86-64"
|
||||
check_libs "[librt.so.1] [libpthread.so.0] [libc.so.6]"
|
||||
check_file "ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, not stripped"
|
||||
check_file "ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, with debug_info, not stripped"
|
||||
|
||||
elif [[ "${CIRCLE_JOB}" == "x86_64-musl" ]]; then
|
||||
|
||||
check_machine "ELF64" "Advanced Micro Devices X86-64"
|
||||
check_libs "" # No dependency on any shared library is intended
|
||||
check_file "ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, with debug_info, not stripped"
|
||||
check_static # Binary should not rely on any dynamic interpreter
|
||||
check_file "ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), statically linked, with debug_info, not stripped"
|
||||
|
||||
elif [[ "${CIRCLE_JOB}" == "x86_32" ]]; then
|
||||
|
||||
check_machine "ELF32" "Intel 80386"
|
||||
check_libs "[librt.so.1] [libpthread.so.0] [libc.so.6]"
|
||||
check_file "ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, not stripped"
|
||||
check_file "ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.0, with debug_info, not stripped"
|
||||
|
||||
elif [[ "${CIRCLE_JOB}" == "aarch64" ]]; then
|
||||
|
||||
check_machine "ELF64" "AArch64"
|
||||
check_libs "[librt.so.1] [libpthread.so.0] [libc.so.6] [ld-linux-aarch64.so.1]"
|
||||
check_file "ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, for GNU/Linux 3.7.0, not stripped"
|
||||
check_file "ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, for GNU/Linux 3.7.0, with debug_info, not stripped"
|
||||
|
||||
elif [[ "${CIRCLE_JOB}" == "arm" ]]; then
|
||||
elif [[ "${CIRCLE_JOB}" == "armv4t" ]]; then
|
||||
|
||||
check_machine "ELF32" "ARM"
|
||||
check_libs "[librt.so.1] [libgcc_s.so.1] [libpthread.so.0] [libc.so.6] [ld-linux.so.3]"
|
||||
check_file "ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.3, for GNU/Linux 3.2.0, not stripped"
|
||||
|
||||
check_CPU_arch "v4T"
|
||||
check_FP_arch "" # No specified FP arch
|
||||
|
||||
elif [[ "${CIRCLE_JOB}" == "armv5te" ]]; then
|
||||
|
||||
check_machine "ELF32" "ARM"
|
||||
check_libs "[librt.so.1] [libgcc_s.so.1] [libpthread.so.0] [libc.so.6] [ld-linux.so.3]"
|
||||
check_file "ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.3, for GNU/Linux 3.2.0, with debug_info, not stripped"
|
||||
|
||||
check_CPU_arch "v5TE"
|
||||
check_FP_arch "" # No specified FP arch
|
||||
|
||||
elif [[ "${CIRCLE_JOB}" == "armv6hf" ]]; then
|
||||
|
||||
check_machine "ELF32" "ARM"
|
||||
check_libs "[librt.so.1] [libgcc_s.so.1] [libpthread.so.0] [libc.so.6] [ld-linux-armhf.so.3]"
|
||||
|
@ -97,27 +125,29 @@ elif [[ "${CIRCLE_JOB}" == "arm" ]]; then
|
|||
check_CPU_arch "v6"
|
||||
check_FP_arch "VFPv2"
|
||||
|
||||
elif [[ "${CIRCLE_JOB}" == "armhf" ]]; then
|
||||
elif [[ "${CIRCLE_JOB}" == "armv7hf" ]]; then
|
||||
|
||||
check_machine "ELF32" "ARM"
|
||||
check_libs "[librt.so.1] [libgcc_s.so.1] [libpthread.so.0] [libc.so.6] [ld-linux-armhf.so.3]"
|
||||
check_file "ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, not stripped"
|
||||
check_file "ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, with debug_info, not stripped"
|
||||
|
||||
check_CPU_arch "v7"
|
||||
check_FP_arch "VFPv3-D16"
|
||||
|
||||
elif [[ "${CIRCLE_JOB}" == "arm-qemu" ]]; then
|
||||
elif [[ "${CIRCLE_JOB}" == "armv8a" ]]; then
|
||||
|
||||
check_machine "ELF32" "ARM"
|
||||
check_libs "[librt.so.1] [libgcc_s.so.1] [libpthread.so.0] [libc.so.6] [ld-linux.so.3]"
|
||||
check_file "ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 3.2.0, not stripped"
|
||||
check_libs "[librt.so.1] [libgcc_s.so.1] [libpthread.so.0] [libc.so.6] [ld-linux-armhf.so.3]"
|
||||
check_file "ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, with debug_info, not stripped"
|
||||
|
||||
check_CPU_arch "v6"
|
||||
check_FP_arch "" # No specified FP arch
|
||||
check_CPU_arch "v8"
|
||||
check_FP_arch "VFPv3-D16"
|
||||
|
||||
else
|
||||
|
||||
echo "Invalid job ${CIRCLE_JOB}"
|
||||
exit 1
|
||||
|
||||
fi
|
||||
|
||||
exit 0
|
|
@ -975,3 +975,40 @@
|
|||
[[ ${lines[0]} == "1" ]]
|
||||
}
|
||||
|
||||
@test "EDNS(0) ECS skipped for loopback address (IPv4)" {
|
||||
# Get number of lines in the log before the test
|
||||
before="$(grep -c ^ /var/log/pihole-FTL.log)"
|
||||
|
||||
# Run test command
|
||||
run bash -c 'dig localhost +short +subnet=127.0.0.1/32 @127.0.0.1'
|
||||
printf "%s\n" "${lines[@]}"
|
||||
[[ ${lines[0]} == "127.0.0.1" ]]
|
||||
[[ $status == 0 ]]
|
||||
|
||||
# Get number of lines in the log after the test
|
||||
after="$(grep -c ^ /var/log/pihole-FTL.log)"
|
||||
|
||||
# Extract relevant log lines
|
||||
run bash -c "sed -n \"${before},${after}p\" /var/log/pihole-FTL.log"
|
||||
printf "%s\n" "${lines[@]}"
|
||||
[[ "${lines[@]}" == *"EDNS(0) CLIENT SUBNET: Skipped 127.0.0.1/32 (IPv4 loopback address)"* ]]
|
||||
}
|
||||
|
||||
@test "EDNS(0) ECS skipped for loopback address (IPv6)" {
|
||||
# Get number of lines in the log before the test
|
||||
before="$(grep -c ^ /var/log/pihole-FTL.log)"
|
||||
|
||||
# Run test command
|
||||
run bash -c 'dig localhost +short +subnet=::1/128 @127.0.0.1'
|
||||
printf "%s\n" "${lines[@]}"
|
||||
[[ ${lines[0]} == "127.0.0.1" ]]
|
||||
[[ $status == 0 ]]
|
||||
|
||||
# Get number of lines in the log after the test
|
||||
after="$(grep -c ^ /var/log/pihole-FTL.log)"
|
||||
|
||||
# Extract relevant log lines
|
||||
run bash -c "sed -n \"${before},${after}p\" /var/log/pihole-FTL.log"
|
||||
printf "%s\n" "${lines[@]}"
|
||||
[[ "${lines[@]}" == *"EDNS(0) CLIENT SUBNET: Skipped ::1/128 (IPv6 loopback address)"* ]]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue