Files
FTL/datastructure.c
2019-04-16 18:04:40 +02:00

238 lines
6.2 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
* Query processing routines
*
* This file is copyright under the latest version of the EUPL.
* Please see LICENSE file for your rights under this license. */
#include "FTL.h"
// converts upper to lower case, and leaves other characters unchanged
void strtolower(char *str)
{
int i = 0;
while(str[i]){ str[i] = tolower(str[i]); i++; }
}
int findForwardID(const char * forwardString, const bool count)
{
// Go through already knows forward servers and see if we used one of those
for(int forwardID=0; forwardID < counters->forwarded; forwardID++)
{
// Get forward pointer
forwardedData* forward = getForward(forwardID, true);
if(strcmp(getstr(forward->ippos), forwardString) == 0)
{
if(count) forward->count++;
return forwardID;
}
}
// This forward server is not known
// Store ID
const int forwardID = counters->forwarded;
logg("New forward server: %s (%i/%u)", forwardString, forwardID, counters->forwarded_MAX);
// Check struct size
memory_check(FORWARDED);
// Get forward pointer
forwardedData* forward = getForward(forwardID, false);
// Set magic byte
forward->magic = MAGICBYTE;
// Initialize its counter
if(count)
forward->count = 1;
else
forward->count = 0;
// Save forward destination IP address
forward->ippos = addstr(forwardString);
forward->failed = 0;
// Initialize forward hostname
// Due to the nature of us being the resolver,
// the actual resolving of the host name has
// to be done separately to be non-blocking
forward->new = true;
forward->namepos = 0; // 0 -> string with length zero
// Increase counter by one
counters->forwarded++;
return forwardID;
}
int findDomainID(const char *domainString)
{
for(int domainID = 0; domainID < counters->domains; domainID++)
{
// Get domain pointer
domainsData* domain = getDomain(domainID, true);
// Quick test: Does the domain start with the same character?
if(getstr(domain->domainpos)[0] != domainString[0])
continue;
// If so, compare the full domain using strcmp
if(strcmp(getstr(domain->domainpos), domainString) == 0)
{
domain->count++;
return domainID;
}
}
// If we did not return until here, then this domain is not known
// Store ID
const int domainID = counters->domains;
// Check struct size
memory_check(DOMAINS);
// Get domain pointer
domainsData* domain = getDomain(domainID, false);
// Set magic byte
domain->magic = MAGICBYTE;
// Set its counter to 1
domain->count = 1;
// Set blocked counter to zero
domain->blockedcount = 0;
// Store domain name - no need to check for NULL here as it doesn't harm
domain->domainpos = addstr(domainString);
// RegEx needs to be evaluated for this new domain
domain->regexmatch = REGEX_UNKNOWN;
// Increase counter by one
counters->domains++;
return domainID;
}
int findClientID(const char *clientIP, const bool count)
{
// Compare content of client against known client IP addresses
for(int clientID=0; clientID < counters->clients; clientID++)
{
// Get client pointer
clientsData* client = getClient(clientID, true);
// Quick test: Does the clients IP start with the same character?
if(getstr(client->ippos)[0] != clientIP[0])
continue;
// If so, compare the full IP using strcmp
if(strcmp(getstr(client->ippos), clientIP) == 0)
{
// Add one if count == true (do not add one, e.g., during ARP table processing)
if(count) client->count++;
return clientID;
}
}
// Return -1 (= not found) if count is false ...
if(!count)
return -1;
// ... otherwise proceed with adding a new client entry
// If we did not return until here, then this client is definitely new
// Store ID
const int clientID = counters->clients;
// Check struct size
memory_check(CLIENTS);
// Get client pointer
clientsData* client = getClient(clientID, false);
// Set magic byte
client->magic = MAGICBYTE;
// Set its counter to 1
client->count = 1;
// Initialize blocked count to zero
client->blockedcount = 0;
// Store client IP - no need to check for NULL here as it doesn't harm
client->ippos = addstr(clientIP);
// Initialize client hostname
// Due to the nature of us being the resolver,
// the actual resolving of the host name has
// to be done separately to be non-blocking
client->new = true;
client->namepos = 0;
// No query seen so far
client->lastQuery = 0;
client->numQueriesARP = 0;
// Initialize client-specific overTime data
for(int i = 0; i < OVERTIME_SLOTS; i++)
client->overTime[i] = 0;
// Increase counter by one
counters->clients++;
return clientID;
}
bool isValidIPv4(const char *addr)
{
struct sockaddr_in sa;
return inet_pton(AF_INET, addr, &(sa.sin_addr)) != 0;
}
bool isValidIPv6(const char *addr)
{
struct sockaddr_in6 sa;
return inet_pton(AF_INET6, addr, &(sa.sin6_addr)) != 0;
}
// Privacy-level sensitive subroutine that returns the domain name
// only when appropriate for the requested query
const char *getDomainString(const int queryID)
{
const queriesData* query = getQuery(queryID, true);
if(query->privacylevel < PRIVACY_HIDE_DOMAINS)
{
// Get domain pointer
const domainsData* domain = getDomain(query->domainID, true);
// Return string
return getstr(domain->domainpos);
}
else
return HIDDEN_DOMAIN;
}
// Privacy-level sensitive subroutine that returns the client IP
// only when appropriate for the requested query
const char *getClientIPString(const int queryID)
{
const queriesData* query = getQuery(queryID, false);
if(query->privacylevel < PRIVACY_HIDE_DOMAINS_CLIENTS)
{
// Get client pointer
const clientsData* client = getClient(query->clientID, false);
// Return string
return getstr(client->ippos);
}
else
return HIDDEN_CLIENT;
}
// Privacy-level sensitive subroutine that returns the client host name
// only when appropriate for the requested query
const char *getClientNameString(const int queryID)
{
const queriesData* query = getQuery(queryID, true);
if(query->privacylevel < PRIVACY_HIDE_DOMAINS_CLIENTS)
{
// Get client pointer
const clientsData* client = getClient(query->clientID, true);
// Return string
return getstr(client->namepos);
}
else
return HIDDEN_CLIENT;
}