mirror of
https://github.com/pi-hole/FTL.git
synced 2026-07-07 11:35:10 +01:00
48fc06d46b
Signed-off-by: DL6ER <dl6er@dl6er.de>
266 lines
6.5 KiB
C
266 lines
6.5 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
|
|
* Config 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"
|
|
#include "toml_reader.h"
|
|
#include "setupVars.h"
|
|
#include "log.h"
|
|
// getprio(), setprio()
|
|
#include <sys/resource.h>
|
|
// argv_dnsmasq
|
|
#include "args.h"
|
|
// INT_MAX
|
|
#include <limits.h>
|
|
|
|
#include "../datastructure.h"
|
|
// openFTLtoml()
|
|
#include "toml_helper.h"
|
|
|
|
// Private prototypes
|
|
static toml_table_t *parseTOML(void);
|
|
static void reportDebugConfig(void);
|
|
|
|
bool readFTLtoml(struct config *conf, toml_table_t *toml, const bool verbose)
|
|
{
|
|
// Parse lines in the config file if we did not receive a pointer to a TOML
|
|
// table (e.g. from an imported Teleporter file)
|
|
bool external = true;
|
|
if(toml == NULL)
|
|
{
|
|
external = false;
|
|
toml = parseTOML();
|
|
if(!toml)
|
|
return false;
|
|
|
|
// Initialize config with default values
|
|
initConfig(conf);
|
|
}
|
|
|
|
// Try to read debug config. This is done before the full config
|
|
// parsing to allow for debug output further down
|
|
toml_table_t *conf_debug = toml_table_in(toml, "debug");
|
|
if(conf_debug)
|
|
readTOMLvalue(&config.debug.config, "config", conf_debug);
|
|
set_debug_flags();
|
|
|
|
log_debug(DEBUG_CONFIG, "Reading %s TOML config file: full config",
|
|
external ? "external" : "default");
|
|
|
|
// Read all known config items
|
|
for(unsigned int i = 0; i < CONFIG_ELEMENTS; i++)
|
|
{
|
|
// Get pointer to memory location of this conf_item
|
|
struct conf_item *conf_item = get_conf_item(conf, i);
|
|
|
|
// Get config path depth
|
|
unsigned int level = config_path_depth(conf_item->p);
|
|
|
|
// Parse tree of properties
|
|
bool item_available = true;
|
|
toml_table_t *table[MAX_CONFIG_PATH_DEPTH] = { 0 };
|
|
for(unsigned int j = 0; j < level-1; j++)
|
|
{
|
|
// Get table at this level
|
|
table[j] = toml_table_in(j > 0 ? table[j-1] : toml, conf_item->p[j]);
|
|
if(!table[j])
|
|
{
|
|
log_debug(DEBUG_CONFIG, "%s DOES NOT EXIST", conf_item->k);
|
|
item_available = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Skip this config item if it does not exist
|
|
if(!item_available)
|
|
continue;
|
|
|
|
// Try to parse config item
|
|
readTOMLvalue(conf_item, conf_item->p[level-1], table[level-2]);
|
|
}
|
|
|
|
// Report debug config if enabled
|
|
set_debug_flags();
|
|
if(verbose)
|
|
reportDebugConfig();
|
|
|
|
// Free memory allocated by the TOML parser and return success
|
|
toml_free(toml);
|
|
return true;
|
|
}
|
|
|
|
// Parse TOML config file
|
|
static toml_table_t *parseTOML(void)
|
|
{
|
|
// Try to open default config file. Use fallback if not found
|
|
FILE *fp;
|
|
if((fp = openFTLtoml("r")) == NULL)
|
|
{
|
|
log_warn("No config file available (%s), using defaults",
|
|
strerror(errno));
|
|
return NULL;
|
|
}
|
|
|
|
// Parse lines in the config file
|
|
char errbuf[200];
|
|
toml_table_t *conf = toml_parse_file(fp, errbuf, sizeof(errbuf));
|
|
|
|
// Close file and release exclusive lock
|
|
closeFTLtoml(fp);
|
|
|
|
// Check for errors
|
|
if(conf == NULL)
|
|
{
|
|
log_err("Cannot parse config file: %s", errbuf);
|
|
return NULL;
|
|
}
|
|
|
|
log_debug(DEBUG_CONFIG, "TOML file parsing: OK");
|
|
return conf;
|
|
}
|
|
|
|
bool getPrivacyLevel(void)
|
|
{
|
|
log_debug(DEBUG_CONFIG, "Reading TOML config file: privacy level");
|
|
|
|
// Parse config file
|
|
toml_table_t *conf = parseTOML();
|
|
if(!conf)
|
|
return false;
|
|
|
|
// Get [misc]
|
|
toml_table_t *misc = toml_table_in(conf, "misc");
|
|
if(!misc)
|
|
{
|
|
log_debug(DEBUG_CONFIG, "misc does not exist");
|
|
toml_free(conf);
|
|
return false;
|
|
}
|
|
|
|
// Get misc.privacyLevel
|
|
toml_datum_t privacylevel = toml_int_in(misc, "privacylevel");
|
|
if(!privacylevel.ok)
|
|
{
|
|
log_debug(DEBUG_CONFIG, "misc.privacylevel does not exist");
|
|
toml_free(conf);
|
|
return false;
|
|
}
|
|
|
|
// Check if privacy level is valid
|
|
if(privacylevel.u.i >= PRIVACY_SHOW_ALL && privacylevel.u.i <= PRIVACY_MAXIMUM)
|
|
config.misc.privacylevel.v.privacy_level = privacylevel.u.i;
|
|
else
|
|
log_warn("Invalid setting for misc.privacylevel, should be an integer between %d and %d",
|
|
PRIVACY_SHOW_ALL, PRIVACY_MAXIMUM);
|
|
|
|
toml_free(conf);
|
|
return true;
|
|
}
|
|
|
|
bool getBlockingMode(void)
|
|
{
|
|
log_debug(DEBUG_CONFIG, "Reading TOML config file: DNS blocking mode");
|
|
|
|
// Parse config file
|
|
toml_table_t *conf = parseTOML();
|
|
if(!conf)
|
|
return false;
|
|
|
|
// Get [dns]
|
|
toml_table_t *dns = toml_table_in(conf, "dns");
|
|
if(!dns)
|
|
{
|
|
log_debug(DEBUG_CONFIG, "dns does not exist");
|
|
toml_free(conf);
|
|
return false;
|
|
}
|
|
|
|
// Get dns.blocking mode
|
|
toml_datum_t blockingmode = toml_string_in(dns, "blockingmode");
|
|
if(!blockingmode.ok)
|
|
{
|
|
log_debug(DEBUG_CONFIG, "dns.blockingmode DOES NOT EXIST");
|
|
toml_free(conf);
|
|
return false;
|
|
}
|
|
|
|
// Iterate over possible blocking modes and check if it applies
|
|
const int blocking_mode = get_blocking_mode_val(blockingmode.u.s);
|
|
if(blocking_mode != -1)
|
|
config.dns.blocking.mode.v.blocking_mode = blocking_mode;
|
|
else
|
|
log_warn("Config setting %s is invalid, allowed options are: %s",
|
|
config.dns.blocking.mode.k, config.dns.blocking.mode.h);
|
|
free(blockingmode.u.s);
|
|
|
|
// Free memory and return success
|
|
toml_free(conf);
|
|
return true;
|
|
}
|
|
|
|
bool getLogFilePathTOML(void)
|
|
{
|
|
log_debug(DEBUG_CONFIG, "Reading TOML config file: log file path");
|
|
|
|
toml_table_t *conf = parseTOML();
|
|
if(!conf)
|
|
return false;
|
|
|
|
toml_table_t *files = toml_table_in(conf, "files");
|
|
if(!files)
|
|
{
|
|
log_debug(DEBUG_CONFIG, "files does not exist");
|
|
toml_free(conf);
|
|
return false;
|
|
}
|
|
|
|
toml_datum_t log = toml_string_in(files, "log");
|
|
if(!log.ok)
|
|
{
|
|
log_debug(DEBUG_CONFIG, "files.log DOES NOT EXIST");
|
|
toml_free(conf);
|
|
return false;
|
|
}
|
|
|
|
// Only replace string when it is different
|
|
if(strcmp(config.files.log.ftl.v.s,log.u.s) != 0)
|
|
{
|
|
config.files.log.ftl.t = CONF_STRING_ALLOCATED;
|
|
config.files.log.ftl.v.s = log.u.s; // Allocated string
|
|
}
|
|
else
|
|
free(log.u.s);
|
|
|
|
toml_free(conf);
|
|
return true;
|
|
}
|
|
|
|
static void reportDebugConfig(void)
|
|
{
|
|
// Print debug settings
|
|
log_debug(DEBUG_ANY, "************************");
|
|
log_debug(DEBUG_ANY, "* DEBUG SETTINGS *");
|
|
|
|
// Read all known debug config items
|
|
for(unsigned int debug_flag = 1; debug_flag < DEBUG_ELEMENTS; debug_flag++)
|
|
{
|
|
const char *name;
|
|
// Get name of debug flag
|
|
// We do not need to add an offset as this loop starts counting
|
|
// at 1
|
|
debugstr(debug_flag, &name);
|
|
// Calculate number of spaces to nicely align output
|
|
unsigned int spaces = 20 - strlen(name);
|
|
// Print debug flag
|
|
// We skip the first 6 characters of the flags as they are always "DEBUG_"
|
|
log_debug(DEBUG_ANY, "* %s:%*s %s *", name+6, spaces, "", debug_flags[debug_flag] ? "YES" : "NO ");
|
|
}
|
|
log_debug(DEBUG_ANY, "************************");
|
|
}
|