From 698832f42c11d1df2b955de37b6b130c980dadce Mon Sep 17 00:00:00 2001 From: xengineering Date: Tue, 15 Apr 2025 17:14:06 +0200 Subject: fw: app: syslog: Make target IP configurable --- fw/app/src/syslog.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) (limited to 'fw/app/src/syslog.c') diff --git a/fw/app/src/syslog.c b/fw/app/src/syslog.c index e19a196..6dc0bd6 100644 --- a/fw/app/src/syslog.c +++ b/fw/app/src/syslog.c @@ -4,8 +4,10 @@ * obtain one at https://mozilla.org/MPL/2.0/. */ +#include #include +#include #include #include #include @@ -14,6 +16,8 @@ #include #include #include +#include +#include #ifdef CONFIG_IOT_CONTACT_NETWORK_HACK #include @@ -23,9 +27,11 @@ LOG_MODULE_REGISTER(syslog); #define NETWORK_BUG_DELAY K_MSEC(4000) #define L4_EVENT_MASK (NET_EVENT_L4_CONNECTED | NET_EVENT_L4_DISCONNECTED) +#define IPV6_STRLEN_MAX 40 // including '\0' struct net_mgmt_event_callback l4_cb; static K_SEM_DEFINE(network_connected, 0, 1); +static char target_ip[IPV6_STRLEN_MAX] = CONFIG_LOG_BACKEND_NET_SERVER; void l4_event_handler( struct net_mgmt_event_callback *cb, @@ -79,6 +85,10 @@ int init_syslog(void) /* flush log messages to ensure first syslog message is reproducible */ while (log_process()); log_backend_init(backend); + LOG_INF("Setting syslog target to: '%s'", target_ip); + if (log_backend_net_set_addr(target_ip) == false) { + LOG_ERR("Could not set target IP to '%s'", target_ip); + } log_backend_enable(backend, backend->cb->ctx, CONFIG_LOG_MAX_LEVEL); LOG_INF("Syslog backend enabled"); } else { @@ -88,3 +98,50 @@ int init_syslog(void) return 0; } SYS_INIT(init_syslog, APPLICATION, 50); + +int syslog_handle_set(const char *name, size_t len, settings_read_cb read_cb, + void *cb_arg) +{ + const char* next = NULL; + + if (settings_name_steq(name, "target/ip", &next) && !next) { + memset(target_ip, '\0', sizeof(target_ip)); + ssize_t ret = read_cb(cb_arg, target_ip, MIN(sizeof(target_ip) - 1, len)); + if (ret < 0) { + LOG_ERR("Failed to read syslog/target/ip setting (%d)", ret); + return (int)ret; + } + LOG_INF("Setting target IP address to '%s'", target_ip); + return 0; + } + + return 0; +} + +int syslog_handle_commit(void) +{ + LOG_WRN("Settings commit not implemented"); + return 0; +} + +int syslog_handle_export(int (*cb)(const char *name, const void *value, + size_t val_len)) +{ + LOG_WRN("Settings export not implemented"); + return 0; +} + +int syslog_handle_get(const char *name, char *val, int val_len_max) +{ + LOG_WRN("Settings get not implemented"); + return 0; +} + +SETTINGS_STATIC_HANDLER_DEFINE( + syslog_settings_handler, + "syslog", + syslog_handle_get, + syslog_handle_set, + syslog_handle_commit, + syslog_handle_export +); -- cgit v1.2.3-70-g09d2 From 0bff2eea39c11b5ad2e762325abeb1457ae0fd7e Mon Sep 17 00:00:00 2001 From: xengineering Date: Tue, 15 Apr 2025 18:06:32 +0200 Subject: fw: app: syslog: Implement commit target --- fw/app/src/settings.c | 2 +- fw/app/src/syslog.c | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'fw/app/src/syslog.c') diff --git a/fw/app/src/settings.c b/fw/app/src/settings.c index 916c7ad..799322e 100644 --- a/fw/app/src/settings.c +++ b/fw/app/src/settings.c @@ -30,4 +30,4 @@ int init_settings(void) { return 0; } -SYS_INIT(init_settings, APPLICATION, 40); +SYS_INIT(init_settings, APPLICATION, 50); diff --git a/fw/app/src/syslog.c b/fw/app/src/syslog.c index 6dc0bd6..8fe2412 100644 --- a/fw/app/src/syslog.c +++ b/fw/app/src/syslog.c @@ -85,10 +85,6 @@ int init_syslog(void) /* flush log messages to ensure first syslog message is reproducible */ while (log_process()); log_backend_init(backend); - LOG_INF("Setting syslog target to: '%s'", target_ip); - if (log_backend_net_set_addr(target_ip) == false) { - LOG_ERR("Could not set target IP to '%s'", target_ip); - } log_backend_enable(backend, backend->cb->ctx, CONFIG_LOG_MAX_LEVEL); LOG_INF("Syslog backend enabled"); } else { @@ -97,7 +93,7 @@ int init_syslog(void) return 0; } -SYS_INIT(init_syslog, APPLICATION, 50); +SYS_INIT(init_syslog, APPLICATION, 40); int syslog_handle_set(const char *name, size_t len, settings_read_cb read_cb, void *cb_arg) @@ -108,10 +104,10 @@ int syslog_handle_set(const char *name, size_t len, settings_read_cb read_cb, memset(target_ip, '\0', sizeof(target_ip)); ssize_t ret = read_cb(cb_arg, target_ip, MIN(sizeof(target_ip) - 1, len)); if (ret < 0) { - LOG_ERR("Failed to read syslog/target/ip setting (%d)", ret); + LOG_ERR("Failed to set target (%d)", ret); return (int)ret; } - LOG_INF("Setting target IP address to '%s'", target_ip); + LOG_INF("Set target to '%s'", target_ip); return 0; } @@ -120,7 +116,11 @@ int syslog_handle_set(const char *name, size_t len, settings_read_cb read_cb, int syslog_handle_commit(void) { - LOG_WRN("Settings commit not implemented"); + if (log_backend_net_set_addr(target_ip) == false) { + LOG_ERR("Could not commit target to '%s'", target_ip); + } + LOG_INF("Committed new target: '%s'", target_ip); + return 0; } -- cgit v1.2.3-70-g09d2 From 409348732bb4cd6ec0c06c4b38f26f528313ffdf Mon Sep 17 00:00:00 2001 From: xengineering Date: Tue, 15 Apr 2025 18:33:31 +0200 Subject: fw: app: syslog: Put only IP into syslog/target/ip The old format contained `[]:`. Nevertheless the format should be as strict as possible. Thus only the IP is used in the setting. --- fw/app/src/syslog.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'fw/app/src/syslog.c') diff --git a/fw/app/src/syslog.c b/fw/app/src/syslog.c index 8fe2412..c3b5815 100644 --- a/fw/app/src/syslog.c +++ b/fw/app/src/syslog.c @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -27,7 +28,8 @@ LOG_MODULE_REGISTER(syslog); #define NETWORK_BUG_DELAY K_MSEC(4000) #define L4_EVENT_MASK (NET_EVENT_L4_CONNECTED | NET_EVENT_L4_DISCONNECTED) -#define IPV6_STRLEN_MAX 40 // including '\0' +#define IPV6_STRLEN_MAX 39 // excluding '\0' +#define SYSLOG_TARGET_PORT 514 struct net_mgmt_event_callback l4_cb; static K_SEM_DEFINE(network_connected, 0, 1); @@ -104,10 +106,10 @@ int syslog_handle_set(const char *name, size_t len, settings_read_cb read_cb, memset(target_ip, '\0', sizeof(target_ip)); ssize_t ret = read_cb(cb_arg, target_ip, MIN(sizeof(target_ip) - 1, len)); if (ret < 0) { - LOG_ERR("Failed to set target (%d)", ret); + LOG_ERR("Failed to set target IP (%d)", ret); return (int)ret; } - LOG_INF("Set target to '%s'", target_ip); + LOG_INF("Set target IP to '%s'", target_ip); return 0; } @@ -116,10 +118,20 @@ int syslog_handle_set(const char *name, size_t len, settings_read_cb read_cb, int syslog_handle_commit(void) { - if (log_backend_net_set_addr(target_ip) == false) { - LOG_ERR("Could not commit target to '%s'", target_ip); + char target[IPV6_STRLEN_MAX + 9]; // 9 for brackets, colon, port and \0 + + int ret = snprintf(target, sizeof(target), "[%s]:%d", target_ip, + SYSLOG_TARGET_PORT); + if (ret < 0) { + LOG_ERR("Failed to format target based on ip and port (%d)", ret); + return ret; + } + + if (log_backend_net_set_addr(target) == false) { + LOG_ERR("Could not commit settings"); + return -EINVAL; } - LOG_INF("Committed new target: '%s'", target_ip); + LOG_INF("Committed settings"); return 0; } -- cgit v1.2.3-70-g09d2 From 11967efab73c43bc5b0c6da33c140dbab7baefa7 Mon Sep 17 00:00:00 2001 From: xengineering Date: Tue, 15 Apr 2025 18:41:27 +0200 Subject: fw: app: syslog: Stop supporting CONFIG_LOG_BACKEND_NET_SERVER From now on the mixed format with IP and port is not supported. The settings system should keep them separate and first only the IP is configurable. Supporting this Kconfig option too is annoying and not necessary. --- fw/app/prj.conf | 1 - fw/app/src/syslog.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'fw/app/src/syslog.c') diff --git a/fw/app/prj.conf b/fw/app/prj.conf index 3258c0f..10de150 100644 --- a/fw/app/prj.conf +++ b/fw/app/prj.conf @@ -21,7 +21,6 @@ CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=4 CONFIG_LOG=y CONFIG_LOG_BACKEND_NET=y -CONFIG_LOG_BACKEND_NET_SERVER="[2001:db8::2]:514" CONFIG_LOG_BACKEND_NET_AUTOSTART=n CONFIG_LOG_MODE_DEFERRED=y diff --git a/fw/app/src/syslog.c b/fw/app/src/syslog.c index c3b5815..47b2edb 100644 --- a/fw/app/src/syslog.c +++ b/fw/app/src/syslog.c @@ -33,7 +33,7 @@ LOG_MODULE_REGISTER(syslog); struct net_mgmt_event_callback l4_cb; static K_SEM_DEFINE(network_connected, 0, 1); -static char target_ip[IPV6_STRLEN_MAX] = CONFIG_LOG_BACKEND_NET_SERVER; +static char target_ip[IPV6_STRLEN_MAX] = "2001:db8::2"; void l4_event_handler( struct net_mgmt_event_callback *cb, -- cgit v1.2.3-70-g09d2 From f4faa103108356bcf53fb7c8829e95f012b21a4a Mon Sep 17 00:00:00 2001 From: xengineering Date: Tue, 15 Apr 2025 22:12:54 +0200 Subject: fw: app: http: Add working GET /settings.json --- fw/app/prj.conf | 2 ++ fw/app/src/http.c | 14 +++++++++++--- fw/app/src/settings.c | 29 +++++++++++++++++++++++++++++ fw/app/src/settings.h | 11 +++++++++++ fw/app/src/syslog.c | 11 +++++++++-- 5 files changed, 62 insertions(+), 5 deletions(-) create mode 100644 fw/app/src/settings.h (limited to 'fw/app/src/syslog.c') diff --git a/fw/app/prj.conf b/fw/app/prj.conf index 10de150..4981bea 100644 --- a/fw/app/prj.conf +++ b/fw/app/prj.conf @@ -55,3 +55,5 @@ CONFIG_SETTINGS=y CONFIG_SETTINGS_RUNTIME=y CONFIG_SETTINGS_NVS=y CONFIG_SETTINGS_SHELL=y + +CONFIG_GNU_C_EXTENSIONS=y diff --git a/fw/app/src/http.c b/fw/app/src/http.c index 081629b..83a3568 100644 --- a/fw/app/src/http.c +++ b/fw/app/src/http.c @@ -13,6 +13,7 @@ #include #include +#include "settings.h" #include "ws.h" @@ -98,9 +99,16 @@ static int settings_handler( struct http_response_ctx *response_ctx, void *user_data ) { - static const char dummy[] = "{\"syslog\":{\"target\":{\"ip\":\"fe80::1\"}}}\n"; - response_ctx->body = (const uint8_t *)dummy; - response_ctx->body_len = sizeof(dummy) - 1; + static char buffer[100]; + + int ret = settings_to_json(buffer, sizeof(buffer)); + if (ret < 0) { + LOG_ERR("Could not serialize payload for settings request"); + return ret; + } + + response_ctx->body = (const uint8_t *)buffer; + response_ctx->body_len = ret; response_ctx->final_chunk = true; response_ctx->status = HTTP_200_OK; diff --git a/fw/app/src/settings.c b/fw/app/src/settings.c index 799322e..89f2f88 100644 --- a/fw/app/src/settings.c +++ b/fw/app/src/settings.c @@ -5,10 +5,14 @@ */ +#include + #include #include #include +#include "settings.h" + LOG_MODULE_DECLARE(settings); @@ -31,3 +35,28 @@ int init_settings(void) { return 0; } SYS_INIT(init_settings, APPLICATION, 50); + +int settings_to_json(void *buffer, size_t len) +{ + static const char format[] = "{\"syslog\":{\"target\":{\"ip\":\"%s\"}}}\n"; + + char ip[100]; + int ret = settings_runtime_get("syslog/target/ip", ip, sizeof(ip)); + if (ret < 0) { + LOG_ERR("Failed to get runtime setting syslog/target/ip (%d)", ret); + return ret; + } + + ret = snprintf(buffer, len, format, ip); + + if (ret >= len) { + LOG_ERR("Buffer too small to serialize settings as JSON"); + return -ENOMEM; + } + + if (ret < 0) { + LOG_ERR("Failed to serialize settings as JSON"); + } + + return ret; +} diff --git a/fw/app/src/settings.h b/fw/app/src/settings.h new file mode 100644 index 0000000..a5cf2ac --- /dev/null +++ b/fw/app/src/settings.h @@ -0,0 +1,11 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at https://mozilla.org/MPL/2.0/. + */ + + +#include + + +int settings_to_json(void *buffer, size_t data); diff --git a/fw/app/src/syslog.c b/fw/app/src/syslog.c index 47b2edb..700547b 100644 --- a/fw/app/src/syslog.c +++ b/fw/app/src/syslog.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -33,7 +34,7 @@ LOG_MODULE_REGISTER(syslog); struct net_mgmt_event_callback l4_cb; static K_SEM_DEFINE(network_connected, 0, 1); -static char target_ip[IPV6_STRLEN_MAX] = "2001:db8::2"; +static char target_ip[IPV6_STRLEN_MAX + 1] = "2001:db8::2"; void l4_event_handler( struct net_mgmt_event_callback *cb, @@ -145,7 +146,13 @@ int syslog_handle_export(int (*cb)(const char *name, const void *value, int syslog_handle_get(const char *name, char *val, int val_len_max) { - LOG_WRN("Settings get not implemented"); + const char* next = NULL; + + if (settings_name_steq(name, "target/ip", &next) && !next) { + size_t len = strnlen(target_ip, sizeof(target_ip)); + memcpy(val, target_ip, MIN(len, val_len_max)); + } + return 0; } -- cgit v1.2.3-70-g09d2 From 993996ab2b9dc7332d06453e2de7315b06ce2458 Mon Sep 17 00:00:00 2001 From: xengineering Date: Wed, 16 Apr 2025 21:58:20 +0200 Subject: fw: app: Encode settings with JSON lib --- fw/app/prj.conf | 2 ++ fw/app/src/http.c | 15 +++++++++++++-- fw/app/src/settings.c | 41 ++++++++++++++++++++++++++++------------- fw/app/src/settings.h | 21 +++++++++++++++++++++ fw/app/src/syslog.c | 3 ++- 5 files changed, 66 insertions(+), 16 deletions(-) (limited to 'fw/app/src/syslog.c') diff --git a/fw/app/prj.conf b/fw/app/prj.conf index 4981bea..6589ec0 100644 --- a/fw/app/prj.conf +++ b/fw/app/prj.conf @@ -57,3 +57,5 @@ CONFIG_SETTINGS_NVS=y CONFIG_SETTINGS_SHELL=y CONFIG_GNU_C_EXTENSIONS=y + +CONFIG_JSON_LIBRARY=y diff --git a/fw/app/src/http.c b/fw/app/src/http.c index 83a3568..1c24490 100644 --- a/fw/app/src/http.c +++ b/fw/app/src/http.c @@ -5,6 +5,7 @@ */ +#include #include #include @@ -101,14 +102,24 @@ static int settings_handler( ) { static char buffer[100]; - int ret = settings_to_json(buffer, sizeof(buffer)); + int ret = settings_to_json(buffer, sizeof(buffer) - 1); if (ret < 0) { LOG_ERR("Could not serialize payload for settings request"); return ret; } + size_t len = strnlen(buffer, sizeof(buffer)); + if (len + 2 > sizeof(buffer)) { + LOG_ERR("Settings JSON requires %d octets but buffer has only %d", + len + 2, sizeof(buffer)); + return -ENOMEM; + } + + buffer[len] = '\n'; + buffer[len + 1] = '\0'; + response_ctx->body = (const uint8_t *)buffer; - response_ctx->body_len = ret; + response_ctx->body_len = len + 1; response_ctx->final_chunk = true; response_ctx->status = HTTP_200_OK; diff --git a/fw/app/src/settings.c b/fw/app/src/settings.c index 89f2f88..4b2c248 100644 --- a/fw/app/src/settings.c +++ b/fw/app/src/settings.c @@ -4,9 +4,9 @@ * obtain one at https://mozilla.org/MPL/2.0/. */ +#include -#include - +#include #include #include #include @@ -36,27 +36,42 @@ int init_settings(void) { } SYS_INIT(init_settings, APPLICATION, 50); +static const struct json_obj_descr settings_syslog_target_descr[] = { + JSON_OBJ_DESCR_PRIM(struct settings_syslog_target, ip, JSON_TOK_STRING), +}; + +static const struct json_obj_descr settings_syslog_descr[] = { + JSON_OBJ_DESCR_OBJECT(struct settings_syslog, target, settings_syslog_target_descr), +}; + +static const struct json_obj_descr settings_descr[] = { + JSON_OBJ_DESCR_OBJECT(struct settings, syslog, settings_syslog_descr), +}; + int settings_to_json(void *buffer, size_t len) { - static const char format[] = "{\"syslog\":{\"target\":{\"ip\":\"%s\"}}}\n"; + struct settings settings = {0,}; + settings.syslog.target.ip = (char *)settings.syslog.target.ip_array; - char ip[100]; - int ret = settings_runtime_get("syslog/target/ip", ip, sizeof(ip)); + int ret = settings_runtime_get("syslog/target/ip", + settings.syslog.target.ip_array, + sizeof(settings.syslog.target.ip_array)); if (ret < 0) { LOG_ERR("Failed to get runtime setting syslog/target/ip (%d)", ret); return ret; } - ret = snprintf(buffer, len, format, ip); - - if (ret >= len) { - LOG_ERR("Buffer too small to serialize settings as JSON"); - return -ENOMEM; - } - + ret = json_obj_encode_buf( + settings_descr, + ARRAY_SIZE(settings_descr), + &settings, + buffer, + len + ); if (ret < 0) { LOG_ERR("Failed to serialize settings as JSON"); + return ret; } - return ret; + return 0; } diff --git a/fw/app/src/settings.h b/fw/app/src/settings.h index a5cf2ac..290d1ff 100644 --- a/fw/app/src/settings.h +++ b/fw/app/src/settings.h @@ -4,8 +4,29 @@ * obtain one at https://mozilla.org/MPL/2.0/. */ +#ifndef SRC_SETTINGS_H +#define SRC_SETTINGS_H #include +#include + +#define IPV6_STRLEN_MAX 39 // excluding '\0' + + +struct settings_syslog_target { + char ip_array[IPV6_STRLEN_MAX]; + char *ip; /* Zephyr's JSON lib does not work with arrays directly */ +}; + +struct settings_syslog { + struct settings_syslog_target target; +}; + +struct settings { + struct settings_syslog syslog; +}; int settings_to_json(void *buffer, size_t data); + +#endif // !SRC_SETTINGS_H diff --git a/fw/app/src/syslog.c b/fw/app/src/syslog.c index 700547b..22aa034 100644 --- a/fw/app/src/syslog.c +++ b/fw/app/src/syslog.c @@ -25,11 +25,12 @@ #include #endif // CONFIG_IOT_CONTACT_NETWORK_HACK +#include "settings.h" + LOG_MODULE_REGISTER(syslog); #define NETWORK_BUG_DELAY K_MSEC(4000) #define L4_EVENT_MASK (NET_EVENT_L4_CONNECTED | NET_EVENT_L4_DISCONNECTED) -#define IPV6_STRLEN_MAX 39 // excluding '\0' #define SYSLOG_TARGET_PORT 514 struct net_mgmt_event_callback l4_cb; -- cgit v1.2.3-70-g09d2