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

Add new explicit migration command #2139

Merged
merged 8 commits into from
Jan 9, 2025
6 changes: 5 additions & 1 deletion src/api/auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include "config/password.h"
// database session functions
#include "database/session-table.h"
// FTLDBerror()
#include "database/common.h"

static uint16_t max_sessions = 0;
static struct session *auth_data = NULL;
Expand All @@ -51,7 +53,9 @@ void init_api(void)
log_crit("Could not allocate memory for API sessions, check config value of webserver.api.max_sessions");
exit(EXIT_FAILURE);
}
restore_db_sessions(auth_data, max_sessions);

if(!FTLDBerror())
restore_db_sessions(auth_data, max_sessions);
}

void free_api(void)
Expand Down
8 changes: 8 additions & 0 deletions src/api/teleporter.c
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,11 @@ static bool import_json_table(cJSON *json, struct teleporter_files *file)
return false;
}

// Set busy timeout to 1 second to access the database in a
// multi-threaded environment
if(sqlite3_busy_timeout(db, 1000) != SQLITE_OK)
log_warn("import_json_table(%s): Unable to set busy timeout: %s", file->filename, sqlite3_errmsg(db));

// Disable foreign key constraints
if(sqlite3_exec(db, "PRAGMA foreign_keys = OFF;", NULL, NULL, NULL) != SQLITE_OK)
{
Expand Down Expand Up @@ -834,6 +839,9 @@ static int process_received_tar_gz(struct ftl_conn *api, struct upload_data *dat
// Free allocated memory
free_upload_data(data);

// Migrate the config to v6
migrate_config_v6();

// Signal FTL we want to restart for re-import
api->ftl.restart_reason = "Teleporter (TAR.GZ) import";
api->ftl.restart = true;
Expand Down
11 changes: 9 additions & 2 deletions src/args.c
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,6 @@ void parse_args(int argc, char *argv[])
}
}


// Set config option through CLI
if(argc == 2 && strcmp(argv[1], "--totp") == 0)
{
Expand All @@ -321,7 +320,6 @@ void parse_args(int argc, char *argv[])
exit(printTOTP());
}


// Create teleporter archive through CLI
if(argc == 2 && strcmp(argv[1], "--teleporter") == 0)
{
Expand Down Expand Up @@ -602,6 +600,15 @@ void parse_args(int argc, char *argv[])
exit(EXIT_SUCCESS);
}


// Set config option through CLI
if(argc == 3 && strcmp(argv[1], "migrate") == 0 && strcmp(argv[2], "v6") == 0)
{
cli_mode = true;
log_ctrl(false, true);
exit(migrate_config_v6() ? EXIT_SUCCESS : EXIT_FAILURE);
}

// start from 1, as argv[0] is the executable name
for(int i = 1; i < argc; i++)
{
Expand Down
160 changes: 100 additions & 60 deletions src/config/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -1611,6 +1611,103 @@ static void reset_config_default(struct conf_item *conf_item)
}
}


/**
* @brief Determine and set default webserver ports if not imported from setupVars.conf.
*
* @param conf Pointer to the configuration structure.
*/
static void get_web_port(struct config *conf)
{
// Determine default webserver ports if not imported from setupVars.conf
if(config.webserver.port.f & FLAG_CONF_IMPORTED)
{
log_info("Webserver ports already imported from setupVars.conf, skipping default port detection");
return;
}

// else:
// Check if ports 80/TCP and 443/TCP are already in use
const in_port_t http_port = port_in_use(80) ? 8080 : 80;
const in_port_t https_port = port_in_use(443) ? 8443 : 443;

// Create a string with the default ports
// Allocate memory for the string
char *ports = calloc(32, sizeof(char));
if(ports == NULL)
{
log_err("Unable to allocate memory for default ports string");
return;
}
// Create the string
snprintf(ports, 32, "%d,%ds", http_port, https_port);

// Append IPv6 ports if IPv6 is enabled
const bool have_ipv6 = ipv6_enabled();
if(have_ipv6)
snprintf(ports + strlen(ports), 32 - strlen(ports),
",[::]:%d,[::]:%ds", http_port, https_port);

// Set default values for webserver ports
if(conf->webserver.port.t == CONF_STRING_ALLOCATED)
free(conf->webserver.port.v.s);
conf->webserver.port.v.s = ports;
conf->webserver.port.t = CONF_STRING_ALLOCATED;

log_info("Config initialized with webserver ports %d (HTTP) and %d (HTTPS), IPv6 support is %s",
http_port, https_port, have_ipv6 ? "enabled" : "disabled");
}

