Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade embedded dnsmasq to v2.80 #401

Merged
merged 44 commits into from
Nov 21, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
b7b038b
Upgrade internal dnsmasq from v2.79 to v2.80
DL6ER Oct 22, 2018
2a50ee2
Add new dnsmasq objects to tree
DL6ER Oct 22, 2018
d8820fb
Declare insert_error static (we don't access it from dnsmasq_interfac…
DL6ER Oct 22, 2018
3bcd059
Correct struct in6_addr pointer/variables
DL6ER Oct 25, 2018
da1e772
Merge branch 'development' into dnsmasq/v2.80
DL6ER Oct 27, 2018
98e191b
Reduce code duplication
DL6ER Nov 4, 2018
cbb7525
Merge branch 'development' into dnsmasq/v2.80
DL6ER Nov 4, 2018
f0a942b
Evaluate detect_blocked_IP() if not already marked as externally bloc…
DL6ER Nov 4, 2018
980729d
Modify the correct corresponding counters for user-defined dnsmasq co…
DL6ER Nov 4, 2018
b9e178c
Merge pull request #411 from pi-hole/fix/user-wildcards
AzureMarker Nov 4, 2018
90f6aea
Merge pull request #412 from pi-hole/release/4.1
DL6ER Nov 5, 2018
8fecafa
Fix usage of wrong callback when a A, AAAA or ANY is returning the NU…
DL6ER Nov 5, 2018
92bb389
Fix interchanged indices in dnsmasq.h. This bug resulted in sometimes…
DL6ER Nov 5, 2018
85dbd3b
Merge branch 'fix/record_source' into dnsmasq/v2.80
DL6ER Nov 5, 2018
e744e08
Merge pull request #413 from pi-hole/fix/record_source
AzureMarker Nov 5, 2018
7fc77c6
Search for readable config file in alternative location in case the d…
DL6ER Nov 7, 2018
d104d6b
Make log file path customizable
DL6ER Nov 7, 2018
c747023
Make PID file path customizable
DL6ER Nov 7, 2018
e68d82d
Add standardized subroutine for reading file path locations as this c…
DL6ER Nov 7, 2018
4240373
Make PORTFILE customizable
DL6ER Nov 7, 2018
f5d8adf
Make SOCKETFILE customizable
DL6ER Nov 7, 2018
32498b5
Remove files.log. It is not used anymore and a relict from pre-v4.0 t…
DL6ER Nov 7, 2018
ce95d08
Remove hard-coded location of preEventHorizon and 01-pihole.conf. The…
DL6ER Nov 7, 2018
ce10699
Use new customizable paths for Travis' tests. Fallback to searching f…
DL6ER Nov 7, 2018
2f8a67f
Make WHITELISTFILE customizable
DL6ER Nov 7, 2018
0a51cfa
Make BLACKLISTFILE customizable
DL6ER Nov 7, 2018
ee6cf89
Make GRAVITYFILE customizable
DL6ER Nov 7, 2018
5e17439
Make REGEXLISTFILE customizable
DL6ER Nov 7, 2018
f7a5ef0
Make SETUPVARSFILE customizable
DL6ER Nov 7, 2018
109861f
Make AUDITLISTFILE customizable
DL6ER Nov 7, 2018
ac3a8ab
Fix incorrect standard log path
DL6ER Nov 7, 2018
46771ff
Improve check in getLogFilePath()
DL6ER Nov 7, 2018
eeae592
Ensure regex validation is working as expected if privacylevel > 0. T…
DL6ER Nov 9, 2018
68181fb
Ensure privacy level can only be increased from starting pihole-FTL o…
DL6ER Nov 9, 2018
41e9a8a
Don't warn if privacy level is reduced. This generates too much outpu…
DL6ER Nov 9, 2018
8de3079
Review comments
DL6ER Nov 10, 2018
ece52c2
Rename conf2 to snapConf
DL6ER Nov 10, 2018
fa39906
Simplify two if expressions using De Morgan's Law
DL6ER Nov 10, 2018
efa86f9
Add documentation for getpath(...)
DL6ER Nov 10, 2018
ebbb3e4
Reimplement skipping of "0.0.0.0" in Top Client output
DL6ER Nov 10, 2018
2e25dda
Merge pull request #417 from pi-hole/fix/privacy_levels_regex_filtering
DL6ER Nov 10, 2018
f9ef0d7
Check return value of sscanf() explicitly (if one element was sucessf…
DL6ER Nov 10, 2018
39d47f0
Merge pull request #416 from pi-hole/new/adjustable_file_locations
DL6ER Nov 10, 2018
99d0927
Merge branch 'release/4.1' into dnsmasq/v2.80
DL6ER Nov 10, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 17 additions & 15 deletions FTL.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,26 +90,28 @@ enum { MODE_IP, MODE_NX, MODE_NULL, MODE_IP_NODATA_AAAA };
enum { REGEX_UNKNOWN, REGEX_BLOCKED, REGEX_NOTBLOCKED };
enum { BLOCKING_DISABLED, BLOCKING_ENABLED, BLOCKING_UNKNOWN };

// Privacy mode constants
#define HIDDEN_DOMAIN "hidden"
#define HIDDEN_CLIENT "0.0.0.0"

// Static structs
typedef struct {
const char* conf;
const char* log;
const char* pid;
const char* port;
const char* snapConf;
char* log;
char* pid;
char* port;
char* db;
const char* socketfile;
char* socketfile;
} FTLFileNamesStruct;

typedef struct {
const char* log;
const char* preEventHorizon;
const char* whitelist;
const char* blacklist;
const char* gravity;
const char* regexlist;
const char* setupVars;
const char* auditlist;
const char* dnsmasqconfig;
char* whitelist;
char* blacklist;
char* gravity;
char* regexlist;
char* setupVars;
char* auditlist;
} logFileNamesStruct;

typedef struct {
Expand Down Expand Up @@ -146,7 +148,7 @@ typedef struct {
int DBinterval;
int port;
int maxlogage;
int privacylevel;
unsigned char privacylevel;
bool ignore_localhost;
unsigned char blockingmode;
bool regex_debugmode;
Expand All @@ -167,7 +169,7 @@ typedef struct {
bool db;
int id; // the ID is a (signed) int in dnsmasq, so no need for a long int here
bool complete;
bool private;
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;
Expand Down
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@
# This file is copyright under the latest version of the EUPL.
# Please see LICENSE file for your rights under this license.

DNSMASQVERSION = "pi-hole-2.79"
DNSMASQVERSION = "pi-hole-2.80"
DNSMASQOPTS = -DHAVE_DNSSEC -DHAVE_DNSSEC_STATIC
# Flags for compiling with libidn : -DHAVE_IDN
# Flags for compiling with libidn2: -DHAVE_LIBIDN2 -DIDN2_VERSION_NUMBER=0x02000003

FTLDEPS = FTL.h routines.h version.h api.h dnsmasq_interface.h
FTLOBJ = main.o memory.o log.o daemon.o datastructure.o signals.o socket.o request.o grep.o setupVars.o args.o threads.o gc.o config.o database.o msgpack.o api.o dnsmasq_interface.o resolve.o regex.o

DNSMASQDEPS = config.h dhcp-protocol.h dns-protocol.h radv-protocol.h dhcp6-protocol.h dnsmasq.h ip6addr.h
DNSMASQOBJ = arp.o dbus.o domain.o lease.o outpacket.o rrfilter.o auth.o dhcp6.o edns0.o log.o poll.o slaac.o blockdata.o dhcp.o forward.o loop.o radv.o tables.o bpf.o dhcp-common.o helper.o netlink.o rfc1035.o tftp.o cache.o dnsmasq.o inotify.o network.o rfc2131.o util.o conntrack.o dnssec.o ipset.o option.o rfc3315.o crypto.o
DNSMASQDEPS = config.h dhcp-protocol.h dns-protocol.h radv-protocol.h dhcp6-protocol.h dnsmasq.h ip6addr.h metrics.h
DNSMASQOBJ = arp.o dbus.o domain.o lease.o outpacket.o rrfilter.o auth.o dhcp6.o edns0.o log.o poll.o slaac.o blockdata.o dhcp.o forward.o loop.o radv.o tables.o bpf.o dhcp-common.o helper.o netlink.o rfc1035.o tftp.o cache.o dnsmasq.o inotify.o network.o rfc2131.o util.o conntrack.o dnssec.o ipset.o option.o rfc3315.o crypto.o dump.o ubus.o metrics.o

# Get git commit version and date
GIT_BRANCH := $(shell git branch | sed -n 's/^\* //p')
Expand Down
30 changes: 17 additions & 13 deletions api.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ void getStats(int *sock)
// Send individual reply type counters
ssend(*sock, "reply_NODATA %i\nreply_NXDOMAIN %i\nreply_CNAME %i\nreply_IP %i\n",
counters.reply_NODATA, counters.reply_NXDOMAIN, counters.reply_CNAME, counters.reply_IP);
ssend(*sock, "privacy_level %i\n", config.privacylevel);
}
else
{
Expand Down Expand Up @@ -264,7 +265,7 @@ void getTopDomains(char *client_message, int *sock)
continue;

// Hidden domain, probably due to privacy level. Skip this in the top lists
if(strcmp(domains[j].domain, "hidden") == 0)
if(strcmp(domains[j].domain, HIDDEN_DOMAIN) == 0)
continue;

if(blocked && showblocked && domains[j].blockedcount > 0)
Expand Down Expand Up @@ -403,7 +404,7 @@ void getTopClients(char *client_message, int *sock)
continue;

// Hidden client, probably due to privacy level. Skip this in the top lists
if(strcmp(clients[j].ip, "0.0.0.0") == 0)
if(strcmp(clients[j].ip, HIDDEN_CLIENT) == 0)
continue;

// Only return name if available
Expand Down Expand Up @@ -760,7 +761,7 @@ void getAllQueries(char *client_message, int *sock)
{
validate_access("queries", i, true, __LINE__, __FUNCTION__, __FILE__);
// Check if this query has been create while in maximum privacy mode
if(queries[i].private) continue;
if(queries[i].privacylevel >= PRIVACY_MAXIMUM) continue;

validate_access("domains", queries[i].domainID, true, __LINE__, __FUNCTION__, __FILE__);
validate_access("clients", queries[i].clientID, true, __LINE__, __FUNCTION__, __FILE__);
Expand Down Expand Up @@ -808,13 +809,17 @@ void getAllQueries(char *client_message, int *sock)
continue;
}

char *domain = domains[queries[i].domainID].domain;
// Ask subroutine for domain. It may return "hidden" depending on
// the privacy settings at the time the query was made
char *domain = getDomainString(i);
// Similarly for the client
char *client;
if(clients[queries[i].clientID].name != NULL &&
strlen(clients[queries[i].clientID].name) > 0)
strlen(clients[queries[i].clientID].name) > 0 &&
queries[i].privacylevel < PRIVACY_HIDE_DOMAINS_CLIENTS)
client = clients[queries[i].clientID].name;
else
client = clients[queries[i].clientID].ip;
client = getClientIPString(i);

unsigned long delay = queries[i].response;
// Check if received (delay should be smaller than 30min)
Expand Down Expand Up @@ -857,11 +862,6 @@ void getRecentBlocked(char *client_message, int *sock)
{
int i, num=1;

// Exit before processing any data if requested via config setting
get_privacy_level(NULL);
if(config.privacylevel >= PRIVACY_HIDE_DOMAINS)
return;

// Test for integer that specifies number of entries to be shown
if(sscanf(client_message, "%*[^(](%i)", &num) > 0) {
// User wants a different number of requests
Expand All @@ -881,9 +881,13 @@ void getRecentBlocked(char *client_message, int *sock)
{
found++;

// Ask subroutine for domain. It may return "hidden" depending on
// the privacy settings at the time the query was made
char *domain = getDomainString(i);

if(istelnet[*sock])
ssend(*sock,"%s\n", domains[queries[i].domainID].domain);
else if(!pack_str32(*sock, domains[queries[i].domainID].domain))
ssend(*sock,"%s\n", domain);
else if(!pack_str32(*sock, domain))
return;
}

Expand Down
5 changes: 0 additions & 5 deletions args.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,6 @@ void parse_args(int argc, char* argv[])
if(strcmp(argv[i], "travis-ci") == 0)
{
travis = true;
FTLfiles.log = "pihole-FTL.log";
// FTLfiles.db will be set to "pihole-FTL.db" via config file on Travis
FTLfiles.conf = "pihole-FTL.conf";
FTLfiles.socketfile = "pihole-FTL.sock";
files.log = "pihole.log";
ok = true;
}

Expand Down
116 changes: 111 additions & 5 deletions config.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,60 @@
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);

char *conflinebuffer = NULL;

void getLogFilePath(void)
{
FILE *fp;
char * buffer;

// Try to open default config file. Use fallback if not found
if( ((fp = fopen(FTLfiles.conf, "r")) == NULL) &&
((fp = fopen(FTLfiles.snapConf, "r")) == NULL) &&
((fp = fopen("pihole-FTL.conf", "r")) == NULL))
{
printf("Notice: Found no readable FTL config file");
}

// Read LOGFILE value if available
// defaults to: "/var/log/pihole-FTL.log"
buffer = parse_FTLconf(fp, "LOGFILE");

errno = 0;
// Use sscanf() to obtain filename from config file parameter only if buffer != NULL
if(buffer == NULL || sscanf(buffer, "%127ms", &FTLfiles.log) != 1)
{
// Use standard path if no custom path was obtained from the config file
FTLfiles.log = strdup("/var/log/pihole-FTL.log");
}

// Test if memory allocation was successful
if(FTLfiles.log == NULL)
{
printf("FATAL: Allocating memory for FTLfiles.log failed (%s, %i). Exiting.",
strerror(errno), errno);
exit(EXIT_FAILURE);
}
else if(strlen(FTLfiles.log) == 0)
{
printf("Fatal: Log file location cannot be empty");
exit(EXIT_FAILURE);
}
else
logg("Using log file %s", FTLfiles.log);
}

void read_FTLconf(void)
{
FILE *fp;
char * buffer;

if((fp = fopen(FTLfiles.conf, "r")) == NULL)
// Try to open default config file. Use fallback if not found
if( ((fp = fopen(FTLfiles.conf, "r")) == NULL) &&
((fp = fopen(FTLfiles.snapConf, "r")) == NULL) &&
((fp = fopen("pihole-FTL.conf", "r")) == NULL))
{
logg("Notice: Found no readable FTL config file");
logg(" Using default settings");
Expand Down Expand Up @@ -244,6 +289,33 @@ void read_FTLconf(void)
else
logg(" DBIMPORT: Not importing history from database");

// PIDFILE
getpath(fp, "PIDFILE", "/var/run/pihole-FTL.pid", &FTLfiles.pid);

// PORTFILE
getpath(fp, "PORTFILE", "/var/run/pihole-FTL.port", &FTLfiles.port);

// SOCKETFILE
getpath(fp, "SOCKETFILE", "/var/run/pihole/FTL.sock", &FTLfiles.socketfile);

// WHITELISTFILE
getpath(fp, "WHITELISTFILE", "/etc/pihole/whitelist.txt", &files.whitelist);

// BLACKLISTFILE
getpath(fp, "BLACKLISTFILE", "/etc/pihole/blacklist.txt", &files.blacklist);

// GRAVITYFILE
getpath(fp, "GRAVITYFILE", "/etc/pihole/gravity.list", &files.gravity);

// REGEXLISTFILE
getpath(fp, "REGEXLISTFILE", "/etc/pihole/regex.list", &files.regexlist);

// SETUPVARSFILE
getpath(fp, "SETUPVARSFILE", "/etc/pihole/setupVars.conf", &files.setupVars);

// AUDITLISTFILE
getpath(fp, "AUDITLISTFILE", "/etc/pihole/auditlog.list", &files.auditlist);

logg("Finished config file parsing");

// Release memory
Expand All @@ -253,6 +325,40 @@ void read_FTLconf(void)
fclose(fp);
}

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
// option: Option string ("key") to try to read
// defaultloc: Value used if key is not found in file
// pointer: Location where read (or default) parameter is stored
char *buffer = parse_FTLconf(fp, "PIDFILE");

errno = 0;
// Use sscanf() to obtain filename from config file parameter only if buffer != NULL
if(buffer == NULL || sscanf(buffer, "%127ms", pointer) != 1)
{
// Use standard path if no custom path was obtained from the config file
*pointer = strdup(defaultloc);
}

// Test if memory allocation was successful
if(*pointer == NULL)
{
logg("FATAL: Allocating memory for %s failed (%s, %i). Exiting.", option, strerror(errno), errno);
exit(EXIT_FAILURE);
}
else if(strlen(*pointer) == 0)
{
logg(" %s: Empty file name is not possible!", option);
exit(EXIT_FAILURE);
}
else
{
logg(" %s: Using %s", option, *pointer);
}
}

static char *parse_FTLconf(FILE *fp, const char * key)
{
// Return NULL if fp is an invalid file pointer
Expand Down Expand Up @@ -326,11 +432,11 @@ void get_privacy_level(FILE *fp)
if(buffer != NULL && sscanf(buffer, "%i", &value) == 1)
{
// Check for change and validity of privacy level (set in FTL.h)
if(value != config.privacylevel &&
value >= PRIVACY_SHOW_ALL &&
value <= PRIVACY_NOSTATS)
if(value >= PRIVACY_SHOW_ALL &&
value <= PRIVACY_NOSTATS &&
value > config.privacylevel)
{
logg("Notice: Changing privacy level from %i to %i", config.privacylevel, value);
logg("Notice: Increasing privacy level from %i to %i", config.privacylevel, value);
config.privacylevel = value;
}
}
Expand Down
10 changes: 5 additions & 5 deletions database.c
Original file line number Diff line number Diff line change
Expand Up @@ -393,10 +393,8 @@ void save_to_DB(void)

// Memory checks
validate_access("queries", i, true, __LINE__, __FUNCTION__, __FILE__);
validate_access("domains", queries[i].domainID, true, __LINE__, __FUNCTION__, __FILE__);
validate_access("clients", queries[i].clientID, true, __LINE__, __FUNCTION__, __FILE__);

if(queries[i].private)
if(queries[i].privacylevel >= PRIVACY_MAXIMUM)
{
// Skip, we never store nor count queries recorded
// while have been in maximum privacy mode in the database
Expand All @@ -413,10 +411,12 @@ void save_to_DB(void)
sqlite3_bind_int(stmt, 3, queries[i].status);

// DOMAIN
sqlite3_bind_text(stmt, 4, domains[queries[i].domainID].domain, -1, SQLITE_TRANSIENT);
char *domain = getDomainString(i);
sqlite3_bind_text(stmt, 4, domain, -1, SQLITE_TRANSIENT);

// CLIENT
sqlite3_bind_text(stmt, 5, clients[queries[i].clientID].ip, -1, SQLITE_TRANSIENT);
char *client = getClientIPString(i);
sqlite3_bind_text(stmt, 5, client, -1, SQLITE_TRANSIENT);

// FORWARD
if(queries[i].status == QUERY_FORWARDED && queries[i].forwardID > -1)
Expand Down
26 changes: 26 additions & 0 deletions datastructure.c
Original file line number Diff line number Diff line change
Expand Up @@ -234,3 +234,29 @@ 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
char *getDomainString(int queryID)
{
if(queries[queryID].privacylevel < PRIVACY_HIDE_DOMAINS)
{
validate_access("domains", queries[queryID].domainID, true, __LINE__, __FUNCTION__, __FILE__);
return domains[queries[queryID].domainID].domain;
}
else
return HIDDEN_DOMAIN;
}

// Privacy-level sensitive subroutine that returns the client IP
// only when appropriate for the requested query
char *getClientIPString(int queryID)
{
if(queries[queryID].privacylevel < PRIVACY_HIDE_DOMAINS_CLIENTS)
{
validate_access("clients", queries[queryID].clientID, true, __LINE__, __FUNCTION__, __FILE__);
return clients[queries[queryID].clientID].ip;
}
else
return HIDDEN_CLIENT;
}
Loading