Files
OpenUniFi/src/state.c
T
KodaandKoda c7687fd35d
Generate and publish developer Wiki / publish-wiki (push) Canceled after 0s
Generate and publish developer Wiki / validate-wiki (push) Canceled after 9s
Build and publish release / create-release (push) Canceled after 0s
Build and publish release / build (push) Canceled after 0s
Build and publish release / publish-release (push) Canceled after 0s
Build and publish release / metadata (push) Canceled after 10s
added log Timestamps (#42)
Reviewed-on: #42
Co-authored-by: Koda YeenBean <n122330@gmail.com>
2026-08-07 14:55:38 +01:00

138 lines
4.6 KiB
C

#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <json-c/json.h>
#include "state.h"
#include "config.h"
#if ENABLE_LOGGING
#include <stdio.h>
extern FILE *log_fp;
#define LOG(fmt, ...) do { if (log_fp) openuf_log_emit(log_fp, __func__, fmt, ##__VA_ARGS__); } while(0)
#else
#define LOG(fmt, ...) do {} while(0)
#endif
static void state_defaults(openuf_state_t *st)
{
memset(st, 0, sizeof(*st));
st->adopted = false;
strncpy(st->authkey, DEFAULT_AUTH_KEY, sizeof(st->authkey) - 1);
strncpy(st->cfgversion, "0", sizeof(st->cfgversion) - 1);
st->config_applied = false;
st->config_schema = 0;
st->use_aes_gcm = false;
}
void state_load(openuf_state_t *st)
{
state_defaults(st);
FILE *f = fopen(OPENUF_STATE_FILE, "r");
if (!f) {
LOG("State file not found, using defaults");
return;
}
/* Read whole file */
fseek(f, 0, SEEK_END);
long sz = ftell(f);
rewind(f);
if (sz <= 0 || sz > 4096) { fclose(f); return; }
char *buf = malloc(sz + 1);
if (!buf) { fclose(f); return; }
fread(buf, 1, sz, f);
buf[sz] = '\0';
fclose(f);
struct json_object *root = json_tokener_parse(buf);
free(buf);
if (!root) {
LOG("Failed to parse state file");
return;
}
struct json_object *v;
#define LOAD_STR(field, key) \
if (json_object_object_get_ex(root, key, &v) && json_object_is_type(v, json_type_string)) \
strncpy(st->field, json_object_get_string(v), sizeof(st->field) - 1)
#define LOAD_BOOL(field, key) \
if (json_object_object_get_ex(root, key, &v)) \
st->field = json_object_get_boolean(v)
#define LOAD_INT(field, key) \
if (json_object_object_get_ex(root, key, &v)) \
st->field = json_object_get_int(v)
LOAD_BOOL(adopted, "adopted");
LOAD_STR (authkey, "authkey");
LOAD_STR (inform_url, "inform_url");
LOAD_STR (cfgversion, "cfgversion");
LOAD_STR (firmware_version, "firmware_version");
LOAD_BOOL(config_applied, "config_applied");
LOAD_INT (config_schema, "config_schema");
LOAD_BOOL(use_aes_gcm, "use_aes_gcm");
LOAD_STR (mac, "mac");
LOAD_STR (ip, "ip");
LOAD_STR (hostname, "hostname");
/*
* Older versions stored cfgversion from setparam before applying the
* corresponding setstate. Force one provisioning request when migrating.
*/
if (!st->config_applied ||
st->config_schema < OPENUF_CONFIG_SCHEMA) {
st->config_applied = false;
strncpy(st->cfgversion, "0", sizeof(st->cfgversion) - 1);
}
/* CRITICAL: If not adopted, force DEFAULT_AUTH_KEY */
if (!st->adopted) {
LOG("Device not adopted - resetting authkey to DEFAULT");
strncpy(st->authkey, DEFAULT_AUTH_KEY, sizeof(st->authkey) - 1);
}
LOG("State loaded: adopted=%d, authkey=%.8s..., inform_url=%s, aes_gcm=%d",
st->adopted, st->authkey[0] ? st->authkey : "DEFAULT",
st->inform_url, st->use_aes_gcm);
json_object_put(root);
}
int state_save(const openuf_state_t *st)
{
/* Ensure directory exists */
mkdir("/etc/openuf", 0755);
LOG("Saving state: adopted=%d, authkey=%.8s..., inform_url=%s, aes_gcm=%d",
st->adopted, st->authkey[0] ? st->authkey : "DEFAULT",
st->inform_url, st->use_aes_gcm);
struct json_object *root = json_object_new_object();
json_object_object_add(root, "adopted", json_object_new_boolean(st->adopted));
json_object_object_add(root, "authkey", json_object_new_string(st->authkey));
json_object_object_add(root, "inform_url", json_object_new_string(st->inform_url));
json_object_object_add(root, "cfgversion", json_object_new_string(st->cfgversion));
json_object_object_add(root, "firmware_version", json_object_new_string(st->firmware_version));
json_object_object_add(root, "config_applied", json_object_new_boolean(st->config_applied));
json_object_object_add(root, "config_schema", json_object_new_int(st->config_schema));
json_object_object_add(root, "use_aes_gcm", json_object_new_boolean(st->use_aes_gcm));
json_object_object_add(root, "mac", json_object_new_string(st->mac));
json_object_object_add(root, "ip", json_object_new_string(st->ip));
json_object_object_add(root, "hostname", json_object_new_string(st->hostname));
const char *s = json_object_to_json_string_ext(root, JSON_C_TO_STRING_PRETTY);
FILE *f = fopen(OPENUF_STATE_FILE, "w");
if (!f) {
LOG("Failed to open state file for writing");
json_object_put(root);
return -1;
}
fputs(s, f);
fclose(f);
json_object_put(root);
LOG("State saved successfully");
return 0;
}