mirror of
https://github.com/pi-hole/FTL.git
synced 2024-10-26 16:52:18 +02:00
d50494b8f4
Signed-off-by: DL6ER <dl6er@dl6er.de>
289 lines
9.7 KiB
C
289 lines
9.7 KiB
C
/* 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/black.list",
|
||
"/etc/pihole/gravity.list",
|
||
"/etc/pihole/setupVars.conf",
|
||
"/etc/dnsmasq.d/03-pihole-wildcard.conf",
|
||
"/etc/pihole/auditlog.list",
|
||
"/etc/dnsmasq.d/01-pihole.conf"
|
||
};
|
||
|
||
// Fixed size structs
|
||
countersStruct counters = { 0 };
|
||
ConfigStruct config;
|
||
memoryStruct memory;
|
||
|
||
// Variable size array structs
|
||
queriesDataStruct *queries;
|
||
forwardedDataStruct *forwarded;
|
||
clientsDataStruct *clients;
|
||
domainsDataStruct *domains;
|
||
overTimeDataStruct *overTime;
|
||
|
||
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:
|
||
if(counters.wildcarddomains >= counters.wildcarddomains_MAX)
|
||
{
|
||
// Enlarge wildcarddomains pointer array
|
||
counters.wildcarddomains_MAX += WILDCARDALLOCSTEP;
|
||
logg_struct_resize("wildcards", counters.wildcarddomains_MAX, WILDCARDALLOCSTEP);
|
||
wildcarddomains = realloc(wildcarddomains, counters.wildcarddomains_MAX*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_oTcl(int timeidx, int clientID, int line, const char * function, const char * file)
|
||
{
|
||
if(clientID < 0)
|
||
{
|
||
logg("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
||
logg("FATAL ERROR: Trying to access overTime.clientdata[%i]", clientID);
|
||
logg(" found in %s() (%s:%i)", function, file, line);
|
||
}
|
||
// 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)
|
||
{
|
||
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);
|
||
}
|