Skip to content

Commit

Permalink
Merge pull request #948 from pi-hole/release/v5.3.2
Browse files Browse the repository at this point in the history
Pi-hole FTL v5.3.2
  • Loading branch information
PromoFaux committed Dec 2, 2020
2 parents e1db31d + 9b1065e commit 0790cf7
Show file tree
Hide file tree
Showing 13 changed files with 126 additions and 184 deletions.
3 changes: 2 additions & 1 deletion src/CMakeLists.txt
Expand Up @@ -41,7 +41,8 @@ set(SQLITE_DEFINES "-DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_DEFAULT_MEMSTATUS=0 -D
# -Wl,-z,defs: Detect and reject underlinking (phenomenon caused by missing shared library arguments when invoking the linked editor to produce another shared library)
# -Wl,-z,now: Disable lazy binding
# -Wl,-z,relro: Read-only segments after relocation
set(HARDENING_FLAGS "-fstack-protector-strong -Wp,-D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now -fexceptions -funwind-tables -fasynchronous-unwind-tables -Wl,-z,defs -Wl,-z,now -Wl,-z,relro")
# -fno-common: Emit globals without explicit initializer from `.bss` to `.data`. This causes GCC to reject multiple definitions of global variables. This is the new default from GCC-10 on.
set(HARDENING_FLAGS "-fstack-protector-strong -Wp,-D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now -fexceptions -funwind-tables -fasynchronous-unwind-tables -Wl,-z,defs -Wl,-z,now -Wl,-z,relro -fno-common")
set(DEBUG_FLAGS "-rdynamic -fno-omit-frame-pointer")

# -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.
Expand Down
26 changes: 25 additions & 1 deletion src/config.c
Expand Up @@ -424,6 +424,26 @@ void read_FTLconf(void)
else
logg(" EDNS0_ECS: Don't use ECS information");

// REFRESH_HOSTNAMES
// defaults to: IPV4
buffer = parse_FTLconf(fp, "REFRESH_HOSTNAMES");

if(buffer != NULL && strcasecmp(buffer, "ALL") == 0)
{
config.refresh_hostnames = REFRESH_ALL;
logg(" REFRESH_HOSTNAMES: Periodically refreshing all names");
}
else if(buffer != NULL && strcasecmp(buffer, "NONE") == 0)
{
config.refresh_hostnames = REFRESH_NONE;
logg(" REFRESH_HOSTNAMES: Not periodically refreshing names");
}
else
{
config.refresh_hostnames = REFRESH_IPV4_ONLY;
logg(" REFRESH_HOSTNAMES: Periodically refreshing IPv4 names");
}

// Read DEBUG_... setting from pihole-FTL.conf
read_debuging_settings(fp);

Expand Down Expand Up @@ -490,6 +510,10 @@ static char *parse_FTLconf(FILE *fp, const char * key)
errno = 0;
while(getline(&conflinebuffer, &size, fp) != -1)
{
// Check if memory allocation failed
if(conflinebuffer == NULL)
break;

// Skip comment lines
if(conflinebuffer[0] == '#' || conflinebuffer[0] == ';')
continue;
Expand All @@ -512,7 +536,7 @@ static char *parse_FTLconf(FILE *fp, const char * key)
if(errno == ENOMEM)
logg("WARN: parse_FTLconf failed: could not allocate memory for getline");

// Key not found -> return NULL
// Key not found or memory error -> return NULL
free(keystr);

return NULL;
Expand Down
1 change: 1 addition & 0 deletions src/config.h
Expand Up @@ -34,6 +34,7 @@ typedef struct {
unsigned int network_expire;
enum privacy_level privacylevel;
enum blocking_mode blockingmode;
enum refresh_hostnames refresh_hostnames;
bool socket_listenlocal;
bool analyze_AAAA;
bool resolveIPv6;
Expand Down
5 changes: 0 additions & 5 deletions src/database/database-thread.c
Expand Up @@ -84,11 +84,6 @@ void *DB_thread(void *val)
if(get_and_clear_event(RELOAD_PRIVACY_LEVEL))
get_privacy_level(NULL);

// Try to resolve host names from clients in the network table
// which have empty/undefined host names
if(get_and_clear_event(RERESOLVE_DATABASE_NAMES))
resolveNetworkTableNames();

// Import alias-clients
if(get_and_clear_event(REIMPORT_ALIASCLIENTS))
{
Expand Down
156 changes: 13 additions & 143 deletions src/database/network-table.c
Expand Up @@ -19,7 +19,6 @@
#include "../timers.h"
// struct config
#include "../config.h"
//#include "../datastructure.h"
// resolveHostname()
#include "../resolve.h"

Expand Down Expand Up @@ -1161,17 +1160,7 @@ void parse_neighbor_cache(void)
// only the changed to the database are collected for latter
// commitment. Read-only access such as this SELECT command will be
// executed immediately on the database.
char *querystr = NULL;
rc = asprintf(&querystr, "SELECT id FROM network WHERE hwaddr = \'%s\';", hwaddr);
if(querystr == NULL || rc < 0)
{
logg("Memory allocation failed in parse_arp_cache(): %i", rc);
break;
}

// Perform SQL query
int dbID = db_query_int(querystr);
free(querystr);
int dbID = find_device_by_hwaddr(hwaddr);

if(dbID == DB_FAILED)
{
Expand Down Expand Up @@ -1393,19 +1382,19 @@ bool unify_hwaddr(void)

// Update firstSeen with lowest value across all rows with the same hwaddr
dbquery("UPDATE network "\
"SET firstSeen = (SELECT MIN(firstSeen) FROM network WHERE hwaddr = \'%s\') "\
"SET firstSeen = (SELECT MIN(firstSeen) FROM network WHERE hwaddr = \'%s\' COLLATE NOCASE) "\
"WHERE id = %i;",\
hwaddr, id);

// Update numQueries with sum of all rows with the same hwaddr
dbquery("UPDATE network "\
"SET numQueries = (SELECT SUM(numQueries) FROM network WHERE hwaddr = \'%s\') "\
"SET numQueries = (SELECT SUM(numQueries) FROM network WHERE hwaddr = \'%s\' COLLATE NOCASE) "\
"WHERE id = %i;",\
hwaddr, id);

// Remove all other lines with the same hwaddr but a different id
dbquery("DELETE FROM network "\
"WHERE hwaddr = \'%s\' "\
"WHERE hwaddr = \'%s\' COLLATE NOCASE "\
"AND id != %i;",\
hwaddr, id);

Expand Down Expand Up @@ -1695,6 +1684,15 @@ char *__attribute__((malloc)) getNameFromIP(const char *ipaddr)
return NULL;
}

// Check if we want to resolve host names
if(!resolve_this_name(ipaddr))
{
if(config.debug & DEBUG_DATABASE)
logg("getNameFromIP(\"%s\") - configured to not resolve host name", ipaddr);

return NULL;
}

// Check for a host name associated with the same IP address
sqlite3_stmt *stmt = NULL;
const char *querystr = "SELECT name FROM network_addresses WHERE name IS NOT NULL AND ip = ?;";
Expand Down Expand Up @@ -1848,131 +1846,3 @@ char *__attribute__((malloc)) getIfaceFromIP(const char *ipaddr)

return iface;
}

// Resolve unknown names of recently seen IP addresses in network table
void resolveNetworkTableNames(void)
{
if(!FTL_DB_avail())
{
logg("resolveNetworkTableNames() - Database not available");
return;
}

const char sql[] = "BEGIN TRANSACTION IMMEDIATE";
int rc = dbquery(sql);
if( rc != SQLITE_OK )
{
const char *text;
if( rc == SQLITE_BUSY )
{
text = "WARNING";
}
else
{
text = "ERROR";
}

// dbquery() above already logs the reson for why the query failed
logg("%s: Trying to resolve unknown network table host names (\"%s\") failed", text, sql);

return;
}

// Get IP addresses seen within the last 24 hours with empty or NULL host names
const char querystr[] = "SELECT ip FROM network_addresses "
"WHERE lastSeen > cast(strftime('%%s', 'now') as int)-86400;";

// Prepare query
sqlite3_stmt *table_stmt = NULL;
rc = sqlite3_prepare_v2(FTL_db, querystr, -1, &table_stmt, NULL);
if(rc != SQLITE_OK)
{
logg("resolveNetworkTableNames() - SQL error prepare: %s",
sqlite3_errstr(rc));
sqlite3_finalize(table_stmt);
return;
}

// Get data
while((rc = sqlite3_step(table_stmt)) == SQLITE_ROW)
{
// Get IP address from database
const char *ip = (const char*)sqlite3_column_text(table_stmt, 0);

if(config.debug & DEBUG_DATABASE)
logg("Resolving database IP %s", ip);

// Try to obtain host name
char *newname = resolveHostname(ip);

if(config.debug & DEBUG_DATABASE)
logg("---> \"%s\"", newname);

// Store new host name in database if not empty
if(newname != NULL && strlen(newname) > 0)
{
const char updatestr[] = "UPDATE network_addresses "
"SET name = ?1,"
"nameUpdated = cast(strftime('%s', 'now') as int) "
"WHERE ip = ?2;";
sqlite3_stmt *update_stmt = NULL;
int rc2 = sqlite3_prepare_v2(FTL_db, updatestr, -1, &update_stmt, NULL);
if(rc2 != SQLITE_OK){
logg("resolveNetworkTableNames(%s -> \"%s\") - SQL error prepare: %s",
ip, newname, sqlite3_errstr(rc2));
sqlite3_finalize(update_stmt);
break;
}

// Bind newname to prepared statement
if((rc2 = sqlite3_bind_text(update_stmt, 1, newname, -1, SQLITE_STATIC)) != SQLITE_OK)
{
logg("resolveNetworkTableNames(%s -> \"%s\"): Failed to bind newname: %s",
ip, newname, sqlite3_errstr(rc2));
sqlite3_finalize(update_stmt);
break;
}

// Bind ip to prepared statement
if((rc2 = sqlite3_bind_text(update_stmt, 2, ip, -1, SQLITE_STATIC)) != SQLITE_OK)
{
logg("resolveNetworkTableNames(%s -> \"%s\"): Failed to bind ip: %s",
ip, newname, sqlite3_errstr(rc2));
sqlite3_finalize(update_stmt);
break;
}

if(config.debug & DEBUG_DATABASE)
logg("dbquery: \"%s\" with ?1 = \"%s\" and ?2 = \"%s\"", updatestr, newname, ip);

rc2 = sqlite3_step(update_stmt);
if(rc2 != SQLITE_BUSY && rc2 != SQLITE_DONE)
{
// Any return code that is neither SQLITE_BUSY not SQLITE_ROW
// is a real error we should log
logg("resolveNetworkTableNames(%s -> \"%s\"): Failed to perform step: %s",
ip, newname, sqlite3_errstr(rc2));
sqlite3_finalize(update_stmt);
break;
}

// Finalize host name update statement
sqlite3_finalize(update_stmt);
}
free(newname);
}

// Possible error handling and reporting
if(rc != SQLITE_DONE)
{
logg("resolveNetworkTableNames() - SQL error step: %s",
sqlite3_errstr(rc));
sqlite3_finalize(table_stmt);
return;
}

// Close and unlock database connection
sqlite3_finalize(table_stmt);

dbquery("COMMIT");
}
9 changes: 6 additions & 3 deletions src/database/query-table.c
Expand Up @@ -523,10 +523,13 @@ void DB_read_queries(void)
overTime[timeidx].cached++;
break;

case QUERY_RETRIED: // Retried query
case QUERY_RETRIED_DNSSEC: // fall through
// Nothing to be done here
break;

default:
logg("Error: Found unknown status %i in long term database!", status);
logg(" Timestamp: %lli", (long long)queryTimeStamp);
logg(" Continuing anyway...");
logg("Warning: Found unknown status %i in long term database!", status);
break;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/datastructure.h
Expand Up @@ -16,7 +16,7 @@
// enum privacy_level
#include "enums.h"

const char *querytypes[TYPE_MAX];
extern const char *querytypes[TYPE_MAX];

typedef struct {
unsigned char magic;
Expand Down
4 changes: 2 additions & 2 deletions src/dnsmasq_interface.c
Expand Up @@ -551,12 +551,12 @@ bool _FTL_new_query(const unsigned int flags, const char *name,
// 127.0.0.1 to avoid queries originating from localhost of the
// *distant* machine as queries coming from the *local* machine
const sa_family_t family = (flags & F_IPV4) ? AF_INET : AF_INET6;
char clientIP[ADDRSTRLEN] = { 0 };
char clientIP[ADDRSTRLEN+1] = { 0 };
if(config.edns0_ecs && edns->client_set)
{
// Use ECS provided client
strncpy(clientIP, edns->client, ADDRSTRLEN);
clientIP[ADDRSTRLEN-1] = '\0';
clientIP[ADDRSTRLEN] = '\0';
}
else
{
Expand Down
7 changes: 6 additions & 1 deletion src/enums.h
Expand Up @@ -147,8 +147,13 @@ enum events {
RERESOLVE_HOSTNAMES,
REIMPORT_ALIASCLIENTS,
PARSE_NEIGHBOR_CACHE,
RERESOLVE_DATABASE_NAMES,
EVENTS_MAX
} __attribute__ ((packed));

enum refresh_hostnames {
REFRESH_ALL,
REFRESH_IPV4_ONLY,
REFRESH_NONE
} __attribute__ ((packed));

#endif // ENUMS_H
2 changes: 0 additions & 2 deletions src/events.c
Expand Up @@ -96,8 +96,6 @@ static const char *eventtext(const enum events event)
return "REIMPORT_ALIASCLIENTS";
case PARSE_NEIGHBOR_CACHE:
return "PARSE_NEIGHBOR_CACHE";
case RERESOLVE_DATABASE_NAMES:
return "RERESOLVE_DATABASE_NAMES";
case EVENTS_MAX: // fall through
default:
return "UNKNOWN";
Expand Down

0 comments on commit 0790cf7

Please sign in to comment.