mirror of
https://github.com/pi-hole/FTL.git
synced 2024-10-26 16:52:18 +02:00
Merge pull request #836 from pi-hole/release/v5.1
Release/v5.1 -> development
This commit is contained in:
@@ -114,6 +114,7 @@ set(sources
|
||||
datastructure.h
|
||||
dnsmasq_interface.c
|
||||
dnsmasq_interface.h
|
||||
enums.h
|
||||
files.c
|
||||
files.h
|
||||
FTL.h
|
||||
|
||||
@@ -103,17 +103,6 @@
|
||||
// Default: 1000 (one second)
|
||||
#define DATABASE_BUSY_TIMEOUT 1000
|
||||
|
||||
// FTLDNS enums
|
||||
enum { QUERIES, UPSTREAMS, CLIENTS, DOMAINS, OVERTIME, WILDCARD, DNS_CACHE };
|
||||
enum { DNSSEC_UNSPECIFIED, DNSSEC_SECURE, DNSSEC_INSECURE, DNSSEC_BOGUS, DNSSEC_ABANDONED };
|
||||
enum { QUERY_UNKNOWN, QUERY_GRAVITY, QUERY_FORWARDED, QUERY_CACHE, QUERY_REGEX, QUERY_BLACKLIST, \
|
||||
QUERY_EXTERNAL_BLOCKED_IP, QUERY_EXTERNAL_BLOCKED_NULL, QUERY_EXTERNAL_BLOCKED_NXRA, \
|
||||
QUERY_GRAVITY_CNAME, QUERY_REGEX_CNAME, QUERY_BLACKLIST_CNAME, QUERY_STATUS_MAX };
|
||||
enum { REPLY_UNKNOWN, REPLY_NODATA, REPLY_NXDOMAIN, REPLY_CNAME, REPLY_IP, REPLY_DOMAIN, REPLY_RRNAME, REPLY_SERVFAIL, REPLY_REFUSED, REPLY_NOTIMP, REPLY_OTHER };
|
||||
enum { PRIVACY_SHOW_ALL = 0, PRIVACY_HIDE_DOMAINS, PRIVACY_HIDE_DOMAINS_CLIENTS, PRIVACY_MAXIMUM, PRIVACY_NOSTATS };
|
||||
enum { MODE_IP, MODE_NX, MODE_NULL, MODE_IP_NODATA_AAAA, MODE_NODATA };
|
||||
enum { REGEX_BLACKLIST, REGEX_WHITELIST };
|
||||
|
||||
// Use out own memory handling functions that will detect possible errors
|
||||
// and report accordingly in the log. This will make debugging FTL crashs
|
||||
// caused by insufficient memory or by code bugs (not properly dealing
|
||||
|
||||
+7
-3
@@ -9,6 +9,7 @@
|
||||
* Please see LICENSE file for your rights under this license. */
|
||||
|
||||
#include "FTL.h"
|
||||
#include "enums.h"
|
||||
#include "memory.h"
|
||||
#include "shmem.h"
|
||||
#include "datastructure.h"
|
||||
@@ -1368,15 +1369,18 @@ void getDomainDetails(const char *client_message, const int *sock)
|
||||
case UNKNOWN_BLOCKED:
|
||||
str = "unknown";
|
||||
break;
|
||||
case BLACKLIST_BLOCKED:
|
||||
str = "blacklisted";
|
||||
break;
|
||||
case GRAVITY_BLOCKED:
|
||||
str = "gravity";
|
||||
break;
|
||||
case BLACKLIST_BLOCKED:
|
||||
str = "blacklisted";
|
||||
break;
|
||||
case REGEX_BLOCKED:
|
||||
str = "regex";
|
||||
break;
|
||||
case WHITELISTED:
|
||||
str = "whitelisted";
|
||||
break;
|
||||
case NOT_BLOCKED:
|
||||
str = "not blocked";
|
||||
break;
|
||||
|
||||
+40
-69
@@ -29,27 +29,11 @@
|
||||
#define BACKLOG 5
|
||||
|
||||
// File descriptors
|
||||
int socketfd, telnetfd4 = 0, telnetfd6 = 0;
|
||||
int socketfd = 0, telnetfd4 = 0, telnetfd6 = 0;
|
||||
bool dualstack = false;
|
||||
bool ipv4telnet = false, ipv6telnet = false;
|
||||
bool sock_avail = false;
|
||||
bool ipv4telnet = false, ipv6telnet = false, sock_avail = false;
|
||||
bool istelnet[MAXCONNS];
|
||||
|
||||
static void saveport(void)
|
||||
{
|
||||
FILE *f;
|
||||
if((f = fopen(FTLfiles.port, "w+")) == NULL)
|
||||
{
|
||||
logg("WARNING: Unable to write used port to file.");
|
||||
logg(" Continuing anyway (API might not find the port).");
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(f, "%i", config.port);
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
|
||||
static bool bind_to_telnet_port_IPv4(int *socketdescriptor)
|
||||
{
|
||||
// IPv4 socket
|
||||
@@ -161,15 +145,14 @@ static bool bind_to_telnet_port_IPv6(int *socketdescriptor)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void bind_to_unix_socket(int *socketdescriptor)
|
||||
static bool bind_to_unix_socket(int *socketdescriptor)
|
||||
{
|
||||
*socketdescriptor = socket(AF_LOCAL, SOCK_STREAM, 0);
|
||||
|
||||
if(*socketdescriptor < 0)
|
||||
{
|
||||
logg("WARNING: Error opening Unix socket.");
|
||||
logg(" Continuing anyway.");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure unix socket file handle does not exist, if it exists, remove it
|
||||
@@ -190,32 +173,18 @@ static void bind_to_unix_socket(int *socketdescriptor)
|
||||
if(bind(*socketdescriptor, (struct sockaddr *) &address, sizeof (address)) != 0)
|
||||
{
|
||||
logg("WARNING: Cannot bind on Unix socket %s: %s (%i)", FTLfiles.socketfile, strerror(errno), errno);
|
||||
logg(" Continuing anyway.");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// The listen system call allows the process to listen on the Unix socket for connections
|
||||
if(listen(*socketdescriptor, BACKLOG) == -1)
|
||||
{
|
||||
logg("WARNING: Cannot listen on Unix socket: %s (%i)", strerror(errno), errno);
|
||||
logg(" Continuing anyway.");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
logg("Listening on Unix socket");
|
||||
sock_avail = true;
|
||||
}
|
||||
|
||||
// Called from main() at graceful shutdown
|
||||
static void removeport(void)
|
||||
{
|
||||
FILE *f;
|
||||
if((f = fopen(FTLfiles.port, "w+")) == NULL)
|
||||
{
|
||||
logg("WARNING: Unable to empty port file");
|
||||
return;
|
||||
}
|
||||
fclose(f);
|
||||
return true;
|
||||
}
|
||||
|
||||
void seom(const int sock)
|
||||
@@ -295,7 +264,6 @@ static int listener(const int sockfd, const char type)
|
||||
|
||||
void close_telnet_socket(void)
|
||||
{
|
||||
removeport();
|
||||
// Using global variable here
|
||||
if(telnetfd4)
|
||||
close(telnetfd4);
|
||||
@@ -303,12 +271,17 @@ void close_telnet_socket(void)
|
||||
close(telnetfd6);
|
||||
}
|
||||
|
||||
void close_unix_socket(void)
|
||||
void close_unix_socket(bool unlink_file)
|
||||
{
|
||||
// The process has to take care of unlinking the socket file description on exit
|
||||
unlink(FTLfiles.socketfile);
|
||||
if(unlink_file)
|
||||
{
|
||||
// The process has to take care of unlinking the socket file description on exit
|
||||
unlink(FTLfiles.socketfile);
|
||||
}
|
||||
|
||||
// Using global variable here
|
||||
close(socketfd);
|
||||
if(sock_avail)
|
||||
close(socketfd);
|
||||
}
|
||||
|
||||
static void *telnet_connection_handler_thread(void *socket_desc)
|
||||
@@ -413,24 +386,6 @@ static void *socket_connection_handler_thread(void *socket_desc)
|
||||
return false;
|
||||
}
|
||||
|
||||
void bind_sockets(void)
|
||||
{
|
||||
// Initialize IPv4 telnet socket
|
||||
if(bind_to_telnet_port_IPv4(&telnetfd4))
|
||||
ipv4telnet = true;
|
||||
|
||||
// Initialize IPv6 telnet socket
|
||||
// only if IPv6 interfaces are available
|
||||
if(ipv6_available())
|
||||
if(bind_to_telnet_port_IPv6(&telnetfd6))
|
||||
ipv6telnet = true;
|
||||
|
||||
saveport();
|
||||
|
||||
// Initialize Unix socket
|
||||
bind_to_unix_socket(&socketfd);
|
||||
}
|
||||
|
||||
void *telnet_listening_thread_IPv4(void *args)
|
||||
{
|
||||
// We will use the attributes object later to start all threads in detached mode
|
||||
@@ -444,6 +399,11 @@ void *telnet_listening_thread_IPv4(void *args)
|
||||
// Set thread name
|
||||
prctl(PR_SET_NAME,"telnet-IPv4",0,0,0);
|
||||
|
||||
// Initialize IPv4 telnet socket
|
||||
ipv4telnet = bind_to_telnet_port_IPv4(&telnetfd4);
|
||||
if(!ipv4telnet)
|
||||
return NULL;
|
||||
|
||||
// Listen as long as FTL is not killed
|
||||
while(!killed)
|
||||
{
|
||||
@@ -466,7 +426,7 @@ void *telnet_listening_thread_IPv4(void *args)
|
||||
if(pthread_create( &telnet_connection_thread, &attr, telnet_connection_handler_thread, (void*) newsock ) != 0)
|
||||
{
|
||||
// Log the error code description
|
||||
logg("WARNING: Unable to open telnet processing thread, error: %s", strerror(errno));
|
||||
logg("WARNING: Unable to open telnet processing thread: %s", strerror(errno));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@@ -485,6 +445,14 @@ void *telnet_listening_thread_IPv6(void *args)
|
||||
// Set thread name
|
||||
prctl(PR_SET_NAME,"telnet-IPv6",0,0,0);
|
||||
|
||||
// Initialize IPv6 telnet socket but only if IPv6 interfaces are available
|
||||
if(!ipv6_available())
|
||||
return NULL;
|
||||
|
||||
ipv6telnet = bind_to_telnet_port_IPv6(&telnetfd6);
|
||||
if(!ipv6telnet)
|
||||
return NULL;
|
||||
|
||||
// Listen as long as FTL is not killed
|
||||
while(!killed)
|
||||
{
|
||||
@@ -507,7 +475,7 @@ void *telnet_listening_thread_IPv6(void *args)
|
||||
if(pthread_create( &telnet_connection_thread, &attr, telnet_connection_handler_thread, (void*) newsock ) != 0)
|
||||
{
|
||||
// Log the error code description
|
||||
logg("WARNING: Unable to open telnet processing thread, error: %s", strerror(errno));
|
||||
logg("WARNING: Unable to open telnet processing thread: %s", strerror(errno));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@@ -527,7 +495,8 @@ void *socket_listening_thread(void *args)
|
||||
prctl(PR_SET_NAME,"socket listener",0,0,0);
|
||||
|
||||
// Return early to avoid CPU spinning if Unix socket is not available
|
||||
if(!sock_avail)
|
||||
sock_avail = bind_to_unix_socket(&socketfd);
|
||||
if(sock_avail)
|
||||
return NULL;
|
||||
|
||||
// Listen as long as FTL is not killed
|
||||
@@ -535,7 +504,8 @@ void *socket_listening_thread(void *args)
|
||||
{
|
||||
// Look for new clients that want to connect
|
||||
const int csck = listener(socketfd, 0);
|
||||
if(csck < 0) continue;
|
||||
if(csck < 0)
|
||||
continue;
|
||||
|
||||
// Allocate memory used to transport client socket ID to client listening thread
|
||||
int *newsock;
|
||||
@@ -548,7 +518,7 @@ void *socket_listening_thread(void *args)
|
||||
if(pthread_create( &socket_connection_thread, &attr, socket_connection_handler_thread, (void*) newsock ) != 0)
|
||||
{
|
||||
// Log the error code description
|
||||
logg("WARNING: Unable to open socket processing thread, error: %s", strerror(errno));
|
||||
logg("WARNING: Unable to open socket processing thread: %s", strerror(errno));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@@ -557,6 +527,7 @@ void *socket_listening_thread(void *args)
|
||||
bool ipv6_available(void)
|
||||
{
|
||||
struct ifaddrs *allInterfaces;
|
||||
enum { IPv4, IPv6 };
|
||||
int iface[2] = { 0 };
|
||||
|
||||
// Get all interfaces
|
||||
@@ -572,7 +543,7 @@ bool ipv6_available(void)
|
||||
// Check only for up and running IPv4, IPv6 interfaces
|
||||
if ((flags & (IFF_UP|IFF_RUNNING)) && addr != NULL)
|
||||
{
|
||||
iface[addr->sa_family == AF_INET6 ? 1 : 0]++;
|
||||
iface[addr->sa_family == AF_INET6 ? IPv6 : IPv4]++;
|
||||
|
||||
if(config.debug & DEBUG_NETWORKING)
|
||||
logg("Interface %s is %s", interface->ifa_name, addr->sa_family == AF_INET6 ? "IPv6" : "IPv4");
|
||||
@@ -583,8 +554,8 @@ bool ipv6_available(void)
|
||||
|
||||
if(config.debug & DEBUG_NETWORKING)
|
||||
{
|
||||
logg("Found %i IPv4 and %i IPv6 capable interfaces", iface[0], iface[1]);
|
||||
logg("Found %i IPv4 and %i IPv6 capable interfaces", iface[IPv4], iface[IPv6]);
|
||||
}
|
||||
|
||||
return (iface[1] > 0);
|
||||
return (iface[IPv6] > 0);
|
||||
}
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@
|
||||
#define SOCKET_H
|
||||
|
||||
void close_telnet_socket(void);
|
||||
void close_unix_socket(void);
|
||||
void close_unix_socket(bool unlink_file);
|
||||
void seom(const int sock);
|
||||
void ssend(const int sock, const char *format, ...) __attribute__ ((format (gnu_printf, 2, 3)));
|
||||
void swrite(const int sock, const void* value, const size_t size);
|
||||
|
||||
+1
-5
@@ -29,7 +29,6 @@ FTLFileNamesStruct FTLfiles = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -301,9 +300,6 @@ void read_FTLconf(void)
|
||||
// PIDFILE
|
||||
getpath(fp, "PIDFILE", "/run/pihole-FTL.pid", &FTLfiles.pid);
|
||||
|
||||
// PORTFILE
|
||||
getpath(fp, "PORTFILE", "/run/pihole-FTL.port", &FTLfiles.port);
|
||||
|
||||
// SOCKETFILE
|
||||
getpath(fp, "SOCKETFILE", "/run/pihole/FTL.sock", &FTLfiles.socketfile);
|
||||
|
||||
@@ -512,7 +508,7 @@ void get_privacy_level(FILE *fp)
|
||||
{
|
||||
// Check for change and validity of privacy level (set in FTL.h)
|
||||
if(value >= PRIVACY_SHOW_ALL &&
|
||||
value <= PRIVACY_NOSTATS &&
|
||||
value <= PRIVACY_MAXIMUM &&
|
||||
value > config.privacylevel)
|
||||
{
|
||||
logg("Notice: Increasing privacy level from %i to %i", config.privacylevel, value);
|
||||
|
||||
+5
-22
@@ -10,6 +10,9 @@
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
// enum privacy_level
|
||||
#include "enums.h"
|
||||
|
||||
// typedef int16_t
|
||||
#include <sys/types.h>
|
||||
|
||||
@@ -27,8 +30,8 @@ typedef struct {
|
||||
int dns_port;
|
||||
unsigned int delay_startup;
|
||||
int16_t debug;
|
||||
unsigned char privacylevel;
|
||||
unsigned char blockingmode;
|
||||
enum privacy_level privacylevel;
|
||||
enum blocking_mode blockingmode;
|
||||
bool socket_listenlocal;
|
||||
bool analyze_AAAA;
|
||||
bool resolveIPv6;
|
||||
@@ -47,7 +50,6 @@ typedef struct {
|
||||
const char* snapConf;
|
||||
char* log;
|
||||
char* pid;
|
||||
char* port;
|
||||
char* socketfile;
|
||||
char* FTL_db;
|
||||
char* gravity_db;
|
||||
@@ -59,23 +61,4 @@ typedef struct {
|
||||
extern ConfigStruct config;
|
||||
extern FTLFileNamesStruct FTLfiles;
|
||||
|
||||
enum {
|
||||
DEBUG_DATABASE = (1 << 0), /* 00000000 00000001 */
|
||||
DEBUG_NETWORKING = (1 << 1), /* 00000000 00000010 */
|
||||
DEBUG_LOCKS = (1 << 2), /* 00000000 00000100 */
|
||||
DEBUG_QUERIES = (1 << 3), /* 00000000 00001000 */
|
||||
DEBUG_FLAGS = (1 << 4), /* 00000000 00010000 */
|
||||
DEBUG_SHMEM = (1 << 5), /* 00000000 00100000 */
|
||||
DEBUG_GC = (1 << 6), /* 00000000 01000000 */
|
||||
DEBUG_ARP = (1 << 7), /* 00000000 10000000 */
|
||||
DEBUG_REGEX = (1 << 8), /* 00000001 00000000 */
|
||||
DEBUG_API = (1 << 9), /* 00000010 00000000 */
|
||||
DEBUG_OVERTIME = (1 << 10), /* 00000100 00000000 */
|
||||
DEBUG_EXTBLOCKED = (1 << 11), /* 00001000 00000000 */
|
||||
DEBUG_CAPS = (1 << 12), /* 00010000 00000000 */
|
||||
DEBUG_DNSMASQ_LINES = (1 << 13), /* 00100000 00000000 */
|
||||
DEBUG_VECTORS = (1 << 14), /* 01000000 00000000 */
|
||||
DEBUG_RESOLVER = (1 << 15), /* 10000000 00000000 */
|
||||
};
|
||||
|
||||
#endif //CONFIG_H
|
||||
|
||||
@@ -141,3 +141,19 @@ void delay_startup(void)
|
||||
sleep(config.delay_startup);
|
||||
logg("Done sleeping, continuing startup of resolver...\n");
|
||||
}
|
||||
|
||||
// Is this a fork?
|
||||
bool __attribute__ ((const)) is_fork(const pid_t mpid, const pid_t pid)
|
||||
{
|
||||
return mpid > -1 && mpid != pid;
|
||||
}
|
||||
|
||||
pid_t FTL_gettid(void)
|
||||
{
|
||||
#ifdef SYS_gettid
|
||||
return (pid_t)syscall(SYS_gettid);
|
||||
#else
|
||||
#warning SYS_gettid is not available on this system
|
||||
return -1;
|
||||
#endif // SYS_gettid
|
||||
}
|
||||
|
||||
@@ -15,5 +15,22 @@ void savepid(void);
|
||||
char * getUserName(void);
|
||||
void removepid(void);
|
||||
void delay_startup(void);
|
||||
bool is_fork(const pid_t mpid, const pid_t pid) __attribute__ ((const));
|
||||
|
||||
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
// Get ID of current thread (incorrectly shown as "PID" in, e.g., htop)
|
||||
// We define this wrapper ourselves as the GNU C Library only added it
|
||||
// in 2019 meaning that, while we're writing this, it will not be widely
|
||||
// available. It was only added even later (end of 2019) to musl libc.
|
||||
// https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=1d0fc213824eaa2a8f8c4385daaa698ee8fb7c92
|
||||
// https://www.openwall.com/lists/musl/2019/08/01/11
|
||||
// To avoid any conflicts, also in the future, we use our own macro for this
|
||||
#if !defined(SYS_gettid) && defined(__NR_gettid)
|
||||
#define SYS_gettid __NR_gettid
|
||||
#endif // !SYS_gettid && __NR_gettid
|
||||
pid_t FTL_gettid(void);
|
||||
#define gettid FTL_gettid
|
||||
|
||||
#endif //DAEMON_H
|
||||
|
||||
@@ -377,7 +377,7 @@ void db_init(void)
|
||||
logg("Database successfully initialized");
|
||||
}
|
||||
|
||||
int db_get_FTL_property(const unsigned int ID)
|
||||
int db_get_FTL_property(const enum ftl_table_props ID)
|
||||
{
|
||||
if(!database || FTL_db == NULL)
|
||||
{
|
||||
@@ -400,7 +400,7 @@ int db_get_FTL_property(const unsigned int ID)
|
||||
return value;
|
||||
}
|
||||
|
||||
bool db_set_FTL_property(const unsigned int ID, const int value)
|
||||
bool db_set_FTL_property(const enum ftl_table_props ID, const int value)
|
||||
{
|
||||
if(!database || FTL_db == NULL)
|
||||
{
|
||||
@@ -410,7 +410,7 @@ bool db_set_FTL_property(const unsigned int ID, const int value)
|
||||
return dbquery("INSERT OR REPLACE INTO ftl (id, value) VALUES ( %u, %i );", ID, value) == SQLITE_OK;
|
||||
}
|
||||
|
||||
bool db_set_counter(const unsigned int ID, const int value)
|
||||
bool db_set_counter(const enum counters_table_props ID, const int value)
|
||||
{
|
||||
if(!database || FTL_db == NULL)
|
||||
{
|
||||
|
||||
+16
-8
@@ -12,9 +12,22 @@
|
||||
|
||||
#include "sqlite3.h"
|
||||
|
||||
// Database table "ftl"
|
||||
enum ftl_table_props {
|
||||
DB_VERSION,
|
||||
DB_LASTTIMESTAMP,
|
||||
DB_FIRSTCOUNTERTIMESTAMP
|
||||
} __attribute__ ((packed));
|
||||
|
||||
// Database table "counters"
|
||||
enum counters_table_props {
|
||||
DB_TOTALQUERIES,
|
||||
DB_BLOCKEDQUERIES
|
||||
} __attribute__ ((packed));
|
||||
|
||||
void db_init(void);
|
||||
int db_get_FTL_property(const unsigned int ID);
|
||||
bool db_set_FTL_property(const unsigned int ID, const int value);
|
||||
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);
|
||||
|
||||
/// Execute a formatted SQL query and get the return code
|
||||
int dbquery(const char *format, ...);
|
||||
@@ -26,7 +39,7 @@ int db_query_int(const char*);
|
||||
long get_lastID(void);
|
||||
void SQLite3LogCallback(void *pArg, int iErrCode, const char *zMsg);
|
||||
long int get_max_query_ID(void);
|
||||
bool db_set_counter(const unsigned int ID, const int value);
|
||||
bool db_set_counter(const enum counters_table_props ID, const int value);
|
||||
bool db_update_counters(const int total, const int blocked);
|
||||
const char *get_sqlite3_version(void);
|
||||
bool use_database(void) __attribute__ ((pure));
|
||||
@@ -59,9 +72,4 @@ extern bool DBdeleteoldqueries;
|
||||
}\
|
||||
}
|
||||
|
||||
// Database table "ftl"
|
||||
enum { DB_VERSION, DB_LASTTIMESTAMP, DB_FIRSTCOUNTERTIMESTAMP };
|
||||
// Database table "counters"
|
||||
enum { DB_TOTALQUERIES, DB_BLOCKEDQUERIES };
|
||||
|
||||
#endif //DATABASE_COMMON_H
|
||||
|
||||
+31
-69
@@ -34,39 +34,16 @@ static sqlite3 *gravity_db = NULL;
|
||||
static sqlite3_stmt* table_stmt = NULL;
|
||||
static sqlite3_stmt* auditlist_stmt = NULL;
|
||||
bool gravityDB_opened = false;
|
||||
static pid_t main_process = 0, this_process = 0;
|
||||
|
||||
// Table names corresponding to the enum defined in gravity-db.h
|
||||
static const char* tablename[] = { "vw_gravity", "vw_blacklist", "vw_whitelist", "vw_regex_blacklist", "vw_regex_whitelist" , ""};
|
||||
static const char* tablename[] = { "vw_gravity", "vw_blacklist", "vw_whitelist", "vw_regex_blacklist", "vw_regex_whitelist" , "" };
|
||||
|
||||
// Prototypes from functions in dnsmasq's source
|
||||
void rehash(int size);
|
||||
|
||||
// Initialize gravity subroutines
|
||||
static void gravityDB_check_fork(void)
|
||||
void gravityDB_forked(void)
|
||||
{
|
||||
// Memorize main process PID on first call of this funtion (guaranteed to be
|
||||
// the main dnsmasq thread)
|
||||
if(main_process == 0)
|
||||
{
|
||||
main_process = getpid();
|
||||
this_process = main_process;
|
||||
}
|
||||
|
||||
if(this_process == getpid())
|
||||
return;
|
||||
|
||||
// If we reach this point, FTL forked to handle TCP connections with
|
||||
// dedicated (forked) workers SQLite3's mentions that carrying an open
|
||||
// database connection across a fork() can lead to all kinds of locking
|
||||
// problems as SQLite3 was not intended to work under such circumstances.
|
||||
// Doing so may easily lead to ending up with a corrupted database.
|
||||
logg("Note: FTL forked to handle TCP requests");
|
||||
|
||||
// Memorize PID of this thread to avoid re-opening the gravity database
|
||||
// connection multiple times for the same fork
|
||||
this_process = getpid();
|
||||
|
||||
// Pretend that we did not open the database so far so it needs to be
|
||||
// re-opened, also pretend we have not yet prepared the list statements
|
||||
gravityDB_opened = false;
|
||||
@@ -546,9 +523,6 @@ void gravityDB_close(void)
|
||||
// blocking domains from a table which is specified when calling this function
|
||||
bool gravityDB_getTable(const unsigned char list)
|
||||
{
|
||||
// First check if FTL forked to handle TCP connections
|
||||
gravityDB_check_fork();
|
||||
|
||||
if(!gravityDB_opened && !gravityDB_open())
|
||||
{
|
||||
logg("gravityDB_getTable(%u): Gravity database not available", list);
|
||||
@@ -637,7 +611,7 @@ void gravityDB_finalizeTable(void)
|
||||
// Get number of domains in a specified table of the gravity database
|
||||
// We return the constant DB_FAILED and log to pihole-FTL.log if we
|
||||
// encounter any error
|
||||
int gravityDB_count(const unsigned char list)
|
||||
int gravityDB_count(const enum gravity_tables list)
|
||||
{
|
||||
if(!gravityDB_opened && !gravityDB_open())
|
||||
{
|
||||
@@ -645,31 +619,37 @@ int gravityDB_count(const unsigned char list)
|
||||
return DB_FAILED;
|
||||
}
|
||||
|
||||
// Checking for smaller than GRAVITY_LIST is omitted due to list being unsigned
|
||||
if(list >= UNKNOWN_TABLE)
|
||||
const char *querystr = NULL;
|
||||
// Build query string to be used depending on list to be read
|
||||
switch (list)
|
||||
{
|
||||
logg("gravityDB_getTable(%u): Requested list is not known!", list);
|
||||
return false;
|
||||
}
|
||||
|
||||
char *querystr = NULL;
|
||||
// Build correct query string to be used depending on list to be read
|
||||
if(list != GRAVITY_TABLE && asprintf(&querystr, "SELECT COUNT(DISTINCT domain) FROM %s", tablename[list]) < 18)
|
||||
{
|
||||
logg("readGravity(%u) - asprintf() error", list);
|
||||
return false;
|
||||
}
|
||||
// We get the number of unique gravity domains as counted and stored by gravity. Counting the number
|
||||
// of distinct domains in vw_gravity may take up to several minutes for very large blocking lists on
|
||||
// very low-end devices such as the Raspierry Pi Zero
|
||||
else if(list == GRAVITY_TABLE && asprintf(&querystr, "SELECT value FROM info WHERE property = 'gravity_count';") < 18)
|
||||
{
|
||||
logg("readGravity(%u) - asprintf() error", list);
|
||||
return false;
|
||||
case GRAVITY_TABLE:
|
||||
// We get the number of unique gravity domains as counted and stored by gravity. Counting the number
|
||||
// of distinct domains in vw_gravity may take up to several minutes for very large blocking lists on
|
||||
// very low-end devices such as the Raspierry Pi Zero
|
||||
querystr = "SELECT value FROM info WHERE property = 'gravity_count';";
|
||||
break;
|
||||
case EXACT_BLACKLIST_TABLE:
|
||||
querystr = "SELECT COUNT(DISTINCT domain) FROM vw_blacklist";
|
||||
break;
|
||||
case EXACT_WHITELIST_TABLE:
|
||||
querystr = "SELECT COUNT(DISTINCT domain) FROM vw_whitelist";
|
||||
break;
|
||||
case REGEX_BLACKLIST_TABLE:
|
||||
querystr = "SELECT COUNT(DISTINCT domain) FROM vw_regex_blacklist";
|
||||
break;
|
||||
case REGEX_WHITELIST_TABLE:
|
||||
querystr = "SELECT COUNT(DISTINCT domain) FROM vw_regex_whitelist";
|
||||
break;
|
||||
case UNKNOWN_TABLE:
|
||||
logg("Error: List type %u unknown!", list);
|
||||
gravityDB_close();
|
||||
return DB_FAILED;
|
||||
}
|
||||
|
||||
if(config.debug & DEBUG_DATABASE)
|
||||
logg("Querying count of distinct domains in gravity database table %s", tablename[list]);
|
||||
logg("Querying count of distinct domains in gravity database table %s: %s",
|
||||
tablename[list], querystr);
|
||||
|
||||
// Prepare query
|
||||
int rc = sqlite3_prepare_v2(gravity_db, querystr, -1, &table_stmt, NULL);
|
||||
@@ -677,7 +657,6 @@ int gravityDB_count(const unsigned char list)
|
||||
logg("gravityDB_count(%s) - SQL error prepare %s", querystr, sqlite3_errstr(rc));
|
||||
gravityDB_finalizeTable();
|
||||
gravityDB_close();
|
||||
free(querystr);
|
||||
return DB_FAILED;
|
||||
}
|
||||
|
||||
@@ -691,7 +670,6 @@ int gravityDB_count(const unsigned char list)
|
||||
}
|
||||
gravityDB_finalizeTable();
|
||||
gravityDB_close();
|
||||
free(querystr);
|
||||
return DB_FAILED;
|
||||
}
|
||||
|
||||
@@ -701,8 +679,7 @@ int gravityDB_count(const unsigned char list)
|
||||
// Finalize statement
|
||||
gravityDB_finalizeTable();
|
||||
|
||||
// Free allocated memory and return result
|
||||
free(querystr);
|
||||
// Return result
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -777,9 +754,6 @@ static bool domain_in_list(const char *domain, sqlite3_stmt* stmt, const char* l
|
||||
|
||||
bool in_whitelist(const char *domain, const int clientID, clientsData* client)
|
||||
{
|
||||
// First check if FTL forked to handle TCP connections
|
||||
gravityDB_check_fork();
|
||||
|
||||
// If list statement is not ready and cannot be initialized (e.g. no
|
||||
// access to the database), we return false to prevent an FTL crash
|
||||
if(whitelist_stmt == NULL)
|
||||
@@ -814,9 +788,6 @@ bool in_whitelist(const char *domain, const int clientID, clientsData* client)
|
||||
|
||||
bool in_gravity(const char *domain, const int clientID, clientsData* client)
|
||||
{
|
||||
// First check if FTL forked to handle TCP connections
|
||||
gravityDB_check_fork();
|
||||
|
||||
// If list statement is not ready and cannot be initialized (e.g. no
|
||||
// access to the database), we return false to prevent an FTL crash
|
||||
if(gravity_stmt == NULL)
|
||||
@@ -844,9 +815,6 @@ bool in_gravity(const char *domain, const int clientID, clientsData* client)
|
||||
|
||||
inline bool in_blacklist(const char *domain, const int clientID, clientsData* client)
|
||||
{
|
||||
// First check if FTL forked to handle TCP connections
|
||||
gravityDB_check_fork();
|
||||
|
||||
// If list statement is not ready and cannot be initialized (e.g. no
|
||||
// access to the database), we return false to prevent an FTL crash
|
||||
if(blacklist_stmt == NULL)
|
||||
@@ -874,9 +842,6 @@ inline bool in_blacklist(const char *domain, const int clientID, clientsData* cl
|
||||
|
||||
bool in_auditlist(const char *domain)
|
||||
{
|
||||
// First check if FTL forked to handle TCP connections
|
||||
gravityDB_check_fork();
|
||||
|
||||
// If audit list statement is not ready and cannot be initialized (e.g. no access
|
||||
// to the database), we return false (not in audit list) to prevent an FTL crash
|
||||
if(auditlist_stmt == NULL)
|
||||
@@ -889,9 +854,6 @@ bool in_auditlist(const char *domain)
|
||||
bool gravityDB_get_regex_client_groups(clientsData* client, const int numregex, const int *regexid,
|
||||
const unsigned char type, const char* table, const int clientID)
|
||||
{
|
||||
// First check if FTL forked to handle TCP connections
|
||||
gravityDB_check_fork();
|
||||
|
||||
char *querystr = NULL;
|
||||
if(!client->found_group && !get_client_groupids(client))
|
||||
return false;
|
||||
|
||||
@@ -16,8 +16,9 @@
|
||||
#include "datastructure.h"
|
||||
|
||||
// Table indices
|
||||
enum { GRAVITY_TABLE, EXACT_BLACKLIST_TABLE, EXACT_WHITELIST_TABLE, REGEX_BLACKLIST_TABLE, REGEX_WHITELIST_TABLE, UNKNOWN_TABLE };
|
||||
enum gravity_tables { GRAVITY_TABLE, EXACT_BLACKLIST_TABLE, EXACT_WHITELIST_TABLE, REGEX_BLACKLIST_TABLE, REGEX_WHITELIST_TABLE, UNKNOWN_TABLE } __attribute__ ((packed));
|
||||
|
||||
void gravityDB_forked(void);
|
||||
bool gravityDB_open(void);
|
||||
bool gravityDB_prepare_client_statements(const int clientID, clientsData* client);
|
||||
void gravityDB_close(void);
|
||||
@@ -25,7 +26,7 @@ bool gravityDB_getTable(unsigned char list);
|
||||
const char* gravityDB_getDomain(int *rowid);
|
||||
char* get_group_names(const char *group_ids) __attribute__ ((malloc));
|
||||
void gravityDB_finalizeTable(void);
|
||||
int gravityDB_count(unsigned char list);
|
||||
int gravityDB_count(const enum gravity_tables list);
|
||||
bool in_auditlist(const char *domain);
|
||||
|
||||
bool in_gravity(const char *domain, const int clientID, clientsData* client);
|
||||
|
||||
@@ -46,10 +46,6 @@ int get_number_of_queries_in_DB(void)
|
||||
|
||||
void DB_save_queries(void)
|
||||
{
|
||||
// Don't save anything to the database if in PRIVACY_NOSTATS mode
|
||||
if(config.privacylevel >= PRIVACY_NOSTATS)
|
||||
return;
|
||||
|
||||
// Start database timer
|
||||
if(config.debug & DEBUG_DATABASE)
|
||||
timer_start(DATABASE_WRITE_TIMER);
|
||||
@@ -296,10 +292,6 @@ void delete_old_queries_in_DB(void)
|
||||
// Get most recent 24 hours data from long-term database
|
||||
void DB_read_queries(void)
|
||||
{
|
||||
// Don't try to load anything to the database if in PRIVACY_NOSTATS mode
|
||||
if(config.privacylevel >= PRIVACY_NOSTATS)
|
||||
return;
|
||||
|
||||
// Open database file
|
||||
if(!dbopen())
|
||||
{
|
||||
|
||||
+9
-9
@@ -13,6 +13,9 @@
|
||||
// Definition of sqlite3_stmt
|
||||
#include "database/sqlite3.h"
|
||||
|
||||
// enum privacy_level
|
||||
#include "enums.h"
|
||||
|
||||
void strtolower(char *str);
|
||||
int findUpstreamID(const char * upstream, const bool count);
|
||||
int findDomainID(const char *domain, const bool count);
|
||||
@@ -24,16 +27,13 @@ bool isValidIPv6(const char *addr);
|
||||
void FTL_reload_all_domainlists(void);
|
||||
void FTL_reset_per_client_domain_data(void);
|
||||
|
||||
enum { TYPE_A = 1, TYPE_AAAA, TYPE_ANY, TYPE_SRV, TYPE_SOA, TYPE_PTR, TYPE_TXT, TYPE_NAPTR,
|
||||
TYPE_MX, TYPE_DS, TYPE_RRSIG, TYPE_DNSKEY, TYPE_OTHER, TYPE_MAX };
|
||||
|
||||
typedef struct {
|
||||
unsigned char magic;
|
||||
unsigned char status;
|
||||
unsigned char type;
|
||||
unsigned char privacylevel;
|
||||
unsigned char reply;
|
||||
unsigned char dnssec;
|
||||
enum query_status status;
|
||||
enum query_types type;
|
||||
enum privacy_level privacylevel;
|
||||
enum reply_type reply;
|
||||
enum dnssec_status dnssec;
|
||||
time_t timestamp;
|
||||
int domainID;
|
||||
int clientID;
|
||||
@@ -79,7 +79,7 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
unsigned char magic;
|
||||
unsigned char blocking_status;
|
||||
enum domain_client_status blocking_status;
|
||||
unsigned char force_reply;
|
||||
int domainID;
|
||||
int clientID;
|
||||
|
||||
@@ -1249,7 +1249,7 @@ static void sig_handler(int sig)
|
||||
{
|
||||
/*** Pi-hole modification ***/
|
||||
// TCP workers ignore all signals except SIGALRM
|
||||
FTL_TCP_worker_terminating();
|
||||
FTL_TCP_worker_terminating(false);
|
||||
/*** Pi-hole modification ***/
|
||||
_exit(0);
|
||||
}
|
||||
@@ -1957,8 +1957,16 @@ static void check_dns_listeners(time_t now)
|
||||
if ((flags = fcntl(confd, F_GETFL, 0)) != -1)
|
||||
fcntl(confd, F_SETFL, flags & ~O_NONBLOCK);
|
||||
|
||||
/******* Pi-hole modification *******/
|
||||
FTL_TCP_worker_created();
|
||||
/************************************/
|
||||
|
||||
buff = tcp_request(confd, now, &tcp_addr, netmask, auth_dns);
|
||||
|
||||
/******* Pi-hole modification *******/
|
||||
FTL_TCP_worker_terminating(true);
|
||||
/************************************/
|
||||
|
||||
shutdown(confd, SHUT_RDWR);
|
||||
close(confd);
|
||||
|
||||
@@ -1974,10 +1982,6 @@ static void check_dns_listeners(time_t now)
|
||||
|
||||
if (!option_bool(OPT_DEBUG))
|
||||
{
|
||||
/*** Pi-hole modification ***/
|
||||
// TCP workers ignore all signals except SIGALRM
|
||||
FTL_TCP_worker_terminating();
|
||||
/****************************/
|
||||
close(daemon->pipe_to_parent);
|
||||
flush_log();
|
||||
_exit(0);
|
||||
|
||||
+49
-50
@@ -12,6 +12,7 @@
|
||||
#include "dnsmasq/dnsmasq.h"
|
||||
#undef __USE_XOPEN
|
||||
#include "FTL.h"
|
||||
#include "enums.h"
|
||||
#include "dnsmasq_interface.h"
|
||||
#include "shmem.h"
|
||||
#include "overTime.h"
|
||||
@@ -302,10 +303,6 @@ static bool _FTL_check_blocking(int queryID, int domainID, int clientID, const c
|
||||
|
||||
bool _FTL_CNAME(const char *domain, const struct crec *cpp, const int id, const char* file, const int line)
|
||||
{
|
||||
// Don't analyze anything if in PRIVACY_NOSTATS mode
|
||||
if(config.privacylevel >= PRIVACY_NOSTATS)
|
||||
return false;
|
||||
|
||||
// Does the user want to skip deep CNAME inspection?
|
||||
if(!config.cname_inspection)
|
||||
{
|
||||
@@ -423,10 +420,6 @@ bool _FTL_new_query(const unsigned int flags, const char *name,
|
||||
{
|
||||
// Create new query in data structure
|
||||
|
||||
// Don't analyze anything if in PRIVACY_NOSTATS mode
|
||||
if(config.privacylevel >= PRIVACY_NOSTATS)
|
||||
return false;
|
||||
|
||||
// Get timestamp
|
||||
const time_t querytimestamp = time(NULL);
|
||||
|
||||
@@ -692,10 +685,6 @@ void _FTL_forwarded(const unsigned int flags, const char *name, const union all_
|
||||
{
|
||||
// Save that this query got forwarded to an upstream server
|
||||
|
||||
// Don't analyze anything if in PRIVACY_NOSTATS mode
|
||||
if(config.privacylevel >= PRIVACY_NOSTATS)
|
||||
return;
|
||||
|
||||
// Lock shared memory
|
||||
lock_shm();
|
||||
|
||||
@@ -810,7 +799,6 @@ void FTL_dnsmasq_reload(void)
|
||||
{
|
||||
// This function is called by the dnsmasq code on receive of SIGHUP
|
||||
// *before* clearing the cache and rereading the lists
|
||||
// This is the only hook that is not skipped in PRIVACY_NOSTATS mode
|
||||
|
||||
logg("Reloading DNS cache");
|
||||
|
||||
@@ -844,10 +832,6 @@ void FTL_dnsmasq_reload(void)
|
||||
void _FTL_reply(const unsigned short flags, const char *name, const union all_addr *addr, const int id,
|
||||
const char* file, const int line)
|
||||
{
|
||||
// Don't analyze anything if in PRIVACY_NOSTATS mode
|
||||
if(config.privacylevel >= PRIVACY_NOSTATS)
|
||||
return;
|
||||
|
||||
// Lock shared memory
|
||||
lock_shm();
|
||||
|
||||
@@ -968,9 +952,9 @@ void _FTL_reply(const unsigned short flags, const char *name, const union all_ad
|
||||
{
|
||||
// Only proceed if query is not already known
|
||||
// to have been blocked by Quad9
|
||||
if(query->reply != QUERY_EXTERNAL_BLOCKED_IP &&
|
||||
query->reply != QUERY_EXTERNAL_BLOCKED_NULL &&
|
||||
query->reply != QUERY_EXTERNAL_BLOCKED_NXRA)
|
||||
if(query->status != QUERY_EXTERNAL_BLOCKED_IP &&
|
||||
query->status != QUERY_EXTERNAL_BLOCKED_NULL &&
|
||||
query->status != QUERY_EXTERNAL_BLOCKED_NXRA)
|
||||
{
|
||||
// Save reply type and update individual reply counters
|
||||
save_reply_type(flags, addr, query, response);
|
||||
@@ -1129,7 +1113,7 @@ static void detect_blocked_IP(const unsigned short flags, const union all_addr *
|
||||
}
|
||||
}
|
||||
|
||||
static void query_externally_blocked(const int queryID, const unsigned char status)
|
||||
static void query_externally_blocked(const int queryID, const enum query_status status)
|
||||
{
|
||||
// Get query pointer
|
||||
queriesData* query = getQuery(queryID, true);
|
||||
@@ -1172,10 +1156,6 @@ void _FTL_cache(const unsigned int flags, const char *name, const union all_addr
|
||||
{
|
||||
// Save that this query got answered from cache
|
||||
|
||||
// Don't analyze anything if in PRIVACY_NOSTATS mode
|
||||
if(config.privacylevel >= PRIVACY_NOSTATS)
|
||||
return;
|
||||
|
||||
// If domain is "pi.hole", we skip this query
|
||||
// We compare case-insensitive here
|
||||
if(strcasecmp(name, "pi.hole") == 0)
|
||||
@@ -1339,10 +1319,6 @@ void _FTL_dnssec(const int status, const int id, const char* file, const int lin
|
||||
{
|
||||
// Process DNSSEC result for a domain
|
||||
|
||||
// Don't analyze anything if in PRIVACY_NOSTATS mode
|
||||
if(config.privacylevel >= PRIVACY_NOSTATS)
|
||||
return;
|
||||
|
||||
// Lock shared memory
|
||||
lock_shm();
|
||||
|
||||
@@ -1393,10 +1369,6 @@ void _FTL_upstream_error(const unsigned int rcode, const int id, const char* fil
|
||||
// Queries with error are those where the RCODE
|
||||
// in the DNS header is neither NOERROR nor NXDOMAIN.
|
||||
|
||||
// Don't analyze anything if in PRIVACY_NOSTATS mode
|
||||
if(config.privacylevel >= PRIVACY_NOSTATS)
|
||||
return;
|
||||
|
||||
// Lock shared memory
|
||||
lock_shm();
|
||||
|
||||
@@ -1469,10 +1441,6 @@ void _FTL_header_analysis(const unsigned char header4, const unsigned int rcode,
|
||||
{
|
||||
// Analyze DNS header bits
|
||||
|
||||
// Don't analyze anything if in PRIVACY_NOSTATS mode
|
||||
if(config.privacylevel >= PRIVACY_NOSTATS)
|
||||
return;
|
||||
|
||||
// Check if RA bit is unset in DNS header and rcode is NXDOMAIN
|
||||
// If the response code (rcode) is NXDOMAIN, we may be seeing a response from
|
||||
// an externally blocked query. As they are not always accompany a necessary
|
||||
@@ -1649,18 +1617,15 @@ void FTL_fork_and_bind_sockets(struct passwd *ent_pw)
|
||||
// join with the terminated thread
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
|
||||
// Bind to sockets
|
||||
bind_sockets();
|
||||
|
||||
// Start TELNET IPv4 thread
|
||||
if(ipv4telnet && pthread_create( &telnet_listenthreadv4, &attr, telnet_listening_thread_IPv4, NULL ) != 0)
|
||||
if(pthread_create( &telnet_listenthreadv4, &attr, telnet_listening_thread_IPv4, NULL ) != 0)
|
||||
{
|
||||
logg("Unable to open IPv4 telnet listening thread. Exiting...");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Start TELNET IPv6 thread
|
||||
if(ipv6telnet && pthread_create( &telnet_listenthreadv6, &attr, telnet_listening_thread_IPv6, NULL ) != 0)
|
||||
if(pthread_create( &telnet_listenthreadv6, &attr, telnet_listening_thread_IPv6, NULL ) != 0)
|
||||
{
|
||||
logg("Unable to open IPv6 telnet listening thread. Exiting...");
|
||||
exit(EXIT_FAILURE);
|
||||
@@ -1735,10 +1700,6 @@ void _FTL_forwarding_failed(const struct server *server, const char* file, const
|
||||
{
|
||||
// Forwarding to upstream server failed
|
||||
|
||||
// Don't analyze anything if in PRIVACY_NOSTATS mode
|
||||
if(config.privacylevel >= PRIVACY_NOSTATS)
|
||||
return;
|
||||
|
||||
// Lock shared memory
|
||||
lock_shm();
|
||||
|
||||
@@ -1824,14 +1785,52 @@ static void prepare_blocking_metadata(void)
|
||||
// Called when a (forked) TCP worker is terminated by receiving SIGALRM
|
||||
// We close the dedicated database connection this client had opened
|
||||
// to avoid dangling database locks
|
||||
void FTL_TCP_worker_terminating(void)
|
||||
void FTL_TCP_worker_terminating(bool finished)
|
||||
{
|
||||
if(config.debug & DEBUG_DATABASE)
|
||||
if(config.debug != 0)
|
||||
{
|
||||
logg("TCP worker terminating, "
|
||||
"closing gravity database connection");
|
||||
const char *reason = finished ? "client disconnected" : "timeout";
|
||||
logg("TCP worker terminating (%s)", reason);
|
||||
}
|
||||
|
||||
if(main_pid() == getpid())
|
||||
{
|
||||
// If this is not really a fork (e.g. in debug mode), we don't
|
||||
// actually close gravity here
|
||||
return;
|
||||
}
|
||||
|
||||
// Close dedicated database connection of this fork
|
||||
gravityDB_close();
|
||||
}
|
||||
|
||||
// Called when a (forked) TCP worker is created
|
||||
// FTL forked to handle TCP connections with dedicated (forked) workers
|
||||
// SQLite3's mentions that carrying an open database connection across a
|
||||
// fork() can lead to all kinds of locking problems as SQLite3 was not
|
||||
// intended to work under such circumstances. Doing so may easily lead
|
||||
// to ending up with a corrupted database.
|
||||
void FTL_TCP_worker_created(void)
|
||||
{
|
||||
if(config.debug != 0)
|
||||
{
|
||||
// Print this if any debug setting is enabled
|
||||
logg("TCP worker forked");
|
||||
}
|
||||
|
||||
if(main_pid() == getpid())
|
||||
{
|
||||
// If this is not really a fork (e.g. in debug mode), we don't
|
||||
// actually re-open gravity or close sockets here
|
||||
return;
|
||||
}
|
||||
|
||||
// Reopen gravity database handle in this fork as the main process's
|
||||
// handle isn't valid here
|
||||
gravityDB_forked();
|
||||
|
||||
// Children inherit file descriptors from their parents
|
||||
// We don't need them in the forks, so we clean them up
|
||||
close_telnet_socket();
|
||||
close_unix_socket(false);
|
||||
}
|
||||
|
||||
@@ -51,7 +51,8 @@ bool _FTL_CNAME(const char *domain, const struct crec *cpp, const int id, const
|
||||
|
||||
void FTL_dnsmasq_reload(void);
|
||||
void FTL_fork_and_bind_sockets(struct passwd *ent_pw);
|
||||
void FTL_TCP_worker_terminating(void);
|
||||
void FTL_TCP_worker_created(void);
|
||||
void FTL_TCP_worker_terminating(bool finished);
|
||||
|
||||
void set_debug_dnsmasq_lines(char enabled);
|
||||
extern char debug_dnsmasq_lines;
|
||||
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
/* Pi-hole: A black hole for Internet advertisements
|
||||
* (c) 2020 Pi-hole, LLC (https://pi-hole.net)
|
||||
* Network-wide ad blocking via your own hardware.
|
||||
*
|
||||
* FTL Engine
|
||||
* Global enums
|
||||
*
|
||||
* This file is copyright under the latest version of the EUPL.
|
||||
* Please see LICENSE file for your rights under this license. */
|
||||
#ifndef ENUMS_H
|
||||
#define ENUMS_H
|
||||
|
||||
enum memory_type {
|
||||
QUERIES,
|
||||
UPSTREAMS,
|
||||
CLIENTS,
|
||||
DOMAINS,
|
||||
OVERTIME,
|
||||
DNS_CACHE
|
||||
} __attribute__ ((packed));
|
||||
|
||||
enum dnssec_status {
|
||||
DNSSEC_UNSPECIFIED,
|
||||
DNSSEC_SECURE,
|
||||
DNSSEC_INSECURE,
|
||||
DNSSEC_BOGUS,
|
||||
DNSSEC_ABANDONED
|
||||
} __attribute__ ((packed));
|
||||
|
||||
enum query_status {
|
||||
QUERY_UNKNOWN,
|
||||
QUERY_GRAVITY,
|
||||
QUERY_FORWARDED,
|
||||
QUERY_CACHE,
|
||||
QUERY_REGEX,
|
||||
QUERY_BLACKLIST,
|
||||
QUERY_EXTERNAL_BLOCKED_IP,
|
||||
QUERY_EXTERNAL_BLOCKED_NULL,
|
||||
QUERY_EXTERNAL_BLOCKED_NXRA,
|
||||
QUERY_GRAVITY_CNAME,
|
||||
QUERY_REGEX_CNAME,
|
||||
QUERY_BLACKLIST_CNAME,
|
||||
QUERY_STATUS_MAX
|
||||
} __attribute__ ((packed));
|
||||
|
||||
enum reply_type {
|
||||
REPLY_UNKNOWN,
|
||||
REPLY_NODATA,
|
||||
REPLY_NXDOMAIN,
|
||||
REPLY_CNAME,
|
||||
REPLY_IP,
|
||||
REPLY_DOMAIN,
|
||||
REPLY_RRNAME,
|
||||
REPLY_SERVFAIL,
|
||||
REPLY_REFUSED,
|
||||
REPLY_NOTIMP,
|
||||
REPLY_OTHER
|
||||
} __attribute__ ((packed));
|
||||
|
||||
enum privacy_level {
|
||||
PRIVACY_SHOW_ALL = 0,
|
||||
PRIVACY_HIDE_DOMAINS,
|
||||
PRIVACY_HIDE_DOMAINS_CLIENTS,
|
||||
PRIVACY_MAXIMUM
|
||||
} __attribute__ ((packed));
|
||||
|
||||
enum blocking_mode {
|
||||
MODE_IP,
|
||||
MODE_NX,
|
||||
MODE_NULL,
|
||||
MODE_IP_NODATA_AAAA,
|
||||
MODE_NODATA
|
||||
} __attribute__ ((packed));
|
||||
|
||||
enum regex_id {
|
||||
REGEX_BLACKLIST,
|
||||
REGEX_WHITELIST
|
||||
} __attribute__ ((packed));
|
||||
|
||||
enum query_types {
|
||||
TYPE_A = 1,
|
||||
TYPE_AAAA,
|
||||
TYPE_ANY,
|
||||
TYPE_SRV,
|
||||
TYPE_SOA,
|
||||
TYPE_PTR,
|
||||
TYPE_TXT,
|
||||
TYPE_NAPTR,
|
||||
TYPE_MX,
|
||||
TYPE_DS,
|
||||
TYPE_RRSIG,
|
||||
TYPE_DNSKEY,
|
||||
TYPE_OTHER,
|
||||
TYPE_MAX
|
||||
} __attribute__ ((packed));
|
||||
|
||||
enum blocking_status {
|
||||
BLOCKING_DISABLED,
|
||||
BLOCKING_ENABLED,
|
||||
BLOCKING_UNKNOWN
|
||||
} __attribute__ ((packed));
|
||||
|
||||
// Blocking status constants used by the dns_cache->blocking_status vector
|
||||
enum domain_client_status {
|
||||
UNKNOWN_BLOCKED = 0,
|
||||
GRAVITY_BLOCKED,
|
||||
BLACKLIST_BLOCKED,
|
||||
REGEX_BLOCKED,
|
||||
WHITELISTED,
|
||||
NOT_BLOCKED
|
||||
} __attribute__ ((packed));
|
||||
|
||||
enum debug_mode {
|
||||
DEBUG_DATABASE = (1 << 0), /* 00000000 00000001 */
|
||||
DEBUG_NETWORKING = (1 << 1), /* 00000000 00000010 */
|
||||
DEBUG_LOCKS = (1 << 2), /* 00000000 00000100 */
|
||||
DEBUG_QUERIES = (1 << 3), /* 00000000 00001000 */
|
||||
DEBUG_FLAGS = (1 << 4), /* 00000000 00010000 */
|
||||
DEBUG_SHMEM = (1 << 5), /* 00000000 00100000 */
|
||||
DEBUG_GC = (1 << 6), /* 00000000 01000000 */
|
||||
DEBUG_ARP = (1 << 7), /* 00000000 10000000 */
|
||||
DEBUG_REGEX = (1 << 8), /* 00000001 00000000 */
|
||||
DEBUG_API = (1 << 9), /* 00000010 00000000 */
|
||||
DEBUG_OVERTIME = (1 << 10), /* 00000100 00000000 */
|
||||
DEBUG_EXTBLOCKED = (1 << 11), /* 00001000 00000000 */
|
||||
DEBUG_CAPS = (1 << 12), /* 00010000 00000000 */
|
||||
DEBUG_DNSMASQ_LINES = (1 << 13), /* 00100000 00000000 */
|
||||
DEBUG_VECTORS = (1 << 14), /* 01000000 00000000 */
|
||||
DEBUG_RESOLVER = (1 << 15), /* 10000000 00000000 */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#endif // ENUMS_H
|
||||
@@ -129,6 +129,7 @@ void *GC_thread(void *val)
|
||||
if(client != NULL)
|
||||
client->blockedcount--;
|
||||
break;
|
||||
case QUERY_STATUS_MAX: // fall through
|
||||
default:
|
||||
/* That cannot happen */
|
||||
break;
|
||||
@@ -138,27 +139,33 @@ void *GC_thread(void *val)
|
||||
switch(query->reply)
|
||||
{
|
||||
case REPLY_NODATA: // NODATA(-IPv6)
|
||||
counters->reply_NODATA--;
|
||||
break;
|
||||
counters->reply_NODATA--;
|
||||
break;
|
||||
|
||||
case REPLY_NXDOMAIN: // NXDOMAIN
|
||||
counters->reply_NXDOMAIN--;
|
||||
break;
|
||||
counters->reply_NXDOMAIN--;
|
||||
break;
|
||||
|
||||
case REPLY_CNAME: // <CNAME>
|
||||
counters->reply_CNAME--;
|
||||
break;
|
||||
counters->reply_CNAME--;
|
||||
break;
|
||||
|
||||
case REPLY_IP: // valid IP
|
||||
counters->reply_IP--;
|
||||
break;
|
||||
counters->reply_IP--;
|
||||
break;
|
||||
|
||||
case REPLY_DOMAIN: // reverse lookup
|
||||
counters->reply_domain--;
|
||||
break;
|
||||
counters->reply_domain--;
|
||||
break;
|
||||
|
||||
default: // Incomplete query or TXT, do nothing
|
||||
break;
|
||||
case REPLY_RRNAME: // fall through
|
||||
case REPLY_SERVFAIL: // fall through
|
||||
case REPLY_REFUSED: // fall through
|
||||
case REPLY_NOTIMP: // fall through
|
||||
case REPLY_OTHER: // fall through
|
||||
case REPLY_UNKNOWN: // fall through
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Update type counters
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "FTL.h"
|
||||
#include "version.h"
|
||||
#include "memory.h"
|
||||
// is_fork()
|
||||
#include "daemon.h"
|
||||
#include "config.h"
|
||||
#include "log.h"
|
||||
@@ -20,6 +21,8 @@
|
||||
#include "args.h"
|
||||
// global counters variable
|
||||
#include "shmem.h"
|
||||
// main_pid()
|
||||
#include "signals.h"
|
||||
|
||||
static pthread_mutex_t lock;
|
||||
static FILE *logfile = NULL;
|
||||
@@ -83,12 +86,31 @@ void __attribute__ ((format (gnu_printf, 1, 2))) logg(const char *format, ...)
|
||||
|
||||
// Get and log PID of current process to avoid ambiguities when more than one
|
||||
// pihole-FTL instance is logging into the same file
|
||||
const long pid = (long)getpid();
|
||||
char idstr[42];
|
||||
const int pid = getpid(); // Get the process ID of the calling process
|
||||
const int mpid = main_pid(); // Get the process ID of the main FTL process
|
||||
const int tid = gettid(); // Get the thread ID of the callig process
|
||||
|
||||
// There are four cases we have to differentiate here:
|
||||
if(pid == tid)
|
||||
if(is_fork(mpid, pid))
|
||||
// Fork of the main process
|
||||
snprintf(idstr, sizeof(idstr)-1, "%i/F%i", pid, mpid);
|
||||
else
|
||||
// Main process
|
||||
snprintf(idstr, sizeof(idstr)-1, "%iM", pid);
|
||||
else
|
||||
if(is_fork(mpid, pid))
|
||||
// Thread of a fork of the main process
|
||||
snprintf(idstr, sizeof(idstr)-1, "%i/F%i/T%i", pid, mpid, tid);
|
||||
else
|
||||
// Thread of the main process
|
||||
snprintf(idstr, sizeof(idstr)-1, "%i/T%i", pid, tid);
|
||||
|
||||
// Print to stdout before writing to file
|
||||
if(!daemonmode)
|
||||
{
|
||||
printf("[%s %ld] ", timestring, pid);
|
||||
printf("[%s %s] ", timestring, idstr);
|
||||
va_start(args, format);
|
||||
vprintf(format, args);
|
||||
va_end(args);
|
||||
@@ -101,7 +123,7 @@ void __attribute__ ((format (gnu_printf, 1, 2))) logg(const char *format, ...)
|
||||
// Write to log file
|
||||
if(logfile != NULL)
|
||||
{
|
||||
fprintf(logfile, "[%s %ld] ", timestring, pid);
|
||||
fprintf(logfile, "[%s %s] ", timestring, idstr);
|
||||
va_start(args, format);
|
||||
vfprintf(logfile, format, args);
|
||||
va_end(args);
|
||||
|
||||
+2
-2
@@ -108,9 +108,9 @@ int main (int argc, char* argv[])
|
||||
logg("Finished final database update");
|
||||
}
|
||||
|
||||
// Close sockets
|
||||
// Close sockets and delete Unix socket file handle
|
||||
close_telnet_socket();
|
||||
close_unix_socket();
|
||||
close_unix_socket(true);
|
||||
|
||||
// Close gravity database connection
|
||||
gravityDB_close();
|
||||
|
||||
+2
-1
@@ -10,7 +10,8 @@
|
||||
#ifndef MEMORY_H
|
||||
#define MEMORY_H
|
||||
|
||||
void memory_check(const int which);
|
||||
#include "enums.h"
|
||||
|
||||
char *FTLstrdup(const char *src, const char *file, const char *function, const int line) __attribute__((malloc));
|
||||
void *FTLcalloc(size_t nmemb, size_t size, const char *file, const char *function, const int line) __attribute__((malloc)) __attribute__((alloc_size(1,2)));
|
||||
void *FTLrealloc(void *ptr_in, size_t size, const char *file, const char *function, const int line) __attribute__((alloc_size(2)));
|
||||
|
||||
+4
-4
@@ -194,10 +194,10 @@ void allocate_regex_client_enabled(clientsData *client, const int clientID)
|
||||
}
|
||||
}
|
||||
|
||||
static void read_regex_table(const unsigned char regexid)
|
||||
static void read_regex_table(const enum regex_id regexid)
|
||||
{
|
||||
// Get table ID
|
||||
unsigned char tableID = (regexid == REGEX_BLACKLIST) ? REGEX_BLACKLIST_TABLE : REGEX_WHITELIST_TABLE;
|
||||
const enum gravity_tables tableID = (regexid == REGEX_BLACKLIST) ? REGEX_BLACKLIST_TABLE : REGEX_WHITELIST_TABLE;
|
||||
|
||||
// Get number of lines in the regex table
|
||||
counters->num_regex[regexid] = gravityDB_count(tableID);
|
||||
@@ -293,7 +293,7 @@ void read_regex_from_database(void)
|
||||
}
|
||||
|
||||
// Print message to FTL's log after reloading regex filters
|
||||
logg("Compiled %i whitelist and %i blacklist regex filters in %.1f msec",
|
||||
logg("Compiled %i whitelist and %i blacklist regex filters for %i clients in %.1f msec",
|
||||
counters->num_regex[REGEX_WHITELIST], counters->num_regex[REGEX_BLACKLIST],
|
||||
timer_elapsed_msec(REGEX_TIMER));
|
||||
counters->clients, timer_elapsed_msec(REGEX_TIMER));
|
||||
}
|
||||
|
||||
@@ -19,9 +19,4 @@ int match_regex(const char *input, const int clientID, const unsigned char regex
|
||||
void allocate_regex_client_enabled(clientsData *client, const int clientID);
|
||||
void read_regex_from_database(void);
|
||||
|
||||
// Blocking status constants used by the domain->clientstatus vector
|
||||
// We explicitly force UNKNOWN_BLOCKED to zero on all platforms as this is the
|
||||
// default value set initially with calloc
|
||||
enum { UNKNOWN_BLOCKED = 0, GRAVITY_BLOCKED, BLACKLIST_BLOCKED, REGEX_BLOCKED, WHITELISTED, NOT_BLOCKED };
|
||||
|
||||
#endif //REGEX_H
|
||||
|
||||
+1
-1
@@ -232,7 +232,7 @@ bool __attribute__((pure)) getSetupVarsBool(const char * input)
|
||||
}
|
||||
|
||||
// Global variable showing current blocking status
|
||||
unsigned char blockingstatus = BLOCKING_UNKNOWN;
|
||||
enum blocking_status blockingstatus = BLOCKING_UNKNOWN;
|
||||
|
||||
void check_blocking_status(void)
|
||||
{
|
||||
|
||||
@@ -22,6 +22,4 @@ void check_blocking_status(void);
|
||||
|
||||
extern unsigned char blockingstatus;
|
||||
|
||||
enum { BLOCKING_DISABLED, BLOCKING_ENABLED, BLOCKING_UNKNOWN };
|
||||
|
||||
#endif //SETUPVARS_H
|
||||
|
||||
+8
-7
@@ -608,7 +608,7 @@ static size_t get_optimal_object_size(const size_t objsize, const size_t minsize
|
||||
}
|
||||
}
|
||||
|
||||
void memory_check(int which)
|
||||
void memory_check(const enum memory_type which)
|
||||
{
|
||||
switch(which)
|
||||
{
|
||||
@@ -623,7 +623,7 @@ void memory_check(int which)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case UPSTREAMS:
|
||||
if(counters->upstreams >= counters->upstreams_MAX-1)
|
||||
{
|
||||
@@ -635,7 +635,7 @@ void memory_check(int which)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case CLIENTS:
|
||||
if(counters->clients >= counters->clients_MAX-1)
|
||||
{
|
||||
@@ -647,7 +647,7 @@ void memory_check(int which)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case DOMAINS:
|
||||
if(counters->domains >= counters->domains_MAX-1)
|
||||
{
|
||||
@@ -659,7 +659,7 @@ void memory_check(int which)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case DNS_CACHE:
|
||||
if(counters->dns_cache_size >= counters->dns_cache_MAX-1)
|
||||
{
|
||||
@@ -671,12 +671,13 @@ void memory_check(int which)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case OVERTIME: // fall through
|
||||
default:
|
||||
/* That cannot happen */
|
||||
logg("Fatal error in memory_check(%i)", which);
|
||||
exit(EXIT_FAILURE);
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -114,4 +114,6 @@ void reset_per_client_regex(const int clientID);
|
||||
bool get_per_client_regex(const int clientID, const int regexID);
|
||||
void set_per_client_regex(const int clientID, const int regexID, const bool value);
|
||||
|
||||
void memory_check(const enum memory_type which);
|
||||
|
||||
#endif //SHARED_MEMORY_SERVER_H
|
||||
|
||||
+40
-12
@@ -20,14 +20,24 @@
|
||||
// FTL_reload_all_domainlists()
|
||||
#include "datastructure.h"
|
||||
#include "config.h"
|
||||
// gettid()
|
||||
#include "daemon.h"
|
||||
|
||||
#define BINARY_NAME "pihole-FTL"
|
||||
|
||||
volatile sig_atomic_t killed = 0;
|
||||
static volatile pid_t pid = 0;
|
||||
static volatile pid_t mpid = -1;
|
||||
static time_t FTLstarttime = 0;
|
||||
extern volatile int exit_code;
|
||||
|
||||
// Return the (null-terminated) name of the calling thread
|
||||
// The name is stored in the buffer as well as returned for convenience
|
||||
static char * __attribute__ ((nonnull (1))) getthread_name(char buffer[16])
|
||||
{
|
||||
prctl(PR_GET_NAME, buffer, 0, 0, 0);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
#if defined(__GLIBC__)
|
||||
static void print_addr2line(const char *symbol, const void *address, const int j, const void *offset)
|
||||
{
|
||||
@@ -57,8 +67,15 @@ static void print_addr2line(const char *symbol, const void *address, const int j
|
||||
// Strip possible newline at the end of the addr2line output
|
||||
if ((pos=strchr(linebuffer, '\n')) != NULL)
|
||||
*pos = '\0';
|
||||
logg("L[%04i]: %s", j, linebuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(linebuffer, sizeof(linebuffer), "N/A (%p)", addr);
|
||||
}
|
||||
// Log result
|
||||
logg("L[%04i]: %s", j, linebuffer);
|
||||
|
||||
// Close pipe
|
||||
pclose(addr2line);
|
||||
}
|
||||
#endif
|
||||
@@ -76,17 +93,22 @@ static void __attribute__((noreturn)) SIGSEGV_handler(int sig, siginfo_t *si, vo
|
||||
logg("FTL has been running for %li seconds", time(NULL)-FTLstarttime);
|
||||
}
|
||||
log_FTL_version(true);
|
||||
char namebuf[16];
|
||||
logg("Process details: MID: %i",mpid);
|
||||
logg(" PID: %i", getpid());
|
||||
logg(" TID: %i", gettid());
|
||||
logg(" Name: %s", getthread_name(namebuf));
|
||||
|
||||
logg("Received signal: %s", strsignal(sig));
|
||||
logg(" at address: %p", si->si_addr);
|
||||
switch (si->si_code)
|
||||
{
|
||||
case SEGV_MAPERR: logg(" with code: SEGV_MAPERR (Address not mapped to object)"); break;
|
||||
case SEGV_ACCERR: logg(" with code: SEGV_ACCERR (Invalid permissions for mapped object)"); break;
|
||||
case SEGV_MAPERR: logg(" with code: SEGV_MAPERR (Address not mapped to object)"); break;
|
||||
case SEGV_ACCERR: logg(" with code: SEGV_ACCERR (Invalid permissions for mapped object)"); break;
|
||||
#if defined(SEGV_BNDERR)
|
||||
case SEGV_BNDERR: logg(" with code: SEGV_BNDERR (Failed address bound checks)"); break;
|
||||
case SEGV_BNDERR: logg(" with code: SEGV_BNDERR (Failed address bound checks)"); break;
|
||||
#endif
|
||||
default: logg(" with code: Unknown (%i)", si->si_code); break;
|
||||
default: logg(" with code: Unknown (%i)", si->si_code); break;
|
||||
}
|
||||
|
||||
// Check GLIBC availability as MUSL does not support live backtrace generation
|
||||
@@ -114,7 +136,7 @@ static void __attribute__((noreturn)) SIGSEGV_handler(int sig, siginfo_t *si, vo
|
||||
|
||||
for(int j = 0; j < calls; j++)
|
||||
{
|
||||
logg("B[%04i]: %p, %s", j, buffer[j],
|
||||
logg("B[%04i]: %s", j,
|
||||
bcktrace != NULL ? bcktrace[j] : "---");
|
||||
|
||||
if(bcktrace != NULL)
|
||||
@@ -132,11 +154,11 @@ static void __attribute__((noreturn)) SIGSEGV_handler(int sig, siginfo_t *si, vo
|
||||
logg("Thank you for helping us to improve our FTL engine!");
|
||||
|
||||
// Terminate main process if crash happened in a TCP worker
|
||||
if(pid != getpid())
|
||||
if(mpid != getpid())
|
||||
{
|
||||
// This is a forked process
|
||||
logg("Asking parent pihole-FTL (PID %i) to shut down", (int)pid);
|
||||
kill(pid, SIGRTMIN+2);
|
||||
logg("Asking parent pihole-FTL (PID %i) to shut down", (int)mpid);
|
||||
kill(mpid, SIGRTMIN+2);
|
||||
logg("FTL fork terminated!");
|
||||
}
|
||||
else
|
||||
@@ -152,7 +174,7 @@ static void __attribute__((noreturn)) SIGSEGV_handler(int sig, siginfo_t *si, vo
|
||||
static void SIGRT_handler(int signum, siginfo_t *si, void *unused)
|
||||
{
|
||||
// Ignore real-time signals outside of the main process (TCP forks)
|
||||
if(pid != getpid())
|
||||
if(mpid != getpid())
|
||||
return;
|
||||
|
||||
int rtsig = signum - SIGRTMIN;
|
||||
@@ -207,7 +229,7 @@ void handle_realtime_signals(void)
|
||||
{
|
||||
// This function is only called once (after forking), store the PID of
|
||||
// the main process
|
||||
pid = getpid();
|
||||
mpid = getpid();
|
||||
|
||||
// Catch first five real-time signals
|
||||
for(unsigned int i = 0; i < 5; i++)
|
||||
@@ -220,3 +242,9 @@ void handle_realtime_signals(void)
|
||||
sigaction(SIGRTMIN + i, &SIGACTION, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
// Return PID of the main FTL process
|
||||
pid_t main_pid(void)
|
||||
{
|
||||
return mpid;
|
||||
}
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
void handle_SIGSEGV(void);
|
||||
void handle_realtime_signals(void);
|
||||
pid_t main_pid(void);
|
||||
|
||||
extern volatile sig_atomic_t killed;
|
||||
|
||||
|
||||
+2
-2
@@ -15,7 +15,7 @@
|
||||
|
||||
struct timeval t0[NUMTIMERS];
|
||||
|
||||
void timer_start(const int i)
|
||||
void timer_start(enum timers i)
|
||||
{
|
||||
if(i >= NUMTIMERS)
|
||||
{
|
||||
@@ -25,7 +25,7 @@ void timer_start(const int i)
|
||||
gettimeofday(&t0[i], 0);
|
||||
}
|
||||
|
||||
double timer_elapsed_msec(const int i)
|
||||
double timer_elapsed_msec(enum timers i)
|
||||
{
|
||||
if(i >= NUMTIMERS)
|
||||
{
|
||||
|
||||
+11
-3
@@ -11,12 +11,20 @@
|
||||
#define TIMERS_H
|
||||
|
||||
// Timer enumeration
|
||||
enum { DATABASE_WRITE_TIMER, EXIT_TIMER, GC_TIMER, LISTS_TIMER, REGEX_TIMER, ARP_TIMER, LAST_TIMER };
|
||||
enum timers {
|
||||
DATABASE_WRITE_TIMER,
|
||||
EXIT_TIMER,
|
||||
GC_TIMER,
|
||||
LISTS_TIMER,
|
||||
REGEX_TIMER,
|
||||
ARP_TIMER,
|
||||
LAST_TIMER
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define NUMTIMERS LAST_TIMER
|
||||
|
||||
void timer_start(const int i);
|
||||
double timer_elapsed_msec(const int i);
|
||||
void timer_start(const enum timers i);
|
||||
double timer_elapsed_msec(const enum timers i);
|
||||
void sleepms(const int milliseconds);
|
||||
|
||||
#endif //TIMERS_H
|
||||
|
||||
Reference in New Issue
Block a user