bool migrate_config_v6(void)
{
// Check if MIGRATION_TARGET_V6 exists and is a directory
// Ideally, this directory should be created by the installer but users
// may have deleted it manually and it is necessary for restoring
// Teleporter files
create_migration_target_v6();

// If the migration target does not exist, we need to migrate the config
log_info("Migrating config to Pi-hole v6.0 format");

// Initialize config with default values
initConfig(&config);

// 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(&config)) != NULL)
{
const char *target = MIGRATION_TARGET_V6"/pihole-FTL.conf";
log_info("Moving %s to %s", path, target);
if(rename(path, target) != 0)
log_warn("Unable to move %s to %s: %s", path, target, strerror(errno));
}
else
log_info("No legacy config file found, using defaults");

// Import bits and pieces from legacy config files
// setupVars.conf
importsetupVarsConf();
// 04-pihole-static-dhcp.conf
read_legacy_dhcp_static_config();
// 05-pihole-custom-cname.conf
read_legacy_cnames_config();
// custom.list
read_legacy_custom_hosts_config();

// Determine and set default webserver ports if not imported from
// setupVars.conf
get_web_port(&config);

// Initialize the TOML config file
writeFTLtoml(true);
write_dnsmasq_config(&config, false, NULL);
write_custom_list();

return true;
}

bool readFTLconf(struct config *conf, const bool rewrite)
{
// Initialize config with default values
Expand Down Expand Up @@ -1649,33 +1746,6 @@ bool readFTLconf(struct config *conf, const bool rewrite)
if(!rewrite)
return false;

// Check if MIGRATION_TARGET_V6 exists and is a directory
// Ideally, this directory should be created by the installer but users
// may have deleted it manually and it is necessary for restoring
// Teleporter files
create_migration_target_v6();

// 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)
{
const char *target = MIGRATION_TARGET_V6"/pihole-FTL.conf";
log_info("Moving %s to %s", path, target);
if(rename(path, target) != 0)
log_warn("Unable to move %s to %s: %s", path, target, strerror(errno));
}
// Import bits and pieces from legacy config files
// setupVars.conf
importsetupVarsConf();
// 04-pihole-static-dhcp.conf
read_legacy_dhcp_static_config();
// 05-pihole-custom-cname.conf
read_legacy_cnames_config();
// custom.list
read_legacy_custom_hosts_config();

// When we reach this point but the FTL TOML config file exists, it may
// contain errors such as syntax errors, etc. We move it into a
// ".broken" location so it can be revisited later
Expand All @@ -1686,39 +1756,9 @@ bool readFTLconf(struct config *conf, const bool rewrite)
rename(GLOBALTOMLPATH, new_name);
}

// Determine default webserver ports if not imported from setupVars.conf
if(!(config.webserver.port.f & FLAG_CONF_IMPORTED))
{
// Check if ports 80/TCP and 443/TCP are already in use
const in_port_t http_port = port_in_use(80) ? 8080 : 80;
const in_port_t https_port = port_in_use(443) ? 8443 : 443;

// Create a string with the default ports
// Allocate memory for the string
char *ports = calloc(32, sizeof(char));
if(ports == NULL)
{
log_err("Unable to allocate memory for default ports string");
return false;
}
// Create the string
snprintf(ports, 32, "%d,%ds", http_port, https_port);

// Append IPv6 ports if IPv6 is enabled
const bool have_ipv6 = ipv6_enabled();
if(have_ipv6)
snprintf(ports + strlen(ports), 32 - strlen(ports),
",[::]:%d,[::]:%ds", http_port, https_port);

// Set default values for webserver ports
if(conf->webserver.port.t == CONF_STRING_ALLOCATED)
free(conf->webserver.port.v.s);
conf->webserver.port.v.s = ports;
conf->webserver.port.t = CONF_STRING_ALLOCATED;

log_info("Config initialized with webserver ports %d (HTTP) and %d (HTTPS), IPv6 support is %s",
http_port, https_port, have_ipv6 ? "enabled" : "disabled");
}
// Determine and set default webserver ports if not imported from
// setupVars.conf
get_web_port(&config);

// Initialize the TOML config file
writeFTLtoml(true);
Expand Down
1 change: 1 addition & 0 deletions src/config/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,7 @@ extern struct config config;
// Defined in config.c
void set_debug_flags(struct config *conf);
void set_all_debug(struct config *conf, const bool status);
bool migrate_config_v6(void);
bool readFTLconf(struct config *conf, const bool rewrite);
bool getLogFilePath(void);
struct conf_item *get_conf_item(struct config *conf, const unsigned int n);
Expand Down
Loading
Loading