Skip to content

Commit

Permalink
Merge branch 'development-v6' into new/validator
Browse files Browse the repository at this point in the history
Signed-off-by: DL6ER <[email protected]>
  • Loading branch information
DL6ER committed Nov 26, 2023
2 parents 98b5a92 + 30c3e9c commit f7b47e6
Show file tree
Hide file tree
Showing 27 changed files with 2,424 additions and 1,399 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@ index 6280ebf6..a5e82f70 100644
char *zHistory;
int nHistory;
+ print_FTL_version();
#if SHELL_WIN_UTF8_OPT
switch( console_utf8_in+2*console_utf8_out ){
default: case 0: break;
#if CIO_WIN_WC_XLATE
# define SHELL_CIO_CHAR_SET (stdout_is_console? " (UTF-16 console I/O)" : "")
#else
4 changes: 4 additions & 0 deletions src/api/docs/content/specs/logs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,10 @@ components:
type: integer
description: Next ID to query if checking for new log lines
example: 229
pid:
type: integer
description: Process ID of FTL. When this changes, FTL was restarted and nextID should be reset to 0.
example: 2258
file:
type: string
description: Path to respective log file on disk
Expand Down
4 changes: 3 additions & 1 deletion src/api/list.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,11 @@ static int api_list_read(struct ftl_conn *api,
char *name = NULL;
if(table.client != NULL)
{
// Try to obtain hostname if this is a valid IP address
// Try to obtain hostname
if(isValidIPv4(table.client) || isValidIPv6(table.client))
name = getNameFromIP(NULL, table.client);
else if(isMAC(table.client))
name = getNameFromMAC(table.client);
}

JSON_COPY_STR_TO_OBJECT(row, "client", table.client);
Expand Down
3 changes: 3 additions & 0 deletions src/api/logs.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
// struct fifologData
#include "log.h"
#include "config/config.h"
// main_pid()
#include "signals.h"

// fifologData is allocated in shared memory for cross-fork compatibility
int api_logs(struct ftl_conn *api)
Expand Down Expand Up @@ -70,6 +72,7 @@ int api_logs(struct ftl_conn *api)
}
JSON_ADD_ITEM_TO_OBJECT(json, "log", log);
JSON_ADD_NUMBER_TO_OBJECT(json, "nextID", fifo_log->logs[api->opts.which].next_id);
JSON_ADD_NUMBER_TO_OBJECT(json, "pid", main_pid());

// Add file name
const char *logfile = NULL;
Expand Down
21 changes: 21 additions & 0 deletions src/args.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@
#include "config/password.h"
// idn2_to_ascii_lz()
#include <idn2.h>
// sha256sum()
#include "files.h"

// defined in dnsmasq.c
extern void print_dnsmasq_version(const char *yellow, const char *green, const char *bold, const char *normal);
Expand Down Expand Up @@ -476,6 +478,24 @@ void parse_args(int argc, char* argv[])
}
}

// sha256sum mode
if(argc == 3 && strcmp(argv[1], "sha256sum") == 0)
{
// Enable stdout printing
cli_mode = true;
uint8_t checksum[SHA256_DIGEST_SIZE];
if(!sha256sum(argv[2], checksum))
exit(EXIT_FAILURE);

// Convert checksum to hex string
char hex[SHA256_DIGEST_SIZE*2+1];
sha256_raw_to_hex(checksum, hex);

// Print result
printf("%s %s\n", hex, argv[2]);
exit(EXIT_SUCCESS);
}

// start from 1, as argv[0] is the executable name
for(int i = 1; i < argc; i++)
{
Expand Down Expand Up @@ -934,6 +954,7 @@ void parse_args(int argc, char* argv[])
printf(" Decoding: %spihole-FTL idn2 -d %spunycode%s\n\n", green, cyan, normal);

printf("%sOther:%s\n", yellow, normal);
printf("\t%ssha256sum %sfile%s Calculate SHA256 checksum of a file\n", green, cyan, normal);
printf("\t%sdhcp-discover%s Discover DHCP servers in the local\n", green, normal);
printf("\t network\n");
printf("\t%sarp-scan %s[-a/-x]%s Use ARP to scan local network for\n", green, cyan, normal);
Expand Down
61 changes: 46 additions & 15 deletions src/config/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,12 @@
#include "signals.h"
// validation functions
#include "config/validator.h"
// sha256sum()
#include "files.h"

struct config config = { 0 };
static bool config_initialized = false;
uint8_t last_checksum[SHA256_DIGEST_SIZE] = { 0 };

// Private prototypes
static bool port_in_use(const in_port_t port);
Expand Down Expand Up @@ -1388,28 +1391,37 @@ void reset_config(struct conf_item *conf_item)
}
}

