/* * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef CONFIG_IOT_CONTACT_NETWORK_HACK #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 SYSLOG_TARGET_PORT 514 struct net_mgmt_event_callback l4_cb; static K_SEM_DEFINE(network_connected, 0, 1); static char target_ip[IPV6_STRLEN_MAX + 1] = "2001:db8::2"; void l4_event_handler( struct net_mgmt_event_callback *cb, uint32_t event, struct net_if *iface) { LOG_DBG("Executing L4 event handler"); switch (event) { case NET_EVENT_L4_CONNECTED: k_sem_give(&network_connected); LOG_INF("Network connected"); break; case NET_EVENT_L4_DISCONNECTED: LOG_INF("Network disconnected"); break; default: break; } } int init_network_monitoring(void) { net_mgmt_init_event_callback(&l4_cb, l4_event_handler, L4_EVENT_MASK); net_mgmt_add_event_callback(&l4_cb); return 0; } SYS_INIT(init_network_monitoring, APPLICATION, 0); int init_syslog(void) { LOG_DBG("Initializing syslog logging backend"); LOG_INF("Waiting for network ..."); #ifdef CONFIG_IOT_CONTACT_NETWORK_HACK int ret = k_sem_take(&network_connected, NETWORK_BUG_DELAY); if (ret == -EAGAIN) { LOG_ERR("Could not connect to network - rebooting system"); log_flush(); sys_reboot(SYS_REBOOT_COLD); } #else k_sem_take(&network_connected, K_FOREVER); #endif // CONFIG_IOT_CONTACT_NETWORK_HACK LOG_INF("Enabling syslog backend"); const struct log_backend *backend = log_backend_net_get(); if (log_backend_is_active(backend) == false) { /* flush log messages to ensure first syslog message is reproducible */ while (log_process()); log_backend_init(backend); log_backend_enable(backend, backend->cb->ctx, CONFIG_LOG_MAX_LEVEL); LOG_INF("Syslog backend enabled"); } else { LOG_INF("Syslog backend was already enabled"); } return 0; } SYS_INIT(init_syslog, APPLICATION, 40); 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 set target IP (%d)", ret); return (int)ret; } LOG_INF("Set target IP to '%s'", target_ip); return 0; } return 0; } int syslog_handle_commit(void) { 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 settings"); 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) { 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; } SETTINGS_STATIC_HANDLER_DEFINE( syslog_settings_handler, "syslog", syslog_handle_get, syslog_handle_set, syslog_handle_commit, syslog_handle_export );