diff --git a/src/config_updater.c b/src/config_updater.c index 13e62df4..c8da33f4 100644 --- a/src/config_updater.c +++ b/src/config_updater.c @@ -222,20 +222,34 @@ static int insert_or_replace_option(char **buf, size_t *buf_len, size_t *buf_cap int config_ensure_keys_and_node_id(const char *filename) { // ── Read config file into memory (single open) ── FILE *fp = fopen(filename, "rb"); - if (!fp) { - DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "Failed to open config file: %s (errno=%d)", filename, errno); - return -1; + char *file_buf = NULL; + size_t file_size = 0; + struct utun_config *config = NULL; + + if (fp) { + fseek(fp, 0, SEEK_END); long fsz = ftell(fp); fseek(fp, 0, SEEK_SET); + if (fsz < 0) { fclose(fp); return -1; } + file_size = (size_t)fsz; + file_buf = u_malloc(file_size + 1); + if (!file_buf || fread(file_buf, 1, file_size, fp) != file_size) { u_free(file_buf); fclose(fp); return -1; } + file_buf[file_size] = '\0'; + fclose(fp); + config = parse_config_from_buf(file_buf, file_size, filename); + if (!config) { DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "Failed to parse config from buffer: %s", filename); u_free(file_buf); return -1; } + } else { + // No file — create minimal config + DEBUG_WARN(DEBUG_CATEGORY_CONFIG, "Config file not found, creating new: %s (errno=%d)", filename, errno); + config = u_calloc(1, sizeof(struct utun_config)); + if (!config) return -1; + config->global.my_node_id = 0; + config->global.my_private_key_hex[0] = '\0'; + config->global.my_public_key_hex[0] = '\0'; + config->global.name[0] = '\0'; + config->global.keepalive_timeout = 2000; + config->global.keepalive_interval = 200; + config->global.keepalive_adaptive = 1; + config->global.bbr_max_cwnd = 1048576; } - fseek(fp, 0, SEEK_END); long fsz = ftell(fp); fseek(fp, 0, SEEK_SET); - if (fsz < 0) { fclose(fp); return -1; } - size_t file_size = (size_t)fsz; - char *file_buf = u_malloc(file_size + 1); - if (!file_buf || fread(file_buf, 1, file_size, fp) != file_size) { u_free(file_buf); fclose(fp); return -1; } - file_buf[file_size] = '\0'; - fclose(fp); - - struct utun_config *config = parse_config_from_buf(file_buf, file_size, filename); - if (!config) { DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "Failed to parse config from buffer: %s", filename); u_free(file_buf); return -1; } struct global_config *global = &config->global; @@ -294,34 +308,54 @@ int config_ensure_keys_and_node_id(const char *filename) { if (!need_priv_key && !need_pub_key && !need_node_id) { free_config(config); u_free(file_buf); return 0; } + char cfg_name[16]; snprintf(cfg_name, sizeof(cfg_name), "%s", global->name[0] ? global->name : "utun"); + free_config(config); - // ── Modify file buffer in place ── - size_t buf_capacity = file_size + 1024; - char *work_buf = u_malloc(buf_capacity); - if (!work_buf) { u_free(file_buf); return -1; } - memcpy(work_buf, file_buf, file_size); - u_free(file_buf); - size_t work_len = file_size; + char node_id_hex[HEXNODEID_LEN + 1]; + snprintf(node_id_hex, sizeof(node_id_hex), "%016llx", (unsigned long long)new_node_id); + + // ── Modify/create config buffer ── + char *work_buf = NULL; size_t work_len = 0; size_t buf_capacity = 0; + int is_new_file = (!file_buf || !file_size); + + if (is_new_file) { + buf_capacity = 2048; + work_buf = u_malloc(buf_capacity); + if (!work_buf) { u_free(file_buf); return -1; } + work_len = (size_t)snprintf(work_buf, buf_capacity, + "[global]\nmy_node_name=%s\nmy_private_key=%s\nmy_public_key=%s\nmy_node_id=%s\n", + cfg_name, new_priv_key, new_pub_key, node_id_hex); + u_free(file_buf); file_buf = NULL; + } else { + buf_capacity = file_size + 1024; + work_buf = u_malloc(buf_capacity); + if (!work_buf) { u_free(file_buf); return -1; } + memcpy(work_buf, file_buf, file_size); + work_len = file_size; + u_free(file_buf); file_buf = NULL; + } + int ret = 0; - int write_keys = (need_priv_key || need_pub_key || need_node_id); - if (need_node_id) { - char node_id_hex[HEXNODEID_LEN + 1]; - snprintf(node_id_hex, sizeof(node_id_hex), "%016llx", (unsigned long long)new_node_id); - DEBUG_WARN(DEBUG_CATEGORY_CONFIG, "Writing my_node_id=%s to %s", node_id_hex, filename); - if (insert_or_replace_option(&work_buf, &work_len, &buf_capacity, "my_node_id", node_id_hex) < 0) ret = -1; - } - if (write_keys && ret == 0) { - DEBUG_WARN(DEBUG_CATEGORY_CONFIG, "Writing my_private_key to %s", filename); - if (insert_or_replace_option(&work_buf, &work_len, &buf_capacity, "my_private_key", new_priv_key) < 0) ret = -1; - } - if (write_keys && ret == 0) { - DEBUG_WARN(DEBUG_CATEGORY_CONFIG, "Writing my_public_key to %s", filename); - if (insert_or_replace_option(&work_buf, &work_len, &buf_capacity, "my_public_key", new_pub_key) < 0) ret = -1; + if (!is_new_file) { + int write_keys = (need_priv_key || need_pub_key || need_node_id); + + if (need_node_id) { + DEBUG_WARN(DEBUG_CATEGORY_CONFIG, "Writing my_node_id=%s to %s", node_id_hex, filename); + if (insert_or_replace_option(&work_buf, &work_len, &buf_capacity, "my_node_id", node_id_hex) < 0) ret = -1; + } + if (write_keys && ret == 0) { + DEBUG_WARN(DEBUG_CATEGORY_CONFIG, "Writing my_private_key to %s", filename); + if (insert_or_replace_option(&work_buf, &work_len, &buf_capacity, "my_private_key", new_priv_key) < 0) ret = -1; + } + if (write_keys && ret == 0) { + DEBUG_WARN(DEBUG_CATEGORY_CONFIG, "Writing my_public_key to %s", filename); + if (insert_or_replace_option(&work_buf, &work_len, &buf_capacity, "my_public_key", new_pub_key) < 0) ret = -1; + } } - if (ret == 0) { + if (ret == 0 && work_buf) { if (write_mem_to_file(filename, work_buf, work_len) < 0) { DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "Failed to write updated config file: %s", filename); ret = -1;