void readFTLconf(struct config *conf, const bool rewrite)
bool readFTLconf(struct config *conf, const bool rewrite)
{
// Initialize config with default values
initConfig(conf);

// First try to read TOML config file
if(readFTLtoml(NULL, conf, NULL, rewrite, NULL))
// If we cannot parse /etc/pihole.toml (due to missing or invalid syntax),
// we try to read the rotated files in /etc/pihole/config_backup starting at
// the most recent one and going back in time until we find a valid config
for(unsigned int i = 0; i < MAX_ROTATIONS; i++)
{
// If successful, we write the config file back to disk
// to ensure that all options are present and comments
// about options deviating from the default are present
if(rewrite)
if(readFTLtoml(NULL, conf, NULL, rewrite, NULL, i))
{
writeFTLtoml(true);
write_dnsmasq_config(conf, false, NULL);
write_custom_list();
// If successful, we write the config file back to disk
// to ensure that all options are present and comments
// about options deviating from the default are present
if(rewrite)
{
writeFTLtoml(true);
write_dnsmasq_config(conf, false, NULL);
write_custom_list();
}
return true;
}
return;
}

// On error, try to read legacy (pre-v6.0) config file. If successful,
// we move the legacy config file out of our way
log_info("No config file nor backup available, using defaults");

// If no previous config file could be read, we are likely either running
// for the first time or we are upgrading from a version prior to v6.0
// In this case, we try to read the legacy config files
const char *path = "";
if((path = readFTLlegacy(conf)) != NULL)
{
Expand Down Expand Up @@ -1449,7 +1461,7 @@ void readFTLconf(struct config *conf, const bool rewrite)
if(ports == NULL)
{
log_err("Unable to allocate memory for default ports string");
return;
return false;
}
// Create the string
snprintf(ports, 32, "%d,%ds", http_port, https_port);
Expand All @@ -1473,6 +1485,8 @@ void readFTLconf(struct config *conf, const bool rewrite)
writeFTLtoml(true);
write_dnsmasq_config(conf, false, NULL);
write_custom_list();

return false;
}

bool getLogFilePath(void)
Expand Down Expand Up @@ -1581,12 +1595,29 @@ void replace_config(struct config *newconf)

void reread_config(void)
{

// Create checksum of config file
uint8_t checksum[SHA256_DIGEST_SIZE];
if(!sha256sum(GLOBALTOMLPATH, checksum))
{
log_err("Unable to create checksum of %s, not re-reading config file", GLOBALTOMLPATH);
return;
}

// Compare checksums
if(memcmp(checksum, last_checksum, SHA256_DIGEST_SIZE) == 0)
{
log_debug(DEBUG_CONFIG, "Checksum of %s has not changed, not re-reading config file", GLOBALTOMLPATH);
return;
}

log_info("Reloading config due to pihole.toml change");
struct config conf_copy;
duplicate_config(&conf_copy, &config);

// Read TOML config file
bool restart = false;
if(readFTLtoml(&config, &conf_copy, NULL, true, &restart))
if(readFTLtoml(&config, &conf_copy, NULL, true, &restart, 0))
{
// Install new configuration
log_debug(DEBUG_CONFIG, "Loaded configuration is valid, installing it");
Expand Down Expand Up @@ -1614,7 +1645,7 @@ void reread_config(void)
else
{
// New configuration is invalid, restore old one
log_debug(DEBUG_CONFIG, "Loaded configuration is invalid, restoring old one");
log_debug(DEBUG_CONFIG, "Modified config file is invalid, discarding and overwriting with current configuration");
free_config(&conf_copy);
}

Expand Down
2 changes: 1 addition & 1 deletion src/config/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ void set_debug_flags(struct config *conf);
void set_all_debug(struct config *conf, const bool status);
void initConfig(struct config *conf);
void reset_config(struct conf_item *conf_item);
void readFTLconf(struct config *conf, const bool rewrite);
bool readFTLconf(struct config *conf, const bool rewrite);
bool getLogFilePath(void);
struct conf_item *get_conf_item(struct config *conf, const unsigned int n);
struct conf_item *get_debug_item(struct config *conf, const enum debug_flag debug);
Expand Down
24 changes: 22 additions & 2 deletions src/config/inotify.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,18 +106,38 @@ bool check_inotify_event(void)
// Check if this is the event we are looking for
if(event->mask & IN_CLOSE_WRITE)
{
// File opened for writing was closed
log_debug(DEBUG_INOTIFY, "File written: "WATCHDIR"/%s", event->name);
if(strcmp(event->name, "pihole.toml") == 0)
config_changed = true;
}
else if(event->mask & IN_CREATE)
{
// File was created
log_debug(DEBUG_INOTIFY, "File created: "WATCHDIR"/%s", event->name);
else if(event->mask & IN_MOVE)
log_debug(DEBUG_INOTIFY, "File moved: "WATCHDIR"/%s", event->name);
}
else if(event->mask & IN_MOVED_FROM)
{
// File was moved (source)
log_debug(DEBUG_INOTIFY, "File moved from: "WATCHDIR"/%s", event->name);
}
else if(event->mask & IN_MOVED_TO)
{
// File was moved (target)
log_debug(DEBUG_INOTIFY, "File moved to: "WATCHDIR"/%s", event->name);
if(strcmp(event->name, "pihole.toml") == 0)
config_changed = true;
}
else if(event->mask & IN_DELETE)
{
// File was deleted
log_debug(DEBUG_INOTIFY, "File deleted: "WATCHDIR"/%s", event->name);
}
else if(event->mask & IN_IGNORED)
{
// Watch descriptor was removed
log_warn("Inotify watch descriptor for "WATCHDIR" was removed (directory deleted or unmounted?)");
}
else
log_debug(DEBUG_INOTIFY, "Unknown event (%X) on watched file: "WATCHDIR"/%s", event->mask, event->name);
}
Expand Down
45 changes: 41 additions & 4 deletions src/config/toml_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,27 +20,64 @@
#include "files.h"
//set_and_check_password()
#include "config/password.h"
// PATH_MAX
#include <limits.h>

// Open the TOML file for reading or writing
FILE * __attribute((malloc)) __attribute((nonnull(1,2))) openFTLtoml(const char *path, const char *mode)
FILE * __attribute((malloc)) __attribute((nonnull(1))) openFTLtoml(const char *mode, const unsigned int version)
{
// Try to open file in requested mode
FILE *fp = fopen(path, mode);
// This should not happen, install a safeguard anyway to unveil
// possible future coding issues early on
if(mode[0] == 'w' && version != 0)
{
log_crit("Writing to version != 0 is not supported in openFTLtoml(%s,%u)",
mode, version);
exit(EXIT_FAILURE);
}

// Build filename based on version
char filename[PATH_MAX] = { 0 };
if(version == 0)
{
// Use global config file
strncpy(filename, GLOBALTOMLPATH, sizeof(filename));

// Append ".tmp" if we are writing
if(mode[0] == 'w')
strncat(filename, ".tmp", sizeof(filename));
}
else
{
// Use rotated config file
snprintf(filename, sizeof(filename), BACKUP_DIR"/pihole.toml.%u", version);
}

// Try to open config file
FILE *fp = fopen(filename, mode);

// Return early if opening failed
if(!fp)
{
log_info("Config %sfile %s not available: %s",
version > 0 ? "backup " : "", filename, strerror(errno));
return NULL;
}

// Lock file, may block if the file is currently opened
if(flock(fileno(fp), LOCK_EX) != 0)
{
const int _e = errno;
log_err("Cannot open FTL's config file in exclusive mode: %s", strerror(errno));
log_err("Cannot open config file %s in exclusive mode: %s",
filename, strerror(errno));
fclose(fp);
errno = _e;
return NULL;
}

// Log if we are using a backup file
if(version > 0)
log_info("Using config backup %s", filename);

errno = 0;
return fp;
}
Expand Down
2 changes: 1 addition & 1 deletion src/config/toml_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
#include "tomlc99/toml.h"

void indentTOML(FILE *fp, const unsigned int indent);
FILE *openFTLtoml(const char *path, const char *mode) __attribute((malloc)) __attribute((nonnull(1,2)));
FILE *openFTLtoml(const char *mode, const unsigned int version) __attribute((malloc)) __attribute((nonnull(1)));
void closeFTLtoml(FILE *fp);
void print_comment(FILE *fp, const char *str, const char *intro, const unsigned int width, const unsigned int indent);
void print_toml_allowed_values(cJSON *allowed_values, FILE *fp, const unsigned int width, const unsigned int indent);
Expand Down
Loading

0 comments on commit f7b47e6

Please sign in to comment.