mirror of
https://github.com/pi-hole/FTL.git
synced 2024-10-26 16:52:18 +02:00
@@ -254,3 +254,14 @@ bool rereadgravity;
|
||||
long int lastDBimportedtimestamp;
|
||||
bool ipv4telnet, ipv6telnet;
|
||||
bool istelnet[MAXCONNS];
|
||||
|
||||
// Use out own memory handling functions that will detect possible errors
|
||||
// and report accordingly in the log. This will make debugging FTL crashs
|
||||
// caused by insufficient memory or by code bugs (not properly dealing
|
||||
// with NULL pointers) much easier.
|
||||
#define free(param) FTLfree(param, __FILE__, __FUNCTION__, __LINE__)
|
||||
#define lib_strdup() strdup()
|
||||
#undef strdup
|
||||
#define strdup(param) FTLstrdup(param, __FILE__, __FUNCTION__, __LINE__)
|
||||
#define calloc(p1,p2) FTLcalloc(p1,p2, __FILE__, __FUNCTION__, __LINE__)
|
||||
#define realloc(p1,p2) FTLrealloc(p1,p2, __FILE__, __FUNCTION__, __LINE__)
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
# Please see LICENSE file for your rights under this license.
|
||||
|
||||
DEPS = FTL.h routines.h api.h version.h
|
||||
OBJ = main.o structs.o log.o daemon.o parser.o signals.o socket.o request.o grep.o setupVars.o args.o flush.o threads.o gc.o config.o database.o api.o msgpack.o
|
||||
OBJ = main.o memory.o log.o daemon.o parser.o signals.o socket.o request.o grep.o setupVars.o args.o flush.o threads.o gc.o config.o database.o api.o msgpack.o
|
||||
|
||||
# Get git commit version and date
|
||||
GIT_BRANCH := $(shell git branch | sed -n 's/^\* //p')
|
||||
|
||||
@@ -272,6 +272,7 @@ void getTopDomains(char *client_message, int *sock)
|
||||
ssend(*sock, "%i %i %s wildcard\n", n, domains[j].blockedcount, domains[j].domain);
|
||||
else {
|
||||
char *fancyWildcard = calloc(3 + strlen(domains[j].domain), sizeof(char));
|
||||
if(fancyWildcard == NULL) return;
|
||||
sprintf(fancyWildcard, "*.%s", domains[j].domain);
|
||||
|
||||
if(!pack_str32(*sock, fancyWildcard))
|
||||
@@ -466,10 +467,8 @@ void getForwardDestinations(char *client_message, int *sock)
|
||||
// Is this the "local" forward destination?
|
||||
if(j == counters.forwarded)
|
||||
{
|
||||
ip = calloc(4,1);
|
||||
strcpy(ip, "::1");
|
||||
name = calloc(6,1);
|
||||
strcpy(name, "local");
|
||||
ip = strdup("::1");
|
||||
name = strdup("local");
|
||||
|
||||
if(totalqueries > 0)
|
||||
// Whats the percentage of (cached + blocked) queries on the total amount of queries?
|
||||
@@ -582,6 +581,7 @@ void getAllQueries(char *client_message, int *sock)
|
||||
if(command(client_message, ">getallqueries-domain")) {
|
||||
// Get domain name we want to see only (limit length to 255 chars)
|
||||
domainname = calloc(256, sizeof(char));
|
||||
if(domainname == NULL) return;
|
||||
sscanf(client_message, ">getallqueries-domain %255s", domainname);
|
||||
if(debugclients)
|
||||
logg("Showing only queries with domain %s", domainname);
|
||||
@@ -589,8 +589,9 @@ void getAllQueries(char *client_message, int *sock)
|
||||
}
|
||||
// Client filtering?
|
||||
if(command(client_message, ">getallqueries-client")) {
|
||||
clientname = calloc(256, sizeof(char));
|
||||
// Get client name we want to see only (limit length to 255 chars)
|
||||
clientname = calloc(256, sizeof(char));
|
||||
if(clientname == NULL) return;
|
||||
sscanf(client_message, ">getallqueries-client %255s", clientname);
|
||||
if(debugclients)
|
||||
logg("Showing only queries with client %s", clientname);
|
||||
@@ -667,8 +668,10 @@ void getAllQueries(char *client_message, int *sock)
|
||||
else
|
||||
strcpy(qtype,"IPv6");
|
||||
|
||||
if((queries[i].status == 1 || queries[i].status == 4) && !showblocked)
|
||||
// 1 = gravity.list, 4 = wildcard, 5 = black.list
|
||||
if((queries[i].status == 1 || queries[i].status == 4 || queries[i].status == 5) && !showblocked)
|
||||
continue;
|
||||
// 2 = forwarded, 3 = cached
|
||||
if((queries[i].status == 2 || queries[i].status == 3) && !showpermitted)
|
||||
continue;
|
||||
|
||||
@@ -785,6 +788,7 @@ void getMemoryUsage(int *sock)
|
||||
{
|
||||
unsigned long int structbytes = sizeof(countersStruct) + sizeof(ConfigStruct) + counters.queries_MAX*sizeof(queriesDataStruct) + counters.forwarded_MAX*sizeof(forwardedDataStruct) + counters.clients_MAX*sizeof(clientsDataStruct) + counters.domains_MAX*sizeof(domainsDataStruct) + counters.overTime_MAX*sizeof(overTimeDataStruct) + (counters.wildcarddomains)*sizeof(*wildcarddomains);
|
||||
char *structprefix = calloc(2, sizeof(char));
|
||||
if(structprefix == NULL) return;
|
||||
double formated = 0.0;
|
||||
format_memory_size(structprefix, structbytes, &formated);
|
||||
|
||||
@@ -796,6 +800,7 @@ void getMemoryUsage(int *sock)
|
||||
|
||||
unsigned long int dynamicbytes = memory.wildcarddomains + memory.domainnames + memory.clientips + memory.clientnames + memory.forwardedips + memory.forwardednames + memory.forwarddata;
|
||||
char *dynamicprefix = calloc(2, sizeof(char));
|
||||
if(dynamicprefix == NULL) return;
|
||||
format_memory_size(dynamicprefix, dynamicbytes, &formated);
|
||||
|
||||
if(istelnet[*sock])
|
||||
@@ -806,6 +811,7 @@ void getMemoryUsage(int *sock)
|
||||
|
||||
unsigned long int totalbytes = structbytes + dynamicbytes;
|
||||
char *totalprefix = calloc(2, sizeof(char));
|
||||
if(totalprefix == NULL) return;
|
||||
format_memory_size(totalprefix, totalbytes, &formated);
|
||||
|
||||
if(istelnet[*sock])
|
||||
@@ -1020,6 +1026,7 @@ void getVersion(int *sock)
|
||||
ssend(*sock, "version vDev-%s\ntag %s\nbranch %s\ndate %s\n", hash, tag, GIT_BRANCH, GIT_DATE);
|
||||
else {
|
||||
char *hashVersion = calloc(6 + strlen(hash), sizeof(char));
|
||||
if(hashVersion == NULL) return;
|
||||
sprintf(hashVersion, "vDev-%s", hash);
|
||||
|
||||
if(!pack_str32(*sock, hashVersion) ||
|
||||
@@ -1048,6 +1055,7 @@ void getDBstats(int *sock)
|
||||
filesize = st.st_size;
|
||||
|
||||
char *prefix = calloc(2, sizeof(char));
|
||||
if(prefix == NULL) return;
|
||||
double formated = 0.0;
|
||||
format_memory_size(prefix, filesize, &formated);
|
||||
|
||||
|
||||
@@ -252,13 +252,12 @@ char *getUserName(void)
|
||||
struct passwd *pw = getpwuid(euid);
|
||||
if(pw)
|
||||
{
|
||||
username = calloc(strlen(pw->pw_name)+1, sizeof(char));
|
||||
strcpy(username, pw->pw_name);
|
||||
username = strdup(pw->pw_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
username = calloc(12, sizeof(char));
|
||||
sprintf(username, "%i", euid);
|
||||
if(asprintf(&username, "%i", euid) < 0)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return username;
|
||||
|
||||
+1
-4
@@ -354,10 +354,7 @@ void save_to_DB(void)
|
||||
sqlite3_bind_text(stmt, 4, domains[queries[i].domainID].domain, -1, SQLITE_TRANSIENT);
|
||||
|
||||
// CLIENT
|
||||
if(strlen(clients[queries[i].clientID].name) > 0)
|
||||
sqlite3_bind_text(stmt, 5, clients[queries[i].clientID].name, -1, SQLITE_TRANSIENT);
|
||||
else
|
||||
sqlite3_bind_text(stmt, 5, clients[queries[i].clientID].ip, -1, SQLITE_TRANSIENT);
|
||||
sqlite3_bind_text(stmt, 5, clients[queries[i].clientID].ip, -1, SQLITE_TRANSIENT);
|
||||
|
||||
// FORWARD
|
||||
if(queries[i].status == 2 && queries[i].forwardID > -1)
|
||||
|
||||
@@ -65,7 +65,8 @@ void pihole_log_flushed(bool message)
|
||||
// overTime struct: Free allocated substructure
|
||||
for(i=0;i<counters.overTime;i++)
|
||||
{
|
||||
free(overTime[i].forwarddata);
|
||||
if(overTime[i].forwarddata != NULL )
|
||||
free(overTime[i].forwarddata);
|
||||
free(overTime[i].querytypedata);
|
||||
}
|
||||
free(overTime);
|
||||
|
||||
@@ -151,6 +151,7 @@ void readWildcardsList()
|
||||
memory_check(WILDCARD);
|
||||
// Allocate space for new domain entry and save domain
|
||||
wildcarddomains[counters.wildcarddomains] = calloc(strlen(domain)+1,sizeof(char));
|
||||
if(wildcarddomains[counters.wildcarddomains] == NULL) return;
|
||||
memory.wildcarddomains += (strlen(domain) + 1) * sizeof(char);
|
||||
strcpy(wildcarddomains[counters.wildcarddomains], domain);
|
||||
|
||||
|
||||
@@ -120,6 +120,7 @@ void logg_struct_resize(const char* str, int to, int step)
|
||||
|
||||
unsigned long int bytes = structbytes + dynamicbytes;
|
||||
char *prefix = calloc(2, sizeof(char));
|
||||
if(prefix == NULL) return;
|
||||
double formated = 0.0;
|
||||
format_memory_size(prefix, bytes, &formated);
|
||||
|
||||
|
||||
@@ -0,0 +1,297 @@
|
||||
/* Pi-hole: A black hole for Internet advertisements
|
||||
* (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
||||
* Network-wide ad blocking via your own hardware.
|
||||
*
|
||||
* FTL Engine
|
||||
* Global variable definitions and memory reallocation handling
|
||||
*
|
||||
* This file is copyright under the latest version of the EUPL.
|
||||
* Please see LICENSE file for your rights under this license. */
|
||||
|
||||
#include "FTL.h"
|
||||
|
||||
FTLFileNamesStruct FTLfiles = {
|
||||
"/etc/pihole/pihole-FTL.conf",
|
||||
"/var/log/pihole-FTL.log",
|
||||
"/var/run/pihole-FTL.pid",
|
||||
"/var/run/pihole-FTL.port",
|
||||
NULL,
|
||||
"/var/run/pihole/FTL.sock"
|
||||
};
|
||||
|
||||
logFileNamesStruct files = {
|
||||
"/var/log/pihole.log",
|
||||
"/etc/pihole/list.preEventHorizon",
|
||||
"/etc/pihole/whitelist.txt",
|
||||
"/etc/pihole/blacklist.txt",
|
||||
"/etc/pihole/setupVars.conf",
|
||||
"/etc/dnsmasq.d/03-pihole-wildcard.conf",
|
||||
"/etc/pihole/auditlog.list",
|
||||
"/etc/dnsmasq.d/01-pihole.conf"
|
||||
};
|
||||
|
||||
countersStruct counters = { 0 };
|
||||
|
||||
void memory_check(int which)
|
||||
{
|
||||
switch(which)
|
||||
{
|
||||
case QUERIES:
|
||||
if(counters.queries >= counters.queries_MAX)
|
||||
{
|
||||
// Have to reallocate memory
|
||||
counters.queries_MAX += QUERIESALLOCSTEP;
|
||||
logg_struct_resize("queries",counters.queries_MAX,QUERIESALLOCSTEP);
|
||||
queries = realloc(queries, counters.queries_MAX*sizeof(queriesDataStruct));
|
||||
if(queries == NULL)
|
||||
{
|
||||
logg("FATAL: Memory allocation failed! Exiting");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case FORWARDED:
|
||||
if(counters.forwarded >= counters.forwarded_MAX)
|
||||
{
|
||||
// Have to reallocate memory
|
||||
counters.forwarded_MAX += FORWARDEDALLOCSTEP;
|
||||
logg_struct_resize("forwarded",counters.forwarded_MAX,FORWARDEDALLOCSTEP);
|
||||
forwarded = realloc(forwarded, counters.forwarded_MAX*sizeof(forwardedDataStruct));
|
||||
if(forwarded == NULL)
|
||||
{
|
||||
logg("FATAL: Memory allocation failed! Exiting");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CLIENTS:
|
||||
if(counters.clients >= counters.clients_MAX)
|
||||
{
|
||||
// Have to reallocate memory
|
||||
counters.clients_MAX += CLIENTSALLOCSTEP;
|
||||
logg_struct_resize("clients",counters.clients_MAX,CLIENTSALLOCSTEP);
|
||||
clients = realloc(clients, counters.clients_MAX*sizeof(clientsDataStruct));
|
||||
if(clients == NULL)
|
||||
{
|
||||
logg("FATAL: Memory allocation failed! Exiting");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DOMAINS:
|
||||
if(counters.domains >= counters.domains_MAX)
|
||||
{
|
||||
// Have to reallocate memory
|
||||
counters.domains_MAX += DOMAINSALLOCSTEP;
|
||||
logg_struct_resize("domains",counters.domains_MAX,DOMAINSALLOCSTEP);
|
||||
domains = realloc(domains, counters.domains_MAX*sizeof(domainsDataStruct));
|
||||
if(domains == NULL)
|
||||
{
|
||||
logg("FATAL: Memory allocation failed! Exiting");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case OVERTIME:
|
||||
if(counters.overTime >= counters.overTime_MAX)
|
||||
{
|
||||
// Have to reallocate memory
|
||||
counters.overTime_MAX += OVERTIMEALLOCSTEP;
|
||||
logg_struct_resize("overTime",counters.overTime_MAX,OVERTIMEALLOCSTEP);
|
||||
overTime = realloc(overTime, counters.overTime_MAX*sizeof(overTimeDataStruct));
|
||||
if(overTime == NULL)
|
||||
{
|
||||
logg("FATAL: Memory allocation failed! Exiting");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WILDCARD:
|
||||
// Definitely enlarge wildcard entry
|
||||
// Enlarge wildcarddomains pointer array
|
||||
logg_struct_resize("wildcards", (counters.wildcarddomains+1), 1);
|
||||
wildcarddomains = realloc(wildcarddomains, (counters.wildcarddomains+1)*sizeof(*wildcarddomains));
|
||||
if(wildcarddomains == NULL)
|
||||
{
|
||||
logg("FATAL: Memory allocation failed! Exiting");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* That cannot happen */
|
||||
logg("Fatal error in memory_check(%i)", which);
|
||||
exit(EXIT_FAILURE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void validate_access(const char * name, int pos, bool testmagic, int line, const char * function, const char * file)
|
||||
{
|
||||
int limit = 0;
|
||||
if(name[0] == 'c') limit = counters.clients_MAX;
|
||||
else if(name[0] == 'd') limit = counters.domains_MAX;
|
||||
else if(name[0] == 'q') limit = counters.queries_MAX;
|
||||
else if(name[0] == 'o') limit = counters.overTime_MAX;
|
||||
else if(name[0] == 'f') limit = counters.forwarded_MAX;
|
||||
else if(name[0] == 'w') limit = counters.wildcarddomains;
|
||||
else { logg("Validator error (range)"); killed = 1; }
|
||||
|
||||
if(pos >= limit || pos < 0)
|
||||
{
|
||||
logg("FATAL ERROR: Trying to access %s[%i], but maximum is %i", name, pos, limit);
|
||||
logg(" found in %s() (%s:%i)", function, file, line);
|
||||
}
|
||||
// Don't test magic byte if detected potential out-of-bounds error
|
||||
else if(testmagic)
|
||||
{
|
||||
unsigned char magic = 0x00;
|
||||
if(name[0] == 'c') magic = clients[pos].magic;
|
||||
else if(name[0] == 'd') magic = domains[pos].magic;
|
||||
else if(name[0] == 'q') magic = queries[pos].magic;
|
||||
else if(name[0] == 'o') magic = overTime[pos].magic;
|
||||
else if(name[0] == 'f') magic = forwarded[pos].magic;
|
||||
else { logg("Validator error (magic byte)"); killed = 1; }
|
||||
if(magic != MAGICBYTE)
|
||||
{
|
||||
logg("FATAL ERROR: Trying to access %s[%i], but magic byte is %x", name, pos, magic);
|
||||
logg(" found in %s() (%s:%i)", function, file, line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void validate_access_oTfd(int timeidx, int forwardID, int line, const char * function, const char * file)
|
||||
{
|
||||
// Determine if there is enough space for saving the current
|
||||
// forwardID in the overTime data structure, allocate space otherwise
|
||||
validate_access("overTime", timeidx, true, __LINE__, __FUNCTION__, __FILE__);
|
||||
if(overTime[timeidx].forwardnum <= forwardID)
|
||||
{
|
||||
// Reallocate more space for forwarddata
|
||||
overTime[timeidx].forwarddata = realloc(overTime[timeidx].forwarddata, (forwardID+1)*sizeof(*overTime[timeidx].forwarddata));
|
||||
// Initialize new data fields with zeroes
|
||||
int j;
|
||||
for(j = overTime[timeidx].forwardnum; j <= forwardID; j++)
|
||||
{
|
||||
overTime[timeidx].forwarddata[j] = 0;
|
||||
memory.forwarddata++;
|
||||
}
|
||||
// Update counter
|
||||
overTime[timeidx].forwardnum = forwardID + 1;
|
||||
}
|
||||
|
||||
int limit = overTime[timeidx].forwardnum;
|
||||
if(forwardID >= limit || forwardID < 0)
|
||||
{
|
||||
logg("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
||||
logg("FATAL ERROR: Trying to access overTime.forwarddata[%i], but maximum is %i", forwardID, limit);
|
||||
logg(" found in %s() (%s:%i)", function, file, line);
|
||||
}
|
||||
}
|
||||
|
||||
void validate_access_oTcl(int timeidx, int clientID, int line, const char * function, const char * file)
|
||||
{
|
||||
// Determine if there is enough space for saving the current
|
||||
// clientID in the overTime data structure, allocate space otherwise
|
||||
if(overTime[timeidx].clientnum <= clientID)
|
||||
{
|
||||
// Reallocate more space for clientdata
|
||||
overTime[timeidx].clientdata = realloc(overTime[timeidx].clientdata, (clientID+1)*sizeof(*overTime[timeidx].clientdata));
|
||||
// Initialize new data fields with zeroes
|
||||
int i;
|
||||
for(i = overTime[timeidx].clientnum; i <= clientID; i++)
|
||||
{
|
||||
overTime[timeidx].clientdata[i] = 0;
|
||||
memory.clientdata++;
|
||||
}
|
||||
// Update counter
|
||||
overTime[timeidx].clientnum = clientID + 1;
|
||||
}
|
||||
int limit = overTime[timeidx].clientnum;
|
||||
if(clientID >= limit || clientID < 0)
|
||||
{
|
||||
logg("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
||||
logg("FATAL ERROR: Trying to access overTime.clientdata[%i], but maximum is %i", clientID, limit);
|
||||
logg(" found in %s() (%s:%i)", function, file, line);
|
||||
}
|
||||
}
|
||||
|
||||
// The special memory handling routines have to be the last ones in this source file
|
||||
// as we restore the original definition of the strdup, free, calloc, and realloc
|
||||
// functions in here, i.e. if anything extra would come below these lines, it would
|
||||
// not be protected by our (error logging) functions!
|
||||
|
||||
#undef strdup
|
||||
char *FTLstrdup(const char *src, const char * file, const char * function, 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
|
||||
// calloc(3), and can be freed with free(3).
|
||||
if(src == NULL)
|
||||
{
|
||||
logg("WARN: Trying to copy a NULL string in %s() (%s:%i)", function, file, line);
|
||||
return NULL;
|
||||
}
|
||||
size_t len = strlen(src);
|
||||
char *dest = calloc(len+1, sizeof(char));
|
||||
if(dest == NULL)
|
||||
{
|
||||
logg("FATAL: Memory allocation failed in %s() (%s:%i)", function, file, line);
|
||||
return NULL;
|
||||
}
|
||||
// Use memcpy as memory areas cannot overlap
|
||||
memcpy(dest, src, len);
|
||||
dest[len] = '\0';
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
#undef calloc
|
||||
void *FTLcalloc(size_t nmemb, size_t size, const char * file, const char * function, 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
|
||||
// memory is set to zero. If nmemb or size is 0, then calloc() returns
|
||||
// either NULL, or a unique pointer value that can later be successfully
|
||||
// passed to free().
|
||||
void *ptr = calloc(nmemb, size);
|
||||
if(ptr == NULL)
|
||||
logg("FATAL: Memory allocation (%u x %u) 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)
|
||||
{
|
||||
// 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
|
||||
// the start of the region up to the minimum of the old and new sizes. If
|
||||
// the new size is larger than the old size, the added memory will not be
|
||||
// initialized. If ptr is NULL, then the call is equivalent to malloc(size),
|
||||
// for all values of size; if size is equal to zero, and ptr is
|
||||
// not NULL, then the call is equivalent to free(ptr). Unless ptr is
|
||||
// NULL, it must have been returned by an earlier call to malloc(), cal‐
|
||||
// loc() or realloc(). If the area pointed to was moved, a free(ptr) is
|
||||
// done.
|
||||
void *ptr_out = realloc(ptr_in, size);
|
||||
if(ptr_out == NULL)
|
||||
logg("FATAL: Memory reallocation (%p -> %u) 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)
|
||||
{
|
||||
// The free() function frees the memory space pointed to by ptr, which
|
||||
// must have been returned by a previous call to malloc(), calloc(), or
|
||||
// realloc(). Otherwise, or if free(ptr) has already been called before,
|
||||
// undefined behavior occurs. If ptr is NULL, no operation is performed.
|
||||
if(ptr == NULL)
|
||||
logg("FATAL: Trying to free NULL pointer in %s() (%s:%i)", function, file, line);
|
||||
|
||||
// We intentionally run free() nevertheless to see the crash in the debugger
|
||||
free(ptr);
|
||||
}
|
||||
@@ -96,7 +96,7 @@ bool pack_str32(int sock, char *string) {
|
||||
// Make sure that the length is less than 4294967296
|
||||
size_t length = strlen(string);
|
||||
|
||||
if(length >= 2147483648) {
|
||||
if(length >= 2147483648u) {
|
||||
logg("Tried to send a str32 longer than 2147483647 bytes!");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -328,6 +328,7 @@ void process_pihole_log(void)
|
||||
}
|
||||
|
||||
char *domain = calloc(domainlen+1,sizeof(char));
|
||||
if(domain == NULL) continue;
|
||||
// strncat() NULL-terminates the copied string (strncpy() doesn't!)
|
||||
strncat(domain,domainstart+2,domainlen);
|
||||
// Convert domain to lower case
|
||||
@@ -363,6 +364,7 @@ void process_pihole_log(void)
|
||||
}
|
||||
|
||||
char *client = calloc(clientlen+1,sizeof(char));
|
||||
if(client == NULL){ free(domain); continue; }
|
||||
// strncat() NULL-terminates the copied string (strncpy() doesn't!)
|
||||
strncat(client,domainend+6,clientlen);
|
||||
// Convert client to lower case
|
||||
@@ -525,6 +527,7 @@ void process_pihole_log(void)
|
||||
}
|
||||
|
||||
char *forward = calloc(forwardlen+1,sizeof(char));
|
||||
if(forward == NULL) continue;
|
||||
// strncat() NULL-terminates the copied string (strncpy() doesn't!)
|
||||
strncat(forward,forwardstart+4,forwardlen);
|
||||
// Convert forward to lower case
|
||||
@@ -970,13 +973,14 @@ char *resolveHostname(const char *addr)
|
||||
if(he == NULL)
|
||||
{
|
||||
// No hostname found
|
||||
hostname = calloc(1,sizeof(char));
|
||||
hostname[0] = '\0';
|
||||
hostname = strdup("");
|
||||
if(hostname == NULL) return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Return hostname copied to new memory location
|
||||
hostname = strdup(he->h_name);
|
||||
if(hostname == NULL) return NULL;
|
||||
// Convert hostname to lower case
|
||||
strtolower(hostname);
|
||||
}
|
||||
@@ -1184,7 +1188,7 @@ int findDomainID(const char *domain)
|
||||
domains[domainID].blockedcount = 0;
|
||||
// Initialize wildcard blocking flag with false
|
||||
domains[domainID].wildcard = false;
|
||||
// Store domain name
|
||||
// Store domain name - no need to check for NULL here as it doesn't harm
|
||||
domains[domainID].domain = strdup(domain);
|
||||
memory.domainnames += (strlen(domain) + 1) * sizeof(char);
|
||||
// Store DNSSEC result for this domain
|
||||
@@ -1269,10 +1273,10 @@ int findClientID(const char *client)
|
||||
clients[clientID].magic = MAGICBYTE;
|
||||
// Set its counter to 1
|
||||
clients[clientID].count = 1;
|
||||
// Store client IP
|
||||
// Store client IP - no need to check for NULL here as it doesn't harm
|
||||
clients[clientID].ip = strdup(client);
|
||||
memory.clientips += (strlen(client) + 1) * sizeof(char);
|
||||
// Store client hostname
|
||||
// Store client hostname - no need to check for NULL here as it doesn't harm
|
||||
clients[clientID].name = strdup(hostname);
|
||||
memory.clientnames += (strlen(hostname) + 1) * sizeof(char);
|
||||
free(hostname);
|
||||
@@ -1282,96 +1286,6 @@ int findClientID(const char *client)
|
||||
return clientID;
|
||||
}
|
||||
|
||||
void validate_access(const char * name, int pos, bool testmagic, int line, const char * function, const char * file)
|
||||
{
|
||||
int limit = 0;
|
||||
if(name[0] == 'c') limit = counters.clients_MAX;
|
||||
else if(name[0] == 'd') limit = counters.domains_MAX;
|
||||
else if(name[0] == 'q') limit = counters.queries_MAX;
|
||||
else if(name[0] == 'o') limit = counters.overTime_MAX;
|
||||
else if(name[0] == 'f') limit = counters.forwarded_MAX;
|
||||
else if(name[0] == 'w') limit = counters.wildcarddomains;
|
||||
else { logg("Validator error (range)"); killed = 1; }
|
||||
|
||||
if(pos >= limit || pos < 0)
|
||||
{
|
||||
logg("FATAL ERROR: Trying to access %s[%i], but maximum is %i", name, pos, limit);
|
||||
logg(" found in %s() (line %i) in %s", function, line, file);
|
||||
}
|
||||
// Don't test magic byte if detected potential out-of-bounds error
|
||||
else if(testmagic)
|
||||
{
|
||||
unsigned char magic = 0x00;
|
||||
if(name[0] == 'c') magic = clients[pos].magic;
|
||||
else if(name[0] == 'd') magic = domains[pos].magic;
|
||||
else if(name[0] == 'q') magic = queries[pos].magic;
|
||||
else if(name[0] == 'o') magic = overTime[pos].magic;
|
||||
else if(name[0] == 'f') magic = forwarded[pos].magic;
|
||||
else { logg("Validator error (magic byte)"); killed = 1; }
|
||||
if(magic != MAGICBYTE)
|
||||
{
|
||||
logg("FATAL ERROR: Trying to access %s[%i], but magic byte is %x", name, pos, magic);
|
||||
logg(" found in %s() (line %i) in %s", function, line, file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void validate_access_oTfd(int timeidx, int forwardID, int line, const char * function, const char * file)
|
||||
{
|
||||
// Determine if there is enough space for saving the current
|
||||
// forwardID in the overTime data structure, allocate space otherwise
|
||||
validate_access("overTime", timeidx, true, __LINE__, __FUNCTION__, __FILE__);
|
||||
if(overTime[timeidx].forwardnum <= forwardID)
|
||||
{
|
||||
// Reallocate more space for forwarddata
|
||||
overTime[timeidx].forwarddata = realloc(overTime[timeidx].forwarddata, (forwardID+1)*sizeof(*overTime[timeidx].forwarddata));
|
||||
// Initialize new data fields with zeroes
|
||||
int j;
|
||||
for(j = overTime[timeidx].forwardnum; j <= forwardID; j++)
|
||||
{
|
||||
overTime[timeidx].forwarddata[j] = 0;
|
||||
memory.forwarddata++;
|
||||
}
|
||||
// Update counter
|
||||
overTime[timeidx].forwardnum = forwardID + 1;
|
||||
}
|
||||
|
||||
int limit = overTime[timeidx].forwardnum;
|
||||
if(forwardID >= limit || forwardID < 0)
|
||||
{
|
||||
logg("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
||||
logg("FATAL ERROR: Trying to access overTime.forwarddata[%i], but maximum is %i", forwardID, limit);
|
||||
logg(" found in %s() (line %i) in %s", function, line, file);
|
||||
}
|
||||
}
|
||||
|
||||
void validate_access_oTcl(int timeidx, int clientID, int line, const char * function, const char * file)
|
||||
{
|
||||
// Determine if there is enough space for saving the current
|
||||
// clientID in the overTime data structure, allocate space otherwise
|
||||
if(overTime[timeidx].clientnum <= clientID)
|
||||
{
|
||||
// Reallocate more space for clientdata
|
||||
overTime[timeidx].clientdata = realloc(overTime[timeidx].clientdata, (clientID+1)*sizeof(*overTime[timeidx].clientdata));
|
||||
// Initialize new data fields with zeroes
|
||||
int i;
|
||||
for(i = overTime[timeidx].clientnum; i <= clientID; i++)
|
||||
{
|
||||
overTime[timeidx].clientdata[i] = 0;
|
||||
memory.clientdata++;
|
||||
}
|
||||
// Update counter
|
||||
overTime[timeidx].clientnum = clientID + 1;
|
||||
}
|
||||
int limit = overTime[timeidx].clientnum;
|
||||
if(clientID >= limit || clientID < 0)
|
||||
{
|
||||
logg("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
||||
logg("FATAL ERROR: Trying to access overTime.clientdata[%i], but maximum is %i", clientID, limit);
|
||||
logg(" found in %s() (line %i) in %s", function, line, file);
|
||||
}
|
||||
}
|
||||
|
||||
void reresolveHostnames(void)
|
||||
{
|
||||
int clientID;
|
||||
|
||||
+9
-3
@@ -29,9 +29,6 @@ void open_pihole_log(void);
|
||||
void handle_signals(void);
|
||||
void process_pihole_log(void);
|
||||
void *pihole_log_thread(void *val);
|
||||
void validate_access(const char * name, int pos, bool testmagic, int line, const char * function, const char * file);
|
||||
void validate_access_oTfd(int timeidx, int forwardID, int line, const char * function, const char * file);
|
||||
void validate_access_oTcl(int timeidx, int clientID, int line, const char * function, const char * file);
|
||||
void reresolveHostnames(void);
|
||||
int findClientID(const char *client);
|
||||
int findDomainID(const char *domain);
|
||||
@@ -88,3 +85,12 @@ void *DB_thread(void *val);
|
||||
int get_number_of_queries_in_DB(void);
|
||||
void save_to_DB(void);
|
||||
void read_data_from_DB(void);
|
||||
|
||||
// memory.c
|
||||
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 validate_access_oTfd(int timeidx, int forwardID, int line, const char * function, const char * file);
|
||||
void validate_access_oTcl(int timeidx, int clientID, int line, const char * function, const char * file);
|
||||
|
||||
@@ -119,12 +119,14 @@ void getSetupVarsArray(char * input)
|
||||
|
||||
while (p) {
|
||||
setupVarsArray = realloc(setupVarsArray, sizeof(char*) * ++setupVarsElements);
|
||||
if(setupVarsArray == NULL) return;
|
||||
setupVarsArray[setupVarsElements-1] = p;
|
||||
p = strtok(NULL, ",");
|
||||
}
|
||||
|
||||
/* realloc one extra element for the last NULL */
|
||||
setupVarsArray = realloc(setupVarsArray, sizeof(char*) * (setupVarsElements+1));
|
||||
if(setupVarsArray == NULL) return;
|
||||
setupVarsArray[setupVarsElements] = NULL;
|
||||
}
|
||||
|
||||
@@ -168,6 +170,7 @@ bool insetupVarsArray(char * str)
|
||||
// Copying strlen-1 chars into buffer of size strlen: OK
|
||||
size_t lenght = strlen(setupVarsArray[i]);
|
||||
char * domain = calloc(lenght, sizeof(char));
|
||||
if(domain == NULL) return false;
|
||||
// strncat() NULL-terminates the copied string (strncpy() doesn't!)
|
||||
strncat(domain, setupVarsArray[i]+1, lenght-1);
|
||||
|
||||
|
||||
@@ -317,8 +317,8 @@ void *telnet_connection_handler_thread(void *socket_desc)
|
||||
{
|
||||
if (n > 0)
|
||||
{
|
||||
char *message = calloc(strlen(client_message)+1,sizeof(char));
|
||||
strcpy(message, client_message);
|
||||
char *message = strdup(client_message);
|
||||
if(message == NULL) break;
|
||||
|
||||
// Clear client message receive buffer
|
||||
memset(client_message, 0, sizeof client_message);
|
||||
@@ -377,8 +377,8 @@ void *socket_connection_handler_thread(void *socket_desc)
|
||||
{
|
||||
if (n > 0)
|
||||
{
|
||||
char *message = calloc(strlen(client_message)+1,sizeof(char));
|
||||
strcpy(message, client_message);
|
||||
char *message = strdup(client_message);
|
||||
if(message == NULL) break;
|
||||
|
||||
// Clear client message receive buffer
|
||||
memset(client_message, 0, sizeof client_message);
|
||||
@@ -460,6 +460,7 @@ void *telnet_listening_thread_IPv4(void *args)
|
||||
// Allocate memory used to transport client socket ID to client listening thread
|
||||
int *newsock;
|
||||
newsock = calloc(1,sizeof(int));
|
||||
if(newsock == NULL) break;
|
||||
*newsock = csck;
|
||||
|
||||
pthread_t telnet_connection_thread;
|
||||
@@ -500,6 +501,7 @@ void *telnet_listening_thread_IPv6(void *args)
|
||||
// Allocate memory used to transport client socket ID to client listening thread
|
||||
int *newsock;
|
||||
newsock = calloc(1,sizeof(int));
|
||||
if(newsock == NULL) break;
|
||||
*newsock = csck;
|
||||
|
||||
pthread_t telnet_connection_thread;
|
||||
@@ -536,6 +538,7 @@ void *socket_listening_thread(void *args)
|
||||
// Allocate memory used to transport client socket ID to client listening thread
|
||||
int *newsock;
|
||||
newsock = calloc(1,sizeof(int));
|
||||
if(newsock == NULL) break;
|
||||
*newsock = csck;
|
||||
|
||||
pthread_t socket_connection_thread;
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
/* Pi-hole: A black hole for Internet advertisements
|
||||
* (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
||||
* Network-wide ad blocking via your own hardware.
|
||||
*
|
||||
* FTL Engine
|
||||
* Global variable definitions and memory reallocation handling
|
||||
*
|
||||
* This file is copyright under the latest version of the EUPL.
|
||||
* Please see LICENSE file for your rights under this license. */
|
||||
|
||||
#include "FTL.h"
|
||||
|
||||
FTLFileNamesStruct FTLfiles = {
|
||||
"/etc/pihole/pihole-FTL.conf",
|
||||
"/var/log/pihole-FTL.log",
|
||||
"/var/run/pihole-FTL.pid",
|
||||
"/var/run/pihole-FTL.port",
|
||||
NULL,
|
||||
"/var/run/pihole/FTL.sock"
|
||||
};
|
||||
|
||||
logFileNamesStruct files = {
|
||||
"/var/log/pihole.log",
|
||||
"/etc/pihole/list.preEventHorizon",
|
||||
"/etc/pihole/whitelist.txt",
|
||||
"/etc/pihole/blacklist.txt",
|
||||
"/etc/pihole/setupVars.conf",
|
||||
"/etc/dnsmasq.d/03-pihole-wildcard.conf",
|
||||
"/etc/pihole/auditlog.list",
|
||||
"/etc/dnsmasq.d/01-pihole.conf"
|
||||
};
|
||||
|
||||
countersStruct counters = { 0 };
|
||||
|
||||
void memory_check(int which)
|
||||
{
|
||||
switch(which)
|
||||
{
|
||||
case QUERIES:
|
||||
if(counters.queries >= counters.queries_MAX)
|
||||
{
|
||||
// Have to reallocate memory
|
||||
counters.queries_MAX += QUERIESALLOCSTEP;
|
||||
logg_struct_resize("queries",counters.queries_MAX,QUERIESALLOCSTEP);
|
||||
queries = realloc(queries, counters.queries_MAX*sizeof(queriesDataStruct));
|
||||
if(queries == NULL)
|
||||
{
|
||||
logg("FATAL: Memory allocation failed! Exiting");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case FORWARDED:
|
||||
if(counters.forwarded >= counters.forwarded_MAX)
|
||||
{
|
||||
// Have to reallocate memory
|
||||
counters.forwarded_MAX += FORWARDEDALLOCSTEP;
|
||||
logg_struct_resize("forwarded",counters.forwarded_MAX,FORWARDEDALLOCSTEP);
|
||||
forwarded = realloc(forwarded, counters.forwarded_MAX*sizeof(forwardedDataStruct));
|
||||
if(forwarded == NULL)
|
||||
{
|
||||
logg("FATAL: Memory allocation failed! Exiting");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CLIENTS:
|
||||
if(counters.clients >= counters.clients_MAX)
|
||||
{
|
||||
// Have to reallocate memory
|
||||
counters.clients_MAX += CLIENTSALLOCSTEP;
|
||||
logg_struct_resize("clients",counters.clients_MAX,CLIENTSALLOCSTEP);
|
||||
clients = realloc(clients, counters.clients_MAX*sizeof(clientsDataStruct));
|
||||
if(clients == NULL)
|
||||
{
|
||||
logg("FATAL: Memory allocation failed! Exiting");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DOMAINS:
|
||||
if(counters.domains >= counters.domains_MAX)
|
||||
{
|
||||
// Have to reallocate memory
|
||||
counters.domains_MAX += DOMAINSALLOCSTEP;
|
||||
logg_struct_resize("domains",counters.domains_MAX,DOMAINSALLOCSTEP);
|
||||
domains = realloc(domains, counters.domains_MAX*sizeof(domainsDataStruct));
|
||||
if(domains == NULL)
|
||||
{
|
||||
logg("FATAL: Memory allocation failed! Exiting");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case OVERTIME:
|
||||
if(counters.overTime >= counters.overTime_MAX)
|
||||
{
|
||||
// Have to reallocate memory
|
||||
counters.overTime_MAX += OVERTIMEALLOCSTEP;
|
||||
logg_struct_resize("overTime",counters.overTime_MAX,OVERTIMEALLOCSTEP);
|
||||
overTime = realloc(overTime, counters.overTime_MAX*sizeof(overTimeDataStruct));
|
||||
if(overTime == NULL)
|
||||
{
|
||||
logg("FATAL: Memory allocation failed! Exiting");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WILDCARD:
|
||||
// Definitely enlarge wildcard entry
|
||||
// Enlarge wildcarddomains pointer array
|
||||
logg_struct_resize("wildcards", (counters.wildcarddomains+1), 1);
|
||||
wildcarddomains = realloc(wildcarddomains, (counters.wildcarddomains+1)*sizeof(*wildcarddomains));
|
||||
if(wildcarddomains == NULL)
|
||||
{
|
||||
logg("FATAL: Memory allocation failed! Exiting");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* That cannot happen */
|
||||
logg("Fatal error in memory_check(%i)", which);
|
||||
exit(EXIT_FAILURE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user