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

Check all env vars and suggest alternatives for misspelled keys #1719

Merged
merged 18 commits into from
Feb 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
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
1 change: 1 addition & 0 deletions .github/.codespellignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ doubleclick
requestor
requestors
punycode
bitap
4 changes: 4 additions & 0 deletions src/config/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,16 @@ set(sources
config.h
dnsmasq_config.c
dnsmasq_config.h
env.c
env.h
inotify.c
inotify.h
legacy_reader.c
legacy_reader.h
password.c
password.h
suggest.c
suggest.h
setupVars.c
setupVars.h
toml_writer.c
Expand Down
43 changes: 33 additions & 10 deletions src/config/cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,17 @@
#include "config/password.h"
// check_capability()
#include "capabilities.h"
// suggest_closest_conf_key()
#include "config/suggest.h"

enum exit_codes {
OKAY = 0,
FAIL = 1,
VALUE_INVALID = 2,
DNSMASQ_TEST_FAILED = 3,
KEY_UNKNOWN = 4,
ENV_VAR_FORCED = 5,
} __attribute__((packed));

// Read a TOML value from a table depending on its type
static bool readStringValue(struct conf_item *conf_item, const char *value, struct config *newconf)
Expand Down Expand Up @@ -402,7 +413,7 @@ int set_config_from_CLI(const char *key, const char *value)
{
log_err("Config option %s is read-only (set via environmental variable)", key);
free_config(&newconf);
return 5;
return ENV_VAR_FORCED;
}

// This is the config option we are looking for
Expand All @@ -418,16 +429,22 @@ int set_config_from_CLI(const char *key, const char *value)
// Check if we found the config option
if(new_item == NULL)
{
log_err("Unknown config option: %s", key);
unsigned int N = 0;
char **matches = suggest_closest_conf_key(false, key, &N);
log_err("Unknown config option %s, did you mean:", key);
for(unsigned int i = 0; i < N; i++)
log_err(" - %s", matches[i]);
free(matches);

free_config(&newconf);
return 4;
return KEY_UNKNOWN;
}

// Parse value
if(!readStringValue(new_item, value, &newconf))
{
free_config(&newconf);
return 2;
return VALUE_INVALID;
}

// Check if value changed compared to current value
Expand All @@ -447,7 +464,7 @@ int set_config_from_CLI(const char *key, const char *value)
// Test failed
log_debug(DEBUG_CONFIG, "Config item %s: dnsmasq config test failed", conf_item->k);
free_config(&newconf);
return 3;
return DNSMASQ_TEST_FAILED;
}
}
else if(conf_item == &config.dns.hosts)
Expand Down Expand Up @@ -475,7 +492,7 @@ int set_config_from_CLI(const char *key, const char *value)

putchar('\n');
writeFTLtoml(false);
return EXIT_SUCCESS;
return OKAY;
}

int get_config_from_CLI(const char *key, const bool quiet)
Expand Down Expand Up @@ -534,14 +551,20 @@ int get_config_from_CLI(const char *key, const bool quiet)
// Check if we found the config option
if(conf_item == NULL)
{
log_err("Unknown config option: %s", key);
return 2;
unsigned int N = 0;
char **matches = suggest_closest_conf_key(false, key, &N);
log_err("Unknown config option %s, did you mean:", key);
for(unsigned int i = 0; i < N; i++)
log_err(" - %s", matches[i]);
free(matches);

return KEY_UNKNOWN;
}

// Use return status if this is a boolean value
// and we are in quiet mode
if(quiet && conf_item != NULL && conf_item->t == CONF_BOOL)
return conf_item->v.b ? EXIT_SUCCESS : EXIT_FAILURE;
return conf_item->v.b ? OKAY : FAIL;

return EXIT_SUCCESS;
return OKAY;
}
32 changes: 22 additions & 10 deletions src/config/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
#include "api/api.h"
// exit_code
#include "signals.h"
// getEnvVars()
#include "config/env.h"
// sha256sum()
#include "files.h"

Expand Down Expand Up @@ -1318,17 +1320,24 @@ void initConfig(struct config *conf)
// Parse and split paths
conf_item->p = gen_config_path(conf_item->k, '.');

// Verify all config options are defined above
if(!conf_item->p || !conf_item->k || !conf_item->h)
{
log_err("Config option %u/%u is not set!", i, (unsigned int)CONFIG_ELEMENTS);
continue;
}
// Initialize environment variable name
// Allocate memory for config key + prefix (sizeof includes the trailing '\0')
const size_t envkey_size = strlen(conf_item->k) + sizeof(FTLCONF_PREFIX);
conf_item->e = calloc(envkey_size, sizeof(char));

// Verify that all config options have a type
if(conf_item->t == 0)
// Build env key to look for
strcpy(conf_item->e, FTLCONF_PREFIX);
strcat(conf_item->e, conf_item->k);

// Replace all "." by "_" as this is the convention used in v5.x and earlier
for(unsigned int j = 0; j < envkey_size - 1; j++)
if(conf_item->e[j] == '.')
conf_item->e[j] = '_';

// Verify all config options are defined above
if(!conf_item->p || !conf_item->k || !conf_item->h || !conf_item->e || conf_item->t == 0)
{
log_err("Config option %s has no type!", conf_item->k);
log_err("Config option %u/%u is not fully configured!", i, (unsigned int)CONFIG_ELEMENTS);
continue;
}

Expand Down Expand Up @@ -1381,7 +1390,10 @@ bool readFTLconf(struct config *conf, const bool rewrite)
// Initialize config with default values
initConfig(conf);

// First try to read TOML config file
// First, read the environment
getEnvVars();

// Try to read TOML config file
// 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
Expand Down
1 change: 1 addition & 0 deletions src/config/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ enum conf_type {
struct conf_item {
const char *k; // item Key
char **p; // item Path
char *e; // item Environment variable
const char *h; // Help text / description
cJSON *a; // JSON array or object of Allowed values (where applicable)
enum conf_type t; // variable Type
Expand Down
Loading