From 4e36d1a86e16a63337959725abe59a811567e397 Mon Sep 17 00:00:00 2001 From: TolaMironcenko Date: Wed, 10 Sep 2025 15:20:37 +0700 Subject: [PATCH] added set_settings functional --- meson.build | 4 +++ src/set_dnsmasq_settings_field.c | 44 ++++++++++++++++++++++++ src/set_hosts.c | 44 ++++++++++++++++++++++++ src/set_resolvs.c | 29 ++++++++++++++++ src/set_settings.c | 58 ++++++++++++++++++++++++++++++++ src/settings.h | 3 ++ web/js/settings/settings.js | 6 +++- 7 files changed, 187 insertions(+), 1 deletion(-) create mode 100644 src/set_dnsmasq_settings_field.c create mode 100644 src/set_hosts.c create mode 100644 src/set_resolvs.c diff --git a/meson.build b/meson.build index 52db0cb..7830e17 100644 --- a/meson.build +++ b/meson.build @@ -17,6 +17,10 @@ executable( 'src/set_settings_file.c', 'src/get_settings_file.c', 'src/static.c', + 'src/set_hosts.c', + 'src/set_resolvs.c', + 'src/set_dnsmasq_settings_field.c', + 'src/restart_dnsmasq.c', include_directories: include_dirs, dependencies: deps, ) diff --git a/src/set_dnsmasq_settings_field.c b/src/set_dnsmasq_settings_field.c new file mode 100644 index 0000000..48ce12f --- /dev/null +++ b/src/set_dnsmasq_settings_field.c @@ -0,0 +1,44 @@ +#include "config.h" +#include "settings.h" + +#define DNSMASQ_CONFIG_FILE_TMP "dnsmasq.conf.tmp" + +char *set_dnsmasq_settings_field(const char *key, cJSON *setting) { + char *filename = cm_get_parameter_as_string(config, "dnsmasq_config"); + if (!filename) { + return "Failed to read config file"; + } + FILE *dnsmasq_config_file = fopen(filename, "r"); + FILE *dnsmasq_config_file_tmp = fopen(DNSMASQ_CONFIG_FILE_TMP, "w"); + + if (dnsmasq_config_file == nullptr || dnsmasq_config_file_tmp == nullptr) { + return "Failed to open config file"; + } + + char line[256]; + char *new_str = malloc(1024); + snprintf(new_str, 1024, "%s=%d", key, setting->valueint); + + while (fgets(line, sizeof(line), dnsmasq_config_file)) { + if (strstr(line, key) != nullptr || strcmp(line, key) == 0) { + fputs(new_str, dnsmasq_config_file_tmp); + fputs("\n", dnsmasq_config_file_tmp); + } else { + fputs(line, dnsmasq_config_file_tmp); + } + } + + fclose(dnsmasq_config_file); + fclose(dnsmasq_config_file_tmp); + free(new_str); + + if (remove(filename) != 0) { + remove(DNSMASQ_CONFIG_FILE_TMP); + return "Failed to remove config file"; + } + if (rename(DNSMASQ_CONFIG_FILE_TMP, filename) != 0) { + remove(DNSMASQ_CONFIG_FILE_TMP); + return "Failed to rename config file"; + } + return nullptr; +} diff --git a/src/set_hosts.c b/src/set_hosts.c new file mode 100644 index 0000000..d78738a --- /dev/null +++ b/src/set_hosts.c @@ -0,0 +1,44 @@ +#include "settings.h" + +#define DNSMASQ_HOSTS_FILE_TMP "hosts.tmp" + +char *set_hosts(cJSON *hosts) { + FILE *hosts_file_tmp = fopen(DNSMASQ_HOSTS_FILE_TMP, "w"); + if (!hosts_file_tmp) { + return "can't open hosts file"; + } + + cJSON *host = hosts->child; + while (host) { + if (!cJSON_IsString(host) && !cJSON_IsArray(host)) { + remove(DNSMASQ_HOSTS_FILE_TMP); + return "Invalid hosts"; + } + if (cJSON_IsString(host)) { + fprintf(hosts_file_tmp, "%s %s\n", host->string, host->valuestring); + } + if (cJSON_IsArray(host)) { + int arrsize = cJSON_GetArraySize(host); + if (arrsize > 0) { + fprintf(hosts_file_tmp, "%s ", host->string); + } + for (int i = 0; i < arrsize; i++) { + cJSON *domain = cJSON_GetArrayItem(host, i); + if (domain && cJSON_IsString(domain)) { + fprintf(hosts_file_tmp, "%s ", domain->valuestring); + } + } + fprintf(hosts_file_tmp, "\n"); + } + host = host->next; + } + + fclose(hosts_file_tmp); + + if (rename(DNSMASQ_HOSTS_FILE_TMP, "/etc/dnsmasq.conf.d/hosts") != 0) { + remove(DNSMASQ_HOSTS_FILE_TMP); + return "Failed to rename hosts file"; + } + remove(DNSMASQ_HOSTS_FILE_TMP); + return nullptr; +} diff --git a/src/set_resolvs.c b/src/set_resolvs.c new file mode 100644 index 0000000..cf8e91d --- /dev/null +++ b/src/set_resolvs.c @@ -0,0 +1,29 @@ +#include "settings.h" + +#define DNSMASQ_RESOLV_FILE_TMP "resolv.conf.tmp" + +char *set_resolvs(cJSON *resolvs) { + FILE *resolvs_file_tmp = fopen(DNSMASQ_RESOLV_FILE_TMP, "w"); + if (!resolvs_file_tmp) { + return "Failed to open resolv file"; + } + + cJSON *resolv = resolvs->child; + while (resolv) { + if (!cJSON_IsString(resolv)) { + remove(DNSMASQ_RESOLV_FILE_TMP); + return "Invalid resolv"; + } + fprintf(resolvs_file_tmp, "nameserver %s\n", resolv->valuestring); + resolv = resolv->next; + } + + fclose(resolvs_file_tmp); + + if (rename(DNSMASQ_RESOLV_FILE_TMP, "/etc/dnsmasq.conf.d/resolv.conf") != 0) { + remove(DNSMASQ_RESOLV_FILE_TMP); + return "Failed to rename resolv file"; + } + remove(DNSMASQ_RESOLV_FILE_TMP); + return nullptr; +} diff --git a/src/set_settings.c b/src/set_settings.c index f898438..e2e2549 100644 --- a/src/set_settings.c +++ b/src/set_settings.c @@ -1,4 +1,62 @@ #include "settings.h" void set_settings(struct mg_connection *c, struct mg_http_message *hm) { + cJSON *jsonbody = cJSON_Parse(hm->body.buf); + if (!jsonbody) { + mg_http_reply(c, 500, HTTP_HEADERS, "{%m:%m}", MG_ESC("error"), + MG_ESC("can't parse JSON body")); + return; + } + + cJSON *cache_size = cJSON_GetObjectItemCaseSensitive(jsonbody, "cache_size"); + if (!cache_size || !cJSON_IsNumber(cache_size)) { + mg_http_reply(c, 500, HTTP_HEADERS, "{%m:%m}", MG_ESC("error"), + MG_ESC("invalid cache_size")); + cJSON_Delete(jsonbody); + return; + } + + char *result_set_dnsmasq_settings_field = + set_dnsmasq_settings_field("cache-size", cache_size); + if (result_set_dnsmasq_settings_field) { + mg_http_reply(c, 200, HTTP_HEADERS, "{%m:%m}", MG_ESC("error"), + MG_ESC(result_set_dnsmasq_settings_field)); + cJSON_Delete(jsonbody); + return; + } + + cJSON *resolvs = cJSON_GetObjectItemCaseSensitive(jsonbody, "resolv"); + if (!resolvs || !cJSON_IsArray(resolvs)) { + mg_http_reply(c, 500, HTTP_HEADERS, "{%m:%m}", MG_ESC("error"), + MG_ESC("invalid resolv")); + cJSON_Delete(jsonbody); + return; + } + + char *result_set_resolvs = set_resolvs(resolvs); + if (result_set_resolvs) { + mg_http_reply(c, 500, HTTP_HEADERS, "{%m:%m}", MG_ESC("error"), + MG_ESC(result_set_resolvs)); + cJSON_Delete(jsonbody); + return; + } + + cJSON *hosts = cJSON_GetObjectItemCaseSensitive(jsonbody, "hosts"); + if (!hosts || !cJSON_IsObject(hosts)) { + mg_http_reply(c, 500, HTTP_HEADERS, "{%m:%m}", MG_ESC("error"), + MG_ESC("invalid hosts")); + cJSON_Delete(jsonbody); + return; + } + + char *result_set_hosts = set_hosts(hosts); + if (result_set_hosts) { + mg_http_reply(c, 500, HTTP_HEADERS, "{%m:%m}", MG_ESC("error"), + MG_ESC(result_set_hosts)); + cJSON_Delete(jsonbody); + return; + } + + mg_http_reply(c, 200, HTTP_HEADERS, "%s", hm->body.buf); + cJSON_Delete(jsonbody); } diff --git a/src/settings.h b/src/settings.h index 99038a4..50f4624 100644 --- a/src/settings.h +++ b/src/settings.h @@ -11,3 +11,6 @@ void set_settings(struct mg_connection *c, struct mg_http_message *hm); cJSON *decode_dnsmasq_settings(char *input, char *pair_delim, char *kv_delim); char **decode_resolvs(char *input, int *count); cJSON *decode_hosts(const char *input); +char *set_hosts(cJSON* hosts); +char *set_resolvs(cJSON* resolvs); +char *set_dnsmasq_settings_field(const char *key, cJSON *setting); diff --git a/web/js/settings/settings.js b/web/js/settings/settings.js index a8ba708..3a24ff3 100644 --- a/web/js/settings/settings.js +++ b/web/js/settings/settings.js @@ -76,6 +76,10 @@ const setSettings = () => { }) .then((data) => data.json()) .then((jsondata) => { + if (jsondata.error) { + alert(jsondata.error); + return; + } settings = jsondata; updateInterface(); alert("Success set settings"); @@ -88,7 +92,7 @@ save_settings_button.addEventListener("click", () => { }); const write_cache_size = (value) => { - settings.cache_size = value; + settings.cache_size = parseInt(value); }; cache_size_input.addEventListener("change", (e) => {