mirror of
https://github.com/pi-hole/FTL.git
synced 2025-12-24 19:35:29 +00:00
Merge branch 'development' into new/gravityDB
Signed-off-by: DL6ER <dl6er@dl6er.de>
This commit is contained in:
87
FTL.h
87
FTL.h
@@ -80,11 +80,19 @@
|
||||
// can be 24 hours + 59 minutes
|
||||
#define OVERTIME_SLOTS ((MAXLOGAGE+1)*3600/OVERTIME_INTERVAL)
|
||||
|
||||
// Interval for resolving NEW client and upstream server host names [seconds]
|
||||
// Default: 60 (once every minute)
|
||||
#define RESOLVE_INTERVAL 60
|
||||
|
||||
// Interval for re-resolving ALL known host names [seconds]
|
||||
// Default: 3600 (once every hour)
|
||||
#define RERESOLVE_INTERVAL 3600
|
||||
|
||||
// FTLDNS enums
|
||||
enum { DATABASE_WRITE_TIMER, EXIT_TIMER, GC_TIMER, LISTS_TIMER, REGEX_TIMER, ARP_TIMER, LAST_TIMER };
|
||||
enum { QUERIES, FORWARDED, CLIENTS, DOMAINS, OVERTIME, WILDCARD };
|
||||
enum { DNSSEC_UNSPECIFIED, DNSSEC_SECURE, DNSSEC_INSECURE, DNSSEC_BOGUS, DNSSEC_ABANDONED, DNSSEC_UNKNOWN };
|
||||
enum { QUERY_UNKNOWN, QUERY_GRAVITY, QUERY_FORWARDED, QUERY_CACHE, QUERY_WILDCARD, QUERY_BLACKLIST, QUERY_EXTERNAL_BLOCKED };
|
||||
enum { QUERY_UNKNOWN, QUERY_GRAVITY, QUERY_FORWARDED, QUERY_CACHE, QUERY_WILDCARD, QUERY_BLACKLIST, QUERY_EXTERNAL_BLOCKED_IP, QUERY_EXTERNAL_BLOCKED_NULL, QUERY_EXTERNAL_BLOCKED_NXRA };
|
||||
enum { TYPE_A = 1, TYPE_AAAA, TYPE_ANY, TYPE_SRV, TYPE_SOA, TYPE_PTR, TYPE_TXT, TYPE_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 };
|
||||
@@ -102,7 +110,10 @@ enum {
|
||||
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 */
|
||||
};
|
||||
|
||||
// Database table "ftl"
|
||||
@@ -161,70 +172,69 @@ typedef struct {
|
||||
} countersStruct;
|
||||
|
||||
typedef struct {
|
||||
bool socket_listenlocal;
|
||||
bool analyze_AAAA;
|
||||
int maxDBdays;
|
||||
bool resolveIPv6;
|
||||
bool resolveIPv4;
|
||||
int DBinterval;
|
||||
int port;
|
||||
int maxlogage;
|
||||
int16_t debug;
|
||||
unsigned char privacylevel;
|
||||
bool ignore_localhost;
|
||||
unsigned char blockingmode;
|
||||
bool socket_listenlocal;
|
||||
bool analyze_AAAA;
|
||||
bool resolveIPv6;
|
||||
bool resolveIPv4;
|
||||
bool ignore_localhost;
|
||||
bool analyze_only_A_AAAA;
|
||||
bool DBimport;
|
||||
bool parse_arp_cache;
|
||||
int16_t debug;
|
||||
} ConfigStruct;
|
||||
|
||||
// Dynamic structs
|
||||
typedef struct {
|
||||
unsigned char magic;
|
||||
time_t timestamp;
|
||||
unsigned int timeidx;
|
||||
unsigned char type;
|
||||
unsigned char status;
|
||||
unsigned char privacylevel;
|
||||
unsigned char reply;
|
||||
unsigned char dnssec;
|
||||
time_t timestamp;
|
||||
int domainID;
|
||||
int clientID;
|
||||
int forwardID;
|
||||
int64_t db;
|
||||
int id; // the ID is a (signed) int in dnsmasq, so no need for a long int here
|
||||
bool complete;
|
||||
unsigned char privacylevel;
|
||||
unsigned long response; // saved in units of 1/10 milliseconds (1 = 0.1ms, 2 = 0.2ms, 2500 = 250.0ms, etc.)
|
||||
unsigned char reply;
|
||||
unsigned char dnssec;
|
||||
bool AD;
|
||||
int64_t db;
|
||||
unsigned int timeidx;
|
||||
bool complete;
|
||||
} queriesDataStruct;
|
||||
|
||||
typedef struct {
|
||||
unsigned char magic;
|
||||
size_t ippos;
|
||||
size_t namepos;
|
||||
int count;
|
||||
int failed;
|
||||
unsigned long long ippos;
|
||||
unsigned long long namepos;
|
||||
bool new;
|
||||
} forwardedDataStruct;
|
||||
|
||||
typedef struct {
|
||||
unsigned char magic;
|
||||
size_t ippos;
|
||||
size_t namepos;
|
||||
time_t lastQuery;
|
||||
int count;
|
||||
int blockedcount;
|
||||
unsigned long long ippos;
|
||||
unsigned long long namepos;
|
||||
bool new;
|
||||
int overTime[OVERTIME_SLOTS];
|
||||
time_t lastQuery;
|
||||
unsigned int numQueriesARP;
|
||||
bool new;
|
||||
} clientsDataStruct;
|
||||
|
||||
typedef struct {
|
||||
unsigned char magic;
|
||||
unsigned char regexmatch;
|
||||
size_t domainpos;
|
||||
int count;
|
||||
int blockedcount;
|
||||
unsigned long long domainpos;
|
||||
unsigned char regexmatch;
|
||||
} domainsDataStruct;
|
||||
|
||||
typedef struct {
|
||||
@@ -238,8 +248,8 @@ typedef struct {
|
||||
} overTimeDataStruct;
|
||||
|
||||
typedef struct {
|
||||
int count;
|
||||
char **domains;
|
||||
int count;
|
||||
} whitelistStruct;
|
||||
|
||||
typedef struct {
|
||||
@@ -269,32 +279,23 @@ extern clientsDataStruct *clients;
|
||||
extern domainsDataStruct *domains;
|
||||
extern overTimeDataStruct *overTime;
|
||||
|
||||
/// Indexed by client ID, then time index (like `overTime`).
|
||||
/// This gets automatically updated whenever a new client or overTime slot is added.
|
||||
extern int **overTimeClientData;
|
||||
|
||||
extern FILE *logfile;
|
||||
// Used in gc.c, memory.c, resolve.c, signals.c, and socket.c
|
||||
extern volatile sig_atomic_t killed;
|
||||
|
||||
extern char ** setupVarsArray;
|
||||
extern int setupVarsElements;
|
||||
|
||||
extern bool initialscan;
|
||||
extern bool threadwritelock;
|
||||
extern bool threadreadlock;
|
||||
// Used in api.c, grep.c, and dnsmasq_interface.c
|
||||
extern unsigned char blockingstatus;
|
||||
|
||||
// Used in main.c, log.c, and others
|
||||
extern char * username;
|
||||
extern char timestamp[16];
|
||||
extern bool flush;
|
||||
extern bool needGC;
|
||||
// Used in main.c, args.c, log.c, and others
|
||||
extern bool daemonmode;
|
||||
// Used in main.c, database.c, and others
|
||||
extern bool database;
|
||||
// Used in database.c and gc.c
|
||||
extern long int lastdbindex;
|
||||
extern bool travis;
|
||||
// Used in database.c and gc.c
|
||||
extern bool DBdeleteoldqueries;
|
||||
extern bool rereadgravity;
|
||||
// Used in main.c, socket.c, and dnsmasq_interface.c
|
||||
extern bool ipv4telnet, ipv6telnet;
|
||||
// Used in api.c, and socket.c
|
||||
extern bool istelnet[MAXCONNS];
|
||||
|
||||
// Use out own memory handling functions that will detect possible errors
|
||||
@@ -309,7 +310,7 @@ extern bool istelnet[MAXCONNS];
|
||||
#define realloc(p1,p2) FTLrealloc(p1,p2, __FILE__, __FUNCTION__, __LINE__)
|
||||
|
||||
extern int argc_dnsmasq;
|
||||
extern char **argv_dnsmasq;
|
||||
extern const char ** argv_dnsmasq;
|
||||
|
||||
extern pthread_t telnet_listenthreadv4;
|
||||
extern pthread_t telnet_listenthreadv6;
|
||||
|
||||
36
Makefile
36
Makefile
@@ -26,6 +26,10 @@ GIT_VERSION := $(shell git --no-pager describe --tags --always --dirty)
|
||||
GIT_DATE := $(shell git --no-pager show --date=short --format="%ai" --name-only | head -n 1)
|
||||
GIT_TAG := $(shell git describe --tags --abbrev=0)
|
||||
|
||||
# Is compiler at least gcc version 8? We cannot do ifgt in Makefile, so we use the shell expr command
|
||||
GCCVERSION8 := $(shell expr `$(CC) -dumpversion | cut -f1 -d.` \>= 8)
|
||||
|
||||
# Code hardening and debugging improvements
|
||||
# -fstack-protector-strong: The program will be resistant to having its stack overflowed
|
||||
# -Wp,-D_FORTIFY_SOURCE=2 and -O1 or higher: This causes certain unsafe glibc functions to be replaced with their safer counterparts
|
||||
# -Wl,-z,relro: reduces the possible areas of memory in a program that can be used by an attacker that performs a successful memory corruption exploit
|
||||
@@ -40,15 +44,18 @@ GIT_TAG := $(shell git describe --tags --abbrev=0)
|
||||
# -Wl,-z,relro: Read-only segments after relocation
|
||||
HARDENING_FLAGS=-fstack-protector-strong -Wp,-D_FORTIFY_SOURCE=2 -O3 -Wl,-z,relro,-z,now -pie -fPIE -fexceptions -fasynchronous-unwind-tables -Wl,-z,defs -Wl,-z,now -Wl,-z,relro
|
||||
DEBUG_FLAGS=-rdynamic -fno-omit-frame-pointer
|
||||
|
||||
# -DSQLITE_OMIT_LOAD_EXTENSION: This option omits the entire extension loading mechanism from SQLite, including sqlite3_enable_load_extension() and sqlite3_load_extension() interfaces. (needs -ldl linking option, otherwise)
|
||||
# -DSQLITE_DEFAULT_MEMSTATUS=0: This setting causes the sqlite3_status() interfaces that track memory usage to be disabled. This helps the sqlite3_malloc() routines run much faster, and since SQLite uses sqlite3_malloc() internally, this helps to make the entire library faster.
|
||||
# -DSQLITE_OMIT_DEPRECATED: Omitting deprecated interfaces and features will not help SQLite to run any faster. It will reduce the library footprint, however. And it is the right thing to do.
|
||||
# -DSQLITE_OMIT_PROGRESS_CALLBACK: The progress handler callback counter must be checked in the inner loop of the bytecode engine. By omitting this interface, a single conditional is removed from the inner loop of the bytecode engine, helping SQL statements to run slightly faster.
|
||||
SQLITEFLAGS=-DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_MEMORYDB
|
||||
|
||||
# -Wall: This enables all the warnings about constructions that some users consider questionable, and that are easy to avoid (or modify to prevent the warning), even in conjunction with macros. This also enables some language-specific warnings described in C++ Dialect Options and Objective-C and Objective-C++ Dialect Options.
|
||||
# -Wextra: This enables some extra warning flags that are not enabled by -Wall.
|
||||
# -Wno-unused-parameter: Disable warning for unused parameters. For threads that don't need arguments, we still have to provide a void* args which is then unused.
|
||||
WARNFLAGS=-Wall -Wextra -Wno-unused-parameter
|
||||
|
||||
# Extra warning flags we apply only to the FTL part of the code (used not for foreign code such as dnsmasq and SQLite3)
|
||||
# -Werror: Halt on any warnings, useful for enforcing clean code without any warnings (we use it only for our code part)
|
||||
# -Waddress: Warn about suspicious uses of memory addresses
|
||||
@@ -59,14 +66,39 @@ WARNFLAGS=-Wall -Wextra -Wno-unused-parameter
|
||||
# -Wformat-nonliteral: If -Wformat is specified, also warn if the format string is not a string literal and so cannot be checked, unless the format function takes its format arguments as a va_list.
|
||||
# -Wuninitialized: Warn if an automatic variable is used without first being initialized
|
||||
# -Wswitch-enum: Warn whenever a switch statement has an index of enumerated type and lacks a case for one or more of the named codes of that enumeration.
|
||||
EXTRAWARN=-Werror -Waddress -Wlogical-op -Wmissing-field-initializers -Woverlength-strings -Wformat -Wformat-nonliteral -Wuninitialized -Wswitch-enum
|
||||
# -Wshadow: Warn whenever a local variable or type declaration shadows another variable, parameter, type, class member, or whenever a built-in function is shadowed.
|
||||
# -Wfloat-equal: Warn if floating-point values are used in equality comparisons
|
||||
# -Wunsafe-loop-optimizations -funsafe-loop-optimizations: Warn if the loop cannot be optimized because the compiler cannot assume anything on the bounds of the loop indices
|
||||
# -Wpointer-arith: Warn about anything that depends on the "size of" a function type or of "void". GNU C assigns these types a size of 1
|
||||
# -Wundef: Warn if an undefined identifier is evaluated in an "#if" directive
|
||||
# -Wbad-function-cast: Warn when a function call is cast to a non-matching type
|
||||
# -Wwrite-strings: When compiling C, give string constants the type "const char[length]" so that copying the address of one into a non-"const" "char *" pointer produces a warning
|
||||
# -Wparentheses: Warn if parentheses are omitted in certain contexts, such as when there is an assignment in a context where a truth value is expected, or when operators are nested whose precedence people often get confused about
|
||||
# -Wlogical-op: Warn about suspicious uses of logical operators in expressions
|
||||
# -Wstrict-prototypes: Warn if a function is declared or defined without specifying the argument types
|
||||
# -Wmissing-prototypes: Warn if a global function is defined without a previous prototype declaration
|
||||
# -Wredundant-decls: Warn if anything is declared more than once in the same scope
|
||||
# -Winline: Warn if a function that is declared as inline cannot be inlined
|
||||
ifeq "$(GCCVERSION8)" "1"
|
||||
# -Wduplicated-cond: Warn about duplicated conditions in an if-else-if chain
|
||||
# -Wduplicated-branches: Warn when an if-else has identical branches
|
||||
# -Wcast-align=strict: Warn whenever a pointer is cast such that the required alignment of the target is increased. For example, warn if a "char *" is cast to an "int *" regardless of the target machine.
|
||||
# -Wlogical-not-parentheses: Warn about logical not used on the left hand side operand of a comparison
|
||||
EXTRAWARNGCC8=-Wduplicated-cond -Wduplicated-branches -Wcast-align=strict -Wlogical-not-parentheses -Wsuggest-attribute=pure -Wsuggest-attribute=const -Wsuggest-attribute=noreturn -Wsuggest-attribute=malloc -Wsuggest-attribute=format -Wsuggest-attribute=cold
|
||||
else
|
||||
EXTRAWARNGCC8=
|
||||
endif
|
||||
EXTRAWARN=-Werror -Waddress -Wlogical-op -Wmissing-field-initializers -Woverlength-strings -Wformat -Wformat-nonliteral -Wuninitialized -Wswitch-enum -Wshadow \
|
||||
-Wfloat-equal -Wunsafe-loop-optimizations -funsafe-loop-optimizations -Wbad-function-cast -Wwrite-strings -Wparentheses -Wlogical-op -Wstrict-prototypes -Wmissing-prototypes -Wredundant-decls -Winline $(EXTRAWARNGCC8)
|
||||
|
||||
# -FILE_OFFSET_BITS=64: used by stat(). Avoids problems with files > 2 GB on 32bit machines
|
||||
CCFLAGS=-std=gnu11 -I$(IDIR) $(WARNFLAGS) -D_FILE_OFFSET_BITS=64 $(HARDENING_FLAGS) $(DEBUG_FLAGS) $(CFLAGS) $(SQLITEFLAGS)
|
||||
|
||||
# for FTL we need the pthread library
|
||||
# for dnsmasq we need the nettle crypto library and the gmp maths library
|
||||
# We link the two libraries statically. Although this increases the binary file size by about 1 MB, it saves about 5 MB of shared libraries and makes deployment easier
|
||||
#LIBS=-pthread -lnettle -lgmp -lhogweed
|
||||
LIBS=-pthread -Wl,-Bstatic -L/usr/local/lib -lhogweed -lgmp -lnettle -Wl,-Bdynamic -lrt -lcap
|
||||
LIBS=-pthread -lrt -Wl,-Bstatic -L/usr/local/lib -lhogweed -lgmp -lnettle -Wl,-Bdynamic
|
||||
# Flags for compiling with libidn : -lidn
|
||||
# Flags for compiling with libidn2: -lidn2
|
||||
|
||||
|
||||
162
api.c
162
api.c
@@ -17,10 +17,10 @@
|
||||
#define min(a,b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a < _b ? _a : _b; })
|
||||
|
||||
/* qsort comparision function (count field), sort ASC */
|
||||
int cmpasc(const void *a, const void *b)
|
||||
static int __attribute__((pure)) cmpasc(const void *a, const void *b)
|
||||
{
|
||||
int *elem1 = (int*)a;
|
||||
int *elem2 = (int*)b;
|
||||
const int *elem1 = (int*)a;
|
||||
const int *elem2 = (int*)b;
|
||||
|
||||
if (elem1[1] < elem2[1])
|
||||
return -1;
|
||||
@@ -31,10 +31,10 @@ int cmpasc(const void *a, const void *b)
|
||||
}
|
||||
|
||||
// qsort subroutine, sort DESC
|
||||
int cmpdesc(const void *a, const void *b)
|
||||
static int __attribute__((pure)) cmpdesc(const void *a, const void *b)
|
||||
{
|
||||
int *elem1 = (int*)a;
|
||||
int *elem2 = (int*)b;
|
||||
const int *elem1 = (int*)a;
|
||||
const int *elem2 = (int*)b;
|
||||
|
||||
if (elem1[1] > elem2[1])
|
||||
return -1;
|
||||
@@ -44,10 +44,10 @@ int cmpdesc(const void *a, const void *b)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void getStats(int *sock)
|
||||
void getStats(const int *sock)
|
||||
{
|
||||
int blocked = counters->blocked;
|
||||
int total = counters->queries;
|
||||
const int blocked = counters->blocked;
|
||||
const int total = counters->queries;
|
||||
float percentage = 0.0f;
|
||||
|
||||
// Avoid 1/0 condition
|
||||
@@ -111,7 +111,7 @@ void getStats(int *sock)
|
||||
pack_uint8(*sock, blockingstatus);
|
||||
}
|
||||
|
||||
void getOverTime(int *sock)
|
||||
void getOverTime(const int *sock)
|
||||
{
|
||||
int i, from = 0, until = OVERTIME_SLOTS;
|
||||
bool found = false;
|
||||
@@ -147,7 +147,7 @@ void getOverTime(int *sock)
|
||||
{
|
||||
for(i = from; i < until; i++)
|
||||
{
|
||||
ssend(*sock,"%i %i %i\n",overTime[i].timestamp,overTime[i].total,overTime[i].blocked);
|
||||
ssend(*sock,"%li %i %i\n",overTime[i].timestamp,overTime[i].total,overTime[i].blocked);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -171,12 +171,12 @@ void getOverTime(int *sock)
|
||||
}
|
||||
}
|
||||
|
||||
void getTopDomains(char *client_message, int *sock)
|
||||
void getTopDomains(const char *client_message, const int *sock)
|
||||
{
|
||||
int i, temparray[counters->domains][2], count=10, num;
|
||||
bool blocked, audit = false, asc = false;
|
||||
bool audit = false, asc = false;
|
||||
|
||||
blocked = command(client_message, ">top-ads");
|
||||
const bool blocked = command(client_message, ">top-ads");
|
||||
|
||||
// Exit before processing any data if requested via config setting
|
||||
get_privacy_level(NULL);
|
||||
@@ -224,7 +224,7 @@ void getTopDomains(char *client_message, int *sock)
|
||||
|
||||
|
||||
// Get filter
|
||||
char * filter = read_setupVarsconf("API_QUERY_LOG_SHOW");
|
||||
const char* filter = read_setupVarsconf("API_QUERY_LOG_SHOW");
|
||||
bool showpermitted = true, showblocked = true;
|
||||
if(filter != NULL)
|
||||
{
|
||||
@@ -264,7 +264,7 @@ void getTopDomains(char *client_message, int *sock)
|
||||
for(i=0; i < counters->domains; i++)
|
||||
{
|
||||
// Get sorted indices
|
||||
int j = temparray[i][0];
|
||||
const int j = temparray[i][0];
|
||||
validate_access("domains", j, true, __LINE__, __FUNCTION__, __FILE__);
|
||||
|
||||
// Skip this domain if there is a filter on it
|
||||
@@ -333,7 +333,7 @@ void getTopDomains(char *client_message, int *sock)
|
||||
clearSetupVarsArray();
|
||||
}
|
||||
|
||||
void getTopClients(char *client_message, int *sock)
|
||||
void getTopClients(const char *client_message, const int *sock)
|
||||
{
|
||||
int i, temparray[counters->clients][2], count=10, num;
|
||||
|
||||
@@ -389,7 +389,7 @@ void getTopClients(char *client_message, int *sock)
|
||||
qsort(temparray, counters->clients, sizeof(int[2]), cmpdesc);
|
||||
|
||||
// Get clients which the user doesn't want to see
|
||||
char * excludeclients = read_setupVarsconf("API_EXCLUDE_CLIENTS");
|
||||
const char* excludeclients = read_setupVarsconf("API_EXCLUDE_CLIENTS");
|
||||
if(excludeclients != NULL)
|
||||
{
|
||||
getSetupVarsArray(excludeclients);
|
||||
@@ -405,8 +405,8 @@ void getTopClients(char *client_message, int *sock)
|
||||
for(i=0; i < counters->clients; i++)
|
||||
{
|
||||
// Get sorted indices and counter values (may be either total or blocked count)
|
||||
int j = temparray[i][0];
|
||||
int ccount = temparray[i][1];
|
||||
const int j = temparray[i][0];
|
||||
const int ccount = temparray[i][1];
|
||||
validate_access("clients", j, true, __LINE__, __FUNCTION__, __FILE__);
|
||||
|
||||
// Skip this client if there is a filter on it
|
||||
@@ -418,8 +418,8 @@ void getTopClients(char *client_message, int *sock)
|
||||
if(strcmp(getstr(clients[j].ippos), HIDDEN_CLIENT) == 0)
|
||||
continue;
|
||||
|
||||
char *client_ip = getstr(clients[j].ippos);
|
||||
char *client_name = getstr(clients[j].namepos);
|
||||
const char *client_ip = getstr(clients[j].ippos);
|
||||
const char *client_name = getstr(clients[j].namepos);
|
||||
|
||||
// Return this client if either
|
||||
// - "withzero" option is set, and/or
|
||||
@@ -447,15 +447,15 @@ void getTopClients(char *client_message, int *sock)
|
||||
}
|
||||
|
||||
|
||||
void getForwardDestinations(char *client_message, int *sock)
|
||||
void getForwardDestinations(const char *client_message, const int *sock)
|
||||
{
|
||||
bool sort = true;
|
||||
int i, temparray[counters->forwarded][2], totalqueries = 0;
|
||||
int temparray[counters->forwarded][2], totalqueries = 0;
|
||||
|
||||
if(command(client_message, "unsorted"))
|
||||
sort = false;
|
||||
|
||||
for(i=0; i < counters->forwarded; i++) {
|
||||
for(int i = 0; i < counters->forwarded; i++) {
|
||||
validate_access("forwarded", i, true, __LINE__, __FUNCTION__, __FILE__);
|
||||
// If we want to print a sorted output, we fill the temporary array with
|
||||
// the values we will use for sorting afterwards
|
||||
@@ -474,10 +474,10 @@ void getForwardDestinations(char *client_message, int *sock)
|
||||
totalqueries = counters->forwardedqueries + counters->cached + counters->blocked;
|
||||
|
||||
// Loop over available forward destinations
|
||||
for(i=-2; i < min(counters->forwarded, 8); i++)
|
||||
for(int i = -2; i < min(counters->forwarded, 8); i++)
|
||||
{
|
||||
char *ip, *name;
|
||||
float percentage = 0.0f;
|
||||
const char* ip, *name;
|
||||
|
||||
if(i == -2)
|
||||
{
|
||||
@@ -538,17 +538,17 @@ void getForwardDestinations(char *client_message, int *sock)
|
||||
}
|
||||
|
||||
|
||||
void getQueryTypes(int *sock)
|
||||
void getQueryTypes(const int *sock)
|
||||
{
|
||||
int i,total = 0;
|
||||
for(i=0; i < TYPE_MAX-1; i++)
|
||||
int total = 0;
|
||||
for(int i=0; i < TYPE_MAX-1; i++)
|
||||
total += counters->querytype[i];
|
||||
|
||||
float percentage[TYPE_MAX-1] = { 0.0 };
|
||||
|
||||
// Prevent floating point exceptions by checking if the divisor is != 0
|
||||
if(total > 0)
|
||||
for(i=0; i < TYPE_MAX-1; i++)
|
||||
for(int i=0; i < TYPE_MAX-1; i++)
|
||||
percentage[i] = 1e2f*counters->querytype[i]/total;
|
||||
|
||||
if(istelnet[*sock]) {
|
||||
@@ -574,9 +574,9 @@ void getQueryTypes(int *sock)
|
||||
}
|
||||
}
|
||||
|
||||
char *querytypes[8] = {"A","AAAA","ANY","SRV","SOA","PTR","TXT","UNKN"};
|
||||
const char *querytypes[8] = {"A","AAAA","ANY","SRV","SOA","PTR","TXT","UNKN"};
|
||||
|
||||
void getAllQueries(char *client_message, int *sock)
|
||||
void getAllQueries(const char *client_message, const int *sock)
|
||||
{
|
||||
// Exit before processing any data if requested via config setting
|
||||
get_privacy_level(NULL);
|
||||
@@ -631,10 +631,9 @@ void getAllQueries(char *client_message, int *sock)
|
||||
else
|
||||
{
|
||||
// Iterate through all known forward destinations
|
||||
int i;
|
||||
validate_access("forwards", MAX(0,counters->forwarded-1), true, __LINE__, __FUNCTION__, __FILE__);
|
||||
forwarddestid = -3;
|
||||
for(i = 0; i < counters->forwarded; i++)
|
||||
for(int i = 0; i < counters->forwarded; i++)
|
||||
{
|
||||
// Try to match the requested string against their IP addresses and
|
||||
// (if available) their host names
|
||||
@@ -664,9 +663,8 @@ void getAllQueries(char *client_message, int *sock)
|
||||
sscanf(client_message, ">getallqueries-domain %255s", domainname);
|
||||
filterdomainname = true;
|
||||
// Iterate through all known domains
|
||||
int i;
|
||||
validate_access("domains", MAX(0,counters->domains-1), true, __LINE__, __FUNCTION__, __FILE__);
|
||||
for(i = 0; i < counters->domains; i++)
|
||||
for(int i = 0; i < counters->domains; i++)
|
||||
{
|
||||
// Try to match the requested string
|
||||
if(strcmp(getstr(domains[i].domainpos), domainname) == 0)
|
||||
@@ -692,9 +690,8 @@ void getAllQueries(char *client_message, int *sock)
|
||||
sscanf(client_message, ">getallqueries-client %255s", clientname);
|
||||
filterclientname = true;
|
||||
// Iterate through all known clients
|
||||
int i;
|
||||
validate_access("clients", MAX(0,counters->clients-1), true, __LINE__, __FUNCTION__, __FILE__);
|
||||
for(i = 0; i < counters->clients; i++)
|
||||
for(int i = 0; i < counters->clients; i++)
|
||||
{
|
||||
// Try to match the requested string
|
||||
if(strcmp(getstr(clients[i].ippos), clientname) == 0 ||
|
||||
@@ -742,8 +739,8 @@ void getAllQueries(char *client_message, int *sock)
|
||||
}
|
||||
clearSetupVarsArray();
|
||||
|
||||
int i;
|
||||
for(i=ibeg; i < counters->queries; i++)
|
||||
// Main loop
|
||||
for(int i=ibeg; i < counters->queries; i++)
|
||||
{
|
||||
validate_access("queries", i, true, __LINE__, __FUNCTION__, __FILE__);
|
||||
// Check if this query has been create while in maximum privacy mode
|
||||
@@ -752,7 +749,7 @@ void getAllQueries(char *client_message, int *sock)
|
||||
validate_access("domains", queries[i].domainID, true, __LINE__, __FUNCTION__, __FILE__);
|
||||
validate_access("clients", queries[i].clientID, true, __LINE__, __FUNCTION__, __FILE__);
|
||||
|
||||
char *qtype = querytypes[queries[i].type - TYPE_A];
|
||||
const char *qtype = querytypes[queries[i].type - TYPE_A];
|
||||
|
||||
// 1 = gravity.list, 4 = wildcard, 5 = black.list
|
||||
if((queries[i].status == QUERY_GRAVITY ||
|
||||
@@ -797,9 +794,9 @@ void getAllQueries(char *client_message, int *sock)
|
||||
|
||||
// Ask subroutine for domain. It may return "hidden" depending on
|
||||
// the privacy settings at the time the query was made
|
||||
char *domain = getDomainString(i);
|
||||
const char *domain = getDomainString(i);
|
||||
// Similarly for the client
|
||||
char *client;
|
||||
const char *client;
|
||||
if(strlen(getstr(clients[queries[i].clientID].namepos)) > 0)
|
||||
client = getClientNameString(i);
|
||||
else
|
||||
@@ -812,7 +809,10 @@ void getAllQueries(char *client_message, int *sock)
|
||||
|
||||
if(istelnet[*sock])
|
||||
{
|
||||
ssend(*sock,"%i %s %s %s %i %i %i %lu\n",queries[i].timestamp,qtype,domain,client,queries[i].status,queries[i].dnssec,queries[i].reply,delay);
|
||||
ssend(*sock,"%li %s %s %s %i %i %i %lu",queries[i].timestamp,qtype,domain,client,queries[i].status,queries[i].dnssec,queries[i].reply,delay);
|
||||
if(config.debug & DEBUG_API)
|
||||
ssend(*sock, " %i", i);
|
||||
ssend(*sock, "\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -842,9 +842,9 @@ void getAllQueries(char *client_message, int *sock)
|
||||
free(forwarddest);
|
||||
}
|
||||
|
||||
void getRecentBlocked(char *client_message, int *sock)
|
||||
void getRecentBlocked(const char *client_message, const int *sock)
|
||||
{
|
||||
int i, num=1;
|
||||
int num=1;
|
||||
|
||||
// Test for integer that specifies number of entries to be shown
|
||||
if(sscanf(client_message, "%*[^(](%i)", &num) > 0) {
|
||||
@@ -855,7 +855,7 @@ void getRecentBlocked(char *client_message, int *sock)
|
||||
|
||||
// Find most recently blocked query
|
||||
int found = 0;
|
||||
for(i = counters->queries - 1; i > 0 ; i--)
|
||||
for(int i = counters->queries - 1; i > 0 ; i--)
|
||||
{
|
||||
validate_access("queries", i, true, __LINE__, __FUNCTION__, __FILE__);
|
||||
|
||||
@@ -867,7 +867,7 @@ void getRecentBlocked(char *client_message, int *sock)
|
||||
|
||||
// Ask subroutine for domain. It may return "hidden" depending on
|
||||
// the privacy settings at the time the query was made
|
||||
char *domain = getDomainString(i);
|
||||
const char *domain = getDomainString(i);
|
||||
|
||||
if(istelnet[*sock])
|
||||
ssend(*sock,"%s\n", domain);
|
||||
@@ -880,7 +880,7 @@ void getRecentBlocked(char *client_message, int *sock)
|
||||
}
|
||||
}
|
||||
|
||||
void getClientID(int *sock)
|
||||
void getClientID(const int *sock)
|
||||
{
|
||||
if(istelnet[*sock])
|
||||
ssend(*sock,"%i\n", *sock);
|
||||
@@ -888,11 +888,11 @@ void getClientID(int *sock)
|
||||
pack_int32(*sock, *sock);
|
||||
}
|
||||
|
||||
void getQueryTypesOverTime(int *sock)
|
||||
void getQueryTypesOverTime(const int *sock)
|
||||
{
|
||||
int i, from = -1, until = OVERTIME_SLOTS;
|
||||
int from = -1, until = OVERTIME_SLOTS;
|
||||
time_t mintime = overTime[0].timestamp;
|
||||
for(i = 0; i < OVERTIME_SLOTS; i++)
|
||||
for(int i = 0; i < OVERTIME_SLOTS; i++)
|
||||
{
|
||||
if((overTime[i].total > 0 || overTime[i].blocked > 0) && overTime[i].timestamp >= mintime)
|
||||
{
|
||||
@@ -902,7 +902,7 @@ void getQueryTypesOverTime(int *sock)
|
||||
}
|
||||
|
||||
// End with last non-empty overTime slot
|
||||
for(i = 0; i < OVERTIME_SLOTS; i++)
|
||||
for(int i = 0; i < OVERTIME_SLOTS; i++)
|
||||
{
|
||||
if(overTime[i].timestamp >= time(NULL))
|
||||
{
|
||||
@@ -915,7 +915,7 @@ void getQueryTypesOverTime(int *sock)
|
||||
if(from < 0)
|
||||
return;
|
||||
|
||||
for(i = from; i < until; i++)
|
||||
for(int i = from; i < until; i++)
|
||||
{
|
||||
float percentageIPv4 = 0.0, percentageIPv6 = 0.0;
|
||||
int sum = overTime[i].querytypedata[0] + overTime[i].querytypedata[1];
|
||||
@@ -926,7 +926,7 @@ void getQueryTypesOverTime(int *sock)
|
||||
}
|
||||
|
||||
if(istelnet[*sock])
|
||||
ssend(*sock, "%i %.2f %.2f\n", overTime[i].timestamp, percentageIPv4, percentageIPv6);
|
||||
ssend(*sock, "%li %.2f %.2f\n", overTime[i].timestamp, percentageIPv4, percentageIPv6);
|
||||
else {
|
||||
pack_int32(*sock, overTime[i].timestamp);
|
||||
pack_float(*sock, percentageIPv4);
|
||||
@@ -935,7 +935,7 @@ void getQueryTypesOverTime(int *sock)
|
||||
}
|
||||
}
|
||||
|
||||
void getVersion(int *sock)
|
||||
void getVersion(const int *sock)
|
||||
{
|
||||
const char * commit = GIT_HASH;
|
||||
const char * tag = GIT_TAG;
|
||||
@@ -984,7 +984,7 @@ void getVersion(int *sock)
|
||||
}
|
||||
}
|
||||
|
||||
void getDBstats(int *sock)
|
||||
void getDBstats(const int *sock)
|
||||
{
|
||||
// Get file details
|
||||
struct stat st;
|
||||
@@ -1011,9 +1011,9 @@ void getDBstats(int *sock)
|
||||
}
|
||||
}
|
||||
|
||||
void getClientsOverTime(int *sock)
|
||||
void getClientsOverTime(const int *sock)
|
||||
{
|
||||
int i, sendit = -1, until = OVERTIME_SLOTS;
|
||||
int sendit = -1, until = OVERTIME_SLOTS;
|
||||
|
||||
// Exit before processing any data if requested via config setting
|
||||
get_privacy_level(NULL);
|
||||
@@ -1021,7 +1021,7 @@ void getClientsOverTime(int *sock)
|
||||
return;
|
||||
|
||||
// Find minimum ID to send
|
||||
for(i = 0; i < OVERTIME_SLOTS; i++)
|
||||
for(int i = 0; i < OVERTIME_SLOTS; i++)
|
||||
{
|
||||
if((overTime[i].total > 0 || overTime[i].blocked > 0) &&
|
||||
overTime[i].timestamp >= overTime[0].timestamp)
|
||||
@@ -1034,7 +1034,7 @@ void getClientsOverTime(int *sock)
|
||||
return;
|
||||
|
||||
// Find minimum ID to send
|
||||
for(i = 0; i < OVERTIME_SLOTS; i++)
|
||||
for(int i = 0; i < OVERTIME_SLOTS; i++)
|
||||
{
|
||||
if(overTime[i].timestamp >= time(NULL))
|
||||
{
|
||||
@@ -1055,7 +1055,7 @@ void getClientsOverTime(int *sock)
|
||||
{
|
||||
getSetupVarsArray(excludeclients);
|
||||
|
||||
for(i=0; i < counters->clients; i++)
|
||||
for(int i=0; i < counters->clients; i++)
|
||||
{
|
||||
validate_access("clients", i, true, __LINE__, __FUNCTION__, __FILE__);
|
||||
// Check if this client should be skipped
|
||||
@@ -1066,10 +1066,10 @@ void getClientsOverTime(int *sock)
|
||||
}
|
||||
|
||||
// Main return loop
|
||||
for(i = sendit; i < until; i++)
|
||||
for(int i = sendit; i < until; i++)
|
||||
{
|
||||
if(istelnet[*sock])
|
||||
ssend(*sock, "%i", overTime[i].timestamp);
|
||||
ssend(*sock, "%li", overTime[i].timestamp);
|
||||
else
|
||||
pack_int32(*sock, overTime[i].timestamp);
|
||||
|
||||
@@ -1079,7 +1079,7 @@ void getClientsOverTime(int *sock)
|
||||
if(skipclient[j])
|
||||
continue;
|
||||
|
||||
int thisclient = clients[j].overTime[i];
|
||||
const int thisclient = clients[j].overTime[i];
|
||||
|
||||
if(istelnet[*sock])
|
||||
ssend(*sock, " %i", thisclient);
|
||||
@@ -1097,10 +1097,8 @@ void getClientsOverTime(int *sock)
|
||||
clearSetupVarsArray();
|
||||
}
|
||||
|
||||
void getClientNames(int *sock)
|
||||
void getClientNames(const int *sock)
|
||||
{
|
||||
int i;
|
||||
|
||||
// Exit before processing any data if requested via config setting
|
||||
get_privacy_level(NULL);
|
||||
if(config.privacylevel >= PRIVACY_HIDE_DOMAINS_CLIENTS)
|
||||
@@ -1118,7 +1116,7 @@ void getClientNames(int *sock)
|
||||
{
|
||||
getSetupVarsArray(excludeclients);
|
||||
|
||||
for(i=0; i < counters->clients; i++)
|
||||
for(int i=0; i < counters->clients; i++)
|
||||
{
|
||||
validate_access("clients", i, true, __LINE__, __FUNCTION__, __FILE__);
|
||||
// Check if this client should be skipped
|
||||
@@ -1129,14 +1127,14 @@ void getClientNames(int *sock)
|
||||
}
|
||||
|
||||
// Loop over clients to generate output to be sent to the client
|
||||
for(i = 0; i < counters->clients; i++)
|
||||
for(int i = 0; i < counters->clients; i++)
|
||||
{
|
||||
validate_access("clients", i, true, __LINE__, __FUNCTION__, __FILE__);
|
||||
if(skipclient[i])
|
||||
continue;
|
||||
|
||||
char *client_ip = getstr(clients[i].ippos);
|
||||
char *client_name = getstr(clients[i].namepos);
|
||||
const char *client_ip = getstr(clients[i].ippos);
|
||||
const char *client_name = getstr(clients[i].namepos);
|
||||
|
||||
if(istelnet[*sock])
|
||||
ssend(*sock, "%s %s\n", client_name, client_ip);
|
||||
@@ -1150,15 +1148,14 @@ void getClientNames(int *sock)
|
||||
clearSetupVarsArray();
|
||||
}
|
||||
|
||||
void getUnknownQueries(int *sock)
|
||||
void getUnknownQueries(const int *sock)
|
||||
{
|
||||
// Exit before processing any data if requested via config setting
|
||||
get_privacy_level(NULL);
|
||||
if(config.privacylevel >= PRIVACY_HIDE_DOMAINS)
|
||||
return;
|
||||
|
||||
int i;
|
||||
for(i=0; i < counters->queries; i++)
|
||||
for(int i=0; i < counters->queries; i++)
|
||||
{
|
||||
validate_access("queries", i, true, __LINE__, __FUNCTION__, __FILE__);
|
||||
if(queries[i].status != QUERY_UNKNOWN && queries[i].complete) continue;
|
||||
@@ -1177,10 +1174,10 @@ void getUnknownQueries(int *sock)
|
||||
validate_access("clients", queries[i].clientID, true, __LINE__, __FUNCTION__, __FILE__);
|
||||
|
||||
|
||||
char *client = getstr(clients[queries[i].clientID].ippos);
|
||||
const char *client = getstr(clients[queries[i].clientID].ippos);
|
||||
|
||||
if(istelnet[*sock])
|
||||
ssend(*sock, "%i %i %i %s %s %s %i %s\n", queries[i].timestamp, i, queries[i].id, type, getstr(domains[queries[i].domainID].domainpos), client, queries[i].status, queries[i].complete ? "true" : "false");
|
||||
ssend(*sock, "%li %i %i %s %s %s %i %s\n", queries[i].timestamp, i, queries[i].id, type, getstr(domains[queries[i].domainID].domainpos), client, queries[i].status, queries[i].complete ? "true" : "false");
|
||||
else {
|
||||
pack_int32(*sock, queries[i].timestamp);
|
||||
pack_int32(*sock, queries[i].id);
|
||||
@@ -1199,7 +1196,7 @@ void getUnknownQueries(int *sock)
|
||||
}
|
||||
}
|
||||
|
||||
void getDomainDetails(char *client_message, int *sock)
|
||||
void getDomainDetails(const char *client_message, const int *sock)
|
||||
{
|
||||
// Get domain name
|
||||
char domain[128];
|
||||
@@ -1209,8 +1206,7 @@ void getDomainDetails(char *client_message, int *sock)
|
||||
return;
|
||||
}
|
||||
|
||||
int i;
|
||||
for(i = 0; i < counters->domains; i++)
|
||||
for(int i = 0; i < counters->domains; i++)
|
||||
{
|
||||
validate_access("domains", i, true, __LINE__, __FUNCTION__, __FILE__);
|
||||
if(strcmp(getstr(domains[i].domainpos), domain) == 0)
|
||||
@@ -1218,10 +1214,10 @@ void getDomainDetails(char *client_message, int *sock)
|
||||
ssend(*sock,"Domain \"%s\", ID: %i\n", domain, i);
|
||||
ssend(*sock,"Total: %i\n", domains[i].count);
|
||||
ssend(*sock,"Blocked: %i\n", domains[i].blockedcount);
|
||||
char *regexstatus;
|
||||
const char *regexstatus;
|
||||
if(domains[i].regexmatch == REGEX_BLOCKED)
|
||||
regexstatus = "blocked";
|
||||
if(domains[i].regexmatch == REGEX_NOTBLOCKED)
|
||||
else if(domains[i].regexmatch == REGEX_NOTBLOCKED)
|
||||
regexstatus = "not blocked";
|
||||
else
|
||||
regexstatus = "unknown";
|
||||
|
||||
54
api.h
54
api.h
@@ -9,36 +9,36 @@
|
||||
* Please see LICENSE file for your rights under this license. */
|
||||
|
||||
// Statistic methods
|
||||
void getStats(int *sock);
|
||||
void getOverTime(int *sock);
|
||||
void getTopDomains(char *client_message, int *sock);
|
||||
void getTopClients(char *client_message, int *sock);
|
||||
void getForwardDestinations(char *client_message, int *sock);
|
||||
void getQueryTypes(int *sock);
|
||||
void getAllQueries(char *client_message, int *sock);
|
||||
void getRecentBlocked(char *client_message, int *sock);
|
||||
void getQueryTypesOverTime(int *sock);
|
||||
void getClientsOverTime(int *sock);
|
||||
void getClientNames(int *sock);
|
||||
void getDomainDetails(char *client_message, int *sock);
|
||||
void getStats(const int *sock);
|
||||
void getOverTime(const int *sock);
|
||||
void getTopDomains(const char *client_message, const int *sock);
|
||||
void getTopClients(const char *client_message, const int *sock);
|
||||
void getForwardDestinations(const char *client_message, const int *sock);
|
||||
void getQueryTypes(const int *sock);
|
||||
void getAllQueries(const char *client_message, const int *sock);
|
||||
void getRecentBlocked(const char *client_message, const int *sock);
|
||||
void getQueryTypesOverTime(const int *sock);
|
||||
void getClientsOverTime(const int *sock);
|
||||
void getClientNames(const int *sock);
|
||||
void getDomainDetails(const char *client_message, const int *sock);
|
||||
|
||||
// FTL methods
|
||||
void getClientID(int *sock);
|
||||
void getVersion(int *sock);
|
||||
void getDBstats(int *sock);
|
||||
void getUnknownQueries(int *sock);
|
||||
void getClientID(const int *sock);
|
||||
void getVersion(const int *sock);
|
||||
void getDBstats(const int *sock);
|
||||
void getUnknownQueries(const int *sock);
|
||||
|
||||
// DNS resolver methods (dnsmasq_interface.c)
|
||||
void getCacheInformation(int *sock);
|
||||
void getCacheInformation(const int *sock);
|
||||
|
||||
// MessagePack serialization helpers
|
||||
void pack_eom(int sock);
|
||||
void pack_bool(int sock, bool value);
|
||||
void pack_uint8(int sock, uint8_t value);
|
||||
void pack_uint64(int sock, uint64_t value);
|
||||
void pack_int32(int sock, int32_t value);
|
||||
void pack_int64(int sock, int64_t value);
|
||||
void pack_float(int sock, float value);
|
||||
bool pack_fixstr(int sock, char *string);
|
||||
bool pack_str32(int sock, char *string);
|
||||
void pack_map16_start(int sock, uint16_t length);
|
||||
void pack_eom(const int sock);
|
||||
void pack_bool(const int sock, const bool value);
|
||||
void pack_uint8(const int sock, const uint8_t value);
|
||||
void pack_uint64(const int sock, const uint64_t value);
|
||||
void pack_int32(const int sock, const int32_t value);
|
||||
void pack_int64(const int sock, const int64_t value);
|
||||
void pack_float(const int sock, const float value);
|
||||
bool pack_fixstr(const int sock, const char *string);
|
||||
bool pack_str32(const int sock, const char *string);
|
||||
void pack_map16_start(const int sock, const uint16_t length);
|
||||
|
||||
10
args.c
10
args.c
@@ -15,7 +15,7 @@ static bool debug = false;
|
||||
bool daemonmode = true;
|
||||
bool travis = false;
|
||||
int argc_dnsmasq = 0;
|
||||
char **argv_dnsmasq = NULL;
|
||||
const char** argv_dnsmasq = NULL;
|
||||
|
||||
void parse_args(int argc, char* argv[])
|
||||
{
|
||||
@@ -52,7 +52,6 @@ void parse_args(int argc, char* argv[])
|
||||
strcmp(argv[i], "version") == 0 ||
|
||||
strcmp(argv[i], "--version") == 0)
|
||||
{
|
||||
const char * commit = GIT_HASH;
|
||||
const char * tag = GIT_TAG;
|
||||
if(strlen(tag) > 1)
|
||||
{
|
||||
@@ -60,6 +59,7 @@ void parse_args(int argc, char* argv[])
|
||||
}
|
||||
else
|
||||
{
|
||||
const char * commit = GIT_HASH;
|
||||
char hash[8];
|
||||
// Extract first 7 characters of the hash
|
||||
strncpy(hash, commit, 7); hash[7] = 0;
|
||||
@@ -100,10 +100,10 @@ void parse_args(int argc, char* argv[])
|
||||
// Implement dnsmasq's test function
|
||||
if(strcmp(argv[i], "dnsmasq-test") == 0)
|
||||
{
|
||||
char *arg[2];
|
||||
const char *arg[2];
|
||||
arg[0] = "";
|
||||
arg[1] = "--test";
|
||||
main_dnsmasq(2,arg);
|
||||
main_dnsmasq(2, arg);
|
||||
ok = true;
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ void parse_args(int argc, char* argv[])
|
||||
int j;
|
||||
argc_dnsmasq = argc - i + 1;
|
||||
if(argv_dnsmasq != NULL) free(argv_dnsmasq);
|
||||
argv_dnsmasq = calloc(argc_dnsmasq + 2,sizeof(char*));
|
||||
argv_dnsmasq = calloc(argc_dnsmasq + 2,sizeof(const char*));
|
||||
argv_dnsmasq[0] = "";
|
||||
if(debug) argv_dnsmasq[1] = "-d";
|
||||
else argv_dnsmasq[1] = "-k";
|
||||
|
||||
101
capabilities.c
101
capabilities.c
@@ -8,36 +8,99 @@
|
||||
* This file is copyright under the latest version of the EUPL.
|
||||
* Please see LICENSE file for your rights under this license. */
|
||||
|
||||
// Definition of LINUX_CAPABILITY_VERSION_*
|
||||
#define FTLDNS
|
||||
#include "dnsmasq/dnsmasq.h"
|
||||
#undef __USE_XOPEN
|
||||
#include "FTL.h"
|
||||
#include <sys/capability.h>
|
||||
|
||||
bool check_capabilities()
|
||||
static const unsigned int capabilityIDs[] = { CAP_CHOWN , CAP_DAC_OVERRIDE , CAP_DAC_READ_SEARCH , CAP_FOWNER , CAP_FSETID , CAP_KILL , CAP_SETGID , CAP_SETUID , CAP_SETPCAP , CAP_LINUX_IMMUTABLE , CAP_NET_BIND_SERVICE , CAP_NET_BROADCAST , CAP_NET_ADMIN , CAP_NET_RAW , CAP_IPC_LOCK , CAP_IPC_OWNER , CAP_SYS_MODULE , CAP_SYS_RAWIO , CAP_SYS_CHROOT , CAP_SYS_PTRACE , CAP_SYS_PACCT , CAP_SYS_ADMIN , CAP_SYS_BOOT , CAP_SYS_NICE , CAP_SYS_RESOURCE , CAP_SYS_TIME , CAP_SYS_TTY_CONFIG , CAP_MKNOD , CAP_LEASE , CAP_AUDIT_WRITE , CAP_AUDIT_CONTROL , CAP_SETFCAP , CAP_MAC_OVERRIDE , CAP_MAC_ADMIN , CAP_SYSLOG , CAP_WAKE_ALARM , CAP_BLOCK_SUSPEND , CAP_AUDIT_READ };
|
||||
static const char* capabilityNames[] = {"CAP_CHOWN", "CAP_DAC_OVERRIDE", "CAP_DAC_READ_SEARCH", "CAP_FOWNER", "CAP_FSETID", "CAP_KILL", "CAP_SETGID", "CAP_SETUID", "CAP_SETPCAP", "CAP_LINUX_IMMUTABLE", "CAP_NET_BIND_SERVICE", "CAP_NET_BROADCAST", "CAP_NET_ADMIN", "CAP_NET_RAW", "CAP_IPC_LOCK", "CAP_IPC_OWNER", "CAP_SYS_MODULE", "CAP_SYS_RAWIO", "CAP_SYS_CHROOT", "CAP_SYS_PTRACE", "CAP_SYS_PACCT", "CAP_SYS_ADMIN", "CAP_SYS_BOOT", "CAP_SYS_NICE", "CAP_SYS_RESOURCE", "CAP_SYS_TIME", "CAP_SYS_TTY_CONFIG", "CAP_MKNOD", "CAP_LEASE", "CAP_AUDIT_WRITE", "CAP_AUDIT_CONTROL", "CAP_SETFCAP", "CAP_MAC_OVERRIDE", "CAP_MAC_ADMIN", "CAP_SYSLOG", "CAP_WAKE_ALARM", "CAP_BLOCK_SUSPEND", "CAP_AUDIT_READ"};
|
||||
static const unsigned int numCaps = sizeof(capabilityIDs) / sizeof(const unsigned int);
|
||||
|
||||
bool check_capabilities(void)
|
||||
{
|
||||
if(!cap_get_bound(CAP_NET_ADMIN))
|
||||
// First assume header version 1
|
||||
int capsize = 1; // VFS_CAP_U32_1
|
||||
cap_user_data_t data = NULL;
|
||||
cap_user_header_t hdr = calloc(sizeof(*hdr), capsize);
|
||||
|
||||
// Determine capabilities version used by the current kernel
|
||||
capget(hdr, NULL);
|
||||
|
||||
// Check version
|
||||
if (hdr->version != LINUX_CAPABILITY_VERSION_1)
|
||||
{
|
||||
// If unknown version, use largest supported version (3)
|
||||
// Version 2 is deprecated according to linux/capability.h
|
||||
if (hdr->version != LINUX_CAPABILITY_VERSION_2)
|
||||
{
|
||||
hdr->version = LINUX_CAPABILITY_VERSION_3;
|
||||
capsize = 2; // VFS_CAP_U32_3
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use version 2
|
||||
capsize = 2; // VFS_CAP_U32_2
|
||||
}
|
||||
}
|
||||
|
||||
// Get current capabilities
|
||||
data = calloc(sizeof(*data), capsize);
|
||||
capget(hdr, data);
|
||||
|
||||
if(config.debug & DEBUG_CAPS)
|
||||
{
|
||||
logg("***************************************");
|
||||
logg("* Linux capability debugging enabled *");
|
||||
for(unsigned int i = 0u; i < numCaps; i++)
|
||||
{
|
||||
const unsigned int capid = capabilityIDs[i];
|
||||
|
||||
// Check if capability is valid for the current kernel
|
||||
// If not, exit loop early
|
||||
if(!cap_valid(capid))
|
||||
break;
|
||||
|
||||
logg("* %-24s (%02u) = %s%s%s *",
|
||||
capabilityNames[capid], capid,
|
||||
((data->permitted & (1 << capid)) ? "P":"-"),
|
||||
((data->inheritable & (1 << capid)) ? "I":"-"),
|
||||
((data->effective & (1 << capid)) ? "E":"-"));
|
||||
}
|
||||
logg("***************************************");
|
||||
}
|
||||
|
||||
bool capabilities_okay = true;
|
||||
if (!(data->permitted & (1 << CAP_NET_ADMIN)))
|
||||
{
|
||||
// Needed for ARP-injection (used when we're the DHCP server)
|
||||
logg("**************************************************************");
|
||||
logg("WARNING: Required linux capability CAP_NET_ADMIN not available");
|
||||
logg("**************************************************************");
|
||||
return false;
|
||||
logg("*************************************************************************");
|
||||
logg("* WARNING: Required Linux capability CAP_NET_ADMIN not available *");
|
||||
logg("*************************************************************************");
|
||||
capabilities_okay = false;
|
||||
}
|
||||
if(!cap_get_bound(CAP_NET_RAW))
|
||||
if (!(data->permitted & (1 << CAP_NET_RAW)))
|
||||
{
|
||||
// Needed for raw socket access (necessary for ICMP)
|
||||
logg("************************************************************");
|
||||
logg("WARNING: Required linux capability CAP_NET_RAW not available");
|
||||
logg("************************************************************");
|
||||
return false;
|
||||
logg("*************************************************************************");
|
||||
logg("* WARNING: Required Linux capability CAP_NET_RAW not available *");
|
||||
logg("*************************************************************************");
|
||||
capabilities_okay = false;
|
||||
}
|
||||
if(!cap_get_bound(CAP_NET_BIND_SERVICE))
|
||||
if (!(data->permitted & (1 << CAP_NET_BIND_SERVICE)))
|
||||
{
|
||||
// Necessary for dynamic port binding
|
||||
logg("*********************************************************************");
|
||||
logg("WARNING: Required linux capability CAP_NET_BIND_SERVICE not available");
|
||||
logg("*********************************************************************");
|
||||
return false;
|
||||
logg("*************************************************************************");
|
||||
logg("* WARNING: Required Linux capability CAP_NET_BIND_SERVICE not available *");
|
||||
logg("*************************************************************************");
|
||||
capabilities_okay = false;
|
||||
}
|
||||
|
||||
// All okay!
|
||||
return true;
|
||||
// Free allocated memory
|
||||
free(hdr);
|
||||
free(data);
|
||||
|
||||
// Return whether capabilities are all okay
|
||||
return capabilities_okay;
|
||||
}
|
||||
|
||||
27
config.c
27
config.c
@@ -13,7 +13,7 @@
|
||||
ConfigStruct config;
|
||||
static char *parse_FTLconf(FILE *fp, const char * key);
|
||||
static void release_config_memory(void);
|
||||
void getpath(FILE* fp, const char *option, const char *defaultloc, char **pointer);
|
||||
static void getpath(FILE* fp, const char *option, const char *defaultloc, char **pointer);
|
||||
|
||||
char *conflinebuffer = NULL;
|
||||
|
||||
@@ -112,7 +112,7 @@ void read_FTLconf(void)
|
||||
config.maxDBdays = value;
|
||||
|
||||
if(config.maxDBdays == 0)
|
||||
logg(" MAXDBDAYS: --- (DB disabled)", config.maxDBdays);
|
||||
logg(" MAXDBDAYS: --- (DB disabled)");
|
||||
else
|
||||
logg(" MAXDBDAYS: max age for stored queries is %i days", config.maxDBdays);
|
||||
|
||||
@@ -337,7 +337,7 @@ void read_FTLconf(void)
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
void getpath(FILE* fp, const char *option, const char *defaultloc, char **pointer)
|
||||
static void getpath(FILE* fp, const char *option, const char *defaultloc, char **pointer)
|
||||
{
|
||||
// This subroutine is used to read paths from pihole-FTL.conf
|
||||
// fp: File pointer to opened and readable config file
|
||||
@@ -579,12 +579,30 @@ void read_debuging_settings(FILE *fp)
|
||||
if(buffer != NULL && strcasecmp(buffer, "true") == 0)
|
||||
config.debug |= DEBUG_REGEX;
|
||||
|
||||
// DEBUG_API
|
||||
// defaults to: false
|
||||
buffer = parse_FTLconf(fp, "DEBUG_API");
|
||||
if(buffer != NULL && strcasecmp(buffer, "true") == 0)
|
||||
config.debug |= DEBUG_API;
|
||||
|
||||
// DEBUG_OVERTIME
|
||||
// defaults to: false
|
||||
buffer = parse_FTLconf(fp, "DEBUG_OVERTIME");
|
||||
if(buffer != NULL && strcasecmp(buffer, "true") == 0)
|
||||
config.debug |= DEBUG_OVERTIME;
|
||||
|
||||
// DEBUG_EXTBLOCKED
|
||||
// defaults to: false
|
||||
buffer = parse_FTLconf(fp, "DEBUG_EXTBLOCKED");
|
||||
if(buffer != NULL && strcasecmp(buffer, "true") == 0)
|
||||
config.debug |= DEBUG_EXTBLOCKED;
|
||||
|
||||
// DEBUG_CAPS
|
||||
// defaults to: false
|
||||
buffer = parse_FTLconf(fp, "DEBUG_CAPS");
|
||||
if(buffer != NULL && strcasecmp(buffer, "true") == 0)
|
||||
config.debug |= DEBUG_CAPS;
|
||||
|
||||
// DEBUG_ALL
|
||||
// defaults to: false
|
||||
buffer = parse_FTLconf(fp, "DEBUG_ALL");
|
||||
@@ -604,7 +622,10 @@ void read_debuging_settings(FILE *fp)
|
||||
logg("* DEBUG_GC %s *", (config.debug & DEBUG_GC)? "YES":"NO ");
|
||||
logg("* DEBUG_ARP %s *", (config.debug & DEBUG_ARP)? "YES":"NO ");
|
||||
logg("* DEBUG_REGEX %s *", (config.debug & DEBUG_REGEX)? "YES":"NO ");
|
||||
logg("* DEBUG_API %s *", (config.debug & DEBUG_API)? "YES":"NO ");
|
||||
logg("* DEBUG_OVERTIME %s *", (config.debug & DEBUG_OVERTIME)? "YES":"NO ");
|
||||
logg("* DEBUG_EXTBLOCKED %s *", (config.debug & DEBUG_EXTBLOCKED)? "YES":"NO ");
|
||||
logg("* DEBUG_CAPS %s *", (config.debug & DEBUG_CAPS)? "YES":"NO ");
|
||||
logg("************************");
|
||||
}
|
||||
|
||||
|
||||
27
daemon.c
27
daemon.c
@@ -14,11 +14,8 @@ struct timeval t0[NUMTIMERS];
|
||||
|
||||
void go_daemon(void)
|
||||
{
|
||||
pid_t process_id = 0;
|
||||
pid_t sid = 0;
|
||||
|
||||
// Create child process
|
||||
process_id = fork();
|
||||
pid_t process_id = fork();
|
||||
|
||||
// Indication of fork() failure
|
||||
if (process_id < 0)
|
||||
@@ -41,7 +38,7 @@ void go_daemon(void)
|
||||
|
||||
//set new session
|
||||
// creates a session and sets the process group ID
|
||||
sid = setsid();
|
||||
const pid_t sid = setsid();
|
||||
if(sid < 0)
|
||||
{
|
||||
// Return failure
|
||||
@@ -80,7 +77,7 @@ void go_daemon(void)
|
||||
// Closing stdin, stdout and stderr is handled by dnsmasq
|
||||
}
|
||||
|
||||
void timer_start(int i)
|
||||
void timer_start(const int i)
|
||||
{
|
||||
if(i >= NUMTIMERS)
|
||||
{
|
||||
@@ -90,7 +87,7 @@ void timer_start(int i)
|
||||
gettimeofday(&t0[i], 0);
|
||||
}
|
||||
|
||||
double timer_elapsed_msec(int i)
|
||||
double timer_elapsed_msec(const int i)
|
||||
{
|
||||
if(i >= NUMTIMERS)
|
||||
{
|
||||
@@ -102,7 +99,7 @@ double timer_elapsed_msec(int i)
|
||||
return (t1.tv_sec - t0[i].tv_sec) * 1000.0f + (t1.tv_usec - t0[i].tv_usec) / 1000.0f;
|
||||
}
|
||||
|
||||
void sleepms(int milliseconds)
|
||||
void sleepms(const int milliseconds)
|
||||
{
|
||||
struct timeval tv;
|
||||
tv.tv_sec = milliseconds / 1000;
|
||||
@@ -113,7 +110,7 @@ void sleepms(int milliseconds)
|
||||
void savepid(void)
|
||||
{
|
||||
FILE *f;
|
||||
pid_t pid = getpid();
|
||||
const pid_t pid = getpid();
|
||||
if((f = fopen(FTLfiles.pid, "w+")) == NULL)
|
||||
{
|
||||
logg("WARNING: Unable to write PID to file.");
|
||||
@@ -140,20 +137,20 @@ void removepid(void)
|
||||
|
||||
char *getUserName(void)
|
||||
{
|
||||
char * username;
|
||||
char * name;
|
||||
// the getpwuid() function shall search the user database for an entry with a matching uid
|
||||
// the geteuid() function shall return the effective user ID of the calling process - this is used as the search criteria for the getpwuid() function
|
||||
uid_t euid = geteuid();
|
||||
struct passwd *pw = getpwuid(euid);
|
||||
const uid_t euid = geteuid();
|
||||
const struct passwd *pw = getpwuid(euid);
|
||||
if(pw)
|
||||
{
|
||||
username = strdup(pw->pw_name);
|
||||
name = strdup(pw->pw_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(asprintf(&username, "%u", euid) < 0)
|
||||
if(asprintf(&name, "%u", euid) < 0)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return username;
|
||||
return name;
|
||||
}
|
||||
|
||||
81
database.c
81
database.c
@@ -19,10 +19,10 @@ long int lastdbindex = 0;
|
||||
|
||||
static pthread_mutex_t dblock;
|
||||
|
||||
bool db_set_counter(unsigned int ID, int value);
|
||||
int db_get_FTL_property(unsigned int ID);
|
||||
static bool db_set_counter(const unsigned int ID, const int value);
|
||||
static int db_get_FTL_property(const unsigned int ID);
|
||||
|
||||
void check_database(int rc)
|
||||
static void check_database(int rc)
|
||||
{
|
||||
// We will retry if the database is busy at the moment
|
||||
// However, we won't retry if any other error happened
|
||||
@@ -49,7 +49,7 @@ void dbclose(void)
|
||||
pthread_mutex_unlock(&dblock);
|
||||
}
|
||||
|
||||
double get_db_filesize(void)
|
||||
static double get_db_filesize(void)
|
||||
{
|
||||
struct stat st;
|
||||
if(stat(FTLfiles.db, &st) != 0)
|
||||
@@ -106,7 +106,7 @@ bool dbquery(const char *format, ...)
|
||||
|
||||
}
|
||||
|
||||
bool create_counter_table(void)
|
||||
static bool create_counter_table(void)
|
||||
{
|
||||
bool ret;
|
||||
// Create FTL table in the database (holds properties like database version, etc.)
|
||||
@@ -132,7 +132,7 @@ bool create_counter_table(void)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool db_create(void)
|
||||
static bool db_create(void)
|
||||
{
|
||||
bool ret;
|
||||
int rc = sqlite3_open_v2(FTLfiles.db, &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
|
||||
@@ -265,7 +265,7 @@ void db_init(void)
|
||||
database = true;
|
||||
}
|
||||
|
||||
int db_get_FTL_property(unsigned int ID)
|
||||
static int db_get_FTL_property(const unsigned int ID)
|
||||
{
|
||||
// Prepare SQL statement
|
||||
char* querystr = NULL;
|
||||
@@ -283,17 +283,17 @@ int db_get_FTL_property(unsigned int ID)
|
||||
return value;
|
||||
}
|
||||
|
||||
bool db_set_FTL_property(unsigned int ID, int value)
|
||||
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);
|
||||
}
|
||||
|
||||
bool db_set_counter(unsigned int ID, int value)
|
||||
static bool db_set_counter(const unsigned int ID, const int value)
|
||||
{
|
||||
return dbquery("INSERT OR REPLACE INTO counters (id, value) VALUES ( %u, %i );", ID, value);
|
||||
}
|
||||
|
||||
bool db_update_counters(int total, int blocked)
|
||||
static bool db_update_counters(const int total, const int blocked)
|
||||
{
|
||||
if(!dbquery("UPDATE counters SET value = value + %i WHERE id = %i;", total, DB_TOTALQUERIES))
|
||||
return false;
|
||||
@@ -338,7 +338,7 @@ int db_query_int(const char* querystr)
|
||||
return result;
|
||||
}
|
||||
|
||||
int number_of_queries_in_DB(void)
|
||||
static int number_of_queries_in_DB(void)
|
||||
{
|
||||
sqlite3_stmt* stmt;
|
||||
|
||||
@@ -429,7 +429,7 @@ void save_to_DB(void)
|
||||
|
||||
unsigned int saved = 0, saved_error = 0;
|
||||
long int i;
|
||||
sqlite3_stmt* stmt;
|
||||
sqlite3_stmt* stmt = NULL;
|
||||
|
||||
// Get last ID stored in the database
|
||||
sqlite3_int64 lastID = last_ID_in_DB();
|
||||
@@ -490,11 +490,11 @@ void save_to_DB(void)
|
||||
sqlite3_bind_int(stmt, 3, queries[i].status);
|
||||
|
||||
// DOMAIN
|
||||
char *domain = getDomainString(i);
|
||||
const char *domain = getDomainString(i);
|
||||
sqlite3_bind_text(stmt, 4, domain, -1, SQLITE_TRANSIENT);
|
||||
|
||||
// CLIENT
|
||||
char *client = getClientIPString(i);
|
||||
const char *client = getClientIPString(i);
|
||||
sqlite3_bind_text(stmt, 5, client, -1, SQLITE_TRANSIENT);
|
||||
|
||||
// FORWARD
|
||||
@@ -538,7 +538,9 @@ void save_to_DB(void)
|
||||
if(queries[i].status == QUERY_GRAVITY ||
|
||||
queries[i].status == QUERY_BLACKLIST ||
|
||||
queries[i].status == QUERY_WILDCARD ||
|
||||
queries[i].status == QUERY_EXTERNAL_BLOCKED)
|
||||
queries[i].status == QUERY_EXTERNAL_BLOCKED_IP ||
|
||||
queries[i].status == QUERY_EXTERNAL_BLOCKED_NULL ||
|
||||
queries[i].status == QUERY_EXTERNAL_BLOCKED_NXRA)
|
||||
blocked++;
|
||||
|
||||
// Update lasttimestamp variable with timestamp of the latest stored query
|
||||
@@ -577,7 +579,7 @@ void save_to_DB(void)
|
||||
}
|
||||
}
|
||||
|
||||
void delete_old_queries_in_DB(void)
|
||||
static void delete_old_queries_in_DB(void)
|
||||
{
|
||||
// Open database
|
||||
if(!dbopen())
|
||||
@@ -597,7 +599,7 @@ void delete_old_queries_in_DB(void)
|
||||
}
|
||||
|
||||
// Get how many rows have been affected (deleted)
|
||||
int affected = sqlite3_changes(db);
|
||||
const int affected = sqlite3_changes(db);
|
||||
|
||||
// Print final message only if there is a difference
|
||||
if((config.debug & DEBUG_DATABASE) || affected)
|
||||
@@ -672,8 +674,8 @@ void read_data_from_DB(void)
|
||||
// Prepare request
|
||||
char *rstr = NULL;
|
||||
// Get time stamp 24 hours in the past
|
||||
time_t now = time(NULL);
|
||||
time_t mintime = now - config.maxlogage;
|
||||
const time_t now = time(NULL);
|
||||
const time_t mintime = now - config.maxlogage;
|
||||
int rc = asprintf(&rstr, "SELECT * FROM queries WHERE timestamp >= %li", mintime);
|
||||
if(rc < 1)
|
||||
{
|
||||
@@ -681,10 +683,10 @@ void read_data_from_DB(void)
|
||||
return;
|
||||
}
|
||||
// Log DB query string in debug mode
|
||||
if(config.debug & DEBUG_DATABASE) logg(rstr);
|
||||
if(config.debug & DEBUG_DATABASE) logg("%s", rstr);
|
||||
|
||||
// Prepare SQLite3 statement
|
||||
sqlite3_stmt* stmt;
|
||||
sqlite3_stmt* stmt = NULL;
|
||||
rc = sqlite3_prepare_v2(db, rstr, -1, &stmt, NULL);
|
||||
if( rc ){
|
||||
logg("read_data_from_DB() - SQL error prepare (%i): %s", rc, sqlite3_errmsg(db));
|
||||
@@ -696,21 +698,21 @@ void read_data_from_DB(void)
|
||||
// Loop through returned database rows
|
||||
while((rc = sqlite3_step(stmt)) == SQLITE_ROW)
|
||||
{
|
||||
sqlite3_int64 dbid = sqlite3_column_int64(stmt, 0);
|
||||
time_t queryTimeStamp = sqlite3_column_int(stmt, 1);
|
||||
const sqlite3_int64 dbid = sqlite3_column_int64(stmt, 0);
|
||||
const time_t queryTimeStamp = sqlite3_column_int(stmt, 1);
|
||||
// 1483228800 = 01/01/2017 @ 12:00am (UTC)
|
||||
if(queryTimeStamp < 1483228800)
|
||||
{
|
||||
logg("DB warn: TIMESTAMP should be larger than 01/01/2017 but is %i", queryTimeStamp);
|
||||
logg("DB warn: TIMESTAMP should be larger than 01/01/2017 but is %li", queryTimeStamp);
|
||||
continue;
|
||||
}
|
||||
if(queryTimeStamp > now)
|
||||
{
|
||||
if(config.debug & DEBUG_DATABASE) logg("DB warn: Skipping query logged in the future (%i)", queryTimeStamp);
|
||||
if(config.debug & DEBUG_DATABASE) logg("DB warn: Skipping query logged in the future (%li)", queryTimeStamp);
|
||||
continue;
|
||||
}
|
||||
|
||||
int type = sqlite3_column_int(stmt, 2);
|
||||
const int type = sqlite3_column_int(stmt, 2);
|
||||
if(type < TYPE_A || type >= TYPE_MAX)
|
||||
{
|
||||
logg("DB warn: TYPE should not be %i", type);
|
||||
@@ -723,24 +725,24 @@ void read_data_from_DB(void)
|
||||
continue;
|
||||
}
|
||||
|
||||
int status = sqlite3_column_int(stmt, 3);
|
||||
if(status < QUERY_UNKNOWN || status > QUERY_EXTERNAL_BLOCKED)
|
||||
const int status = sqlite3_column_int(stmt, 3);
|
||||
if(status < QUERY_UNKNOWN || status > QUERY_EXTERNAL_BLOCKED_NXRA)
|
||||
{
|
||||
logg("DB warn: STATUS should be within [%i,%i] but is %i", QUERY_UNKNOWN, QUERY_EXTERNAL_BLOCKED, status);
|
||||
logg("DB warn: STATUS should be within [%i,%i] but is %i", QUERY_UNKNOWN, QUERY_EXTERNAL_BLOCKED_NXRA, status);
|
||||
continue;
|
||||
}
|
||||
|
||||
const char * domain = (const char *)sqlite3_column_text(stmt, 4);
|
||||
if(domain == NULL)
|
||||
{
|
||||
logg("DB warn: DOMAIN should never be NULL, %i", queryTimeStamp);
|
||||
logg("DB warn: DOMAIN should never be NULL, %li", queryTimeStamp);
|
||||
continue;
|
||||
}
|
||||
|
||||
const char * client = (const char *)sqlite3_column_text(stmt, 5);
|
||||
if(client == NULL)
|
||||
{
|
||||
logg("DB warn: CLIENT should never be NULL, %i", queryTimeStamp);
|
||||
logg("DB warn: CLIENT should never be NULL, %li", queryTimeStamp);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -759,22 +761,22 @@ void read_data_from_DB(void)
|
||||
{
|
||||
if(forwarddest == NULL)
|
||||
{
|
||||
logg("DB warn: FORWARD should not be NULL with status QUERY_FORWARDED, %i", queryTimeStamp);
|
||||
logg("DB warn: FORWARD should not be NULL with status QUERY_FORWARDED, %li", queryTimeStamp);
|
||||
continue;
|
||||
}
|
||||
forwardID = findForwardID(forwarddest, true);
|
||||
}
|
||||
|
||||
// Obtain IDs only after filtering which queries we want to keep
|
||||
int timeidx = getOverTimeID(queryTimeStamp);
|
||||
int domainID = findDomainID(domain);
|
||||
int clientID = findClientID(client, true);
|
||||
const int timeidx = getOverTimeID(queryTimeStamp);
|
||||
const int domainID = findDomainID(domain);
|
||||
const int clientID = findClientID(client, true);
|
||||
|
||||
// Ensure we have enough space in the queries struct
|
||||
memory_check(QUERIES);
|
||||
|
||||
// Set index for this query
|
||||
int queryIndex = counters->queries;
|
||||
const int queryIndex = counters->queries;
|
||||
|
||||
// Store this query in memory
|
||||
validate_access("queries", queryIndex, false, __LINE__, __FUNCTION__, __FILE__);
|
||||
@@ -791,7 +793,6 @@ void read_data_from_DB(void)
|
||||
queries[queryIndex].id = 0;
|
||||
queries[queryIndex].complete = true; // Mark as all information is available
|
||||
queries[queryIndex].response = 0;
|
||||
queries[queryIndex].AD = false;
|
||||
queries[queryIndex].dnssec = DNSSEC_UNKNOWN;
|
||||
queries[queryIndex].reply = REPLY_UNKNOWN;
|
||||
|
||||
@@ -824,7 +825,9 @@ void read_data_from_DB(void)
|
||||
case QUERY_GRAVITY: // Blocked by gravity.list
|
||||
case QUERY_WILDCARD: // Blocked by regex filter
|
||||
case QUERY_BLACKLIST: // Blocked by black.list
|
||||
case QUERY_EXTERNAL_BLOCKED: // Blocked by external provider
|
||||
case QUERY_EXTERNAL_BLOCKED_IP: // Blocked by external provider
|
||||
case QUERY_EXTERNAL_BLOCKED_NULL: // Blocked by external provider
|
||||
case QUERY_EXTERNAL_BLOCKED_NXRA: // Blocked by external provider
|
||||
counters->blocked++;
|
||||
domains[domainID].blockedcount++;
|
||||
clients[clientID].blockedcount++;
|
||||
@@ -846,7 +849,7 @@ void read_data_from_DB(void)
|
||||
|
||||
default:
|
||||
logg("Error: Found unknown status %i in long term database!", status);
|
||||
logg(" Timestamp: %i", queryTimeStamp);
|
||||
logg(" Timestamp: %li", queryTimeStamp);
|
||||
logg(" Continuing anyway...");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ void strtolower(char *str)
|
||||
while(str[i]){ str[i] = tolower(str[i]); i++; }
|
||||
}
|
||||
|
||||
int findForwardID(const char * forward, bool count)
|
||||
int findForwardID(const char * forward, const bool count)
|
||||
{
|
||||
int i, forwardID = -1;
|
||||
if(counters->forwarded > 0)
|
||||
@@ -106,13 +106,12 @@ int findDomainID(const char *domain)
|
||||
return domainID;
|
||||
}
|
||||
|
||||
int findClientID(const char *client, bool count)
|
||||
int findClientID(const char *client, const bool count)
|
||||
{
|
||||
int i;
|
||||
// Compare content of client against known client IP addresses
|
||||
if(counters->clients > 0)
|
||||
validate_access("clients", counters->clients-1, true, __LINE__, __FUNCTION__, __FILE__);
|
||||
for(i=0; i < counters->clients; i++)
|
||||
for(int i=0; i < counters->clients; i++)
|
||||
{
|
||||
// Quick test: Does the clients IP start with the same character?
|
||||
if(getstr(clients[i].ippos)[0] != client[0])
|
||||
@@ -182,7 +181,7 @@ bool isValidIPv6(const char *addr)
|
||||
|
||||
// Privacy-level sensitive subroutine that returns the domain name
|
||||
// only when appropriate for the requested query
|
||||
char *getDomainString(int queryID)
|
||||
const char *getDomainString(const int queryID)
|
||||
{
|
||||
if(queries[queryID].privacylevel < PRIVACY_HIDE_DOMAINS)
|
||||
{
|
||||
@@ -195,7 +194,7 @@ char *getDomainString(int queryID)
|
||||
|
||||
// Privacy-level sensitive subroutine that returns the client IP
|
||||
// only when appropriate for the requested query
|
||||
char *getClientIPString(int queryID)
|
||||
const char *getClientIPString(const int queryID)
|
||||
{
|
||||
if(queries[queryID].privacylevel < PRIVACY_HIDE_DOMAINS_CLIENTS)
|
||||
{
|
||||
@@ -208,7 +207,7 @@ char *getClientIPString(int queryID)
|
||||
|
||||
// Privacy-level sensitive subroutine that returns the client host name
|
||||
// only when appropriate for the requested query
|
||||
char *getClientNameString(int queryID)
|
||||
const char *getClientNameString(const int queryID)
|
||||
{
|
||||
if(queries[queryID].privacylevel < PRIVACY_HIDE_DOMAINS_CLIENTS)
|
||||
{
|
||||
|
||||
@@ -1220,9 +1220,6 @@ size_t resize_packet(struct dns_header *header, size_t plen,
|
||||
int add_resource_record(struct dns_header *header, char *limit, int *truncp,
|
||||
int nameoffset, unsigned char **pp, unsigned long ttl,
|
||||
int *offset, unsigned short type, unsigned short class, char *format, ...);
|
||||
unsigned char *skip_questions(struct dns_header *header, size_t plen);
|
||||
int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
||||
char *name, int isExtract, int extrabytes);
|
||||
int in_arpa_name_2_addr(char *namein, struct all_addr *addrp);
|
||||
int private_net(struct in_addr addr, int ban_localhost);
|
||||
|
||||
@@ -1463,7 +1460,18 @@ void route_sock(void);
|
||||
#endif
|
||||
|
||||
/* bpf.c or netlink.c */
|
||||
/************ Pi-hole modification ************/
|
||||
// We need to skip this function declaration
|
||||
// when compiling FTLDNS code as it is not
|
||||
// a valid prototype such that this line
|
||||
// would throw an error when compiling
|
||||
// dnsmasq_interface.c
|
||||
#if !defined(FTLDNS)
|
||||
/**********************************************/
|
||||
int iface_enumerate(int family, void *parm, int (callback)());
|
||||
/************ Pi-hole modification ************/
|
||||
#endif
|
||||
/**********************************************/
|
||||
|
||||
/* dbus.c */
|
||||
#ifdef HAVE_DBUS
|
||||
@@ -1564,8 +1572,6 @@ void dhcp_update_configs(struct dhcp_config *configs);
|
||||
void display_opts(void);
|
||||
int lookup_dhcp_opt(int prot, char *name);
|
||||
int lookup_dhcp_len(int prot, int val);
|
||||
char *option_string(int prot, unsigned int opt, unsigned char *val,
|
||||
int opt_len, char *buf, int buf_len);
|
||||
struct dhcp_config *find_config(struct dhcp_config *configs,
|
||||
struct dhcp_context *context,
|
||||
unsigned char *clid, int clid_len,
|
||||
|
||||
@@ -687,7 +687,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
|
||||
}
|
||||
}
|
||||
|
||||
FTL_header_ADbit(header->hb4, RCODE(header), daemon->log_display_id);
|
||||
FTL_header_analysis(header->hb4, rcode, daemon->log_display_id);
|
||||
|
||||
/* RFC 4035 sect 4.6 para 3 */
|
||||
if (!is_sign && !option_bool(OPT_DNSSEC_PROXY))
|
||||
|
||||
@@ -8,24 +8,29 @@
|
||||
* This file is copyright under the latest version of the EUPL.
|
||||
* Please see LICENSE file for your rights under this license. */
|
||||
|
||||
#define FTLDNS
|
||||
#include "dnsmasq/dnsmasq.h"
|
||||
#undef __USE_XOPEN
|
||||
#include "FTL.h"
|
||||
#include "dnsmasq_interface.h"
|
||||
#include "shmem.h"
|
||||
// Prototype of getCacheInformation()
|
||||
#include "api.h"
|
||||
|
||||
void print_flags(unsigned int flags);
|
||||
void save_reply_type(unsigned int flags, int queryID, struct timeval response);
|
||||
unsigned long converttimeval(struct timeval time);
|
||||
static void block_single_domain_regex(char *domain);
|
||||
static void detect_blocked_IP(unsigned short flags, char* answer, int queryID);
|
||||
static void query_externally_blocked(int i);
|
||||
static int findQueryID(int id);
|
||||
static void print_flags(const unsigned int flags);
|
||||
static void save_reply_type(const unsigned int flags, const int queryID, const struct timeval response);
|
||||
static unsigned long converttimeval(const struct timeval time) __attribute__((const));
|
||||
static void block_single_domain_regex(const char *domain);
|
||||
static void detect_blocked_IP(const unsigned short flags, const char* answer, const int queryID);
|
||||
static void query_externally_blocked(const int queryID, const unsigned char status);
|
||||
static int findQueryID(const int id);
|
||||
|
||||
unsigned char* pihole_privacylevel = &config.privacylevel;
|
||||
char flagnames[28][12] = {"F_IMMORTAL ", "F_NAMEP ", "F_REVERSE ", "F_FORWARD ", "F_DHCP ", "F_NEG ", "F_HOSTS ", "F_IPV4 ", "F_IPV6 ", "F_BIGNAME ", "F_NXDOMAIN ", "F_CNAME ", "F_DNSKEY ", "F_CONFIG ", "F_DS ", "F_DNSSECOK ", "F_UPSTREAM ", "F_RRNAME ", "F_SERVER ", "F_QUERY ", "F_NOERR ", "F_AUTH ", "F_DNSSEC ", "F_KEYTAG ", "F_SECSTAT ", "F_NO_RR ", "F_IPSET ", "F_NOEXTRA "};
|
||||
const char flagnames[28][12] = {"F_IMMORTAL ", "F_NAMEP ", "F_REVERSE ", "F_FORWARD ", "F_DHCP ", "F_NEG ", "F_HOSTS ", "F_IPV4 ", "F_IPV6 ", "F_BIGNAME ", "F_NXDOMAIN ", "F_CNAME ", "F_DNSKEY ", "F_CONFIG ", "F_DS ", "F_DNSSECOK ", "F_UPSTREAM ", "F_RRNAME ", "F_SERVER ", "F_QUERY ", "F_NOERR ", "F_AUTH ", "F_DNSSEC ", "F_KEYTAG ", "F_SECSTAT ", "F_NO_RR ", "F_IPSET ", "F_NOEXTRA "};
|
||||
|
||||
void _FTL_new_query(unsigned int flags, char *name, struct all_addr *addr, char *types, int id, char type, const char* file, const int line)
|
||||
void _FTL_new_query(const unsigned int flags, const char *name, const struct all_addr *addr,
|
||||
const char *types, const int id, const char type,
|
||||
const char* file, const int line)
|
||||
{
|
||||
// Don't analyze anything if in PRIVACY_NOSTATS mode
|
||||
if(config.privacylevel >= PRIVACY_NOSTATS)
|
||||
@@ -35,7 +40,7 @@ void _FTL_new_query(unsigned int flags, char *name, struct all_addr *addr, char
|
||||
lock_shm();
|
||||
|
||||
// Get timestamp
|
||||
time_t querytimestamp = time(NULL);
|
||||
const time_t querytimestamp = time(NULL);
|
||||
|
||||
// Save request time
|
||||
struct timeval request;
|
||||
@@ -75,7 +80,7 @@ void _FTL_new_query(unsigned int flags, char *name, struct all_addr *addr, char
|
||||
|
||||
// Ensure we have enough space in the queries struct
|
||||
memory_check(QUERIES);
|
||||
int queryID = counters->queries;
|
||||
const int queryID = counters->queries;
|
||||
|
||||
// Convert domain to lower case
|
||||
char *domain = strdup(name);
|
||||
@@ -110,14 +115,18 @@ void _FTL_new_query(unsigned int flags, char *name, struct all_addr *addr, char
|
||||
}
|
||||
|
||||
// Log new query if in debug mode
|
||||
char *proto = (type == UDP) ? "UDP" : "TCP";
|
||||
if(config.debug & DEBUG_QUERIES) logg("**** new %s %s \"%s\" from %s (ID %i, %s:%i)", proto, types, domain, client, id, file, line);
|
||||
const char *proto = (type == UDP) ? "UDP" : "TCP";
|
||||
if(config.debug & DEBUG_QUERIES)
|
||||
{
|
||||
logg("**** new %s %s \"%s\" from %s (ID %i, FTL %i, %s:%i)",
|
||||
proto, types, domain, client, id, queryID, file, line);
|
||||
}
|
||||
|
||||
// Update counters
|
||||
counters->querytype[querytype-1]++;
|
||||
|
||||
// Update overTime
|
||||
unsigned int timeidx = getOverTimeID(querytimestamp);
|
||||
const unsigned int timeidx = getOverTimeID(querytimestamp);
|
||||
overTime[timeidx].querytypedata[querytype-1]++;
|
||||
|
||||
// Skip rest of the analysis if this query is not of type A or AAAA
|
||||
@@ -134,10 +143,10 @@ void _FTL_new_query(unsigned int flags, char *name, struct all_addr *addr, char
|
||||
}
|
||||
|
||||
// Go through already knows domains and see if it is one of them
|
||||
int domainID = findDomainID(domain);
|
||||
const int domainID = findDomainID(domain);
|
||||
|
||||
// Go through already knows clients and see if it is one of them
|
||||
int clientID = findClientID(client, true);
|
||||
const int clientID = findClientID(client, true);
|
||||
|
||||
// Save everything
|
||||
validate_access("queries", queryID, false, __LINE__, __FUNCTION__, __FILE__);
|
||||
@@ -157,8 +166,6 @@ void _FTL_new_query(unsigned int flags, char *name, struct all_addr *addr, char
|
||||
queries[queryID].reply = REPLY_UNKNOWN;
|
||||
// Store DNSSEC result for this domain
|
||||
queries[queryID].dnssec = DNSSEC_UNSPECIFIED;
|
||||
// AD has not yet been received for this query
|
||||
queries[queryID].AD = false;
|
||||
|
||||
// Check and apply possible privacy level rules
|
||||
// The currently set privacy level (at the time the query is
|
||||
@@ -218,7 +225,7 @@ void _FTL_new_query(unsigned int flags, char *name, struct all_addr *addr, char
|
||||
unlock_shm();
|
||||
}
|
||||
|
||||
static int findQueryID(int id)
|
||||
static int findQueryID(const int id)
|
||||
{
|
||||
// Loop over all queries - we loop in reverse order (start from the most recent query and
|
||||
// continuously walk older queries while trying to find a match. Ideally, we should always
|
||||
@@ -229,8 +236,8 @@ static int findQueryID(int id)
|
||||
// MAX(0, a) is used to return 0 in case a is negative (negative array indices are harmful)
|
||||
|
||||
// Validate access only once for the maximum index (all lower will work)
|
||||
int until = MAX(0, counters->queries-MAXITER);
|
||||
int start = MAX(0, counters->queries-1);
|
||||
const int until = MAX(0, counters->queries-MAXITER);
|
||||
const int start = MAX(0, counters->queries-1);
|
||||
validate_access("queries", until, false, __LINE__, __FUNCTION__, __FILE__);
|
||||
|
||||
// Check UUIDs of queries
|
||||
@@ -242,7 +249,8 @@ static int findQueryID(int id)
|
||||
return -1;
|
||||
}
|
||||
|
||||
void _FTL_forwarded(unsigned int flags, char *name, struct all_addr *addr, int id, const char* file, const int line)
|
||||
void _FTL_forwarded(const unsigned int flags, const char *name, const struct 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)
|
||||
@@ -265,7 +273,7 @@ void _FTL_forwarded(unsigned int flags, char *name, struct all_addr *addr, int i
|
||||
if(config.debug & DEBUG_QUERIES) logg("**** forwarded %s to %s (ID %i, %s:%i)", name, forward, id, file, line);
|
||||
|
||||
// Save status and forwardID in corresponding query identified by dnsmasq's ID
|
||||
int i = findQueryID(id);
|
||||
const int i = findQueryID(id);
|
||||
if(i < 0)
|
||||
{
|
||||
// This may happen e.g. if the original query was a PTR query or "pi.hole"
|
||||
@@ -290,10 +298,10 @@ void _FTL_forwarded(unsigned int flags, char *name, struct all_addr *addr, int i
|
||||
|
||||
// Get ID of forward destination, create new forward destination record
|
||||
// if not found in current data structure
|
||||
int forwardID = findForwardID(forward, true);
|
||||
const int forwardID = findForwardID(forward, true);
|
||||
queries[i].forwardID = forwardID;
|
||||
|
||||
unsigned int timeidx = queries[i].timeidx;
|
||||
const unsigned int timeidx = queries[i].timeidx;
|
||||
|
||||
if(queries[i].status == QUERY_CACHE)
|
||||
{
|
||||
@@ -356,6 +364,8 @@ void FTL_dnsmasq_reload(void)
|
||||
// *before* clearing the cache and rereading the lists
|
||||
// This is the only hook that is not skipped in PRIVACY_NOSTATS mode
|
||||
|
||||
logg("Received SIGHUP, reloading cache");
|
||||
|
||||
// Called when dnsmasq re-reads its config and hosts files
|
||||
// Reset number of blocked domains
|
||||
counters->gravity = 0;
|
||||
@@ -387,9 +397,14 @@ void FTL_dnsmasq_reload(void)
|
||||
|
||||
// Reread pihole-FTL.conf to see which debugging flags are set
|
||||
read_debuging_settings(NULL);
|
||||
|
||||
// Print current set of capabilities if requested via debug flag
|
||||
if(config.debug & DEBUG_CAPS)
|
||||
check_capabilities();
|
||||
}
|
||||
|
||||
void _FTL_reply(unsigned short flags, char *name, struct all_addr *addr, int id, const char* file, const int line)
|
||||
void _FTL_reply(const unsigned short flags, const char *name, const struct 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)
|
||||
@@ -406,7 +421,7 @@ void _FTL_reply(unsigned short flags, char *name, struct all_addr *addr, int id,
|
||||
|
||||
// Extract answer (used e.g. for detecting if a local config is a user-defined
|
||||
// wildcard blocking entry in form "server=/tobeblocked.com/")
|
||||
char *answer = dest;
|
||||
const char *answer = dest;
|
||||
if(flags & F_CNAME)
|
||||
answer = "(CNAME)";
|
||||
else if((flags & F_NEG) && (flags & F_NXDOMAIN))
|
||||
@@ -425,7 +440,7 @@ void _FTL_reply(unsigned short flags, char *name, struct all_addr *addr, int id,
|
||||
gettimeofday(&response, 0);
|
||||
|
||||
// Save status in corresponding query identified by dnsmasq's ID
|
||||
int i = findQueryID(id);
|
||||
const int i = findQueryID(id);
|
||||
if(i < 0)
|
||||
{
|
||||
// This may happen e.g. if the original query was "pi.hole"
|
||||
@@ -442,9 +457,9 @@ void _FTL_reply(unsigned short flags, char *name, struct all_addr *addr, int id,
|
||||
}
|
||||
|
||||
// Determine if this reply is an exact match for the queried domain
|
||||
int domainID = queries[i].domainID;
|
||||
const int domainID = queries[i].domainID;
|
||||
validate_access("domains", domainID, true, __LINE__, __FUNCTION__, __FILE__);
|
||||
bool isExactMatch = (name != NULL && strcmp(getstr(domains[domainID].domainpos), name) == 0);
|
||||
const bool isExactMatch = (name != NULL && strcmp(getstr(domains[domainID].domainpos), name) == 0);
|
||||
|
||||
if((flags & F_CONFIG) && isExactMatch && !queries[i].complete)
|
||||
{
|
||||
@@ -453,7 +468,7 @@ void _FTL_reply(unsigned short flags, char *name, struct all_addr *addr, int id,
|
||||
counters->unknown--;
|
||||
|
||||
// Get time index
|
||||
unsigned int timeidx = queries[i].timeidx;
|
||||
const unsigned int timeidx = queries[i].timeidx;
|
||||
|
||||
if(strcmp(answer, "(NXDOMAIN)") == 0 ||
|
||||
strcmp(answer, "0.0.0.0") == 0 ||
|
||||
@@ -488,17 +503,18 @@ void _FTL_reply(unsigned short flags, char *name, struct all_addr *addr, int id,
|
||||
}
|
||||
else if((flags & F_FORWARD) && isExactMatch)
|
||||
{
|
||||
// Save reply type and update individual reply counters
|
||||
save_reply_type(flags, i, response);
|
||||
|
||||
// If received NXDOMAIN and AD bit is set, Quad9 may have blocked this query
|
||||
if(flags & F_NXDOMAIN && queries[i].AD)
|
||||
// Only proceed if query is not already known
|
||||
// to have been blocked by Quad9
|
||||
if(queries[i].reply != QUERY_EXTERNAL_BLOCKED_IP &&
|
||||
queries[i].reply != QUERY_EXTERNAL_BLOCKED_NULL &&
|
||||
queries[i].reply != QUERY_EXTERNAL_BLOCKED_NXRA)
|
||||
{
|
||||
query_externally_blocked(i);
|
||||
}
|
||||
// Save reply type and update individual reply counters
|
||||
save_reply_type(flags, i, response);
|
||||
|
||||
// Detect if returned IP indicates that this query was blocked
|
||||
detect_blocked_IP(flags, answer, i);
|
||||
// Detect if returned IP indicates that this query was blocked
|
||||
detect_blocked_IP(flags, answer, i);
|
||||
}
|
||||
}
|
||||
else if(flags & F_REVERSE)
|
||||
{
|
||||
@@ -523,12 +539,25 @@ void _FTL_reply(unsigned short flags, char *name, struct all_addr *addr, int id,
|
||||
unlock_shm();
|
||||
}
|
||||
|
||||
static void detect_blocked_IP(unsigned short flags, char* answer, int queryID)
|
||||
static void detect_blocked_IP(const unsigned short flags, const char* answer, const int queryID)
|
||||
{
|
||||
// Skip replies which originated locally. Otherwise, we would count
|
||||
// gravity.list blocked queries as externally blocked.
|
||||
if(flags & F_HOSTS)
|
||||
{
|
||||
// Skip replies which originated locally. Otherwise, we would
|
||||
// count gravity.list blocked queries as externally blocked.
|
||||
if(config.debug & DEBUG_EXTBLOCKED)
|
||||
{
|
||||
logg("Skipping detection of external blocking IP for ID %i as origin is HOSTS", queryID);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if(flags & F_REVERSE)
|
||||
{
|
||||
// Do not mark responses of PTR requests as externally blocked.
|
||||
if(config.debug & DEBUG_EXTBLOCKED)
|
||||
{
|
||||
logg("Skipping detection of external blocking IP for ID %i as query is PTR", queryID);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -545,7 +574,14 @@ static void detect_blocked_IP(unsigned short flags, char* answer, int queryID)
|
||||
strcmp("146.112.61.109", answer) == 0 ||
|
||||
strcmp("146.112.61.110", answer) == 0 ))
|
||||
{
|
||||
query_externally_blocked(queryID);
|
||||
if(config.debug & DEBUG_EXTBLOCKED)
|
||||
{
|
||||
logg("Upstream responded with known blocking page (IPv4), ID %i:\n\t\"%s\" -> \"%s\"",
|
||||
queryID, getstr(domains[queryID].domainpos), answer);
|
||||
}
|
||||
|
||||
// Update status
|
||||
query_externally_blocked(queryID, QUERY_EXTERNAL_BLOCKED_IP);
|
||||
}
|
||||
|
||||
else if(flags & F_IPV6 && answer != NULL &&
|
||||
@@ -557,7 +593,14 @@ static void detect_blocked_IP(unsigned short flags, char* answer, int queryID)
|
||||
strcmp("::ffff:146.112.61.109", answer) == 0 ||
|
||||
strcmp("::ffff:146.112.61.110", answer) == 0 ))
|
||||
{
|
||||
query_externally_blocked(queryID);
|
||||
if(config.debug & DEBUG_EXTBLOCKED)
|
||||
{
|
||||
logg("Upstream responded with known blocking page (IPv6), ID %i:\n\t\"%s\" -> \"%s\"",
|
||||
queryID, getstr(domains[queryID].domainpos), answer);
|
||||
}
|
||||
|
||||
// Update status
|
||||
query_externally_blocked(queryID, QUERY_EXTERNAL_BLOCKED_IP);
|
||||
}
|
||||
|
||||
// If upstream replied with 0.0.0.0 or ::,
|
||||
@@ -566,41 +609,64 @@ static void detect_blocked_IP(unsigned short flags, char* answer, int queryID)
|
||||
else if(flags & F_IPV4 && answer != NULL &&
|
||||
strcmp("0.0.0.0", answer) == 0)
|
||||
{
|
||||
query_externally_blocked(queryID);
|
||||
if(config.debug & DEBUG_EXTBLOCKED)
|
||||
{
|
||||
logg("Upstream responded with 0.0.0.0, ID %i:\n\t\"%s\" -> \"%s\"",
|
||||
queryID, getstr(domains[queryID].domainpos), answer);
|
||||
}
|
||||
|
||||
// Update status
|
||||
query_externally_blocked(queryID, QUERY_EXTERNAL_BLOCKED_NULL);
|
||||
}
|
||||
|
||||
else if(flags & F_IPV6 && answer != NULL &&
|
||||
strcmp("::", answer) == 0)
|
||||
{
|
||||
query_externally_blocked(queryID);
|
||||
if(config.debug & DEBUG_EXTBLOCKED)
|
||||
{
|
||||
logg("Upstream responded with ::, ID %i:\n\t\"%s\" -> \"%s\"",
|
||||
queryID, getstr(domains[queryID].domainpos), answer);
|
||||
}
|
||||
|
||||
// Update status
|
||||
query_externally_blocked(queryID, QUERY_EXTERNAL_BLOCKED_NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void query_externally_blocked(int i)
|
||||
static void query_externally_blocked(const int queryID, const unsigned char status)
|
||||
{
|
||||
unsigned int timeidx = queries[i].timeidx;
|
||||
// If query is already known to be externally blocked,
|
||||
// then we have nothing to do here
|
||||
if(queries[queryID].status == QUERY_EXTERNAL_BLOCKED_IP ||
|
||||
queries[queryID].status == QUERY_EXTERNAL_BLOCKED_NULL ||
|
||||
queries[queryID].status == QUERY_EXTERNAL_BLOCKED_NXRA)
|
||||
return;
|
||||
|
||||
// Get time index of this query
|
||||
const unsigned int timeidx = queries[queryID].timeidx;
|
||||
|
||||
// Correct counters if necessary ...
|
||||
if(queries[i].status == QUERY_FORWARDED)
|
||||
if(queries[queryID].status == QUERY_FORWARDED)
|
||||
{
|
||||
counters->forwardedqueries--;
|
||||
overTime[timeidx].forwarded--;
|
||||
validate_access("forwarded", queries[i].forwardID, true, __LINE__, __FUNCTION__, __FILE__);
|
||||
forwarded[queries[i].forwardID].count--;
|
||||
validate_access("forwarded", queries[queryID].forwardID, true, __LINE__, __FUNCTION__, __FILE__);
|
||||
forwarded[queries[queryID].forwardID].count--;
|
||||
}
|
||||
|
||||
// ... but as blocked
|
||||
counters->blocked++;
|
||||
overTime[timeidx].blocked++;
|
||||
validate_access("domains", queries[i].domainID, true, __LINE__, __FUNCTION__, __FILE__);
|
||||
domains[queries[i].domainID].blockedcount++;
|
||||
validate_access("clients", queries[i].clientID, true, __LINE__, __FUNCTION__, __FILE__);
|
||||
clients[queries[i].clientID].blockedcount++;
|
||||
validate_access("domains", queries[queryID].domainID, true, __LINE__, __FUNCTION__, __FILE__);
|
||||
domains[queries[queryID].domainID].blockedcount++;
|
||||
validate_access("clients", queries[queryID].clientID, true, __LINE__, __FUNCTION__, __FILE__);
|
||||
clients[queries[queryID].clientID].blockedcount++;
|
||||
|
||||
queries[i].status = QUERY_EXTERNAL_BLOCKED;
|
||||
// Update status
|
||||
queries[queryID].status = status;
|
||||
}
|
||||
|
||||
void _FTL_cache(unsigned int flags, char *name, struct all_addr *addr, char *arg, int id, const char* file, const int line)
|
||||
void _FTL_cache(const unsigned int flags, const char *name, const struct all_addr *addr,
|
||||
const char *arg, const int id, const char* file, const int line)
|
||||
{
|
||||
// Don't analyze anything if in PRIVACY_NOSTATS mode
|
||||
if(config.privacylevel >= PRIVACY_NOSTATS)
|
||||
@@ -678,8 +744,8 @@ void _FTL_cache(unsigned int flags, char *name, struct all_addr *addr, char *arg
|
||||
print_flags(flags);
|
||||
}
|
||||
|
||||
int i = findQueryID(id);
|
||||
if(i < 0 || queries[i].complete)
|
||||
const int queryID = findQueryID(id);
|
||||
if(queryID < 0 || queries[queryID].complete)
|
||||
{
|
||||
// This may happen e.g. if the original query was a PTR query or "pi.hole"
|
||||
// as we ignore them altogether or if the query is already complete
|
||||
@@ -691,25 +757,25 @@ void _FTL_cache(unsigned int flags, char *name, struct all_addr *addr, char *arg
|
||||
counters->unknown--;
|
||||
|
||||
// Get time index
|
||||
unsigned int timeidx = queries[i].timeidx;
|
||||
const unsigned int timeidx = queries[queryID].timeidx;
|
||||
|
||||
int domainID = queries[i].domainID;
|
||||
const int domainID = queries[queryID].domainID;
|
||||
validate_access("domains", domainID, true, __LINE__, __FUNCTION__, __FILE__);
|
||||
|
||||
int clientID = queries[i].clientID;
|
||||
const int clientID = queries[queryID].clientID;
|
||||
validate_access("clients", clientID, true, __LINE__, __FUNCTION__, __FILE__);
|
||||
|
||||
// Mark this query as blocked if domain was matched by a regex
|
||||
if(domains[domainID].regexmatch == REGEX_BLOCKED)
|
||||
requesttype = QUERY_WILDCARD;
|
||||
|
||||
queries[i].status = requesttype;
|
||||
queries[queryID].status = requesttype;
|
||||
|
||||
// Detect if returned IP indicates that this query was blocked
|
||||
detect_blocked_IP(flags, dest, i);
|
||||
detect_blocked_IP(flags, dest, queryID);
|
||||
|
||||
// Re-read requesttype as detect_blocked_IP() might have changed it
|
||||
requesttype = queries[i].status;
|
||||
requesttype = queries[queryID].status;
|
||||
|
||||
// Handle counters accordingly
|
||||
switch(requesttype)
|
||||
@@ -726,17 +792,19 @@ void _FTL_cache(unsigned int flags, char *name, struct all_addr *addr, char *arg
|
||||
counters->cached++;
|
||||
overTime[timeidx].cached++;
|
||||
break;
|
||||
case QUERY_EXTERNAL_BLOCKED:
|
||||
case QUERY_EXTERNAL_BLOCKED_IP:
|
||||
case QUERY_EXTERNAL_BLOCKED_NULL:
|
||||
case QUERY_EXTERNAL_BLOCKED_NXRA:
|
||||
// everything has already been done
|
||||
// in query_externally_blocked()
|
||||
break;
|
||||
}
|
||||
|
||||
// Save reply type and update individual reply counters
|
||||
save_reply_type(flags, i, response);
|
||||
save_reply_type(flags, queryID, response);
|
||||
|
||||
// Hereby, this query is now fully determined
|
||||
queries[i].complete = true;
|
||||
queries[queryID].complete = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -746,7 +814,7 @@ void _FTL_cache(unsigned int flags, char *name, struct all_addr *addr, char *arg
|
||||
unlock_shm();
|
||||
}
|
||||
|
||||
void _FTL_dnssec(int status, int id, const char* file, const int line)
|
||||
void _FTL_dnssec(const int status, const int id, const char* file, const int line)
|
||||
{
|
||||
// Don't analyze anything if in PRIVACY_NOSTATS mode
|
||||
if(config.privacylevel >= PRIVACY_NOSTATS)
|
||||
@@ -755,8 +823,8 @@ void _FTL_dnssec(int status, int id, const char* file, const int line)
|
||||
// Process DNSSEC result for a domain
|
||||
lock_shm();
|
||||
// Search for corresponding query identified by ID
|
||||
int i = findQueryID(id);
|
||||
if(i < 0)
|
||||
const int queryID = findQueryID(id);
|
||||
if(queryID < 0)
|
||||
{
|
||||
// This may happen e.g. if the original query was an unhandled query type
|
||||
unlock_shm();
|
||||
@@ -766,23 +834,23 @@ void _FTL_dnssec(int status, int id, const char* file, const int line)
|
||||
// Debug logging
|
||||
if(config.debug & DEBUG_QUERIES)
|
||||
{
|
||||
int domainID = queries[i].domainID;
|
||||
const int domainID = queries[queryID].domainID;
|
||||
validate_access("domains", domainID, true, __LINE__, __FUNCTION__, __FILE__);
|
||||
logg("**** got DNSSEC details for %s: %i (ID %i, %s:%i)", getstr(domains[domainID].domainpos), status, id, file, line);
|
||||
}
|
||||
|
||||
// Iterate through possible values
|
||||
if(status == STAT_SECURE)
|
||||
queries[i].dnssec = DNSSEC_SECURE;
|
||||
queries[queryID].dnssec = DNSSEC_SECURE;
|
||||
else if(status == STAT_INSECURE)
|
||||
queries[i].dnssec = DNSSEC_INSECURE;
|
||||
queries[queryID].dnssec = DNSSEC_INSECURE;
|
||||
else
|
||||
queries[i].dnssec = DNSSEC_BOGUS;
|
||||
queries[queryID].dnssec = DNSSEC_BOGUS;
|
||||
|
||||
unlock_shm();
|
||||
}
|
||||
|
||||
void _FTL_upstream_error(unsigned int rcode, int id, const char* file, const int line)
|
||||
void _FTL_upstream_error(const unsigned int rcode, const int id, const char* file, const int line)
|
||||
{
|
||||
// Process upstream errors
|
||||
// Queries with error are those where the RCODE
|
||||
@@ -795,70 +863,74 @@ void _FTL_upstream_error(unsigned int rcode, int id, const char* file, const int
|
||||
// Process DNSSEC result for a domain
|
||||
lock_shm();
|
||||
// Search for corresponding query identified by ID
|
||||
int i = findQueryID(id);
|
||||
if(i < 0)
|
||||
const int queryID = findQueryID(id);
|
||||
if(queryID < 0)
|
||||
{
|
||||
// This may happen e.g. if the original query was an unhandled query type
|
||||
unlock_shm();
|
||||
return;
|
||||
}
|
||||
// Translate dnsmasq's rcode into something we can use
|
||||
char *rcodestr = NULL;
|
||||
bool alloc = false;
|
||||
const char *rcodestr = NULL;
|
||||
switch(rcode)
|
||||
{
|
||||
case SERVFAIL:
|
||||
rcodestr = "SERVFAIL";
|
||||
queries[i].reply = REPLY_SERVFAIL;
|
||||
queries[queryID].reply = REPLY_SERVFAIL;
|
||||
break;
|
||||
case REFUSED:
|
||||
rcodestr = "REFUSED";
|
||||
queries[i].reply = REPLY_REFUSED;
|
||||
queries[queryID].reply = REPLY_REFUSED;
|
||||
break;
|
||||
case NOTIMP:
|
||||
rcodestr = "NOT IMPLEMENTED";
|
||||
queries[i].reply = REPLY_NOTIMP;
|
||||
queries[queryID].reply = REPLY_NOTIMP;
|
||||
break;
|
||||
default:
|
||||
if(asprintf(&rcodestr, "Unknown error type (%u)", rcode) > -1)
|
||||
alloc = true;
|
||||
queries[i].reply = REPLY_OTHER;
|
||||
rcodestr = "UNKNOWN";
|
||||
queries[queryID].reply = REPLY_OTHER;
|
||||
break;
|
||||
}
|
||||
|
||||
// Debug logging
|
||||
if(config.debug & DEBUG_QUERIES)
|
||||
{
|
||||
int domainID = queries[i].domainID;
|
||||
const int domainID = queries[queryID].domainID;
|
||||
validate_access("domains", domainID, true, __LINE__, __FUNCTION__, __FILE__);
|
||||
logg("**** got error report for %s: %s (ID %i, %s:%i)", getstr(domains[domainID].domainpos), rcodestr, id, file, line);
|
||||
if(queries[queryID].reply == REPLY_OTHER)
|
||||
{
|
||||
logg("Unknown rcode = %i", rcode);
|
||||
}
|
||||
}
|
||||
|
||||
// If we allocated memory (due to an unknown error type), we need to free it here
|
||||
if(alloc)
|
||||
free(rcodestr);
|
||||
|
||||
unlock_shm();
|
||||
}
|
||||
|
||||
void _FTL_header_ADbit(unsigned char header4, unsigned int rcode, int id, const char* file, const int line)
|
||||
void _FTL_header_analysis(const unsigned char header4, const unsigned int rcode, const int id, const char* file, const int line)
|
||||
{
|
||||
// Don't analyze anything if in PRIVACY_NOSTATS mode
|
||||
if(config.privacylevel >= PRIVACY_NOSTATS)
|
||||
return;
|
||||
|
||||
// Check if AD is set and RA bit is unset in DNS header
|
||||
// AD RA
|
||||
if(!(header4 & 0x20) || (header4 & 0x80))
|
||||
// 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
|
||||
// SOA record, they are not getting added to our cache and, therefore,
|
||||
// FTL_reply() is never getting called from within the cache routines.
|
||||
// Hence, we have to store the necessary information about the NXDOMAIN
|
||||
// reply already here.
|
||||
if((header4 & 0x80) || rcode != NXDOMAIN)
|
||||
{
|
||||
// AD bit not set or RA bit set
|
||||
// RA bit is set or rcode is not NXDOMAIN
|
||||
return;
|
||||
}
|
||||
|
||||
lock_shm();
|
||||
|
||||
// Search for corresponding query identified by ID
|
||||
int i = findQueryID(id);
|
||||
if(i < 0)
|
||||
const int queryID = findQueryID(id);
|
||||
if(queryID < 0)
|
||||
{
|
||||
// This may happen e.g. if the original query was an unhandled query type
|
||||
unlock_shm();
|
||||
@@ -867,37 +939,26 @@ void _FTL_header_ADbit(unsigned char header4, unsigned int rcode, int id, const
|
||||
|
||||
if(config.debug & DEBUG_QUERIES)
|
||||
{
|
||||
int domainID = queries[i].domainID;
|
||||
const int domainID = queries[queryID].domainID;
|
||||
validate_access("domains", domainID, true, __LINE__, __FUNCTION__, __FILE__);
|
||||
logg("**** AD bit set for %s (ID %i, RCODE %u, %s:%i)", getstr(domains[domainID].domainpos), id, rcode, file, line);
|
||||
logg("**** %s externally blocked (ID %i, FTL %i, %s:%i)", getstr(domains[domainID].domainpos), id, queryID, file, line);
|
||||
}
|
||||
|
||||
// Store AD bit in query data
|
||||
queries[i].AD = true;
|
||||
|
||||
// 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
|
||||
// SOA record, they are not getting added to our cache and, therefore,
|
||||
// FTL_reply() is never getting called from within the cache routines.
|
||||
// Hence, we have to store the necessary information about the NXDOMAIN
|
||||
// reply already here.
|
||||
if(rcode == NXDOMAIN)
|
||||
{
|
||||
// Get response time
|
||||
struct timeval response;
|
||||
gettimeofday(&response, 0);
|
||||
// Get response time
|
||||
struct timeval response;
|
||||
gettimeofday(&response, 0);
|
||||
|
||||
// Store query as externally blocked
|
||||
query_externally_blocked(i);
|
||||
// Store query as externally blocked
|
||||
query_externally_blocked(queryID, QUERY_EXTERNAL_BLOCKED_NXRA);
|
||||
|
||||
// Store reply type as replied with NXDOMAIN
|
||||
save_reply_type(F_NEG | F_NXDOMAIN, i, response);
|
||||
}
|
||||
// Store reply type as replied with NXDOMAIN
|
||||
save_reply_type(F_NEG | F_NXDOMAIN, queryID, response);
|
||||
|
||||
unlock_shm();
|
||||
}
|
||||
|
||||
void print_flags(unsigned int flags)
|
||||
void print_flags(const unsigned int flags)
|
||||
{
|
||||
// Debug function, listing resolver flags in clear text
|
||||
// e.g. "Flags: F_FORWARD F_NEG F_IPV6"
|
||||
@@ -906,16 +967,15 @@ void print_flags(unsigned int flags)
|
||||
if(!(config.debug & DEBUG_FLAGS))
|
||||
return;
|
||||
|
||||
unsigned int i;
|
||||
char *flagstr = calloc(256,sizeof(char));
|
||||
for(i = 0; i < sizeof(flags)*8; i++)
|
||||
for(unsigned int i = 0; i < sizeof(flags)*8; i++)
|
||||
if(flags & (1u << i))
|
||||
strcat(flagstr, flagnames[i]);
|
||||
logg(" Flags: %s", flagstr);
|
||||
free(flagstr);
|
||||
}
|
||||
|
||||
void save_reply_type(unsigned int flags, int queryID, struct timeval response)
|
||||
void save_reply_type(const unsigned int flags, const int queryID, const struct timeval response)
|
||||
{
|
||||
// Iterate through possible values
|
||||
validate_access("queries", queryID, false, __LINE__, __FUNCTION__, __FILE__);
|
||||
@@ -1042,7 +1102,7 @@ void FTL_fork_and_bind_sockets(struct passwd *ent_pw)
|
||||
}
|
||||
|
||||
// int cache_inserted, cache_live_freed are defined in dnsmasq/cache.c
|
||||
void getCacheInformation(int *sock)
|
||||
void getCacheInformation(const int *sock)
|
||||
{
|
||||
ssend(*sock,"cache-size: %i\ncache-live-freed: %i\ncache-inserted: %i\n",
|
||||
daemon->cachesize,
|
||||
@@ -1058,7 +1118,7 @@ void getCacheInformation(int *sock)
|
||||
// which hasn't been looked up for the longest time is evicted.
|
||||
}
|
||||
|
||||
void _FTL_forwarding_failed(struct server *server, const char* file, const int line)
|
||||
void _FTL_forwarding_failed(const struct server *server, const char* file, const int line)
|
||||
{
|
||||
// Don't analyze anything if in PRIVACY_NOSTATS mode
|
||||
if(config.privacylevel >= PRIVACY_NOSTATS)
|
||||
@@ -1075,7 +1135,7 @@ void _FTL_forwarding_failed(struct server *server, const char* file, const int l
|
||||
// Convert forward to lower case
|
||||
char *forward = strdup(dest);
|
||||
strtolower(forward);
|
||||
int forwardID = findForwardID(forward, false);
|
||||
const int forwardID = findForwardID(forward, false);
|
||||
|
||||
if(config.debug & DEBUG_QUERIES) logg("**** forwarding to %s (ID %i, %s:%i) failed", dest, forwardID, file, line);
|
||||
|
||||
@@ -1086,7 +1146,7 @@ void _FTL_forwarding_failed(struct server *server, const char* file, const int l
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned long converttimeval(struct timeval time)
|
||||
static unsigned long __attribute__((const)) converttimeval(const struct timeval time)
|
||||
{
|
||||
// Convert time from struct timeval into units
|
||||
// of 10*milliseconds
|
||||
@@ -1125,11 +1185,21 @@ static void prepare_blocking_mode(struct all_addr *addr4, struct all_addr *addr6
|
||||
if(inet_pton(AF_INET6, IPv6addr, addr6) > 0)
|
||||
*has_IPv6 = true;
|
||||
}
|
||||
else
|
||||
else if(config.blockingmode == MODE_IP_NODATA_AAAA)
|
||||
{
|
||||
// Blocking mode will use zero-initialized all_addr struct
|
||||
// This is irrelevant, however, as this blocking mode will
|
||||
// reply with NODATA to AAAA queries. Still, we need to
|
||||
// generate separate IPv4 (IP) and AAAA (NODATA) records
|
||||
*has_IPv6 = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Don't create IPv6 cache entries when we don't need them
|
||||
// Also, don't create them if we are in IP blocking mode and
|
||||
// strlen(IPv6addr) == 0
|
||||
*has_IPv6 = false;
|
||||
}
|
||||
clearSetupVarsArray(); // will free/invalidate IPv6addr
|
||||
}
|
||||
|
||||
@@ -1195,7 +1265,7 @@ static int add_blocked_domain(struct all_addr *addr4, struct all_addr *addr6, co
|
||||
// Add a single domain to resolver's cache. This respects the configured blocking mode
|
||||
// Note: This routine is meant for adding a single domain at a time. It should not be
|
||||
// invoked for batch processing
|
||||
static void block_single_domain_regex(char *domain)
|
||||
static void block_single_domain_regex(const char *domain)
|
||||
{
|
||||
struct all_addr addr4 = {{{ 0 }}}, addr6 = {{{ 0 }}};
|
||||
bool has_IPv4 = false, has_IPv6 = false;
|
||||
@@ -1208,7 +1278,7 @@ static void block_single_domain_regex(char *domain)
|
||||
if(config.debug & DEBUG_QUERIES) logg("Added %s to cache", domain);
|
||||
}
|
||||
|
||||
int FTL_listsfile(char* filename, unsigned int index, FILE *f, int cache_size, struct crec **rhash, int hashsz)
|
||||
int FTL_listsfile(const char* filename, unsigned int index, FILE *f, int cache_size, struct crec **rhash, int hashsz)
|
||||
{
|
||||
int name_count = cache_size;
|
||||
int added = 0;
|
||||
|
||||
@@ -12,29 +12,29 @@ extern unsigned char* pihole_privacylevel;
|
||||
enum { TCP, UDP };
|
||||
|
||||
#define FTL_new_query(flags, name, addr, types, id, type) _FTL_new_query(flags, name, addr, types, id, type, __FILE__, __LINE__)
|
||||
void _FTL_new_query(unsigned int flags, char *name, struct all_addr *addr, char *types, int id, char type, const char* file, const int line);
|
||||
void _FTL_new_query(const unsigned int flags, const char *name, const struct all_addr *addr, const char *types, const int id, const char type, const char* file, const int line);
|
||||
|
||||
#define FTL_forwarded(flags, name, addr, id) _FTL_forwarded(flags, name, addr, id, __FILE__, __LINE__)
|
||||
void _FTL_forwarded(unsigned int flags, char *name, struct all_addr *addr, int id, const char* file, const int line);
|
||||
void _FTL_forwarded(const unsigned int flags, const char *name, const struct all_addr *addr, 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(unsigned short flags, char *name, struct all_addr *addr, int id, const char* file, const int line);
|
||||
void _FTL_reply(const unsigned short flags, const char *name, const struct all_addr *addr, const int id, const char* file, const int line);
|
||||
|
||||
#define FTL_cache(flags, name, addr, arg, id) _FTL_cache(flags, name, addr, arg, id, __FILE__, __LINE__)
|
||||
void _FTL_cache(unsigned int flags, char *name, struct all_addr *addr, char * arg, int id, const char* file, const int line);
|
||||
void _FTL_cache(const unsigned int flags, const char *name, const struct all_addr *addr, const char * arg, const int id, const char* file, const int line);
|
||||
|
||||
#define FTL_dnssec(status, id) _FTL_dnssec(status, id, __FILE__, __LINE__)
|
||||
void _FTL_dnssec(int status, int id, const char* file, const int line);
|
||||
void _FTL_dnssec(const int status, const int id, const char* file, const int line);
|
||||
|
||||
#define FTL_header_ADbit(header4, rcode, id) _FTL_header_ADbit(header4, rcode, id, __FILE__, __LINE__)
|
||||
void _FTL_header_ADbit(unsigned char header4, unsigned int rcode, int id, const char* file, const int line);
|
||||
#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(struct server *server, const char* file, const int line);
|
||||
void _FTL_forwarding_failed(const struct server *server, const char* file, const int line);
|
||||
|
||||
#define FTL_upstream_error(rcode, id) _FTL_upstream_error(rcode, id, __FILE__, __LINE__)
|
||||
void _FTL_upstream_error(unsigned int rcode, int id, const char* file, const int line);
|
||||
void _FTL_upstream_error(const unsigned int rcode, const int id, const char* file, const int line);
|
||||
|
||||
void FTL_dnsmasq_reload(void);
|
||||
void FTL_fork_and_bind_sockets(struct passwd *ent_pw);
|
||||
int FTL_listsfile(char* filename, unsigned int index, FILE *f, int cache_size, struct crec **rhash, int hashsz);
|
||||
int FTL_listsfile(const char* filename, unsigned int index, FILE *f, int cache_size, struct crec **rhash, int hashsz);
|
||||
|
||||
18
gc.c
18
gc.c
@@ -44,12 +44,11 @@ void *GC_thread(void *val)
|
||||
|
||||
if(config.debug & DEBUG_GC) timer_start(GC_TIMER);
|
||||
|
||||
long int i;
|
||||
int removed = 0;
|
||||
if(config.debug & DEBUG_GC) logg("GC starting, mintime: %u %s", mintime, ctime(&mintime));
|
||||
if(config.debug & DEBUG_GC) logg("GC starting, mintime: %lu %s", mintime, ctime(&mintime));
|
||||
|
||||
// Process all queries
|
||||
for(i=0; i < counters->queries; i++)
|
||||
for(long int i=0; i < counters->queries; i++)
|
||||
{
|
||||
validate_access("queries", i, true, __LINE__, __FUNCTION__, __FILE__);
|
||||
// Test if this query is too new
|
||||
@@ -57,18 +56,18 @@ void *GC_thread(void *val)
|
||||
break;
|
||||
|
||||
// Adjust client counter
|
||||
int clientID = queries[i].clientID;
|
||||
const int clientID = queries[i].clientID;
|
||||
validate_access("clients", clientID, true, __LINE__, __FUNCTION__, __FILE__);
|
||||
clients[clientID].count--;
|
||||
|
||||
// Adjust total counters and total over time data
|
||||
int timeidx = queries[i].timeidx;
|
||||
const int timeidx = queries[i].timeidx;
|
||||
overTime[timeidx].total--;
|
||||
// Adjust corresponding overTime counters
|
||||
clients[clientID].overTime[timeidx]--;
|
||||
|
||||
// Adjust domain counter (no overTime information)
|
||||
int domainID = queries[i].domainID;
|
||||
const int domainID = queries[i].domainID;
|
||||
validate_access("domains", domainID, true, __LINE__, __FUNCTION__, __FILE__);
|
||||
domains[domainID].count--;
|
||||
|
||||
@@ -94,7 +93,9 @@ void *GC_thread(void *val)
|
||||
case QUERY_GRAVITY: // Blocked by Pi-hole's blocking lists (fall through)
|
||||
case QUERY_BLACKLIST: // Exact blocked (fall through)
|
||||
case QUERY_WILDCARD: // Regex blocked (fall through)
|
||||
case QUERY_EXTERNAL_BLOCKED: // Blocked by upstream provider (fall through)
|
||||
case QUERY_EXTERNAL_BLOCKED_IP: // Blocked by upstream provider (fall through)
|
||||
case QUERY_EXTERNAL_BLOCKED_NXRA: // Blocked by upstream provider (fall through)
|
||||
case QUERY_EXTERNAL_BLOCKED_NULL: // Blocked by upstream provider (fall through)
|
||||
counters->blocked--;
|
||||
overTime[timeidx].blocked--;
|
||||
domains[domainID].blockedcount--;
|
||||
@@ -162,7 +163,8 @@ void *GC_thread(void *val)
|
||||
// Determine if overTime memory needs to get moved
|
||||
moveOverTimeMemory(mintime);
|
||||
|
||||
if(config.debug & DEBUG_GC) logg("Notice: GC removed %i queries (took %.2f ms)", removed, timer_elapsed_msec(GC_TIMER));
|
||||
if(config.debug & DEBUG_GC)
|
||||
logg("Notice: GC removed %i queries (took %.2f ms)", removed, timer_elapsed_msec(GC_TIMER));
|
||||
|
||||
// Release thread lock
|
||||
unlock_shm();
|
||||
|
||||
@@ -59,7 +59,7 @@ bool gravityDB_getTable(unsigned char list)
|
||||
{
|
||||
// Read gravity domains
|
||||
gravityDB_open();
|
||||
char *querystr = NULL;
|
||||
const char *querystr = NULL;
|
||||
switch(list)
|
||||
{
|
||||
case GRAVITY_LIST:
|
||||
@@ -101,7 +101,6 @@ const char* gravityDB_getDomain(void)
|
||||
return domain;
|
||||
}
|
||||
|
||||
|
||||
// Error ?
|
||||
if(rc != SQLITE_DONE)
|
||||
{
|
||||
@@ -126,7 +125,7 @@ void gravityDB_finalizeTable(void)
|
||||
|
||||
int gravityDB_count(unsigned char list)
|
||||
{
|
||||
char *querystr = NULL;
|
||||
const char* querystr = NULL;
|
||||
switch(list)
|
||||
{
|
||||
case GRAVITY_LIST:
|
||||
@@ -150,7 +149,6 @@ int gravityDB_count(unsigned char list)
|
||||
if(!gravityDB_open())
|
||||
return DB_FAILED;
|
||||
|
||||
sqlite3_stmt* stmt;
|
||||
// Prepare query
|
||||
int rc = sqlite3_prepare_v2(gravitydb, querystr, -1, &stmt, NULL);
|
||||
if( rc ){
|
||||
|
||||
23
grep.c
23
grep.c
@@ -45,25 +45,6 @@ int countlines(const char* fname)
|
||||
return lines;
|
||||
}
|
||||
|
||||
int readnumberfromfile(const char* fname)
|
||||
{
|
||||
FILE *fp;
|
||||
int num;
|
||||
|
||||
if((fp = fopen(fname, "r")) == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(fscanf(fp,"%i",&num) != 1)
|
||||
{
|
||||
num = -1;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return num;
|
||||
}
|
||||
|
||||
int countlineswith(const char* str, const char* fname)
|
||||
{
|
||||
FILE *fp;
|
||||
@@ -124,8 +105,8 @@ int countlineswith(const char* str, const char* fname)
|
||||
|
||||
void check_blocking_status(void)
|
||||
{
|
||||
char* blocking = read_setupVarsconf("BLOCKING_ENABLED");
|
||||
char* message;
|
||||
const char* blocking = read_setupVarsconf("BLOCKING_ENABLED");
|
||||
const char* message;
|
||||
|
||||
if(blocking == NULL || getSetupVarsBool(blocking))
|
||||
{
|
||||
|
||||
31
log.c
31
log.c
@@ -11,16 +11,16 @@
|
||||
#include "FTL.h"
|
||||
#include "version.h"
|
||||
|
||||
pthread_mutex_t lock;
|
||||
FILE *logfile = NULL;
|
||||
static pthread_mutex_t lock;
|
||||
static FILE *logfile = NULL;
|
||||
|
||||
void close_FTL_log(void)
|
||||
static void close_FTL_log(void)
|
||||
{
|
||||
if(logfile != NULL)
|
||||
fclose(logfile);
|
||||
}
|
||||
|
||||
void open_FTL_log(bool test)
|
||||
void open_FTL_log(const bool test)
|
||||
{
|
||||
if(test)
|
||||
{
|
||||
@@ -50,20 +50,20 @@ void open_FTL_log(bool test)
|
||||
}
|
||||
}
|
||||
|
||||
void get_timestr(char *timestring)
|
||||
static void get_timestr(char *timestring)
|
||||
{
|
||||
time_t t = time(NULL);
|
||||
struct tm tm = *localtime(&t);
|
||||
const time_t t = time(NULL);
|
||||
const struct tm tm = *localtime(&t);
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
int millisec = tv.tv_usec/1000;
|
||||
const int millisec = tv.tv_usec/1000;
|
||||
|
||||
sprintf(timestring,"%d-%02d-%02d %02d:%02d:%02d.%03i", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, millisec);
|
||||
}
|
||||
|
||||
void logg(const char *format, ...)
|
||||
void __attribute__ ((format (gnu_printf, 1, 2))) logg(const char *format, ...)
|
||||
{
|
||||
char timestring[32] = "";
|
||||
char timestring[84] = "";
|
||||
va_list args;
|
||||
|
||||
pthread_mutex_lock(&lock);
|
||||
@@ -72,7 +72,7 @@ void 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
|
||||
long pid = (long)getpid();
|
||||
const long pid = (long)getpid();
|
||||
|
||||
// Print to stdout before writing to file
|
||||
if(!daemonmode)
|
||||
@@ -108,7 +108,7 @@ void logg(const char *format, ...)
|
||||
pthread_mutex_unlock(&lock);
|
||||
}
|
||||
|
||||
void format_memory_size(char *prefix, unsigned long int bytes, double *formated)
|
||||
void format_memory_size(char *prefix, const unsigned long int bytes, double *formated)
|
||||
{
|
||||
int i;
|
||||
*formated = bytes;
|
||||
@@ -124,11 +124,6 @@ void format_memory_size(char *prefix, unsigned long int bytes, double *formated)
|
||||
strcpy(prefix, prefixes[i]);
|
||||
}
|
||||
|
||||
void logg_struct_resize(const char* str, int to, int step)
|
||||
{
|
||||
logg("Notice: Increasing %s struct size from %i to %i", str, (to-step), to);
|
||||
}
|
||||
|
||||
void log_counter_info(void)
|
||||
{
|
||||
logg(" -> Total DNS queries: %i", counters->queries);
|
||||
@@ -141,7 +136,7 @@ void log_counter_info(void)
|
||||
logg(" -> Known forward destinations: %i", counters->forwarded);
|
||||
}
|
||||
|
||||
void log_FTL_version(bool crashreport)
|
||||
void log_FTL_version(const bool crashreport)
|
||||
{
|
||||
logg("FTL branch: %s", GIT_BRANCH);
|
||||
logg("FTL version: %s", GIT_TAG);
|
||||
|
||||
17
main.c
17
main.c
@@ -14,9 +14,6 @@ char * username;
|
||||
bool needGC = false;
|
||||
bool needDBGC = false;
|
||||
|
||||
// Prototype
|
||||
int main_dnsmasq(int argc, char **argv);
|
||||
|
||||
int main (int argc, char* argv[])
|
||||
{
|
||||
// Get user pihole-FTL is running as
|
||||
@@ -36,6 +33,13 @@ int main (int argc, char* argv[])
|
||||
logg("########## FTL started! ##########");
|
||||
log_FTL_version(false);
|
||||
|
||||
// Catch signals like SIGTERM and SIGINT
|
||||
// Other signals like SIGHUP, SIGUSR1 are handled by the resolver part
|
||||
handle_signals();
|
||||
|
||||
// Process pihole-FTL.conf
|
||||
read_FTLconf();
|
||||
|
||||
// Initialize shared memory
|
||||
if(!init_shmem())
|
||||
{
|
||||
@@ -48,13 +52,6 @@ int main (int argc, char* argv[])
|
||||
if(strcmp(username, "pihole") != 0)
|
||||
logg("WARNING: Starting pihole-FTL as user %s is not recommended", username);
|
||||
|
||||
// Process pihole-FTL.conf
|
||||
read_FTLconf();
|
||||
|
||||
// Catch signals like SIGTERM and SIGINT
|
||||
// Other signals like SIGHUP, SIGUSR1 are handled by the resolver part
|
||||
handle_signals();
|
||||
|
||||
// Initialize database
|
||||
if(config.maxDBdays != 0)
|
||||
db_init();
|
||||
|
||||
19
memory.c
19
memory.c
@@ -45,7 +45,7 @@ clientsDataStruct *clients = NULL;
|
||||
domainsDataStruct *domains = NULL;
|
||||
overTimeDataStruct *overTime = NULL;
|
||||
|
||||
void memory_check(int which)
|
||||
void memory_check(const int which)
|
||||
{
|
||||
switch(which)
|
||||
{
|
||||
@@ -105,7 +105,8 @@ void memory_check(int which)
|
||||
}
|
||||
}
|
||||
|
||||
void validate_access(const char * name, int pos, bool testmagic, int line, const char * function, const char * file)
|
||||
void validate_access(const char * name, const int pos, const bool testmagic,
|
||||
const int line, const char * function, const char * file)
|
||||
{
|
||||
int limit = 0;
|
||||
if(name[0] == 'c') limit = counters->clients_MAX;
|
||||
@@ -142,7 +143,7 @@ void validate_access(const char * name, int pos, bool testmagic, int line, const
|
||||
// not be protected by our (error logging) functions!
|
||||
|
||||
#undef strdup
|
||||
char *FTLstrdup(const char *src, const char * file, const char * function, int line)
|
||||
char* __attribute__((malloc)) FTLstrdup(const char *src, const char * file, const char * function, const int line)
|
||||
{
|
||||
// The FTLstrdup() function returns a pointer to a new string which is a
|
||||
// duplicate of the string s. Memory for the new string is obtained with
|
||||
@@ -152,7 +153,7 @@ char *FTLstrdup(const char *src, const char * file, const char * function, int l
|
||||
logg("WARN: Trying to copy a NULL string in %s() (%s:%i)", function, file, line);
|
||||
return NULL;
|
||||
}
|
||||
size_t len = strlen(src);
|
||||
const size_t len = strlen(src);
|
||||
char *dest = calloc(len+1, sizeof(char));
|
||||
if(dest == NULL)
|
||||
{
|
||||
@@ -167,7 +168,7 @@ char *FTLstrdup(const char *src, const char * file, const char * function, int l
|
||||
}
|
||||
|
||||
#undef calloc
|
||||
void *FTLcalloc(size_t nmemb, size_t size, const char * file, const char * function, int line)
|
||||
void* __attribute__((malloc)) __attribute__((alloc_size(1,2))) FTLcalloc(const size_t nmemb, const size_t size, const char * file, const char * function, const int line)
|
||||
{
|
||||
// The FTLcalloc() function allocates memory for an array of nmemb elements
|
||||
// of size bytes each and returns a pointer to the allocated memory. The
|
||||
@@ -176,14 +177,14 @@ void *FTLcalloc(size_t nmemb, size_t size, const char * file, const char * funct
|
||||
// passed to free().
|
||||
void *ptr = calloc(nmemb, size);
|
||||
if(ptr == NULL)
|
||||
logg("FATAL: Memory allocation (%u x %u) failed in %s() (%s:%i)",
|
||||
logg("FATAL: Memory allocation (%zu x %zu) failed in %s() (%s:%i)",
|
||||
nmemb, size, function, file, line);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
#undef realloc
|
||||
void *FTLrealloc(void *ptr_in, size_t size, const char * file, const char * function, int line)
|
||||
void __attribute__((alloc_size(2))) *FTLrealloc(void *ptr_in, const size_t size, const char * file, const char * function, const int line)
|
||||
{
|
||||
// The FTLrealloc() function changes the size of the memory block pointed to
|
||||
// by ptr to size bytes. The contents will be unchanged in the range from
|
||||
@@ -197,14 +198,14 @@ void *FTLrealloc(void *ptr_in, size_t size, const char * file, const char * func
|
||||
// done.
|
||||
void *ptr_out = realloc(ptr_in, size);
|
||||
if(ptr_out == NULL)
|
||||
logg("FATAL: Memory reallocation (%p -> %u) failed in %s() (%s:%i)",
|
||||
logg("FATAL: Memory reallocation (%p -> %zu) failed in %s() (%s:%i)",
|
||||
ptr_in, size, function, file, line);
|
||||
|
||||
return ptr_out;
|
||||
}
|
||||
|
||||
#undef free
|
||||
void FTLfree(void *ptr, const char * file, const char * function, int line)
|
||||
void FTLfree(void *ptr, const char * file, const char * function, const int line)
|
||||
{
|
||||
// The free() function frees the memory space pointed to by ptr, which
|
||||
// must have been returned by a previous call to malloc(), calloc(), or
|
||||
|
||||
44
msgpack.c
44
msgpack.c
@@ -11,19 +11,19 @@
|
||||
#include "FTL.h"
|
||||
#include "api.h"
|
||||
|
||||
void pack_eom(int sock) {
|
||||
void pack_eom(const int sock) {
|
||||
// This byte is explicitly never used in the MessagePack spec, so it is perfect to use as an EOM for this API.
|
||||
uint8_t eom = 0xc1;
|
||||
swrite(sock, &eom, sizeof(eom));
|
||||
}
|
||||
|
||||
void pack_basic(int sock, uint8_t format, void *value, size_t size) {
|
||||
static void pack_basic(const int sock, const uint8_t format, const void *value, const size_t size) {
|
||||
swrite(sock, &format, sizeof(format));
|
||||
swrite(sock, value, size);
|
||||
}
|
||||
|
||||
uint64_t leToBe64(uint64_t value) {
|
||||
char *ptr = (char *) &value;
|
||||
static uint64_t __attribute__((const)) leToBe64(const uint64_t value) {
|
||||
const char *ptr = (char *) &value;
|
||||
uint32_t part1, part2;
|
||||
|
||||
// Copy the two halves of the 64 bit input into uint32_t's so we can use htonl
|
||||
@@ -38,26 +38,26 @@ uint64_t leToBe64(uint64_t value) {
|
||||
return (uint64_t) part1 << 32 | part2;
|
||||
}
|
||||
|
||||
void pack_bool(int sock, bool value) {
|
||||
void pack_bool(const int sock, const bool value) {
|
||||
uint8_t packed = (uint8_t) (value ? 0xc3 : 0xc2);
|
||||
swrite(sock, &packed, sizeof(packed));
|
||||
}
|
||||
|
||||
void pack_uint8(int sock, uint8_t value) {
|
||||
void pack_uint8(const int sock, const uint8_t value) {
|
||||
pack_basic(sock, 0xcc, &value, sizeof(value));
|
||||
}
|
||||
|
||||
void pack_uint64(int sock, uint64_t value) {
|
||||
uint64_t bigEValue = leToBe64(value);
|
||||
void pack_uint64(const int sock, const uint64_t value) {
|
||||
const uint64_t bigEValue = leToBe64(value);
|
||||
pack_basic(sock, 0xcf, &bigEValue, sizeof(bigEValue));
|
||||
}
|
||||
|
||||
void pack_int32(int sock, int32_t value) {
|
||||
uint32_t bigEValue = htonl((uint32_t) value);
|
||||
void pack_int32(const int sock, const int32_t value) {
|
||||
const uint32_t bigEValue = htonl((uint32_t) value);
|
||||
pack_basic(sock, 0xd2, &bigEValue, sizeof(bigEValue));
|
||||
}
|
||||
|
||||
void pack_int64(int sock, int64_t value) {
|
||||
void pack_int64(const int sock, const int64_t value) {
|
||||
// Need to use memcpy to do a direct copy without reinterpreting the bytes (making negatives into positives).
|
||||
// It should get optimized away.
|
||||
uint64_t bigEValue;
|
||||
@@ -66,7 +66,7 @@ void pack_int64(int sock, int64_t value) {
|
||||
pack_basic(sock, 0xd3, &bigEValue, sizeof(bigEValue));
|
||||
}
|
||||
|
||||
void pack_float(int sock, float value) {
|
||||
void pack_float(const int sock, const float value) {
|
||||
// Need to use memcpy to do a direct copy without reinterpreting the bytes. It should get optimized away.
|
||||
uint32_t bigEValue;
|
||||
memcpy(&bigEValue, &value, sizeof(bigEValue));
|
||||
@@ -75,16 +75,16 @@ void pack_float(int sock, float value) {
|
||||
}
|
||||
|
||||
// Return true if successful
|
||||
bool pack_fixstr(int sock, char *string) {
|
||||
bool pack_fixstr(const int sock, const char *string) {
|
||||
// Make sure that the length is less than 32
|
||||
size_t length = strlen(string);
|
||||
const size_t length = strlen(string);
|
||||
|
||||
if(length >= 32) {
|
||||
logg("Tried to send a fixstr longer than 31 bytes!");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t format = (uint8_t) (0xA0 | length);
|
||||
const uint8_t format = (uint8_t) (0xA0 | length);
|
||||
swrite(sock, &format, sizeof(format));
|
||||
swrite(sock, string, length);
|
||||
|
||||
@@ -92,27 +92,27 @@ bool pack_fixstr(int sock, char *string) {
|
||||
}
|
||||
|
||||
// Return true if successful
|
||||
bool pack_str32(int sock, char *string) {
|
||||
bool pack_str32(const int sock, const char *string) {
|
||||
// Make sure that the length is less than 4294967296
|
||||
size_t length = strlen(string);
|
||||
const size_t length = strlen(string);
|
||||
|
||||
if(length >= 2147483648u) {
|
||||
logg("Tried to send a str32 longer than 2147483647 bytes!");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t format = 0xdb;
|
||||
const uint8_t format = 0xdb;
|
||||
swrite(sock, &format, sizeof(format));
|
||||
uint32_t bigELength = htonl((uint32_t) length);
|
||||
const uint32_t bigELength = htonl((uint32_t) length);
|
||||
swrite(sock, &bigELength, sizeof(bigELength));
|
||||
swrite(sock, string, length);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void pack_map16_start(int sock, uint16_t length) {
|
||||
uint8_t format = 0xde;
|
||||
void pack_map16_start(const int sock, const uint16_t length) {
|
||||
const uint8_t format = 0xde;
|
||||
swrite(sock, &format, sizeof(format));
|
||||
uint16_t bigELength = htons(length);
|
||||
const uint16_t bigELength = htons(length);
|
||||
swrite(sock, &bigELength, sizeof(bigELength));
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ void parse_arp_cache(void)
|
||||
char * linebuffer = NULL;
|
||||
size_t linebuffersize = 0;
|
||||
char ip[100], mask[100], hwaddr[100], iface[100];
|
||||
int type, flags, entries = 0;
|
||||
unsigned int type, flags, entries = 0;
|
||||
time_t now = time(NULL);
|
||||
|
||||
// Start collecting database commands
|
||||
@@ -101,7 +101,7 @@ void parse_arp_cache(void)
|
||||
}
|
||||
|
||||
// Perform SQL query
|
||||
int dbID = db_query_int(querystr);
|
||||
const int dbID = db_query_int(querystr);
|
||||
free(querystr);
|
||||
|
||||
if(dbID == DB_FAILED)
|
||||
@@ -120,10 +120,10 @@ void parse_arp_cache(void)
|
||||
|
||||
// This client is known (by its IP address) to pihole-FTL if
|
||||
// findClientID() returned a non-negative index
|
||||
bool clientKnown = clientID >= 0;
|
||||
const bool clientKnown = clientID >= 0;
|
||||
|
||||
// Get hostname of this client if the client is known
|
||||
char *hostname = "";
|
||||
const char *hostname = "";
|
||||
if(clientKnown)
|
||||
{
|
||||
validate_access("clients", clientID, true, __LINE__, __FUNCTION__, __FILE__);
|
||||
@@ -206,7 +206,7 @@ static char* getMACVendor(const char* hwaddr)
|
||||
else if(strlen(hwaddr) != 17)
|
||||
{
|
||||
// MAC address is incomplete
|
||||
if(config.debug & DEBUG_ARP) logg("getMACVenor(%s): MAC invalid (length %lu)", hwaddr, strlen(hwaddr));
|
||||
if(config.debug & DEBUG_ARP) logg("getMACVenor(%s): MAC invalid (length %zu)", hwaddr, strlen(hwaddr));
|
||||
return strdup("");
|
||||
}
|
||||
|
||||
@@ -283,10 +283,10 @@ void updateMACVendorRecords()
|
||||
}
|
||||
|
||||
sqlite3_stmt* stmt;
|
||||
const char* querystr = "SELECT id,hwaddr FROM network;";
|
||||
rc = sqlite3_prepare_v2(db, querystr, -1, &stmt, NULL);
|
||||
const char* selectstr = "SELECT id,hwaddr FROM network;";
|
||||
rc = sqlite3_prepare_v2(db, selectstr, -1, &stmt, NULL);
|
||||
if( rc ){
|
||||
logg("updateMACVendorRecords() - SQL error prepare (%s, %i): %s", querystr, rc, sqlite3_errmsg(db));
|
||||
logg("updateMACVendorRecords() - SQL error prepare (%s, %i): %s", selectstr, rc, sqlite3_errmsg(db));
|
||||
sqlite3_close(db);
|
||||
return;
|
||||
}
|
||||
@@ -302,8 +302,8 @@ void updateMACVendorRecords()
|
||||
hwaddr = NULL;
|
||||
|
||||
// Prepare UPDATE statement
|
||||
char *querystr = NULL;
|
||||
if(asprintf(&querystr, "UPDATE network SET macVendor = \'%s\' WHERE id = %i", vendor, id) < 1)
|
||||
char *updatestr = NULL;
|
||||
if(asprintf(&updatestr, "UPDATE network SET macVendor = \'%s\' WHERE id = %i", vendor, id) < 1)
|
||||
{
|
||||
logg("updateMACVendorRecords() - Allocation error 2");
|
||||
free(vendor);
|
||||
@@ -312,17 +312,17 @@ void updateMACVendorRecords()
|
||||
|
||||
// Execute prepared statement
|
||||
char *zErrMsg = NULL;
|
||||
rc = sqlite3_exec(db, querystr, NULL, NULL, &zErrMsg);
|
||||
rc = sqlite3_exec(db, updatestr, NULL, NULL, &zErrMsg);
|
||||
if( rc != SQLITE_OK ){
|
||||
logg("updateMACVendorRecords() - SQL exec error: %s (%i): %s", querystr, rc, zErrMsg);
|
||||
logg("updateMACVendorRecords() - SQL exec error: %s (%i): %s", updatestr, rc, zErrMsg);
|
||||
sqlite3_free(zErrMsg);
|
||||
free(querystr);
|
||||
free(updatestr);
|
||||
free(vendor);
|
||||
break;
|
||||
}
|
||||
|
||||
// Free allocated memory
|
||||
free(querystr);
|
||||
free(updatestr);
|
||||
free(vendor);
|
||||
}
|
||||
if(rc != SQLITE_DONE)
|
||||
|
||||
28
overTime.c
28
overTime.c
@@ -16,11 +16,11 @@
|
||||
* @param index The overTime slot index
|
||||
* @param timestamp The timestamp of the slot
|
||||
*/
|
||||
static void initSlot(unsigned int index, time_t timestamp)
|
||||
static void initSlot(const unsigned int index, const time_t timestamp)
|
||||
{
|
||||
// Possible debug printing
|
||||
if(config.debug & DEBUG_OVERTIME)
|
||||
logg("initSlot(%u, %u): Zeroing overTIme slot", index, timestamp);
|
||||
logg("initSlot(%u, %lu): Zeroing overTime slot", index, timestamp);
|
||||
|
||||
overTime[index].magic = MAGICBYTE;
|
||||
overTime[index].timestamp = timestamp;
|
||||
@@ -48,7 +48,7 @@ void initOverTime(void)
|
||||
time_t timestamp = now - now % 3600 + 3600 - (OVERTIME_INTERVAL / 2);
|
||||
|
||||
if(config.debug & DEBUG_OVERTIME)
|
||||
logg("initOverTime(): Initializing %i slots from %u to %u", OVERTIME_SLOTS, timestamp-OVERTIME_SLOTS*OVERTIME_INTERVAL, timestamp);
|
||||
logg("initOverTime(): Initializing %i slots from %lu to %lu", OVERTIME_SLOTS, timestamp-OVERTIME_SLOTS*OVERTIME_INTERVAL, timestamp);
|
||||
|
||||
// Iterate over overTime and initialize it
|
||||
for(int i = OVERTIME_SLOTS-1; i >= 0 ; i--)
|
||||
@@ -67,35 +67,35 @@ unsigned int getOverTimeID(time_t timestamp)
|
||||
timestamp += OVERTIME_INTERVAL/2;
|
||||
|
||||
// Get timestamp of first interval
|
||||
time_t firstTimestamp = overTime[0].timestamp;
|
||||
const time_t firstTimestamp = overTime[0].timestamp;
|
||||
|
||||
// Compute overTime ID
|
||||
int id = (int) ((timestamp - firstTimestamp) / OVERTIME_INTERVAL);
|
||||
const int id = (int) ((timestamp - firstTimestamp) / OVERTIME_INTERVAL);
|
||||
|
||||
// Check bounds manually
|
||||
if(id < 0)
|
||||
{
|
||||
logg("WARN: getOverTimeID(%u): %u is negative: %u", timestamp, id, firstTimestamp);
|
||||
logg("WARN: getOverTimeID(%lu): %u is negative: %lu", timestamp, id, firstTimestamp);
|
||||
// Return first timestamp in case negative timestamp was determined
|
||||
return 0;
|
||||
}
|
||||
else if(id > OVERTIME_SLOTS-1)
|
||||
{
|
||||
logg("WARN: getOverTimeID(%u): %i is too large: %u", timestamp, id, firstTimestamp);
|
||||
logg("WARN: getOverTimeID(%lu): %i is too large: %lu", timestamp, id, firstTimestamp);
|
||||
// Return last timestamp in case a too large timestamp was determined
|
||||
return OVERTIME_SLOTS-1;
|
||||
}
|
||||
|
||||
if(config.debug & DEBUG_OVERTIME)
|
||||
logg("getOverTimeID(%u): %i", timestamp, id);
|
||||
logg("getOverTimeID(%lu): %i", timestamp, id);
|
||||
|
||||
return (unsigned int) id;
|
||||
}
|
||||
|
||||
// This routine is called by garbage collection to rearrange the overTime structure for the next hour
|
||||
void moveOverTimeMemory(time_t mintime)
|
||||
void moveOverTimeMemory(const time_t mintime)
|
||||
{
|
||||
time_t oldestOverTimeIS = overTime[0].timestamp;
|
||||
const time_t oldestOverTimeIS = overTime[0].timestamp;
|
||||
// Shift SHOULD timestemp into the future by the amount GC is running earlier
|
||||
time_t oldestOverTimeSHOULD = mintime;
|
||||
|
||||
@@ -105,13 +105,13 @@ void moveOverTimeMemory(time_t mintime)
|
||||
|
||||
// Calculate the number of slots to be garbage collected, which is also the
|
||||
// ID of the slot to move to the zero position
|
||||
unsigned int moveOverTime = (unsigned int) ((oldestOverTimeSHOULD - oldestOverTimeIS) / OVERTIME_INTERVAL);
|
||||
const unsigned int moveOverTime = (unsigned int) ((oldestOverTimeSHOULD - oldestOverTimeIS) / OVERTIME_INTERVAL);
|
||||
|
||||
// The number of slots which will be moved (not garbage collected)
|
||||
unsigned int remainingSlots = OVERTIME_SLOTS - moveOverTime;
|
||||
const unsigned int remainingSlots = OVERTIME_SLOTS - moveOverTime;
|
||||
|
||||
if(config.debug & DEBUG_OVERTIME)
|
||||
logg("moveOverTimeMemory(): IS: %u, SHOULD: %u, MOVING: %u", oldestOverTimeIS, oldestOverTimeSHOULD, moveOverTime);
|
||||
logg("moveOverTimeMemory(): IS: %lu, SHOULD: %lu, MOVING: %u", oldestOverTimeIS, oldestOverTimeSHOULD, moveOverTime);
|
||||
|
||||
// Check if the move over amount is valid. This prevents errors if the
|
||||
// function is called before GC is necessary.
|
||||
@@ -148,7 +148,7 @@ void moveOverTimeMemory(time_t mintime)
|
||||
for(unsigned int timeidx = remainingSlots; timeidx < OVERTIME_SLOTS ; timeidx++)
|
||||
{
|
||||
// This slot is OVERTIME_INTERVAL seconds after the previous slot
|
||||
time_t timestamp = overTime[timeidx-1].timestamp + OVERTIME_INTERVAL;
|
||||
const time_t timestamp = overTime[timeidx-1].timestamp + OVERTIME_INTERVAL;
|
||||
initSlot(timeidx, timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
19
regex.c
19
regex.c
@@ -15,24 +15,24 @@ static int num_regex;
|
||||
static regex_t *regex = NULL;
|
||||
static bool *regexconfigured = NULL;
|
||||
static char **regexbuffer = NULL;
|
||||
static whitelistStruct whitelist = { 0, NULL };
|
||||
static whitelistStruct whitelist = { NULL, 0 };
|
||||
|
||||
static void log_regex_error(char *where, int errcode, int index)
|
||||
static void log_regex_error(const char *where, const int errcode, const int index)
|
||||
{
|
||||
// Regex failed for some reason (probably user syntax error)
|
||||
// Get error string and log it
|
||||
size_t length = regerror(errcode, ®ex[index], NULL, 0);
|
||||
const size_t length = regerror(errcode, ®ex[index], NULL, 0);
|
||||
char *buffer = calloc(length,sizeof(char));
|
||||
(void) regerror (errcode, ®ex[index], buffer, length);
|
||||
logg("ERROR %s regex on line %i: %s (%i)", where, index+1, buffer, errcode);
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
static bool init_regex(const char *regexin, int index)
|
||||
static bool init_regex(const char *regexin, const int index)
|
||||
{
|
||||
// compile regular expressions into data structures that
|
||||
// can be used with regexec to match against a string
|
||||
int errcode = regcomp(®ex[index], regexin, REG_EXTENDED);
|
||||
const int errcode = regcomp(®ex[index], regexin, REG_EXTENDED);
|
||||
if(errcode != 0)
|
||||
{
|
||||
log_regex_error("compiling", errcode, index);
|
||||
@@ -47,7 +47,7 @@ static bool init_regex(const char *regexin, int index)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool in_whitelist(char *domain)
|
||||
bool __attribute__((pure)) in_whitelist(const char *domain)
|
||||
{
|
||||
bool found = false;
|
||||
for(int i=0; i < whitelist.count; i++)
|
||||
@@ -77,14 +77,13 @@ void free_whitelist_domains(void)
|
||||
}
|
||||
}
|
||||
|
||||
bool match_regex(char *input)
|
||||
bool match_regex(const char *input)
|
||||
{
|
||||
int index;
|
||||
bool matched = false;
|
||||
|
||||
// Start matching timer
|
||||
timer_start(REGEX_TIMER);
|
||||
for(index = 0; index < num_regex; index++)
|
||||
for(int index = 0; index < num_regex; index++)
|
||||
{
|
||||
// Only check regex which have been successfully compiled
|
||||
if(!regexconfigured[index])
|
||||
@@ -267,7 +266,7 @@ void read_regex_from_database(void)
|
||||
gravityDB_finalizeTable();
|
||||
}
|
||||
|
||||
void log_regex_whitelist(double time)
|
||||
void log_regex_whitelist(const double time)
|
||||
{
|
||||
logg("Compiled %i Regex filters and %i whitelisted domains in %.1f msec", num_regex, whitelist.count, time);
|
||||
}
|
||||
|
||||
@@ -12,11 +12,11 @@
|
||||
#include "api.h"
|
||||
#include "shmem.h"
|
||||
|
||||
bool command(char *client_message, const char* cmd) {
|
||||
bool __attribute__((pure)) command(const char *client_message, const char* cmd) {
|
||||
return strstr(client_message, cmd) != NULL;
|
||||
}
|
||||
|
||||
void process_request(char *client_message, int *sock)
|
||||
void process_request(const char *client_message, int *sock)
|
||||
{
|
||||
char EOT[2];
|
||||
EOT[0] = 0x04;
|
||||
|
||||
118
resolve.c
118
resolve.c
@@ -11,15 +11,7 @@
|
||||
#include "FTL.h"
|
||||
#include "shmem.h"
|
||||
|
||||
// Resolve new client and upstream server host names
|
||||
// once every minute
|
||||
#define RESOLVE_INTERVAL 60
|
||||
|
||||
// Re-resolve client names
|
||||
// once every hour
|
||||
#define RERESOLVE_INTERVAL 3600
|
||||
|
||||
char *resolveHostname(const char *addr)
|
||||
static char *resolveHostname(const char *addr)
|
||||
{
|
||||
// Get host name
|
||||
struct hostent *he = NULL;
|
||||
@@ -71,64 +63,110 @@ char *resolveHostname(const char *addr)
|
||||
return hostname;
|
||||
}
|
||||
|
||||
// Resolve client host names
|
||||
void resolveClients(bool onlynew)
|
||||
// Resolve upstream destination host names
|
||||
static size_t resolveAndAddHostname(size_t ippos, size_t oldnamepos)
|
||||
{
|
||||
int clientID;
|
||||
for(clientID = 0; clientID < counters->clients; clientID++)
|
||||
// Get IP and host name strings
|
||||
lock_shm();
|
||||
const char* ipaddr = getstr(ippos);
|
||||
const char* oldname = getstr(oldnamepos);
|
||||
unlock_shm();
|
||||
|
||||
// Important: Don't hold a lock while resolving as the main thread
|
||||
// (dnsmasq) needs to be operable during the call to resolveHostname()
|
||||
char* newname = resolveHostname(ipaddr);
|
||||
|
||||
// Only store new newname if it is valid and differs from oldname
|
||||
// We do not need to check for oldname == NULL as names are
|
||||
// always initialized with an empty string at position 0
|
||||
if(newname != NULL && strcmp(oldname, newname) != 0)
|
||||
{
|
||||
lock_shm();
|
||||
size_t newnamepos = addstr(newname);
|
||||
// newname has already been checked against NULL
|
||||
// so we can safely free it
|
||||
free(newname);
|
||||
unlock_shm();
|
||||
return newnamepos;
|
||||
}
|
||||
else if(config.debug & DEBUG_SHMEM)
|
||||
{
|
||||
// Debugging output
|
||||
logg("Not adding \"%s\" to buffer (unchanged)", oldname);
|
||||
}
|
||||
|
||||
// Not changed, return old namepos
|
||||
return oldnamepos;
|
||||
}
|
||||
|
||||
// Resolve client host names
|
||||
void resolveClients(const bool onlynew)
|
||||
{
|
||||
// Lock counter access here, we use a copy in the following loop
|
||||
lock_shm();
|
||||
int clientscount = counters->clients;
|
||||
unlock_shm();
|
||||
for(int clientID = 0; clientID < clientscount; clientID++)
|
||||
{
|
||||
// Memory validation
|
||||
validate_access("clients", clientID, true, __LINE__, __FUNCTION__, __FILE__);
|
||||
|
||||
// If onlynew flag is set, we will only resolve new clients
|
||||
// If not, we will try to re-resolve all known clients
|
||||
if(onlynew && !clients[clientID].new)
|
||||
continue;
|
||||
|
||||
// Lock data when obtaining IP of this client
|
||||
// Memory access needs to get locked
|
||||
lock_shm();
|
||||
const char* ipaddr = getstr(clients[clientID].ippos);
|
||||
bool newflag = clients[clientID].new;
|
||||
size_t ippos = clients[clientID].ippos;
|
||||
size_t oldnamepos = clients[clientID].namepos;
|
||||
unlock_shm();
|
||||
|
||||
// Important: Don't hold a lock while resolving as the main thread
|
||||
// (dnsmasq) needs to be operable during the call to resolveHostname()
|
||||
const char* hostname = resolveHostname(ipaddr);
|
||||
// If onlynew flag is set, we will only resolve new clients
|
||||
// If not, we will try to re-resolve all known clients
|
||||
if(onlynew && !newflag)
|
||||
continue;
|
||||
|
||||
// Obtain/update hostname of this client
|
||||
size_t newnamepos = resolveAndAddHostname(ippos, oldnamepos);
|
||||
|
||||
// Finally, lock data when storing obtained hostname
|
||||
lock_shm();
|
||||
clients[clientID].namepos = addstr(hostname);
|
||||
// Store obtained host name (may be unchanged)
|
||||
clients[clientID].namepos = newnamepos;
|
||||
|
||||
// Mark entry as not new
|
||||
clients[clientID].new = false;
|
||||
unlock_shm();
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve upstream destination host names
|
||||
void resolveForwardDestinations(bool onlynew)
|
||||
void resolveForwardDestinations(const bool onlynew)
|
||||
{
|
||||
int forwardID;
|
||||
for(forwardID = 0; forwardID < counters->forwarded; forwardID++)
|
||||
// Lock counter access here, we use a copy in the following loop
|
||||
lock_shm();
|
||||
int forwardedcount = counters->forwarded;
|
||||
unlock_shm();
|
||||
for(int forwardID = 0; forwardID < forwardedcount; forwardID++)
|
||||
{
|
||||
// Memory validation
|
||||
validate_access("forwarded", forwardID, true, __LINE__, __FUNCTION__, __FILE__);
|
||||
|
||||
// If onlynew flag is set, we will only resolve new upstream destinations
|
||||
// If not, we will try to re-resolve all known upstream destinations
|
||||
if(onlynew && !forwarded[forwardID].new)
|
||||
continue;
|
||||
|
||||
// Lock data when obtaining IP of this forward destination
|
||||
// Memory access needs to get locked
|
||||
lock_shm();
|
||||
const char* ipaddr = getstr(forwarded[forwardID].ippos);
|
||||
bool newflag = forwarded[forwardID].new;
|
||||
size_t ippos = forwarded[forwardID].ippos;
|
||||
size_t oldnamepos = forwarded[forwardID].namepos;
|
||||
unlock_shm();
|
||||
|
||||
// If onlynew flag is set, we will only resolve new upstream destinations
|
||||
// If not, we will try to re-resolve all known upstream destinations
|
||||
if(onlynew && !newflag)
|
||||
continue;
|
||||
|
||||
// Important: Don't hold a lock while resolving as the main thread
|
||||
// (dnsmasq) needs to be operable during the call to resolveHostname()
|
||||
const char* hostname = resolveHostname(ipaddr);
|
||||
// Obtain/update hostname of this client
|
||||
size_t newnamepos = resolveAndAddHostname(ippos, oldnamepos);
|
||||
|
||||
// Finally, lock data when storing obtained hostname
|
||||
lock_shm();
|
||||
forwarded[forwardID].namepos = addstr(hostname);
|
||||
// Store obtained host name (may be unchanged)
|
||||
forwarded[forwardID].namepos = newnamepos;
|
||||
// Mark entry as not new
|
||||
forwarded[forwardID].new = false;
|
||||
unlock_shm();
|
||||
}
|
||||
|
||||
81
routines.h
81
routines.h
@@ -9,36 +9,35 @@
|
||||
* Please see LICENSE file for your rights under this license. */
|
||||
|
||||
void go_daemon(void);
|
||||
void timer_start(int i);
|
||||
double timer_elapsed_msec(int i);
|
||||
void sleepms(int milliseconds);
|
||||
void timer_start(const int i);
|
||||
double timer_elapsed_msec(const int i);
|
||||
void sleepms(const int milliseconds);
|
||||
void savepid(void);
|
||||
char * getUserName(void);
|
||||
void removepid(void);
|
||||
|
||||
void open_FTL_log(bool test);
|
||||
void logg(const char* format, ...);
|
||||
void logg_struct_resize(const char* str, int to, int step);
|
||||
void open_FTL_log(const bool test);
|
||||
void logg(const char* format, ...) __attribute__ ((format (gnu_printf, 1, 2)));
|
||||
void log_counter_info(void);
|
||||
void format_memory_size(char *prefix, unsigned long int bytes, double *formated);
|
||||
void log_FTL_version(bool crashreport);
|
||||
|
||||
// datastructure.c
|
||||
void strtolower(char *str);
|
||||
int findForwardID(const char * forward, bool count);
|
||||
int findForwardID(const char * forward, const bool count);
|
||||
int findDomainID(const char *domain);
|
||||
int findClientID(const char *client, bool addNew);
|
||||
int findClientID(const char *client, const bool count);
|
||||
bool isValidIPv4(const char *addr);
|
||||
bool isValidIPv6(const char *addr);
|
||||
char *getDomainString(int queryID);
|
||||
char *getClientIPString(int queryID);
|
||||
char *getClientNameString(int queryID);
|
||||
const char *getDomainString(const int queryID);
|
||||
const char *getClientIPString(const int queryID);
|
||||
const char *getClientNameString(const int queryID);
|
||||
|
||||
void close_telnet_socket(void);
|
||||
void close_unix_socket(void);
|
||||
void seom(int sock);
|
||||
void ssend(int sock, const char *format, ...);
|
||||
void swrite(int sock, void *value, size_t size);
|
||||
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);
|
||||
void *telnet_listening_thread_IPv4(void *args);
|
||||
void *telnet_listening_thread_IPv6(void *args);
|
||||
|
||||
@@ -46,9 +45,8 @@ void *socket_listening_thread(void *args);
|
||||
bool ipv6_available(void);
|
||||
void bind_sockets(void);
|
||||
|
||||
void process_request(char *client_message, int *sock);
|
||||
bool command(char *client_message, const char* cmd);
|
||||
bool matchesEndpoint(char *client_message, const char *cmd);
|
||||
void process_request(const char *client_message, int *sock);
|
||||
bool command(const char *client_message, const char* cmd) __attribute__((pure));
|
||||
|
||||
// grep.c
|
||||
int countlines(const char* fname);
|
||||
@@ -57,15 +55,15 @@ void check_blocking_status(void);
|
||||
|
||||
void check_setupVarsconf(void);
|
||||
char * read_setupVarsconf(const char * key);
|
||||
void getSetupVarsArray(char * input);
|
||||
void getSetupVarsArray(const char * input);
|
||||
void clearSetupVarsArray(void);
|
||||
bool insetupVarsArray(char * str);
|
||||
bool getSetupVarsBool(char * input);
|
||||
bool insetupVarsArray(const char * str);
|
||||
bool getSetupVarsBool(const char * input) __attribute__((pure));
|
||||
|
||||
void parse_args(int argc, char* argv[]);
|
||||
|
||||
// setupVars.c
|
||||
char* find_equals(const char* s);
|
||||
char* find_equals(const char* s) __attribute__((pure));
|
||||
void trim_whitespace(char *string);
|
||||
|
||||
// config.c
|
||||
@@ -84,61 +82,62 @@ void *DB_thread(void *val);
|
||||
int get_number_of_queries_in_DB(void);
|
||||
void save_to_DB(void);
|
||||
void read_data_from_DB(void);
|
||||
bool db_set_FTL_property(unsigned int ID, int value);
|
||||
bool db_set_FTL_property(const unsigned int ID, const int value);
|
||||
bool dbquery(const char *format, ...);
|
||||
bool dbopen(void);
|
||||
void dbclose(void);
|
||||
int db_query_int(const char*);
|
||||
void SQLite3LogCallback(void *pArg, int iErrCode, const char *zMsg);
|
||||
|
||||
// memory.c
|
||||
void memory_check(int which);
|
||||
char *FTLstrdup(const char *src, const char *file, const char *function, int line);
|
||||
void *FTLcalloc(size_t nmemb, size_t size, const char *file, const char *function, int line);
|
||||
void *FTLrealloc(void *ptr_in, size_t size, const char *file, const char *function, int line);
|
||||
void FTLfree(void *ptr, const char* file, const char *function, int line);
|
||||
void validate_access(const char * name, int pos, bool testmagic, int line, const char * function, const char * file);
|
||||
void memory_check(const int which);
|
||||
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)));
|
||||
void FTLfree(void *ptr, const char* file, const char *function, const int line);
|
||||
void validate_access(const char * name, int pos, bool testmagic, const int line, const char * function, const char * file);
|
||||
|
||||
int main_dnsmasq(int argc, char **argv);
|
||||
int main_dnsmasq(int argc, const char ** argv);
|
||||
|
||||
// signals.c
|
||||
void handle_signals(void);
|
||||
|
||||
// resolve.c
|
||||
void *DNSclient_thread(void *val);
|
||||
void resolveClients(bool onlynew);
|
||||
void resolveForwardDestinations(bool onlynew);
|
||||
void resolveClients(const bool onlynew);
|
||||
void resolveForwardDestinations(const bool onlynew);
|
||||
|
||||
// regex.c
|
||||
bool match_regex(char *input);
|
||||
bool match_regex(const char *input);
|
||||
void free_regex(void);
|
||||
void free_whitelist_domains(void);
|
||||
void read_regex_from_database(void);
|
||||
void read_whitelist_from_database(void);
|
||||
bool in_whitelist(char *domain);
|
||||
void log_regex_whitelist(double time);
|
||||
bool in_whitelist(const char *domain) __attribute__((pure));
|
||||
void log_regex_whitelist(const double time);
|
||||
|
||||
// shmem.c
|
||||
bool init_shmem(void);
|
||||
void destroy_shmem(void);
|
||||
unsigned long long addstr(const char *str);
|
||||
char *getstr(unsigned long long pos);
|
||||
void *enlarge_shmem_struct(char type);
|
||||
size_t addstr(const char *str);
|
||||
const char *getstr(const size_t pos);
|
||||
void *enlarge_shmem_struct(const char type);
|
||||
|
||||
/**
|
||||
* Create a new overTime client shared memory block.
|
||||
* This also updates `overTimeClientData`.
|
||||
*/
|
||||
void newOverTimeClient(int clientID);
|
||||
void newOverTimeClient(const int clientID);
|
||||
|
||||
/**
|
||||
* Add a new overTime slot to each overTime client shared memory block.
|
||||
* This also updates `overTimeClientData`.
|
||||
*/
|
||||
void addOverTimeClientSlot();
|
||||
void addOverTimeClientSlot(void);
|
||||
|
||||
// overTime.c
|
||||
void initOverTime(void);
|
||||
unsigned int getOverTimeID(time_t timestamp);
|
||||
unsigned int getOverTimeID(const time_t timestamp);
|
||||
|
||||
/**
|
||||
* Move the overTime slots so the oldest interval starts with mintime. The time
|
||||
@@ -146,7 +145,7 @@ unsigned int getOverTimeID(time_t timestamp);
|
||||
*
|
||||
* @param mintime The start of the oldest interval
|
||||
*/
|
||||
void moveOverTimeMemory(time_t mintime);
|
||||
void moveOverTimeMemory(const time_t mintime);
|
||||
|
||||
// capabilities.c
|
||||
bool check_capabilities(void);
|
||||
|
||||
13
setupVars.c
13
setupVars.c
@@ -30,7 +30,7 @@ void check_setupVarsconf(void)
|
||||
}
|
||||
}
|
||||
|
||||
char* find_equals(const char* s)
|
||||
char* __attribute__((pure)) find_equals(const char* s)
|
||||
{
|
||||
const char* chars = "=";
|
||||
while (*s && (!chars || !strchr(chars, *s)))
|
||||
@@ -133,9 +133,9 @@ char * read_setupVarsconf(const char * key)
|
||||
// setupVarsArray[1] = def
|
||||
// setupVarsArray[2] = ghi
|
||||
// setupVarsArray[3] = NULL
|
||||
void getSetupVarsArray(char * input)
|
||||
void getSetupVarsArray(const char * input)
|
||||
{
|
||||
char * p = strtok(input, ",");
|
||||
char * p = strtok((char*)input, ",");
|
||||
|
||||
/* split string and append tokens to 'res' */
|
||||
|
||||
@@ -182,16 +182,15 @@ void clearSetupVarsArray(void)
|
||||
clearSetupVarsArray();
|
||||
*/
|
||||
|
||||
bool insetupVarsArray(char * str)
|
||||
bool insetupVarsArray(const char * str)
|
||||
{
|
||||
int i;
|
||||
// Check for possible NULL pointer
|
||||
// (this is valid input, e.g. if clients[i].name is unspecified)
|
||||
if(str == NULL)
|
||||
return false;
|
||||
|
||||
// Loop over all entries in setupVarsArray
|
||||
for (i = 0; i < setupVarsElements; ++i)
|
||||
for (int i = 0; i < setupVarsElements; ++i)
|
||||
if(setupVarsArray[i][0] == '*')
|
||||
{
|
||||
// Copying strlen-1 chars into buffer of size strlen: OK
|
||||
@@ -221,7 +220,7 @@ bool insetupVarsArray(char * str)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool getSetupVarsBool(char * input)
|
||||
bool __attribute__((pure)) getSetupVarsBool(const char * input)
|
||||
{
|
||||
if((strcmp(input, "true")) == 0)
|
||||
return true;
|
||||
|
||||
155
shmem.c
155
shmem.c
@@ -12,7 +12,7 @@
|
||||
#include "shmem.h"
|
||||
|
||||
/// The version of shared memory used
|
||||
#define SHARED_MEMORY_VERSION 4
|
||||
#define SHARED_MEMORY_VERSION 6
|
||||
|
||||
/// The name of the shared memory. Use this when connecting to the shared memory.
|
||||
#define SHARED_LOCK_NAME "/FTL-lock"
|
||||
@@ -46,9 +46,9 @@ static ShmSettings *shmSettings = NULL;
|
||||
static int pagesize;
|
||||
static unsigned int local_shm_counter = 0;
|
||||
|
||||
static size_t get_optimal_object_size(size_t objsize);
|
||||
static size_t get_optimal_object_size(const size_t objsize, const size_t minsize);
|
||||
|
||||
unsigned long long addstr(const char *str)
|
||||
size_t addstr(const char *str)
|
||||
{
|
||||
if(str == NULL)
|
||||
{
|
||||
@@ -66,7 +66,7 @@ unsigned long long addstr(const char *str)
|
||||
|
||||
// Debugging output
|
||||
if(config.debug & DEBUG_SHMEM)
|
||||
logg("Adding \"%s\" (len %i) to buffer. next_str_pos is %i", str, len, shmSettings->next_str_pos);
|
||||
logg("Adding \"%s\" (len %zu) to buffer. next_str_pos is %u", str, len, shmSettings->next_str_pos);
|
||||
|
||||
// Reserve additional memory if necessary
|
||||
size_t required_size = shmSettings->next_str_pos + len + 1;
|
||||
@@ -90,13 +90,20 @@ unsigned long long addstr(const char *str)
|
||||
return (shmSettings->next_str_pos - (len + 1));
|
||||
}
|
||||
|
||||
char *getstr(unsigned long long pos)
|
||||
const char *getstr(const size_t pos)
|
||||
{
|
||||
return &((char*)shm_strings.ptr)[pos];
|
||||
// Only access the string memory if this memory region has already been set
|
||||
if(pos < shmSettings->next_str_pos)
|
||||
return &((const char*)shm_strings.ptr)[pos];
|
||||
else
|
||||
{
|
||||
logg("WARN: Tried to access %zu but next_str_pos is %u", pos, shmSettings->next_str_pos);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a mutex for shared memory
|
||||
pthread_mutex_t create_mutex() {
|
||||
static pthread_mutex_t create_mutex(void) {
|
||||
pthread_mutexattr_t lock_attr = {};
|
||||
pthread_mutex_t lock = {};
|
||||
|
||||
@@ -118,7 +125,7 @@ pthread_mutex_t create_mutex() {
|
||||
return lock;
|
||||
}
|
||||
|
||||
void remap_shm(void)
|
||||
static void remap_shm(void)
|
||||
{
|
||||
// Remap shared object pointers which might have changed
|
||||
realloc_shm(&shm_queries, counters->queries_MAX*sizeof(queriesDataStruct), false);
|
||||
@@ -136,17 +143,17 @@ void remap_shm(void)
|
||||
local_shm_counter = shmSettings->global_shm_counter;
|
||||
}
|
||||
|
||||
void _lock_shm(const char* function, const int line, const char * file) {
|
||||
void _lock_shm(const char* func, const int line, const char * file) {
|
||||
// Signal that FTL is waiting for a lock
|
||||
shmLock->waitingForLock = true;
|
||||
|
||||
if(config.debug & DEBUG_LOCKS)
|
||||
logg("Waiting for lock in %s() (%s:%i)", function, file, line);
|
||||
logg("Waiting for lock in %s() (%s:%i)", func, file, line);
|
||||
|
||||
int result = pthread_mutex_lock(&shmLock->lock);
|
||||
|
||||
if(config.debug & DEBUG_LOCKS)
|
||||
logg("Obtained lock for %s() (%s:%i)", function, file, line);
|
||||
logg("Obtained lock for %s() (%s:%i)", func, file, line);
|
||||
|
||||
// Check if this process needs to remap the shared memory objects
|
||||
if(shmSettings != NULL &&
|
||||
@@ -172,11 +179,11 @@ void _lock_shm(const char* function, const int line, const char * file) {
|
||||
logg("Failed to obtain SHM lock: %s", strerror(result));
|
||||
}
|
||||
|
||||
void _unlock_shm(const char* function, const int line, const char * file) {
|
||||
void _unlock_shm(const char* func, const int line, const char * file) {
|
||||
int result = pthread_mutex_unlock(&shmLock->lock);
|
||||
|
||||
if(config.debug & DEBUG_LOCKS)
|
||||
logg("Removed lock in %s() (%s:%i)", function, file, line);
|
||||
logg("Removed lock in %s() (%s:%i)", func, file, line);
|
||||
|
||||
if(result != 0)
|
||||
logg("Failed to unlock SHM lock: %s", strerror(result));
|
||||
@@ -222,16 +229,18 @@ bool init_shmem(void)
|
||||
counters->domains_MAX = pagesize;
|
||||
|
||||
/****************************** shared clients struct ******************************/
|
||||
size_t size = get_optimal_object_size(sizeof(clientsDataStruct), 1);
|
||||
// Try to create shared memory object
|
||||
shm_clients = create_shm(SHARED_CLIENTS_NAME, pagesize*sizeof(clientsDataStruct));
|
||||
shm_clients = create_shm(SHARED_CLIENTS_NAME, size*sizeof(clientsDataStruct));
|
||||
clients = (clientsDataStruct*)shm_clients.ptr;
|
||||
counters->clients_MAX = pagesize;
|
||||
counters->clients_MAX = size;
|
||||
|
||||
/****************************** shared forwarded struct ******************************/
|
||||
size = get_optimal_object_size(sizeof(forwardedDataStruct), 1);
|
||||
// Try to create shared memory object
|
||||
shm_forwarded = create_shm(SHARED_FORWARDED_NAME, pagesize*sizeof(forwardedDataStruct));
|
||||
shm_forwarded = create_shm(SHARED_FORWARDED_NAME, size*sizeof(forwardedDataStruct));
|
||||
forwarded = (forwardedDataStruct*)shm_forwarded.ptr;
|
||||
counters->forwarded_MAX = pagesize;
|
||||
counters->forwarded_MAX = size;
|
||||
|
||||
/****************************** shared queries struct ******************************/
|
||||
// Try to create shared memory object
|
||||
@@ -240,14 +249,9 @@ bool init_shmem(void)
|
||||
counters->queries_MAX = pagesize;
|
||||
|
||||
/****************************** shared overTime struct ******************************/
|
||||
size_t size = get_optimal_object_size(sizeof(overTimeDataStruct));
|
||||
size_t required_size = OVERTIME_SLOTS*sizeof(overTimeDataStruct);
|
||||
if(size < required_size)
|
||||
{
|
||||
logg("FATAL: LCM(%i, %zu) == %zu < %zu", pagesize, sizeof(overTimeDataStruct), size, required_size);
|
||||
}
|
||||
size = get_optimal_object_size(sizeof(overTimeDataStruct), OVERTIME_SLOTS);
|
||||
// Try to create shared memory object
|
||||
shm_overTime = create_shm(SHARED_OVERTIME_NAME, size);
|
||||
shm_overTime = create_shm(SHARED_OVERTIME_NAME, size*sizeof(overTimeDataStruct));
|
||||
overTime = (overTimeDataStruct*)shm_overTime.ptr;
|
||||
initOverTime();
|
||||
|
||||
@@ -270,7 +274,7 @@ void destroy_shmem(void)
|
||||
delete_shm(&shm_settings);
|
||||
}
|
||||
|
||||
SharedMemory create_shm(char *name, size_t size)
|
||||
SharedMemory create_shm(const char *name, const size_t size)
|
||||
{
|
||||
if(config.debug & DEBUG_SHMEM)
|
||||
logg("Creating shared memory with name \"%s\" and size %zu", name, size);
|
||||
@@ -303,10 +307,10 @@ SharedMemory create_shm(char *name, size_t size)
|
||||
}
|
||||
|
||||
// Resize shared memory file
|
||||
int result = ftruncate(fd, size);
|
||||
ret = ftruncate(fd, size);
|
||||
|
||||
// Check for `ftruncate` error
|
||||
if(result == -1)
|
||||
if(ret == -1)
|
||||
{
|
||||
logg("FATAL: create_shm(): ftruncate(%i, %zu): Failed to resize shared memory object \"%s\": %s",
|
||||
fd, size, sharedMemory.name, strerror(errno));
|
||||
@@ -332,32 +336,36 @@ SharedMemory create_shm(char *name, size_t size)
|
||||
return sharedMemory;
|
||||
}
|
||||
|
||||
void *enlarge_shmem_struct(char type)
|
||||
void *enlarge_shmem_struct(const char type)
|
||||
{
|
||||
SharedMemory *sharedMemory;
|
||||
size_t sizeofobj;
|
||||
int *counter;
|
||||
SharedMemory *sharedMemory = NULL;
|
||||
size_t sizeofobj, allocation_step;
|
||||
int *counter = NULL;
|
||||
|
||||
// Select type of struct that should be enlarged
|
||||
switch(type)
|
||||
{
|
||||
case QUERIES:
|
||||
sharedMemory = &shm_queries;
|
||||
allocation_step = pagesize;
|
||||
sizeofobj = sizeof(queriesDataStruct);
|
||||
counter = &counters->queries_MAX;
|
||||
break;
|
||||
case CLIENTS:
|
||||
sharedMemory = &shm_clients;
|
||||
allocation_step = get_optimal_object_size(sizeof(clientsDataStruct), 1);
|
||||
sizeofobj = sizeof(clientsDataStruct);
|
||||
counter = &counters->clients_MAX;
|
||||
break;
|
||||
case DOMAINS:
|
||||
sharedMemory = &shm_domains;
|
||||
allocation_step = pagesize;
|
||||
sizeofobj = sizeof(domainsDataStruct);
|
||||
counter = &counters->domains_MAX;
|
||||
break;
|
||||
case FORWARDED:
|
||||
sharedMemory = &shm_forwarded;
|
||||
allocation_step = get_optimal_object_size(sizeof(forwardedDataStruct), 1);
|
||||
sizeofobj = sizeof(forwardedDataStruct);
|
||||
counter = &counters->forwarded_MAX;
|
||||
break;
|
||||
@@ -367,15 +375,15 @@ void *enlarge_shmem_struct(char type)
|
||||
}
|
||||
|
||||
// Reallocate enough space for 4096 instances of requested object
|
||||
realloc_shm(sharedMemory, sharedMemory->size + pagesize*sizeofobj, true);
|
||||
realloc_shm(sharedMemory, sharedMemory->size + allocation_step*sizeofobj, true);
|
||||
|
||||
// Add allocated memory to corresponding counter
|
||||
*counter += pagesize;
|
||||
*counter += allocation_step;
|
||||
|
||||
return sharedMemory->ptr;
|
||||
}
|
||||
|
||||
bool realloc_shm(SharedMemory *sharedMemory, size_t size, bool resize)
|
||||
bool realloc_shm(SharedMemory *sharedMemory, const size_t size, const bool resize)
|
||||
{
|
||||
// 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
|
||||
@@ -393,7 +401,7 @@ bool realloc_shm(SharedMemory *sharedMemory, size_t size, bool resize)
|
||||
if(resize)
|
||||
{
|
||||
// Open shared memory object
|
||||
int fd = shm_open(sharedMemory->name, O_RDWR, S_IRUSR | S_IWUSR);
|
||||
const int fd = shm_open(sharedMemory->name, O_RDWR, S_IRUSR | S_IWUSR);
|
||||
if(fd == -1)
|
||||
{
|
||||
logg("FATAL: realloc_shm(): Failed to open shared memory object \"%s\": %s",
|
||||
@@ -402,7 +410,7 @@ bool realloc_shm(SharedMemory *sharedMemory, size_t size, bool resize)
|
||||
}
|
||||
|
||||
// Truncate shared memory object to specified size
|
||||
int result = ftruncate(fd, 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));
|
||||
@@ -436,8 +444,7 @@ bool realloc_shm(SharedMemory *sharedMemory, size_t size, bool resize)
|
||||
void delete_shm(SharedMemory *sharedMemory)
|
||||
{
|
||||
// Unmap shared memory
|
||||
int ret;
|
||||
ret = munmap(sharedMemory->ptr, sharedMemory->size);
|
||||
int ret = munmap(sharedMemory->ptr, sharedMemory->size);
|
||||
if(ret != 0)
|
||||
logg("delete_shm(): munmap(%p, %zu) failed: %s", sharedMemory->ptr, sharedMemory->size, strerror(errno));
|
||||
|
||||
@@ -448,33 +455,63 @@ void delete_shm(SharedMemory *sharedMemory)
|
||||
logg("delete_shm(): shm_unlink(%s) failed: %s", sharedMemory->name, strerror(errno));
|
||||
}
|
||||
|
||||
// Recursive function to return GCD of a and b
|
||||
// Credits: https://www.geeksforgeeks.org/program-to-find-lcm-of-two-numbers/
|
||||
// The code in this link has been modified by the Pi-hole developers
|
||||
static size_t gcd(size_t a, size_t b)
|
||||
// Euclidean algorithm to return greatest common divisor of the numbers
|
||||
static size_t __attribute__((const)) gcd(size_t a, size_t b)
|
||||
{
|
||||
// Everything divides 0
|
||||
// (except maybe zero)
|
||||
if (a == 0 || b == 0)
|
||||
return 1;
|
||||
|
||||
// Base case
|
||||
if (a == b)
|
||||
return a;
|
||||
|
||||
// a is greater
|
||||
if (a > b)
|
||||
return gcd(a-b, b);
|
||||
|
||||
// b is greater
|
||||
return gcd(a, b-a);
|
||||
while(b != 0)
|
||||
{
|
||||
size_t temp = b;
|
||||
b = a % b;
|
||||
a = temp;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
// Function to return the optimal (minimum) size for page-aligned
|
||||
// shared memory objects. This routine works by computing the LCM
|
||||
// of two numbers, the pagesize and the size of a single element
|
||||
// in the shared memory object
|
||||
static size_t get_optimal_object_size(size_t objsize)
|
||||
static size_t get_optimal_object_size(const size_t objsize, const size_t minsize)
|
||||
{
|
||||
return (pagesize*objsize)/gcd(pagesize, objsize);
|
||||
const size_t optsize = pagesize / gcd(pagesize, objsize);
|
||||
if(optsize < minsize)
|
||||
{
|
||||
if(config.debug & DEBUG_SHMEM)
|
||||
{
|
||||
logg("DEBUG: LCM(%i, %zu) == %zu < %zu",
|
||||
pagesize, objsize,
|
||||
optsize*objsize,
|
||||
minsize*objsize);
|
||||
}
|
||||
|
||||
// Upscale optimal size by a certain factor
|
||||
// Logic of this computation:
|
||||
// First part: Integer division, may cause clipping, e.g., 5/3 = 1
|
||||
// Second part: Catch a possibly happened clipping event by adding
|
||||
// one to the number: (5 % 3 != 0) is 1
|
||||
const size_t multiplier = (minsize/optsize) + ((minsize % optsize != 0) ? 1u : 0u);
|
||||
if(config.debug & DEBUG_SHMEM)
|
||||
{
|
||||
logg("DEBUG: Using %zu*%zu == %zu >= %zu",
|
||||
multiplier, optsize*objsize,
|
||||
multiplier*optsize*objsize,
|
||||
minsize*objsize);
|
||||
}
|
||||
// As optsize ensures perfect page-alignment,
|
||||
// any multiple of it will be aligned as well
|
||||
return multiplier*optsize;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(config.debug & DEBUG_SHMEM)
|
||||
{
|
||||
logg("DEBUG: LCM(%i, %zu) == %zu >= %zu",
|
||||
pagesize, objsize,
|
||||
optsize*objsize,
|
||||
minsize*objsize);
|
||||
}
|
||||
|
||||
// Return computed optimal size
|
||||
return optsize;
|
||||
}
|
||||
}
|
||||
|
||||
6
shmem.h
6
shmem.h
@@ -16,7 +16,7 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
const char *name;
|
||||
size_t size;
|
||||
void *ptr;
|
||||
} SharedMemory;
|
||||
@@ -27,7 +27,7 @@ typedef struct {
|
||||
/// \param size the size to allocate
|
||||
/// \return a structure with a pointer to the mounted shared memory. The pointer
|
||||
/// will always be valid, because if it failed FTL will have exited.
|
||||
SharedMemory create_shm(char *name, size_t size);
|
||||
SharedMemory create_shm(const char *name, const size_t size);
|
||||
|
||||
/// Reallocate shared memory
|
||||
///
|
||||
@@ -35,7 +35,7 @@ SharedMemory create_shm(char *name, size_t size);
|
||||
/// \param size the new size
|
||||
/// \param resize whether the object should be resized or only remapped
|
||||
/// \return if reallocation was successful
|
||||
bool realloc_shm(SharedMemory *sharedMemory, size_t size, bool resize);
|
||||
bool realloc_shm(SharedMemory *sharedMemory, const size_t size, const bool resize);
|
||||
|
||||
/// Disconnect from shared memory. If there are no other connections to shared memory, it will be deleted.
|
||||
///
|
||||
|
||||
@@ -24,7 +24,7 @@ static void SIGSEGV_handler(int sig, siginfo_t *si, void *unused)
|
||||
|
||||
if(FTLstarttime != 0)
|
||||
{
|
||||
logg("FTL has been running for %i seconds", time(NULL)-FTLstarttime);
|
||||
logg("FTL has been running for %li seconds", time(NULL)-FTLstarttime);
|
||||
}
|
||||
log_FTL_version(true);
|
||||
|
||||
|
||||
34
socket.c
34
socket.c
@@ -28,7 +28,7 @@ bool dualstack = false;
|
||||
bool ipv4telnet = false, ipv6telnet = false;
|
||||
bool istelnet[MAXCONNS];
|
||||
|
||||
void saveport(void)
|
||||
static void saveport(void)
|
||||
{
|
||||
FILE *f;
|
||||
if((f = fopen(FTLfiles.port, "w+")) == NULL)
|
||||
@@ -43,7 +43,7 @@ void saveport(void)
|
||||
}
|
||||
}
|
||||
|
||||
bool bind_to_telnet_port_IPv4(int *socketdescriptor)
|
||||
static bool bind_to_telnet_port_IPv4(int *socketdescriptor)
|
||||
{
|
||||
// IPv4 socket
|
||||
*socketdescriptor = socket(AF_INET, SOCK_STREAM, 0);
|
||||
@@ -92,7 +92,7 @@ bool bind_to_telnet_port_IPv4(int *socketdescriptor)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool bind_to_telnet_port_IPv6(int *socketdescriptor)
|
||||
static bool bind_to_telnet_port_IPv6(int *socketdescriptor)
|
||||
{
|
||||
// IPv6 socket
|
||||
*socketdescriptor = socket(AF_INET6, SOCK_STREAM, 0);
|
||||
@@ -154,7 +154,7 @@ bool bind_to_telnet_port_IPv6(int *socketdescriptor)
|
||||
return true;
|
||||
}
|
||||
|
||||
void bind_to_unix_socket(int *socketdescriptor)
|
||||
static void bind_to_unix_socket(int *socketdescriptor)
|
||||
{
|
||||
*socketdescriptor = socket(AF_LOCAL, SOCK_STREAM, 0);
|
||||
|
||||
@@ -190,7 +190,7 @@ void bind_to_unix_socket(int *socketdescriptor)
|
||||
}
|
||||
|
||||
// Called from main() at graceful shutdown
|
||||
void removeport(void)
|
||||
static void removeport(void)
|
||||
{
|
||||
FILE *f;
|
||||
if((f = fopen(FTLfiles.port, "w+")) == NULL)
|
||||
@@ -201,7 +201,7 @@ void removeport(void)
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
void seom(int sock)
|
||||
void seom(const int sock)
|
||||
{
|
||||
if(istelnet[sock])
|
||||
ssend(sock, "---EOM---\n\n");
|
||||
@@ -209,7 +209,7 @@ void seom(int sock)
|
||||
pack_eom(sock);
|
||||
}
|
||||
|
||||
void ssend(int sock, const char *format, ...)
|
||||
void __attribute__ ((format (gnu_printf, 2, 3))) ssend(const int sock, const char *format, ...)
|
||||
{
|
||||
char *buffer;
|
||||
va_list args;
|
||||
@@ -224,12 +224,12 @@ void ssend(int sock, const char *format, ...)
|
||||
}
|
||||
}
|
||||
|
||||
void swrite(int sock, void *value, size_t size) {
|
||||
void swrite(const int sock, const void *value, size_t size) {
|
||||
if(write(sock, value, size) == -1)
|
||||
logg("WARNING: Socket write returned error code %i", errno);
|
||||
}
|
||||
|
||||
int checkClientLimit(int socket) {
|
||||
static inline int checkClientLimit(const int socket) {
|
||||
if(socket < MAXCONNS)
|
||||
{
|
||||
return socket;
|
||||
@@ -243,7 +243,7 @@ int checkClientLimit(int socket) {
|
||||
}
|
||||
}
|
||||
|
||||
int listener(int sockfd, char type)
|
||||
static int listener(const int sockfd, const char type)
|
||||
{
|
||||
struct sockaddr_un un_addr;
|
||||
struct sockaddr_in in4_addr;
|
||||
@@ -294,7 +294,7 @@ void close_unix_socket(void)
|
||||
close(socketfd);
|
||||
}
|
||||
|
||||
void *telnet_connection_handler_thread(void *socket_desc)
|
||||
static void *telnet_connection_handler_thread(void *socket_desc)
|
||||
{
|
||||
//Get the socket descriptor
|
||||
int sock = *(int*)socket_desc;
|
||||
@@ -345,7 +345,7 @@ void *telnet_connection_handler_thread(void *socket_desc)
|
||||
}
|
||||
|
||||
|
||||
void *socket_connection_handler_thread(void *socket_desc)
|
||||
static void *socket_connection_handler_thread(void *socket_desc)
|
||||
{
|
||||
//Get the socket descriptor
|
||||
int sock = *(int*)socket_desc;
|
||||
@@ -430,7 +430,7 @@ void *telnet_listening_thread_IPv4(void *args)
|
||||
while(!killed)
|
||||
{
|
||||
// Look for new clients that want to connect
|
||||
int csck = listener(telnetfd4, 4);
|
||||
const int csck = listener(telnetfd4, 4);
|
||||
if(csck == -1)
|
||||
{
|
||||
logg("IPv4 telnet error: %s (%i)", strerror(errno), errno);
|
||||
@@ -471,7 +471,7 @@ void *telnet_listening_thread_IPv6(void *args)
|
||||
while(!killed)
|
||||
{
|
||||
// Look for new clients that want to connect
|
||||
int csck = listener(telnetfd6, 6);
|
||||
const int csck = listener(telnetfd6, 6);
|
||||
if(csck == -1)
|
||||
{
|
||||
logg("IPv6 telnet error: %s (%i)", strerror(errno), errno);
|
||||
@@ -512,7 +512,7 @@ void *socket_listening_thread(void *args)
|
||||
while(!killed)
|
||||
{
|
||||
// Look for new clients that want to connect
|
||||
int csck = listener(socketfd, 0);
|
||||
const int csck = listener(socketfd, 0);
|
||||
if(csck < 0) continue;
|
||||
|
||||
// Allocate memory used to transport client socket ID to client listening thread
|
||||
@@ -544,8 +544,8 @@ bool ipv6_available(void)
|
||||
// Loop over interfaces
|
||||
for (interface = allInterfaces; interface != NULL; interface = interface->ifa_next)
|
||||
{
|
||||
unsigned int flags = interface->ifa_flags;
|
||||
struct sockaddr *addr = interface->ifa_addr;
|
||||
const unsigned int flags = interface->ifa_flags;
|
||||
const struct sockaddr *addr = interface->ifa_addr;
|
||||
|
||||
// Check only for up and running IPv4, IPv6 interfaces
|
||||
if ((flags & (IFF_UP|IFF_RUNNING)) && addr != NULL)
|
||||
|
||||
Reference in New Issue
Block a user